def testDelete(self): files.File('/foo').write('') files.File('/bar').write(LARGE_FILE_CONTENT) files.File('/qux').write('') blob_key = files.File('/bar').blob.key() files.Files(['/foo', '/bar']).delete() self.assertEqual(files.Files(['/qux']), files.Files(['/foo', '/bar', '/qux']).load()) # Verify that the blob is also deleted. self.assertIsNone(blobstore.get(blob_key))
def testCopyTo(self): # Populate the in-context cache by reading the file before creation. self.assertFalse(files.File('/x/b/foo').exists) files.File('/foo').write('') files.File('/a/foo').write('') files.File('/a/b/foo').write('') files.File('/c/foo').write('') result_files = files.Files() failed_files = files.Files() files.Files.list('/').copy_to(dir_path='/x', result_files=result_files, failed_files=failed_files) expected_paths = [ '/x/foo', ] self.assertSameElements(expected_paths, result_files.keys()) self.assertEqual([], failed_files.keys()) titan_files = files.Files.list('/a/', recursive=True) titan_files.copy_to('/x', strip_prefix='/a/', result_files=result_files) expected_paths = [ '/x/foo', '/x/b/foo', ] self.assertSameElements(expected_paths, result_files.keys()) # With trailing slashes should be the same. result_files.clear() titan_files.copy_to('/x/', strip_prefix='/a/', result_files=result_files) self.assertSameElements(expected_paths, result_files.keys()) result_files = files.Files() failed_files = files.Files() files_paths = ['/foo', '/fake'] self.assertRaises(files.CopyFilesError, files.Files(files_paths).copy_to, dir_path='/x', result_files=result_files, failed_files=failed_files) expected_paths = [ '/x/foo', ] failed_paths = [ '/x/fake', ] self.assertSameElements(expected_paths, result_files.keys()) self.assertSameElements(failed_paths, failed_files.keys()) # Verify that the NDB in-context cache was cleared correctly. self.assertTrue(files.File('/x/b/foo').exists)
def testMoveTo(self): # Populate the in-context cache by reading the file before creation. self.assertFalse(files.File('/x/b/foo').exists) files.File('/foo').write('') files.File('/a/foo').write('') files.File('/a/b/foo').write('') files.File('/c/foo').write('') result_files = files.Files() titan_files = files.Files.list('/a/', recursive=True) titan_files.move_to('/x', strip_prefix='/a/', result_files=result_files) expected_paths = [ '/x/foo', '/x/b/foo', ] self.assertSameElements(expected_paths, result_files.keys()) # Verify files has been deleted from the old directory. self.assertFalse(files.File('/a/foo').exists) self.assertFalse(files.File('/a/b/foo').exists) result_files = files.Files() failed_files = files.Files() files_paths = ['/foo', '/fake'] self.assertRaises(files.CopyFilesError, files.Files(files_paths).move_to, dir_path='/x', result_files=result_files, failed_files=failed_files) expected_paths = [ '/x/foo', ] failed_paths = [ '/x/fake', ] self.assertSameElements(expected_paths, result_files.keys()) self.assertSameElements(failed_paths, failed_files.keys()) # Verify files has been deleted from the old directory. self.assertFalse(files.File('/foo').exists) # Verify that the NDB in-context cache was cleared correctly. self.assertTrue(files.File('/x/b/foo').exists)
def testFilesCount(self): # Create files for testing. root_level = files.Files(['/index.html', '/qux']) first_level = files.Files(['/foo/bar']) second_level = files.Files([ '/foo/bar/baz', '/foo/bar/baz.html', '/foo/bar/baz.txt', ]) root_and_first_levels = files.Files.merge(root_level, first_level) all_files = files.Files(root_level.keys() + first_level.keys() + second_level.keys()) for titan_file in all_files.itervalues(): titan_file.write('') # Empty. self.assertEqual(0, files.Files.count('/fake/path')) # From root. self.assertEqual(len(root_level), files.Files.count('/')) self.assertEqual(len(all_files), files.Files.count('/', recursive=True)) # Limit recursion depth. self.assertEqual(len(root_and_first_levels), files.Files.count('/', recursive=True, depth=1)) # Custom filters: files.File('/a/foo').write('', meta={'color': 'red', 'item_id': 1}) files.File('/a/bar/qux').write('', meta={'color': 'red', 'item_id': 2}) files.File('/a/baz').write('', meta={'color': 'blue', 'item_id': 3}) # Single filter: filters = [files.FileProperty('color') == 'blue'] self.assertEqual( 1, files.Files.count('/', recursive=True, filters=filters)) # Multiple filters: filters = [ files.FileProperty('color') == 'red', files.FileProperty('item_id') == 2, ] self.assertEqual( 1, files.Files.count('/', recursive=True, filters=filters))
def testLoad(self): files.File('/foo').write('') files.File('/bar').write('') titan_files = files.Files(paths=['/foo', '/bar', '/fake']) titan_files.load() self.assertIn('/foo', titan_files) self.assertIn('/bar', titan_files) self.assertTrue(titan_files['/foo'].is_loaded) self.assertTrue(titan_files['/bar'].is_loaded) self.assertNotIn('/fake', titan_files)
def testMixin(self): # NOTE: Look here first. If this test fails, other tests are likely broken. changeset = self.vcs.new_staging_changeset() meta = {'color': 'blue', 'flag': False} files.File('/foo', changeset=changeset).write('foo-versioned') files.File('/bar', changeset=changeset).write('bar-versioned', meta=meta) # exists(). self.assertFalse(files.File('/foo').exists) self.assertTrue(files.File('/foo', changeset=changeset).exists) self.assertFalse(files.File('/fake', changeset=changeset).exists) # Init with an uncommitted file path: self.assertFalse(files.File('/foo').exists) # Init with an uncommitted file within a changeset: titan_file = files.File('/foo', changeset=changeset) self.assertEqual('/foo', titan_file.path) self.assertEqual('/_titan/ver/1/foo', titan_file.versioned_path) expected_foo = files.File('/foo', changeset=changeset) expected_bar = files.File('/bar', changeset=changeset) actual_titan_files = files.Files(files=[ expected_foo, expected_bar, files.File('/fake', changeset=changeset), ]) actual_titan_files.load() expected_titan_files = files.Files(files=[ expected_foo, expected_bar, ]) self.assertEqual(expected_titan_files, actual_titan_files) # write(). titan_file = files.File('/foo', changeset=changeset) titan_file.write('foo', meta={'color': 'blue'}) self.assertEqual('/_titan/ver/1/foo', titan_file.versioned_path) # Delete (really "mark for deletion"). titan_file = files.File('/foo', changeset=changeset).delete() self.assertEqual('/_titan/ver/1/foo', titan_file.versioned_path) # Just for testing, set make sure the status is correct. titan_file._allow_deleted_files = True self.assertEqual(FILE_DELETED, titan_file.meta.status) # Files marked for delete technically exist at the versioned path, # but through the file interface they should pretend to not exist: self.assertFalse(files.File('/foo', changeset=changeset).exists) self.assertRaises(files.BadFileError, lambda: files.File('/foo', changeset=changeset).content) # Revert a file marked for deletion. changeset.revert_file(files.File('/foo', changeset=changeset)) self.assertFalse(files.File('/foo').exists) self.assertFalse(files.File('/foo', changeset=changeset).exists) # Commit the changeset (/bar is the only remaining file). changeset.finalize_associated_files() self.vcs.commit(changeset) # Check exists() with a committed file path. self.assertFalse(files.File('/foo').exists) self.assertTrue(files.File('/bar').exists) # Writing an already-existing file in a new changeset should # copy the existing file's content and attributes. changeset = self.vcs.new_staging_changeset() titan_file = files.File('/bar', changeset=changeset) # Should copy from last-committed file: titan_file.write(meta={'color': 'red'}) # Test original object: self.assertEqual('bar-versioned', titan_file.content) self.assertEqual('red', titan_file.meta.color) self.assertEqual(False, titan_file.meta.flag) # untouched meta property. # Test re-inited object: titan_file = files.File('/bar', changeset=changeset) self.assertEqual('bar-versioned', titan_file.content) self.assertEqual('red', titan_file.meta.color) self.assertEqual(False, titan_file.meta.flag) # untouched meta property.
def testOrderedFiles(self): # Create files for testing. root_level = files.OrderedFiles([ # These need to be alphabetically ordered here because they will be # usually returned that way from queries inside files.Files.list(), # except for when other filters are applied. '/bar', '/baz', '/foo', ]) for titan_file in root_level.itervalues(): titan_file.write('') # Verify that equality handles order checking. Do this first to make sure # that following assertEqual() calls are also checking for order. root_level_same_order = files.OrderedFiles([ # Intentionally not the same order, to test Sort() right below. '/baz', '/foo', '/bar', ]) root_level_same_order.sort() root_level_different_order = files.OrderedFiles([ '/foo', '/baz', '/bar', ]) self.assertEqual(root_level, root_level_same_order) self.assertNotEqual(root_level, root_level_different_order) self.assertNotEqual(files.OrderedFiles([]), root_level) # Test updating and removing items. new_root_level = files.OrderedFiles([ '/bar', '/baz', '/foo', ]) new_root_level.update(files.Files(['/qux'])) self.assertNotEqual(root_level, new_root_level) del new_root_level['/qux'] self.assertEqual(root_level, new_root_level) # Test files.OrderedFiles.list(). self.assertEqual(root_level, files.OrderedFiles.list('/')) self.assertNotEqual(root_level_different_order, files.OrderedFiles.list('/')) # Test files.OrderedFiles.list() with order= kwarg. self.Login('*****@*****.**') files.File('/a/middle').write('') self.Login('*****@*****.**') files.File('/a/last').write('') self.Login('*****@*****.**') files.File('/a/first').write('') order = [files.FileProperty('created_by')] results = files.OrderedFiles.list('/a', order=order) expected = files.OrderedFiles([ '/a/first', '/a/middle', '/a/last', ]) self.assertEqual(expected, results) # Test reverse order. order = [-files.FileProperty('created_by')] results = files.OrderedFiles.list('/a', order=order) expected = files.OrderedFiles([ '/a/last', '/a/middle', '/a/first', ]) self.assertEqual(expected, results) # Error handling. self.assertRaises(AttributeError, new_root_level.__setitem__, '/qux', files.File('/qux'))
def testFilesList(self): # Create files for testing. root_level = files.Files(['/index.html', '/qux']) first_level = files.Files(['/foo/bar']) second_level = files.Files([ '/foo/bar/baz', '/foo/bar/baz.html', '/foo/bar/baz.txt', ]) root_and_first_levels = files.Files.merge(root_level, first_level) first_and_second_levels = files.Files.merge(first_level, second_level) # files.Files.update(). all_files = files.Files([]) all_files.update(root_level) all_files.update(first_level) all_files.update(second_level) self.assertEqual(6, len(all_files)) # Test __eq__ (don't use assertEqual). self.assertTrue(files.Files(['/a', '/b']) == files.Files(['/a', '/b'])) self.assertFalse(files.Files(['/a', '/b']) == files.Files(['/a'])) for titan_file in all_files.itervalues(): titan_file.write('') # Empty. self.assertSameObjects(files.Files(), files.Files.list('/fake/path')) self.assertSameObjects(files.Files([]), files.Files.list('/fake/path')) # From root. self.assertSameObjects(root_level, files.Files.list('/')) titan_files = files.Files.list('/', recursive=True) self.assertSameObjects(all_files, titan_files) # From first level dir. self.assertSameObjects(first_level, files.Files.list('/foo')) self.assertSameObjects(first_level, files.Files.list('/foo/')) titan_files = files.Files.list('/foo', recursive=True) self.assertSameObjects(first_and_second_levels, titan_files) # From second level dir. self.assertSameObjects(second_level, files.Files.list('/foo/bar')) titan_files = files.Files.list('/foo/bar', recursive=True) self.assertSameObjects(second_level, titan_files) # Limit recursion depth. titan_files = files.Files.list('/', recursive=True, depth=1) self.assertSameObjects(root_and_first_levels, titan_files) titan_files = files.Files.list('/', recursive=True, depth=2) self.assertSameObjects(all_files, titan_files) titan_files = files.Files.list('/foo/', recursive=True, depth=1) self.assertSameObjects(first_and_second_levels, titan_files) # Limit the number of files returned. titan_files = files.Files.list('/foo', recursive=True, limit=1) self.assertEqual(1, len(titan_files)) # Support trailing slashes. self.assertSameObjects(second_level, files.Files.list('/foo/bar/')) titan_files = files.Files.list('/foo/bar/', recursive=True) self.assertSameObjects(second_level, titan_files) # Custom filters: files.File('/a/foo').write('', meta={'color': 'red', 'count': 1}) files.File('/a/bar/qux').write('', meta={'color': 'red', 'count': 2}) files.File('/a/baz').write('', meta={'color': 'blue', 'count': 3}) # Single filter: filters = [files.FileProperty('color') == 'red'] titan_files = files.Files.list('/a', filters=filters) self.assertSameObjects(['/a/foo'], titan_files) # Multiple filters: filters = [ files.FileProperty('color') == 'blue', files.FileProperty('count') == 3, ] titan_files = files.Files.list('/', recursive=True, filters=filters) self.assertEqual(files.Files(['/a/baz']), titan_files) # Recursive: filters = [files.FileProperty('color') == 'red'] titan_files = files.Files.list('/', recursive=True, filters=filters) self.assertEqual(files.Files(['/a/foo', '/a/bar/qux']), titan_files) # Non-meta property: user = users.TitanUser('*****@*****.**') filters = [ files.FileProperty('created_by') == str(user), files.FileProperty('count') == 2, ] titan_files = files.Files.list('/a/', recursive=True, filters=filters) self.assertEqual(files.Files(['/a/bar/qux']), titan_files) # Error handling. self.assertRaises(ValueError, files.Files.list, '') self.assertRaises(ValueError, files.Files.list, '//') self.assertRaises(ValueError, files.Files.list, '/..') self.assertRaises(ValueError, files.Files.list, '/', recursive=True, depth=0) self.assertRaises(ValueError, files.Files.list, '/', recursive=False, depth=1)
def testNamespaces(self): self.write_namespace_testdata() # Verify the state of the filesystem in the default namespace. self.assertEqual('foo', files.File('/foo').content) self.assertEqual('bar', files.File('/b/bar').content) self.assertFalse(files.File('/b/qux').exists) titan_files = files.Files.list('/', recursive=True) self.assertEqual({'/foo', '/b/bar'}, set(titan_files)) titan_files = files.Files(paths=['/foo', '/b/bar', '/b/qux']).load() self.assertEqual({'/foo', '/b/bar'}, set(titan_files)) # Verify the state of the filesystem in the 'aaa' namespace. self.assertEqual('aaa-foo', files.File('/foo', namespace='aaa').content) self.assertEqual('aaa-bar', files.File('/b/bar', namespace='aaa').content) self.assertFalse(files.File('/b/qux', namespace='aaa').exists) titan_files = files.Files.list('/', recursive=True, namespace='aaa') self.assertEqual({'/foo', '/b/bar'}, set(titan_files)) self.assertEqual('aaa-foo', titan_files['/foo'].content) self.assertEqual('aaa-bar', titan_files['/b/bar'].content) titan_files = files.Files(paths=['/foo', '/b/bar', '/b/qux'], namespace='aaa').load() self.assertEqual({'/foo', '/b/bar'}, set(titan_files)) self.assertEqual('aaa-foo', titan_files['/foo'].content) self.assertEqual('aaa-bar', titan_files['/b/bar'].content) # Verify the state of the filesystem in the 'bbb' namespace. self.assertEqual('bbb-qux', files.File('/b/qux', namespace='bbb').content) self.assertFalse(files.File('/foo', namespace='bbb').exists) self.assertFalse(files.File('/b/bar', namespace='bbb').exists) titan_files = files.Files.list('/', recursive=True, namespace='bbb') self.assertEqual({'/b/qux'}, set(titan_files)) self.assertEqual('bbb-qux', titan_files['/b/qux'].content) titan_files = files.Files(paths=['/foo', '/b/bar', '/b/qux'], namespace='bbb').load() self.assertEqual({'/b/qux'}, set(titan_files)) self.assertEqual('bbb-qux', titan_files['/b/qux'].content) # Namespace is not affected by file existence. self.assertIsNone(files.File('/foo').namespace) self.assertIsNone(files.File('/fake').namespace) self.assertEqual('aaa', files.File('/foo', namespace='aaa').namespace) self.assertEqual('zzz', files.File('/fake', namespace='zzz').namespace) # Cannot mix namespaces in files.Files. titan_files = files.Files() with self.assertRaises(files.NamespaceMismatchError): other_files = files.Files(paths=['/foo'], namespace='aaa') titan_files.update(other_files) # Files are not the same if their namespace is different. self.assertNotEqual(files.File('/foo'), files.File('/foo', namespace='aaa')) self.assertNotEqual(files.File('/foo', namespace='aaa'), files.File('/foo', namespace='zzz')) # Error handling (more extensive namespace validate tests in utils_test.py). self.assertRaises(ValueError, files.File, '/a', namespace='/') self.assertRaises(ValueError, files.File, '/a', namespace=u'∆')