def test_non_root(self): """Main non-root -> root test""" input_rp1, input_rp2 = self.make_root_dirs() Globals.change_ownership = 1 output_rp = rpath.RPath(Globals.local_connection, abs_output_dir) re_init_rpath_dir(output_rp, userid) restore_rp = rpath.RPath(Globals.local_connection, abs_restore_dir) empty_rp = rpath.RPath(Globals.local_connection, os.path.join(old_test_dir, b"empty")) self.backup(input_rp1, output_rp, 1000000) self.restore(output_rp, restore_rp) self.assertTrue( compare_recursive(input_rp1, restore_rp, compare_ownership=1)) self.backup(input_rp2, output_rp, 2000000) self.restore(output_rp, restore_rp) self.assertTrue( compare_recursive(input_rp2, restore_rp, compare_ownership=1)) self.backup(empty_rp, output_rp, 3000000) self.restore(output_rp, restore_rp) self.assertTrue( compare_recursive(empty_rp, restore_rp, compare_ownership=1)) self.restore(output_rp, restore_rp, 1000000) self.assertTrue( compare_recursive(input_rp1, restore_rp, compare_ownership=1)) self.restore(output_rp, restore_rp, 2000000) self.assertTrue( compare_recursive(input_rp2, restore_rp, compare_ownership=1))
def testLongFilenames(self): """See if long quoted filenames cause crash""" MakeOutputDir() outrp = rpath.RPath(Globals.local_connection, abs_output_dir) inrp = rpath.RPath(Globals.local_connection, os.path.join(abs_test_dir, b"quotetest")) re_init_rpath_dir(inrp) long_filename = b"A" * 200 # when quoted should cause overflow longrp = inrp.append(long_filename) longrp.touch() shortrp = inrp.append(b"B") shortrp.touch() rdiff_backup(1, 1, inrp.path, outrp.path, 100000, extra_options=b"--override-chars-to-quote A") longrp_out = outrp.append(long_filename) assert not longrp_out.lstat() shortrp_out = outrp.append('B') assert shortrp_out.lstat() rdiff_backup(1, 1, os.path.join(old_test_dir, b"empty"), outrp.path, 200000) shortrp_out.setdata() assert not shortrp_out.lstat() rdiff_backup(1, 1, inrp.path, outrp.path, 300000) shortrp_out.setdata() assert shortrp_out.lstat()
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 write_ownership_dir(): """Write the directory testfiles/root_mapping""" rp = rpath.RPath(Globals.local_connection, os.path.join(abs_test_dir, b"root_mapping")) re_init_rpath_dir(rp) rp1 = rp.append('1') rp1.touch() rp2 = rp.append('2') rp2.touch() rp2.chown(userid, 1) # use groupid 1, usually bin return rp
def testDuplicateMetadataTimestamp(self): """This test is based on issue #322 where a diff and a snapshot metadata mirror files had the same timestamp, which made rdiff-backup choke. We check that rdiff-backup still fails by default but can be taught to ignore the error with --allow-duplicate-timestamps so that the repo can be fixed.""" # create an empty directory test_base_rp = self.makerp(abs_test_dir).append("dupl_meta_time") re_init_rpath_dir(test_base_rp) # create enough incremental backups to have one metadata snapshot # in-between, which we can manipulate to simulate the error source_rp = test_base_rp.append("source") target_rp = test_base_rp.append("target") source_rp.mkdir() for suffix in range(1, 15): source_rp.append("file%02d" % suffix).touch() rdiff_backup(1, 1, source_rp.__fspath__(), target_rp.__fspath__(), current_time=suffix * 10000) # identify the oldest (aka first) mirror metadata snapshot # and sort the list because some filesystems don't respect the order rb_data_rp = target_rp.append("rdiff-backup-data") files_list = sorted(filter( lambda x: x.startswith(b"mirror_metadata."), rb_data_rp.listdir())) meta_snapshot_rp = rb_data_rp.append(files_list[8]) # create a diff with the same data as the identified snapshot meta_dupldiff_rp = rb_data_rp.append(files_list[8].replace( b".snapshot.gz", b".diff.gz")) rpath.copy(meta_snapshot_rp, meta_dupldiff_rp) # this succeeds rdiff_backup(1, 1, target_rp.__fspath__(), None, extra_options=b"--check-destination-dir") # now this should fail source_rp.append("file15").touch() rdiff_backup(1, 1, source_rp.__fspath__(), target_rp.__fspath__(), current_time=15 * 10000, expected_ret_val=1) # and this should also fail rdiff_backup(1, 1, target_rp.__fspath__(), None, expected_ret_val=1, extra_options=b"--check-destination-dir") # but this should succeed rdiff_backup(1, 1, target_rp.__fspath__(), None, extra_options=b"--allow-duplicate-timestamps --check-destination-dir") # now we can clean-up, getting rid of the duplicate metadata mirrors # NOTE: we could have cleaned-up even without checking/fixing the directory # but this shouldn't be the recommended practice. rdiff_backup(1, 1, target_rp.__fspath__(), None, extra_options=b"--remove-older-than 100000 --force") # and this should at last succeed source_rp.append("file16").touch() rdiff_backup(1, 1, source_rp.__fspath__(), target_rp.__fspath__(), current_time=16 * 10000)
def make_dir(): re_init_rpath_dir(dirrp) rp1 = dirrp.append('file1') rp2 = dirrp.append('file2') rp3 = dirrp.append('file3') rp4 = dirrp.append('file4') rp5 = dirrp.append('symlink') rp1.touch() rp2.touch() rp3.touch() rp4.touch() rp5.symlink(b'foobar') rp1.chown(2000, 2000) rp2.chown(2001, 2001) rp3.chown(2002, 2002) rp4.chown(2003, 2003) rp5.chown(2004, 2004)
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_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 testReQuote(self): inrp = rpath.RPath(Globals.local_connection, os.path.join(ct.abs_test_dir, b"requote")) ct.re_init_rpath_dir(inrp) inrp.append("ABC_XYZ.1").touch() outrp = rpath.RPath(Globals.local_connection, ct.abs_output_dir) ct.re_init_rpath_dir(outrp) self.assertEqual( ct.rdiff_backup_action(True, True, inrp.path, outrp.path, ("--chars-to-quote", "A-C"), b"backup", ()), 0) time.sleep(1) inrp.append("ABC_XYZ.2").touch() # enforce a requote of the whole repository and see it refused self.assertNotEqual( ct.rdiff_backup_action(True, True, inrp.path, outrp.path, ("--chars-to-quote", "X-Z", "--force"), b"backup", ()), 0)
def testEmptyDirInclude(self): """Make sure empty directories are included with **xx exps This checks for a bug present in 1.0.3/1.1.5 and similar. """ outrp = MakeOutputDir() # we need to change directory to be able to work with relative paths os.chdir(abs_test_dir) os.chdir(os.pardir) # chdir one level up selrp = rpath.RPath(Globals.local_connection, 'testfiles/seltest') re_init_rpath_dir(selrp) emptydir = selrp.append('emptydir') emptydir.mkdir() rdiff_backup(1, 1, selrp.path, outrp.path, extra_options=(b"--include **XX " b"--exclude testfiles/seltest/YYYY")) outempty = outrp.append('emptydir') assert outempty.isdir(), outempty
def test_maybe_gzip(self): """Test MaybeGzip""" dirrp = rpath.RPath(self.lc, abs_output_dir) re_init_rpath_dir(dirrp) base_rp = dirrp.append('foo') fileobj = rpath.MaybeGzip(base_rp) fileobj.close() base_rp.setdata() self.assertTrue(base_rp.isreg()) self.assertEqual(base_rp.getsize(), 0) base_rp.delete() base_gz = dirrp.append('foo.gz') self.assertFalse(base_gz.lstat()) fileobj = rpath.MaybeGzip(base_rp) fileobj.write(b"lala") fileobj.close() base_rp.setdata() base_gz.setdata() self.assertFalse(base_rp.lstat()) self.assertTrue(base_gz.isreg()) data = base_gz.get_bytes(compressed=1) self.assertEqual(data, b"lala")
def make_dirs(self): """Make source directories, return rpaths These make a directory with a changing file that is not self-readable. (Caused problems earlier.) """ rp1 = rpath.RPath(Globals.local_connection, os.path.join(abs_test_dir, b"root_half1")) re_init_rpath_dir(rp1) rp1_1 = rp1.append('foo') rp1_1.write_string('hello') rp1_1.chmod(0) rp1_2 = rp1.append('to be deleted') rp1_2.write_string('aosetuhaosetnuhontu') rp1_2.chmod(0) rp1_3 = rp1.append('unreadable_dir') rp1_3.mkdir() rp1_3_1 = rp1_3.append('file_inside') rp1_3_1.write_string('blah') rp1_3_1.chmod(0) rp1_3_2 = rp1_3.append('subdir_inside') rp1_3_2.mkdir() rp1_3_2_1 = rp1_3_2.append('foo') rp1_3_2_1.write_string('saotnhu') rp1_3_2_1.chmod(0) rp1_3_2.chmod(0) rp1_3.chmod(0) rp2 = rpath.RPath(Globals.local_connection, os.path.join(abs_test_dir, b"root_half2")) re_init_rpath_dir(rp2) rp2_1 = rp2.append('foo') rp2_1.write_string('goodbye') rp2_1.chmod(0) rp2_3 = rp2.append('unreadable_dir') rp2_3.mkdir() rp2_3_1 = rp2_3.append('file_inside') rp2_3_1.write_string('new string') rp2_3_1.chmod(0) rp2_3_2 = rp2_3.append('subdir_inside') rp2_3_2.mkdir() rp2_3_2_1 = rp2_3_2.append('foo') rp2_3_2_1.write_string('asoetn;oet') rp2_3_2_1.chmod(0) rp2_3_2.chmod(0) rp2_3_3 = rp2_3.append('file2') rp2_3_3.touch() rp2_3.chmod(0) # The rp_2_4 below test for a perm error, also tested in # regressiontest.py testConfig1 rp2_4 = rp2.append('test2') rp2_4.mkdir() rp2_4_1 = rp2_4.append('1-dir') rp2_4_1.mkdir() reg2_4_1_1 = rp2_4_1.append('reg') reg2_4_1_1.touch() reg2_4_1_1.chmod(0) rp2_4_1.chmod(0) reg2_4_2 = rp2_4.append('2-reg') reg2_4_2.touch() reg2_4_2.chmod(0) rp2_4.chmod(0) return rp1, rp2
def setUp(self): self.base_dir = os.path.join(comtst.abs_test_dir, b"location_lock") self.base_rp = rpath.RPath(Globals.local_connection, self.base_dir) self.lockfile = self.base_rp.append("lock") comtst.re_init_rpath_dir(self.base_rp) self.success = False