#!/usr/bin/perl # # Test script for the ownCloud module of csync. # This script requires a running ownCloud instance accessible via HTTP. # It does quite some fancy tests and asserts the results. # # Copyright (C) by Olivier Goffart # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # use lib "."; use File::Copy; use ownCloud::Test; use strict; sub getInode($) { my ($filename) = @_; my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename); return $ino; } print "Hello, this is t4, a tester for A) files that cannot be stated and B) excluded files C) hard links\n"; # stat error occours on windsows when the file is busy for example initTesting(); printInfo( "Copy some files to the remote location" ); mkdir( localDir() . 'test_stat' ); system( "echo foobar > " . localDir() . 'test_stat/file.txt' ); mkdir( localDir() . 'test_ignored' ); mkdir( localDir() . 'test_ignored/sub' ); system( "echo foobarfoo > " . localDir() . 'test_ignored/sub/file.txt' ); # call csync, sync local t1 to remote t1 csync(); # Check if the files from toremote1 are now in t1/remoteToLocal1 # they should have taken the way via the ownCloud. print "Assert the local file copy\n"; assertLocalAndRemoteDir( '', 0 ); printInfo( "Make a file not statable" ); system( "echo foobar2 >> " . localDir() . 'test_stat/file.txt' ); #make the file not statable by changing the directory right system( "chmod 400 " . localDir() . 'test_stat' ); csync(); # TODO: some check here. printInfo("Add a file in a read only directory"); system( "echo \"Hello World\" >> /tmp/kernelcrash.txt" ); put_to_dir( '/tmp/kernelcrash.txt', 'test_stat' ); csync(); assert( ! -e localDir().'test_stat/kernelcrash' ); printInfo("Restore the original rights"); system( "chmod 700 " . localDir() . 'test_stat' ); system( "echo foobar3 >> " . localDir() . 'test_stat/file.txt' ); csync(); print "Check if everything is still the same\n"; assertLocalAndRemoteDir( '', 0 ); # TODO: Check that the file content is fine on the server and that there was no conflict assert( -e localDir().'test_stat/file.txt' ); assert( -e localDir().'test_stat/kernelcrash.txt' ); my $localMD5 = md5OfFile( localDir().'test_stat/kernelcrash.txt' ); my $realMD5 = md5OfFile( '/tmp/kernelcrash.txt' ); print "MD5 compare $localMD5 <-> $realMD5\n"; assert( $localMD5 eq $realMD5 ); printInfo("Added a file that is on the ignore list"); # (*.directory is in the ignored list that needs cleanup) # (it is names with _conflict) because i want the conflicft detection of assertLocalAndRemoteDir to work system( "echo dir >> " . localDir() . 'test_stat/file_conflict.directory' ); # this one should retain the directory system( "echo foobarfoo > " . localDir() . 'test_ignored/sub/ignored_conflict.part' ); csync(); # The file_conflict.directory is seen as a conflict assertLocalAndRemoteDir( '', 1 ); # TODO: check that the file_conflict.directory is indeed NOT on the server # TODO: check that test_ignored/sub/ignored_conflict.part is NOT on the server assert(-e localDir() . 'test_ignored/sub/ignored_conflict.part'); printInfo("Remove a directory containing an ignored file that should not be removed\n"); remoteCleanup('test_ignored'); csync(); assert(-e localDir() . 'test_ignored/sub/ignored_conflict.part'); #remove the file so next sync allow the directory to be removed system( "rm " . localDir() . 'test_ignored/sub/ignored_conflict.part' ); printInfo("Remove a directory containing a local file\n"); remoteCleanup('test_stat'); #Add an executable file for next test system( "echo echo hello >> " . localDir() . 'echo.sh' ); chmod 0751, localDir() . 'echo.sh'; #and add a file in anotherdir for the next test mkdir( localDir() . 'anotherdir' ); mkdir( localDir() . 'anotherdir/sub' ); system( "echo foobar > " . localDir() . 'anotherdir/file1.txt' ); system( "echo foobar > " . localDir() . 'anotherdir/sub/file2.txt' ); csync(); assertLocalAndRemoteDir( '', 0 ); open(my $fh, "<", localDir() . 'echo.sh'); my $perm = (stat $fh)[2] & 07777; assert( $perm eq 0751, "permissions not kept" ); printInfo("Modify a file in the remote and check its permission\n"); system( "echo \"echo bonjour\" > /tmp/echo.sh" ); put_to_dir( '/tmp/echo.sh', "" ); csync(); assertLocalAndRemoteDir( '', 0 ); open(my $fh, "<", localDir() . 'echo.sh'); my $perm = (stat $fh)[2] & 07777; assert( $perm eq 0751, "permissions not kept" ); printInfo("Remove a directory and make it a symlink instead\n"); system( "rm -rf " . localDir() . 'anotherdir' ); system( "ln -s /bin " . localDir() . 'anotherdir' ); # remember the fileid of the file on the server my $oldfileid1 = remoteFileId( 'anotherdir/', 'file1.txt' ); my $oldfileid2 = remoteFileId( 'anotherdir/sub', 'file2.txt' ); csync(); #check that the files in ignored directory has NOT been removed my $newfileid1 = remoteFileId( 'anotherdir/', 'file1.txt' ); my $newfileid2 = remoteFileId( 'anotherdir/sub', 'file2.txt' ); assert( $oldfileid1 eq $newfileid1, "File removed (file1.txt)" ); assert( $oldfileid2 eq $newfileid2, "File removed (file2.txt)" ); printInfo("Now remove the symlink\n"); system( "rm -f " . localDir() . 'anotherdir' ); csync(); assertLocalAndRemoteDir( '', 0 ); assert(! -e localDir(). 'anotherdir' ); printInfo("Test hardlinks\n"); #make a hard link mkdir( localDir() . 'subdir' ); createLocalFile( localDir() .'subdir/original.data', 1568 ); system( "ln " . localDir() . 'subdir/original.data ' . localDir() . 'file.link'); csync(); assertLocalAndRemoteDir( '', 0 ); my $inode = getInode(localDir() . 'subdir/original.data'); my $inode2 = getInode(localDir() . 'file.link'); assert( $inode == $inode2, "Inode is not the same!"); printInfo("Modify hard link\n"); system( "echo 'another line' >> " . localDir() . 'file.link'); csync(); assertLocalAndRemoteDir( '', 0 ); my $inode1 = getInode(localDir() .'subdir/original.data'); $inode2 = getInode( localDir() .'file.link'); assert( $inode == $inode1, "Inode is not the same!"); assert( $inode == $inode2, "Inode is not the same!"); printInfo("Rename a hard link\n"); move( localDir() . 'subdir/original.data', localDir() . 'subdir/kernelcrash.txt' ); csync(); assertLocalAndRemoteDir( '', 0 ); $inode1 = getInode(localDir() .'subdir/kernelcrash.txt'); $inode2 = getInode(localDir() .'file.link'); assert( $inode == $inode1, "Inode is not the same!"); assert( $inode == $inode2, "Inode is not the same!"); printInfo("Modify a hard link on the server\n"); put_to_dir( '/tmp/kernelcrash.txt', 'subdir' ); csync(); assertLocalAndRemoteDir( '', 0 ); $inode1 = getInode(localDir() .'subdir/kernelcrash.txt'); $inode2 = getInode( localDir() .'file.link'); # only the first inode must change print(" $inode $inode1 $inode2" ); assert( $inode != $inode1, "Inode did not change"); assert( $inode == $inode2, "Inode is not the same!"); cleanup(); # --