def generic_regress_test(self, extra_args): """Used for regress tests below""" in1, in2 = self.make_input_dirs() Myrm(self.out_rp.path) restore_dir = self.root_rp.append('longname_out') Myrm(restore_dir.path) rdiff_backup(1, 1, in1.path, self.out_rp.path, 10000, extra_options=extra_args) rdiff_backup(1, 1, in2.path, self.out_rp.path, 20000, extra_options=extra_args) # Regress repository back to in1 condition Globals.rbdir = self.out_rp.append_path('rdiff-backup-data') self.add_current_mirror(10000) self.out_rp.setdata() regress.Regress(self.out_rp) # Restore in1 and compare rdiff_backup(1, 1, self.out_rp.path, restore_dir.path, 30000, extra_options=b'-r now ' + extra_args) self.check_dir1(restore_dir)
def test_restrict_negative(self): """Test that --restrict switch denies certain operations""" # Backup to wrong directory output2_dir = abs_output_dir + b"2" Myrm(abs_output_dir) Myrm(output2_dir) self.secure_rdiff_backup(self.various_files_dir, output2_dir, 1, b'--restrict %b' % abs_output_dir, success=0) # Restore to wrong directory Myrm(abs_output_dir) Myrm(abs_restore_dir) rdiff_backup(1, 1, self.various_files_dir, abs_output_dir) self.secure_rdiff_backup(abs_output_dir, abs_restore_dir, 1, b'--restrict %b' % output2_dir, extra_args=b'-r now', success=0) # Backup from wrong directory Myrm(abs_output_dir) wrong_files_dir = os.path.join(old_test_dir, b"foobar") self.secure_rdiff_backup(self.various_files_dir, abs_output_dir, 0, b'--restrict %b' % wrong_files_dir, success=0)
def test_restrict_readonly_positive(self): """Test that --restrict-read-only switch doesn't impair normal ops""" Myrm(abs_output_dir) Myrm(abs_restore_dir) self.secure_rdiff_backup( self.various_files_dir, abs_output_dir, 0, b'--restrict-read-only %b' % self.various_files_dir) self.secure_rdiff_backup(abs_output_dir, abs_restore_dir, 0, b'--restrict-read-only %b' % abs_output_dir, extra_args=b'-r now')
def testRestoreNoincs(self): """Test restoring a directory with no increments, just mirror""" Myrm(abs_output_dir) InternalRestore( 1, 1, os.path.join(old_test_dir, b'restoretest5', b'regular_file'), abs_output_dir, 10000) assert os.lstat(abs_output_dir)
def make_root_dirs(self): """Make directory createable only by root""" rp = rpath.RPath(Globals.local_connection, os.path.join(abs_test_dir, b"root_out1")) re_init_rpath_dir(rp) rp1 = rp.append("1") rp1.touch() rp2 = rp.append("2") rp2.touch() rp2.chown(1, 1) rp3 = rp.append("3") rp3.touch() rp3.chown(2, 2) rp4 = rp.append("dev") rp4.makedev('c', 4, 28) sp = rpath.RPath(Globals.local_connection, os.path.join(abs_test_dir, b"root_out2")) if sp.lstat(): Myrm(sp.path) xcopytree(rp.path, sp.path) rp2 = sp.append("2") rp2.chown(2, 2) rp3 = sp.append("3") rp3.chown(1, 1) self.assertFalse(compare_recursive(rp, sp, compare_ownership=1)) return rp, sp
def testReadWrite(self): """Test basic querying read/write""" base_dir = rpath.RPath(Globals.local_connection, self.dir_to_test) new_dir = base_dir.append("fs_abilitiestest") if new_dir.lstat(): Myrm(new_dir.path) new_dir.setdata() new_dir.mkdir() t = time.time() fsa = fs_abilities.FSAbilities('read/write', new_dir) print("Time elapsed = ", time.time() - t) print(fsa) self.assertEqual(fsa.read_only, 0) self.assertEqual(fsa.eas, self.eas) self.assertEqual(fsa.acls, self.acls) self.assertEqual(fsa.ownership, self.ownership) self.assertEqual(fsa.hardlinks, self.hardlinks) self.assertEqual(fsa.fsync_dirs, self.fsync_dirs) self.assertEqual(fsa.dir_inc_perms, self.dir_inc_perms) self.assertEqual(fsa.resource_forks, self.resource_forks) self.assertEqual(fsa.carbonfile, self.carbonfile) self.assertEqual(fsa.high_perms, self.high_perms) self.assertEqual(fsa.extended_filenames, self.extended_filenames) new_dir.delete()
def runtest(self, regress_function): """Test regressing a full directory to older state Make two directories, one with one more backup in it. Then regress the bigger one, and then make sure they compare the same. Regress_function takes a time and should regress self.output_rp back to that time. """ self.output_rp.setdata() if self.output_rp.lstat(): Myrm(self.output_rp.path) rdiff_backup(1, 1, self.incrp[0].path, self.output_rp.path, current_time=10000) self.assertTrue(compare_recursive(self.incrp[0], self.output_rp)) rdiff_backup(1, 1, self.incrp[1].path, self.output_rp.path, current_time=20000) self.assertTrue(compare_recursive(self.incrp[1], self.output_rp)) rdiff_backup(1, 1, self.incrp[2].path, self.output_rp.path, current_time=30000) self.assertTrue(compare_recursive(self.incrp[2], self.output_rp)) rdiff_backup(1, 1, self.incrp[3].path, self.output_rp.path, current_time=40000) self.assertTrue(compare_recursive(self.incrp[3], self.output_rp)) Globals.rbdir = self.output_rbdir_rp regress_function(30000) self.assertTrue( compare_recursive(self.incrp[2], self.output_rp, compare_hardlinks=0)) regress_function(20000) self.assertTrue( compare_recursive(self.incrp[1], self.output_rp, compare_hardlinks=0)) regress_function(10000) self.assertTrue( compare_recursive(self.incrp[0], self.output_rp, compare_hardlinks=0))
def restore_dir_test(self, mirror_local, dest_local): """Run whole dir tests If any of the above tests don't work, try rerunning makerestoretest3. """ Myrm(abs_output_dir) restore3_dir = os.path.join(old_test_dir, b"restoretest3") target_rp = rpath.RPath(Globals.local_connection, abs_output_dir) inc1_rp = rpath.RPath(Globals.local_connection, os.path.join(old_test_dir, b"increment1")) inc2_rp = rpath.RPath(Globals.local_connection, os.path.join(old_test_dir, b"increment2")) inc3_rp = rpath.RPath(Globals.local_connection, os.path.join(old_test_dir, b"increment3")) inc4_rp = rpath.RPath(Globals.local_connection, os.path.join(old_test_dir, b"increment4")) InternalRestore(mirror_local, dest_local, restore3_dir, abs_output_dir, 45000) assert CompareRecursive(inc4_rp, target_rp) InternalRestore(mirror_local, dest_local, restore3_dir, abs_output_dir, 35000) assert CompareRecursive(inc3_rp, target_rp, compare_hardlinks=0) InternalRestore(mirror_local, dest_local, restore3_dir, abs_output_dir, 25000) assert CompareRecursive(inc2_rp, target_rp, compare_hardlinks=0) InternalRestore(mirror_local, dest_local, restore3_dir, abs_output_dir, 5000) assert CompareRecursive(inc1_rp, target_rp, compare_hardlinks=0)
def test_session(self): """Run actual sessions and make sure proper hashes recorded There are a few code paths here we need to test: creating ordinary files, updating ordinary files with diffs, hard linking, and keeping files the same. """ in_rp1, hashlist1, in_rp2, hashlist2 = self.make_dirs() Myrm(abs_output_dir) rdiff_backup(1, 1, in_rp1.path, abs_output_dir, 10000) meta_prefix = rpath.RPath( Globals.local_connection, os.path.join(abs_output_dir, b"rdiff-backup-data", b"mirror_metadata")) incs = meta_prefix.get_incfiles_list() self.assertEqual(len(incs), 1) metadata_rp = incs[0] hashlist = self.extract_hashs(metadata_rp) self.assertEqual(hashlist, hashlist1) rdiff_backup(1, 1, in_rp2.path, abs_output_dir, 20000) incs = meta_prefix.get_incfiles_list() self.assertEqual(len(incs), 2) if incs[0].getinctype() == 'snapshot': inc = incs[0] else: inc = incs[1] hashlist = self.extract_hashs(inc) self.assertEqual(hashlist, hashlist2)
def test_backup(self): """Test back up, simple restores""" in_rp1, in_rp2 = self.make_dirs() outrp = rpath.RPath(Globals.local_connection, abs_output_dir) re_init_rpath_dir(outrp, userid) remote_schema = b'su -c "rdiff-backup --server" %s' % (user.encode(), ) cmd_schema = (b"rdiff-backup -v%i" % verbosity + b" --current-time %i --remote-schema '%%s' %b '%b'::%b") cmd1 = cmd_schema % (10000, in_rp1.path, remote_schema, outrp.path) Run(cmd1) in_rp1.setdata() outrp.setdata() cmd2 = cmd_schema % (20000, in_rp2.path, remote_schema, outrp.path) Run(cmd2) in_rp2.setdata() outrp.setdata() rout_rp = rpath.RPath(Globals.local_connection, abs_restore_dir) restore_schema = (b"rdiff-backup -v%i" % verbosity + b" -r %b --remote-schema '%%s' '%b'::%b %b") Myrm(rout_rp.path) cmd3 = restore_schema % (b'10000', remote_schema, outrp.path, rout_rp.path) Run(cmd3) assert CompareRecursive(in_rp1, rout_rp) rout_perms = rout_rp.append('unreadable_dir').getperms() outrp_perms = outrp.append('unreadable_dir').getperms() assert rout_perms == 0, rout_perms assert outrp_perms == 0, outrp_perms Myrm(rout_rp.path) cmd4 = restore_schema % (b"now", remote_schema, outrp.path, rout_rp.path) Run(cmd4) assert CompareRecursive(in_rp2, rout_rp) rout_perms = rout_rp.append('unreadable_dir').getperms() outrp_perms = outrp.append('unreadable_dir').getperms() assert rout_perms == 0, rout_perms assert outrp_perms == 0, outrp_perms self.cause_regress(outrp) cmd5 = (b'su -c "rdiff-backup --check-destination-dir %s" %s' % (outrp.path, user.encode())) Run(cmd5)
def test_quoting_bug(self): """Test for bug 14545 --- quoting causes bad violation""" Myrm(abs_output_dir) self.secure_rdiff_backup(self.various_files_dir, abs_output_dir, 1, b'', extra_args=b'--override-chars-to-quote e')
def test_backup(self): """Test back up, simple restores""" in_rp1, in_rp2 = self.make_dirs() outrp = rpath.RPath(Globals.local_connection, abs_output_dir) re_init_rpath_dir(outrp, userid) remote_schema = b'su -c "%s server" %s' % (RBBin, user.encode()) cmd_schema = (RBBin + b" --current-time %i --remote-schema '{h}' %b '%b'::%b") cmd1 = cmd_schema % (10000, in_rp1.path, remote_schema, outrp.path) self._run_cmd(cmd1) in_rp1.setdata() outrp.setdata() cmd2 = cmd_schema % (20000, in_rp2.path, remote_schema, outrp.path) self._run_cmd(cmd2) in_rp2.setdata() outrp.setdata() rout_rp = rpath.RPath(Globals.local_connection, abs_restore_dir) restore_schema = (RBBin + b" -r %b --remote-schema '{h}' '%b'::%b %b") Myrm(rout_rp.path) cmd3 = restore_schema % (b'10000', remote_schema, outrp.path, rout_rp.path) self._run_cmd(cmd3) self.assertTrue(compare_recursive(in_rp1, rout_rp)) rout_perms = rout_rp.append('unreadable_dir').getperms() outrp_perms = outrp.append('unreadable_dir').getperms() self.assertEqual(rout_perms, 0) self.assertEqual(outrp_perms, 0) Myrm(rout_rp.path) cmd4 = restore_schema % (b"now", remote_schema, outrp.path, rout_rp.path) self._run_cmd(cmd4) self.assertTrue(compare_recursive(in_rp2, rout_rp)) rout_perms = rout_rp.append('unreadable_dir').getperms() outrp_perms = outrp.append('unreadable_dir').getperms() self.assertEqual(rout_perms, 0) self.assertEqual(outrp_perms, 0) self.cause_regress(outrp) cmd5 = (b'su -c "%s --check-destination-dir %s" %s' % (RBBin, outrp.path, user.encode())) self._run_cmd(cmd5)
def restore(self, dest_rp, restore_rp, time=None): Myrm(restore_rp.path) if time is None or time == "now": restore_cmd = b"%s -r now %b %b" % (RBBin, dest_rp.path, restore_rp.path) else: restore_cmd = b"%s -r %i %b %b" % (RBBin, time, dest_rp.path, restore_rp.path) self._run_cmd(restore_cmd)
def restore(self, dest_rp, restore_rp, time=None): Myrm(restore_rp.path) if time is None or time == "now": restore_cmd = b"rdiff-backup -r now %b %b" % (dest_rp.path, restore_rp.path) else: restore_cmd = b"rdiff-backup -r %i %b %b" % (time, dest_rp.path, restore_rp.path) Run(restore_cmd)
def testNonExistingTempDir(self): """Test that a missing tempdir is properly catched as an error""" Myrm(Local.rpout.path) rdiff_backup(True, True, Local.vftrp.path, Local.rpout.path, extra_options=b"--tempdir DoesSurelyNotExist", expected_ret_val=1)
def test_restrict_updateonly_negative(self): """Test that --restrict-update-only impairs unintended""" Myrm(abs_output_dir) self.secure_rdiff_backup(self.various_files_dir, abs_output_dir, 1, b'--restrict-update-only %b' % abs_output_dir, success=0) Myrm(abs_output_dir) Myrm(abs_restore_dir) rdiff_backup(1, 1, self.various_files_dir, abs_output_dir) self.secure_rdiff_backup(abs_output_dir, abs_restore_dir, 1, b'--restrict-update-only %b' % abs_restore_dir, extra_args=b'-r now', success=0)
def test_restrict_bug(self): """Test for bug 14209 --- mkdir outside --restrict arg""" Myrm(abs_output_dir) self.secure_rdiff_backup(self.various_files_dir, abs_output_dir, 1, b'--restrict foobar', success=0) output = rpath.RPath(Globals.local_connection, abs_output_dir) assert not output.lstat()
def test_long_socket_name(self): """Test when socket name is saved to a backup directory with a long name It addresses an issue where socket wasn't created with mknod but with socket.socket and bind, which has a limit at 107 characters.""" input_dir = os.path.join(old_test_dir, b"select", b"filetypes") # create a target directory with a long name next to 107 output_dir = os.path.join(abs_test_dir, b"tenletters" * 10) Myrm(output_dir) restore_dir = os.path.join(abs_test_dir, b"restoresme" * 10) Myrm(restore_dir) # backup and restore the input directory with socket, then compare rdiff_backup(True, True, input_dir, output_dir) rdiff_backup(True, True, output_dir, restore_dir, extra_options=b'-r 0') compare_recursive(rpath.RPath(Globals.local_connection, input_dir), rpath.RPath(Globals.local_connection, restore_dir))
def test_restrict_updateonly_positive(self): """Test that --restrict-update-only allows intended use""" Myrm(abs_output_dir) rdiff_backup(1, 1, self.various_files_dir, abs_output_dir, current_time=10000) self.secure_rdiff_backup(self.various_files_dir, abs_output_dir, 1, b'--restrict-update-only %b' % abs_output_dir)
def make_restore_sel_dir(self, source_local, dest_local): """Create rdiff-backup repository at Local.rpout""" self.delete_tmpdirs() Local.vft_out.mkdir() rp1 = Local.vft_out.append("file1") rp2 = Local.vft_out.append("file2") rp1.touch() rp2.touch() rdiff_backup(source_local, dest_local, Local.vft_out.path, Local.rpout.path) Myrm(Local.vft_out.path)
def test_restrict_readonly_negative(self): """Test that --restrict-read-only doesn't allow too much""" # Backup to restricted directory Myrm(abs_output_dir) self.secure_rdiff_backup(self.various_files_dir, abs_output_dir, 1, b'--restrict-read-only %b' % abs_output_dir, success=0) # Restore to restricted directory Myrm(abs_output_dir) Myrm(abs_restore_dir) rdiff_backup(1, 1, self.various_files_dir, abs_output_dir) self.secure_rdiff_backup(abs_output_dir, abs_restore_dir, 1, b'--restrict-read-only %b' % abs_restore_dir, extra_args=b'-r now', success=0)
def generic_test(self, inlocal, outlocal, extra_args, compare_back): """Used for some of the tests below""" in1, in2 = self.make_input_dirs() Myrm(self.out_rp.path) restore_dir = self.root_rp.append('longname_out') # Test backing up rdiff_backup(inlocal, outlocal, in1.path, self.out_rp.path, 10000, extra_options=extra_args) if compare_back: self.check_dir1(self.out_rp) rdiff_backup(inlocal, outlocal, in2.path, self.out_rp.path, 20000, extra_options=extra_args) if compare_back: self.check_dir2(self.out_rp) # Now try restoring Myrm(restore_dir.path) rdiff_backup(inlocal, outlocal, self.out_rp.path, restore_dir.path, 30000, extra_options=b"-r now " + extra_args) self.check_dir2(restore_dir) Myrm(restore_dir.path) rdiff_backup(1, 1, self.out_rp.path, restore_dir.path, 30000, extra_options=b"-r 10000 " + extra_args) self.check_dir1(restore_dir)
def testRemoveOlderThanRemote(self): """Test --remove-older-than remotely""" Myrm(Local.rpout.path) xcopytree(Local.backup3rp.path, Local.rpout.path) rdiff_backup(False, True, Local.rpout.path, None, extra_options=b"--remove-older-than 20000") rbdir = Local.rpout.append("rdiff-backup-data") for inc in self.get_all_increments(rbdir): self.assertGreaterEqual(inc.getinctime(), 20000)
def testRemoveOlderThan2(self): """Test --remove-older-than, but '1B'. Uses restoretest3""" Myrm(Local.rpout.path) xcopytree(Local.backup3rp.path, Local.rpout.path) rdiff_backup(True, True, Local.rpout.path, None, extra_options=b"--remove-older-than 1B --force") rbdir = Local.rpout.append("rdiff-backup-data") for inc in self.get_all_increments(rbdir): self.assertGreaterEqual(inc.getinctime(), 30000)
def make_dir(self): self.delete_tmpdirs() rp1 = Local.get_tgt_local_rp('final_deleted1') if rp1.lstat(): Myrm(rp1.path) rp1.mkdir() rp1_1 = rp1.append('regfile') rp1_1.touch() rp1_2 = rp1.append('dir') rp1_2.mkdir() rp1_2_1 = rp1_2.append('regfile2') rp1_2_1.write_string('foo') rp2 = Local.get_tgt_local_rp('final_deleted2') if rp2.lstat(): Myrm(rp2.path) os.system(b'cp -a %b %b' % (rp1.path, rp2.path)) rp2_2_1 = rp2.append('dir', 'regfile2') assert rp2_2_1.lstat() rp2_2_1.delete() rp2_2_1.touch() return rp1, rp1_2, rp2
def testRemoveOlderThanRemote(self): """Test --remove-older-than remotely""" Myrm(Local.rpout.path) assert not os.system(b"cp -a %b %b" % (Local.backup3rp.path, Local.rpout.path)) rdiff_backup(False, True, Local.rpout.path, None, extra_options=b"--remove-older-than 20000") rbdir = Local.rpout.append("rdiff-backup-data") for inc in self.get_all_increments(rbdir): assert inc.getinctime() >= 20000
def testRemoveOlderThan2(self): """Test --remove-older-than, but '1B'. Uses restoretest3""" Myrm(Local.rpout.path) assert not os.system(b"cp -a %b %b" % (Local.backup3rp.path, Local.rpout.path)) rdiff_backup(True, True, Local.rpout.path, None, extra_options=b"--remove-older-than 1B --force") rbdir = Local.rpout.append("rdiff-backup-data") for inc in self.get_all_increments(rbdir): assert inc.getinctime() >= 30000
def testStatistics(self): """Test the writing of statistics The file sizes are approximate because the size of directories could change with different file systems... """ def sorti(inclist): templist = [(inc.getinctime(), inc) for inc in inclist] templist.sort() return [inc for (t, inc) in templist] Globals.compression = 1 Myrm(abs_output_dir) InternalBackup(1, 1, os.path.join(old_test_dir, b"stattest1"), abs_output_dir) InternalBackup(1, 1, os.path.join(old_test_dir, b"stattest2"), abs_output_dir, time.time() + 1) rbdir = rpath.RPath(Globals.local_connection, os.path.join(abs_output_dir, b"rdiff-backup-data")) incs = sorti(restore.get_inclist(rbdir.append("session_statistics"))) self.assertEqual(len(incs), 2) s2 = statistics.StatsObj().read_stats_from_rp(incs[0]) self.assertEqual(s2.SourceFiles, 7) self.assertLessEqual(700000, s2.SourceFileSize) self.assertLess(s2.SourceFileSize, 750000) self.stats_check_initial(s2) root_stats = statistics.StatsObj().read_stats_from_rp(incs[1]) self.assertEqual(root_stats.SourceFiles, 7) self.assertLessEqual(550000, root_stats.SourceFileSize) self.assertLess(root_stats.SourceFileSize, 570000) self.assertEqual(root_stats.MirrorFiles, 7) self.assertLessEqual(700000, root_stats.MirrorFileSize) self.assertLess(root_stats.MirrorFileSize, 750000) self.assertEqual(root_stats.NewFiles, 1) self.assertEqual(root_stats.NewFileSize, 0) self.assertEqual(root_stats.DeletedFiles, 1) self.assertEqual(root_stats.DeletedFileSize, 200000) self.assertLessEqual(3, root_stats.ChangedFiles) self.assertLessEqual(root_stats.ChangedFiles, 4) self.assertLessEqual(450000, root_stats.ChangedSourceSize) self.assertLess(root_stats.ChangedSourceSize, 470000) self.assertLessEqual(400000, root_stats.ChangedMirrorSize) self.assertLess(root_stats.ChangedMirrorSize, 420000) self.assertLess(10, root_stats.IncrementFileSize) self.assertLess(root_stats.IncrementFileSize, 30000)
def test_restrict_positive(self): """Test that --restrict switch doesn't get in the way This makes sure that basic backups with the restrict operator work, (initial backup, incremental, restore). """ Myrm(abs_output_dir) self.secure_rdiff_backup(self.various_files_dir, abs_output_dir, 1, b'--restrict %b' % abs_output_dir, current_time=10000) # Note the backslash below -- eest for bug in path normalization self.secure_rdiff_backup(self.various_files_dir, abs_output_dir, 1, b'--restrict %b/' % abs_output_dir) Myrm(abs_restore_dir) self.secure_rdiff_backup(abs_output_dir, abs_restore_dir, 1, b'--restrict %b' % abs_restore_dir, extra_args=b'-r now')
def make_input_dirs(self): """Create two input directories with long filename(s) in them""" dir1 = self.root_rp.append('longname1') dir2 = self.root_rp.append('longname2') Myrm(dir1.path) Myrm(dir2.path) dir1.mkdir() rp11 = dir1.append('A' * max_len) rp11.write_string('foobar') rp12 = dir1.append('B' * max_len) rp12.mkdir() rp121 = rp12.append('C' * max_len) rp121.touch() dir2.mkdir() rp21 = dir2.append('A' * max_len) rp21.write_string('Hello, world') rp22 = dir2.append('D' * max_len) rp22.mkdir() rp221 = rp22.append('C' * max_len) rp221.touch() return dir1, dir2