def setUp(self): services = { 'database.open': lambda tree, path: TwoBackupsDatabaseStub(), 'database.create': raiseUnexpectedCallError, } self.backupcollection = backupcollection.open_collection( SimpleDirectoryStub(), ('path', 'to', 'store'), services=services)
def test_add_content_data(self): db = SimpleDatabaseSpy(self) services = { 'database.open': lambda tree, path: db, 'database.create': raiseUnexpectedCallError, } bc = backupcollection.open_collection( SimpleDirectoryStub(), ('backup',), services=services) backup = bc.start_backup( datetime.datetime(2015, 2, 14, 19, 55, 32, 328629)) with backup: cid1 = bc.add_content_data( b'This is some content!', now=datetime.datetime(2015, 2, 14, 19, 56, 7)) mtime1 = datetime.datetime(2014, 9, 11, 9, 3, 54) mtime1_nsec = 759831036 backup.add_file( ('homedir', 'file.txt'), cid1, 21, mtime1, mtime1_nsec) backup.commit() self.assertEqual(1, len(db._backups_created)) bk = db._backups_created[0] self.assertEqual(1, len(db._content_added)) self.assertEqual(b'cid:This is some c', db._content_added[0]) self.assertEqual(1, len(bk._files_added)) f = bk._files_added[0] self.assertEqual(('homedir', 'file.txt'), f.path) self.assertEqual(cid1, f.cid) self.assertEqual(21, f.size) self.assertEqual(mtime1, f.mtime) self.assertEqual(mtime1_nsec, f.mtime_nsec) self.assertEqual('file', f.filetype) self.assertEqual({}, f.extra)
def test_default_start_and_end_time(self): db = SimpleDatabaseSpy(self) services = { 'database.open': lambda tree, path: db, 'database.create': raiseUnexpectedCallError, } bc = backupcollection.open_collection( SimpleDirectoryStub(), ('backup',), services=services) before_backup = datetime.datetime.utcnow() backup = bc.start_backup() after_backup_started = datetime.datetime.utcnow() with backup: cid = bc.add_content_data( b'some data', now=datetime.datetime.utcnow()) backup.add_file( ('homedir', 'file.txt'), cid, 127, datetime.datetime(2014, 9, 11, 9, 3, 54), 759831036) before_backup_committed = datetime.datetime.utcnow() backup.commit() after_backup_committed = datetime.datetime.utcnow() self.assertEqual(1, len(db._backups_created)) bk = db._backups_created[0] self.assertLessEqual(before_backup, bk._starttime) self.assertLessEqual(bk._starttime, after_backup_started) self.assertLessEqual(before_backup_committed, bk._endtime) self.assertLessEqual(bk._endtime, after_backup_committed)
def test_make_path_from_contentid_in_new_collection(self): # _make_path_from_contentid() is currently slightly broken in # that it doesn't check the existing splitting choices. Nor # does it make any attempt at optimized number of splits. # However, for a clean, new collection, I think the strategy # in this test makes sense anyway. services = { 'database.open': lambda tree, path: BackupDummy(), 'database.create': raiseUnexpectedCallError } bc = backupcollection.open_collection( SimpleDirectoryStub(), ('path', 'to', 'store'), services=services) mkpath = bc._make_path_from_contentid self.assertEqual( ('path', 'to', 'store', 'content', '00', '01', '0203'), mkpath(b'\x00\x01\x02\x03')) self.assertEqual( ('path', 'to', 'store', 'content', '61', '62', '63646566676869'), mkpath(b'abcdefghi')) self.assertEqual( ('path', 'to', 'store', 'content', '6c', 'a4', '98884051015ba8bba86e70ffea620166e65ef7c86d4e9400dfdb340a7364d2'), mkpath(b'l\xa4\x98\x88@Q\x01[\xa8\xbb\xa8np\xff\xeab\x01f' b'\xe6^\xf7\xc8mN\x94\x00\xdf\xdb4\nsd\xd2'))
def test_get_most_recent_backup_when_no_backup_available(self): services = { 'database.open': lambda tree, path: EmptyDatabaseStub(), 'database.create': raiseUnexpectedCallError, } bc = backupcollection.open_collection( SimpleDirectoryStub(), ('backup',), services=services) self.assertEqual(None, bc.get_most_recent_backup())
def setUp(self): self.storetree = SimpleDirectorySpy() services = { 'database.open': lambda tree, path: BasicBackupDatabaseStub(), 'database.create': raiseUnexpectedCallError, } self.backupcollection = backupcollection.open_collection( BasicBackupDirectoryStub(), ('backup',), services=services)
def test_create_backup(self): db = SimpleDatabaseSpy(self) services = { 'database.open': lambda tree, path: db, 'database.create': raiseUnexpectedCallError } bc = backupcollection.open_collection( SimpleDirectoryStub(), ('backup',), services=services) backup = bc.start_backup( datetime.datetime(2015, 2, 14, 19, 55, 32, 328629)) with backup: content = [ b'127' * 42 + b'1', b'7029' * 1757 + b'7', b'5028' * 1257, b'21516' * 4303 + b'2', b'127' * 42 + b'1' ] cids = [] cids.append(bc.add_content( SimpleFileItemStub(content[0]), now=datetime.datetime(2015, 2, 14, 19, 56, 7))) backup.add_file( ('homedir', 'file.txt'), cids[-1], 127, datetime.datetime(2014, 9, 11, 9, 3, 54), 759831036) cids.append(bc.add_content(SimpleFileItemStub(content[1]))) backup.add_file( ('homedir', 'other.txt'), cids[-1], 7029, datetime.datetime(2015, 2, 1, 22, 43, 34), 51746409) cids.append(bc.add_content(SimpleFileItemStub(content[2]))) backup.add_file( ('outside', 'store', 'deep', 'data'), cids[-1], 5028, datetime.datetime(2014, 4, 21, 8, 29, 46), 826447) cids.append(bc.add_content(SimpleFileItemStub(content[3]))) backup.add_file( ('toplevel',), cids[-1], 21516, datetime.datetime(2014, 10, 17, 15, 33, 2), 781606397) cids.append(bc.add_content(SimpleFileItemStub(content[4]))) backup.add_file( ('homedir', 'copy'), cids[-1], 127, datetime.datetime(2014, 9, 22, 2, 11, 1), 797641421) backup.commit(datetime.datetime(2015, 2, 14, 19, 55, 54, 954321)) self.assertEqual(1, len(db._backups_created)) self.assertEqual(5, len(db._content_added)) expectedcids = [ b'cid:' + x[:14] for x in content ] for expected, cid in zip(expectedcids, cids): self.assertEqual(expected, cid) for expected, added in zip(expectedcids, db._content_added): self.assertEqual(expected, added) bk = db._backups_created[0] self.assertEqual(5, len(bk._files_added)) for expected, added in zip(expectedcids, bk._files_added): self.assertEqual(expected, added.cid)
def test_add_two_files_with_same_path(self): services = { 'database.open': lambda tree, path: FileExistsDatabaseStub(), 'database.create': raiseUnexpectedCallError, } bc = backupcollection.open_collection( SimpleDirectoryStub(), ('backup',), services=services) backup = bc.start_backup( datetime.datetime(2015, 2, 14, 19, 55, 32, 328629)) with backup: cid = b'one cid' self.assertRaisesRegex( FileExistsError, 'already exists.*file\\.txt', backup.add_file, ('homedir', 'file.txt'), cid, 127, datetime.datetime(2014, 9, 11, 9, 3, 54), 759831036)
def _check_db_after_second_backup(self): coll = backupcollection.open_collection(self.fs, ('backups', 'home')) bkup = coll.get_most_recent_backup() self.assertEqual( datetime.datetime(1995, 1, 5, 0, 44, 0), bkup.get_start_time()) self.assertEqual( datetime.datetime(1995, 1, 5, 0, 44, 0), bkup.get_end_time()) info = bkup.get_file_info(('other', self.invalid_unicode)) self.assertEqual( datetime.datetime(1995, 1, 2, 7, 48, 24, 769151), info.mtime) self.assertEqual(40, info.size) self.assertEqual( b'\x92\xc7\xa7|(v2T\x9dmN9 (\x93\xe5\xe7\x7f\x823' b'Er\xc9:M\xcfZR\xa1b\x08\xf6', info.good_checksum) self.assertEqual('file', info.filetype) self.assertEqual( {'owner': 'other', 'group': 'me', 'unix-access': 0o640}, info.extra_data)
def setUp(self): storetree = fake_filesys.FakeFileSystem() storetree._allow_full_access_to_subtree(('path', 'to', 'backup')) collection = backupcollection.create_collection( storetree, ('path', 'to', 'backup')) sourcetree = fake_filesys.FakeFileSystem() basepath = ('home', 'me') sourcetree._make_files( basepath, ('.emacs', 'notes.txt'), fileid_first=0) sourcetree._make_files( basepath + ('.cache', 'chromium', 'Default', 'Cache'), ('index', 'data_0', 'data_1', 'f_000001', 'f_000002', 'f_000003'), fileid_first=10) sourcetree._make_files( basepath + ('Documents',), ('Letter.odt', 'Photo.jpg'), fileid_first=20) sourcetree._make_files( basepath + ('tmp',), ('scratchpad.txt', 'funny.jpg', 'Q.pdf'), fileid_first=30) sourcetree._make_files( basepath + ('Pictures', 'Christmas'), ('DSC_1886.JPG', 'DSC_1887.JPG', 'DSC_1888.JPG', 'DSC_1889.JPG'), fileid_first=40) sourcetree._allow_reading_subtree(basepath) operation = backupoperation.BackupOperation(collection) backuptree = operation.add_tree_to_backup(sourcetree, basepath, ()) bkroot = make_cfgsubtree( (('plain', ('tmp',), 'ignore'), ('plain', ('tmp', 'Q.pdf'), 'dynamic'), ('plain', ('.cache',), 'ignore'), ('plain', ('Pictures',), 'static'))) backuptree.set_backup_handlers(bkroot) self.storetree = storetree self.sourcetree = sourcetree self.basepath = basepath self.backuptree = backuptree self.collection = collection self.operation = operation self.before_backup = datetime.datetime.utcnow() operation.execute_backup() self.after_backup = datetime.datetime.utcnow() self.collection2 = backupcollection.open_collection( storetree, ('path', 'to', 'backup'))
def _check_db_after_initial_backup(self): coll = backupcollection.open_collection( self.fs, ('backups', 'home'), services=self.services) bkup = coll.get_most_recent_backup() self.assertEqual( datetime.datetime(1995, 1, 1, 0, 0, 20), bkup.get_start_time()) self.assertEqual( datetime.datetime(1995, 1, 1, 0, 0, 20), bkup.get_end_time()) self.assertEqual( None, coll.get_most_recent_backup_before( datetime.datetime(1995, 1, 1, 0, 0, 20))) self.assertEqual( bkup.get_start_time(), coll.get_oldest_backup().get_start_time()) self.assertEqual( None, coll.get_oldest_backup_after( datetime.datetime(1995, 1, 1, 0, 0, 20))) dirs, files = bkup.list_directory(()) self.assertCountEqual(('.config', 'My Pictures', 'system'), dirs) self.assertCountEqual( ('notes.txt', 'socket', 'runme', 'symlink'), files) dirs, files = bkup.list_directory(('My Pictures',)) self.assertCountEqual((), dirs) self.assertCountEqual(('DSC_1886.JPG', 'DSC_1903.JPG'), files) dirs, files = bkup.list_directory(('system',)) self.assertCountEqual((), dirs) self.assertCountEqual(('notes.txt',), files) info = bkup.get_dir_info(('My Pictures',)) self.assertEqual( {'owner': 'me', 'group': 'me', 'unix-access': 0o755}, info.extra_data) info = bkup.get_dir_info(('system',)) self.assertEqual( {'owner': 'root', 'group': 'root', 'unix-access': 0o755}, info.extra_data) info = bkup.get_file_info(('notes.txt',)) self.assertEqual( datetime.datetime(1994, 11, 28, 16, 48, 56, 394323), info.mtime) self.assertEqual(394323854, info.mtime_nsec) self.assertEqual(17, info.size) self.assertEqual( b"?27\x9f\xe4\x10\x8e\x99'\x98\x90\xfa" b"\xf4J\x83lj\xd86\xad3\x1e\xa2v\xd0\xa4\xb7\x85\x847\t\x1a", info.good_checksum) self.assertEqual('file', info.filetype) self.assertEqual( {'owner': 'me', 'group': 'me', 'unix-access': 0o644}, info.extra_data) info = bkup.get_file_info(('My Pictures', 'DSC_1903.JPG')) self.assertEqual( datetime.datetime(1994, 4, 5, 2, 36, 23, 34763), info.mtime) self.assertEqual(34763519, info.mtime_nsec) self.assertEqual(17, info.size) self.assertEqual( b'8M\x1c\xd1\xec\xf7\xcb\xd6\xdf\xbd\x82\x89' b'J\xf0\x92+\xc1\x13X\x9d\x14\xd0lF^\xb1E\x92*\xe0\r\xd7', info.good_checksum) self.assertEqual('file', info.filetype) self.assertEqual( {'owner': 'me', 'group': 'me', 'unix-access': 0o644}, info.extra_data) cid = info.contentid reader = coll.get_content_reader(cid) self.assertEqual(17, reader.get_size()) self.assertEqual(b'A different photo', reader.get_data_slice(0,100)) self.assertEqual(b'A different photo', reader.get_data_slice(0,17)) self.assertEqual(b'A different pho', reader.get_data_slice(0,15)) self.assertEqual(b'feren', reader.get_data_slice(5,10)) contentinfo = coll.get_content_info(cid) self.assertEqual( b'8M\x1c\xd1\xec\xf7\xcb\xd6\xdf\xbd\x82\x89' b'J\xf0\x92+\xc1\x13X\x9d\x14\xd0lF^\xb1E\x92*\xe0\r\xd7', contentinfo.goodsum) info = bkup.get_file_info(('system', 'notes.txt')) self.assertEqual( datetime.datetime(1994, 6, 2, 21, 36, 54, 419844), info.mtime) self.assertEqual(419844710, info.mtime_nsec) self.assertEqual(18, info.size) self.assertEqual( b'\xf4\xce\xfb\xc7\xf7\x9dB"Nc\x8b\x1f\x1c\x9f&' b'\xec^F=BX\x94\x1f\xfb\x01Y\xc2\xa9{\x84m\xc8', info.good_checksum) self.assertEqual('file', info.filetype) self.assertEqual( {'owner': 'root', 'group': 'root', 'unix-access': 0o644}, info.extra_data) info = bkup.get_file_info(('socket',)) self.assertEqual( datetime.datetime(1994, 2, 20, 3, 59, 16, 60446), info.mtime) self.assertEqual(60446634, info.mtime_nsec) self.assertEqual(0, info.size) self.assertEqual(b'', info.good_checksum) self.assertEqual('socket', info.filetype) self.assertEqual( {'owner': 'me', 'group': 'me', 'unix-access': 0o644}, info.extra_data) info = bkup.get_file_info(('runme',)) self.assertEqual( datetime.datetime(1994, 5, 29, 9, 28, 58, 751700), info.mtime) self.assertEqual(751700129, info.mtime_nsec) self.assertEqual(14, info.size) self.assertEqual( b'I\xa9XA0\x1cX\x08z\x0b{1\xbb\xed-K\xee\x95\xdd\xa7J' b'X\xa5\x13E{|\xd2b\xf8u\x9a', info.good_checksum) self.assertEqual('file', info.filetype) self.assertEqual( {'owner': 'me', 'group': 'me', 'unix-access': 0o755}, info.extra_data) info = bkup.get_file_info(('symlink',)) self.assertEqual( datetime.datetime(1994, 6, 15, 14, 2, 47, 145225), info.mtime) self.assertEqual(145225216, info.mtime_nsec) self.assertEqual(16, info.size) self.assertEqual('symlink', info.filetype) self.assertEqual( {'owner': 'me', 'group': 'me', 'unix-access': 0o644}, info.extra_data)
def test_checksum_timeline(self): bc = backupcollection.open_collection( self.storetree, ('path', 'to', 'store'), services=self.services) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 2, 15, 8, 4, 32), self.checksum1) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 2, 15, 12, 9, 2), self.checksum1) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 2, 17, 9, 9, 11), self.checksum1) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 2, 22, 12, 18, 41), b'1' * 32) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 2, 27, 23, 0, 5), b'1' * 32) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 3, 4, 18, 35, 12), b'1' * 32) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 3, 7, 10, 23, 55), b'2' * 32) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 3, 9, 4, 13, 18), b'3' * 32) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 3, 11, 12, 18, 3), self.checksum1, restored=True) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 3, 12, 7, 22, 7), self.checksum1) bc.update_content_checksum( self.cid1, datetime.datetime(2015, 3, 16, 9, 52, 14), b'4' * 32) info = self.backupcollection.get_content_info(self.cid1) self.assertEqual(self.checksum1, info.goodsum) self.assertEqual(b'4' * 32, info.lastsum) self.assertEqual(6, len(info.timeline)) cs = info.timeline[0] self.assertEqual(self.checksum1, cs.checksum) self.assertTrue(cs.restored) self.assertEqual(datetime.datetime(2015, 2, 14, 19, 56, 7), cs.first) self.assertEqual(datetime.datetime(2015, 2, 17, 9, 9, 11), cs.last) cs = info.timeline[1] self.assertEqual(b'1' * 32, cs.checksum) self.assertFalse(cs.restored) self.assertEqual(datetime.datetime(2015, 2, 22, 12, 18, 41), cs.first) self.assertEqual(datetime.datetime(2015, 3, 4, 18, 35, 12), cs.last) cs = info.timeline[2] self.assertEqual(b'2' * 32, cs.checksum) self.assertFalse(cs.restored) self.assertEqual(datetime.datetime(2015, 3, 7, 10, 23, 55), cs.first) self.assertEqual(datetime.datetime(2015, 3, 7, 10, 23, 55), cs.last) cs = info.timeline[3] self.assertEqual(b'3' * 32, cs.checksum) self.assertFalse(cs.restored) self.assertEqual(datetime.datetime(2015, 3, 9, 4, 13, 18), cs.first) self.assertEqual(datetime.datetime(2015, 3, 9, 4, 13, 18), cs.last) cs = info.timeline[4] self.assertEqual(self.checksum1, cs.checksum) self.assertTrue(cs.restored) self.assertEqual(datetime.datetime(2015, 3, 11, 12, 18, 3), cs.first) self.assertEqual(datetime.datetime(2015, 3, 12, 7, 22, 7), cs.last) cs = info.timeline[5] self.assertEqual(b'4' * 32, cs.checksum) self.assertFalse(cs.restored) self.assertEqual(datetime.datetime(2015, 3, 16, 9, 52, 14), cs.first) self.assertEqual(datetime.datetime(2015, 3, 16, 9, 52, 14), cs.last)