3 import arvados_fuse as fuse
16 import multiprocessing
17 import run_test_server
21 from mount_test_base import MountTestBase
23 logger = logging.getLogger('arvados.arv-mount')
26 class AssertWithTimeout(object):
27 """Allow some time for an assertion to pass."""
29 def __init__(self, timeout=0):
30 self.timeout = timeout
33 self.deadline = time.time() + self.timeout
42 def attempt(self, fn, *args, **kwargs):
45 except AssertionError:
46 if time.time() > self.deadline:
53 class FuseMountTest(MountTestBase):
55 super(FuseMountTest, self).setUp()
57 cw = arvados.CollectionWriter()
59 cw.start_new_file('thing1.txt')
61 cw.start_new_file('thing2.txt')
64 cw.start_new_stream('dir1')
65 cw.start_new_file('thing3.txt')
67 cw.start_new_file('thing4.txt')
70 cw.start_new_stream('dir2')
71 cw.start_new_file('thing5.txt')
73 cw.start_new_file('thing6.txt')
76 cw.start_new_stream('dir2/dir3')
77 cw.start_new_file('thing7.txt')
80 cw.start_new_file('thing8.txt')
83 cw.start_new_stream('edgecases')
84 for f in ":/.../-/*/\x01\\/ ".split("/"):
88 for f in ":/.../-/*/\x01\\/ ".split("/"):
89 cw.start_new_stream('edgecases/dirs/' + f)
90 cw.start_new_file('x/x')
93 self.testcollection = cw.finish()
94 self.api.collections().create(body={"manifest_text":cw.manifest_text()}).execute()
97 self.make_mount(fuse.CollectionDirectory, collection_record=self.testcollection)
99 self.assertDirContents(None, ['thing1.txt', 'thing2.txt',
100 'edgecases', 'dir1', 'dir2'])
101 self.assertDirContents('dir1', ['thing3.txt', 'thing4.txt'])
102 self.assertDirContents('dir2', ['thing5.txt', 'thing6.txt', 'dir3'])
103 self.assertDirContents('dir2/dir3', ['thing7.txt', 'thing8.txt'])
104 self.assertDirContents('edgecases',
105 "dirs/:/.../-/*/\x01\\/ ".split("/"))
106 self.assertDirContents('edgecases/dirs',
107 ":/.../-/*/\x01\\/ ".split("/"))
109 files = {'thing1.txt': 'data 1',
110 'thing2.txt': 'data 2',
111 'dir1/thing3.txt': 'data 3',
112 'dir1/thing4.txt': 'data 4',
113 'dir2/thing5.txt': 'data 5',
114 'dir2/thing6.txt': 'data 6',
115 'dir2/dir3/thing7.txt': 'data 7',
116 'dir2/dir3/thing8.txt': 'data 8'}
118 for k, v in files.items():
119 with open(os.path.join(self.mounttmp, k)) as f:
120 self.assertEqual(v, f.read())
123 class FuseNoAPITest(MountTestBase):
125 super(FuseNoAPITest, self).setUp()
126 keep = arvados.keep.KeepClient(local_store=self.keeptmp)
127 self.file_data = "API-free text\n"
128 self.file_loc = keep.put(self.file_data)
129 self.coll_loc = keep.put(". {} 0:{}:api-free.txt\n".format(
130 self.file_loc, len(self.file_data)))
133 self.make_mount(fuse.MagicDirectory)
134 self.assertDirContents(self.coll_loc, ['api-free.txt'])
135 with open(os.path.join(
136 self.mounttmp, self.coll_loc, 'api-free.txt')) as keep_file:
137 actual = keep_file.read(-1)
138 self.assertEqual(self.file_data, actual)
141 class FuseMagicTest(MountTestBase):
142 def setUp(self, api=None):
143 super(FuseMagicTest, self).setUp(api=api)
145 cw = arvados.CollectionWriter()
147 cw.start_new_file('thing1.txt')
150 self.testcollection = cw.finish()
151 self.test_manifest = cw.manifest_text()
152 self.api.collections().create(body={"manifest_text":self.test_manifest}).execute()
155 self.make_mount(fuse.MagicDirectory)
157 mount_ls = llfuse.listdir(self.mounttmp)
158 self.assertIn('README', mount_ls)
159 self.assertFalse(any(arvados.util.keep_locator_pattern.match(fn) or
160 arvados.util.uuid_pattern.match(fn)
162 "new FUSE MagicDirectory lists Collection")
163 self.assertDirContents(self.testcollection, ['thing1.txt'])
164 self.assertDirContents(os.path.join('by_id', self.testcollection),
166 mount_ls = llfuse.listdir(self.mounttmp)
167 self.assertIn('README', mount_ls)
168 self.assertIn(self.testcollection, mount_ls)
169 self.assertIn(self.testcollection,
170 llfuse.listdir(os.path.join(self.mounttmp, 'by_id')))
173 files[os.path.join(self.mounttmp, self.testcollection, 'thing1.txt')] = 'data 1'
175 for k, v in files.items():
176 with open(os.path.join(self.mounttmp, k)) as f:
177 self.assertEqual(v, f.read())
180 class FuseTagsTest(MountTestBase):
182 self.make_mount(fuse.TagsDirectory)
184 d1 = llfuse.listdir(self.mounttmp)
186 self.assertEqual(['foo_tag'], d1)
188 d2 = llfuse.listdir(os.path.join(self.mounttmp, 'foo_tag'))
190 self.assertEqual(['zzzzz-4zz18-fy296fx3hot09f7'], d2)
192 d3 = llfuse.listdir(os.path.join(self.mounttmp, 'foo_tag', 'zzzzz-4zz18-fy296fx3hot09f7'))
194 self.assertEqual(['foo'], d3)
197 class FuseTagsUpdateTest(MountTestBase):
198 def tag_collection(self, coll_uuid, tag_name):
199 return self.api.links().create(
200 body={'link': {'head_uuid': coll_uuid,
206 self.make_mount(fuse.TagsDirectory, poll_time=1)
208 self.assertIn('foo_tag', llfuse.listdir(self.mounttmp))
210 bar_uuid = run_test_server.fixture('collections')['bar_file']['uuid']
211 self.tag_collection(bar_uuid, 'fuse_test_tag')
212 for attempt in AssertWithTimeout(10):
213 attempt(self.assertIn, 'fuse_test_tag', llfuse.listdir(self.mounttmp))
214 self.assertDirContents('fuse_test_tag', [bar_uuid])
216 baz_uuid = run_test_server.fixture('collections')['baz_file']['uuid']
217 l = self.tag_collection(baz_uuid, 'fuse_test_tag')
218 for attempt in AssertWithTimeout(10):
219 attempt(self.assertDirContents, 'fuse_test_tag', [bar_uuid, baz_uuid])
221 self.api.links().delete(uuid=l['uuid']).execute()
222 for attempt in AssertWithTimeout(10):
223 attempt(self.assertDirContents, 'fuse_test_tag', [bar_uuid])
226 class FuseSharedTest(MountTestBase):
228 self.make_mount(fuse.SharedDirectory,
229 exclude=self.api.users().current().execute()['uuid'])
231 # shared_dirs is a list of the directories exposed
232 # by fuse.SharedDirectory (i.e. any object visible
233 # to the current user)
234 shared_dirs = llfuse.listdir(self.mounttmp)
236 self.assertIn('FUSE User', shared_dirs)
238 # fuse_user_objs is a list of the objects owned by the FUSE
239 # test user (which present as files in the 'FUSE User'
241 fuse_user_objs = llfuse.listdir(os.path.join(self.mounttmp, 'FUSE User'))
242 fuse_user_objs.sort()
243 self.assertEqual(['FUSE Test Project', # project owned by user
244 'collection #1 owned by FUSE', # collection owned by user
245 'collection #2 owned by FUSE', # collection owned by user
246 'pipeline instance owned by FUSE.pipelineInstance', # pipeline instance owned by user
249 # test_proj_files is a list of the files in the FUSE Test Project.
250 test_proj_files = llfuse.listdir(os.path.join(self.mounttmp, 'FUSE User', 'FUSE Test Project'))
251 test_proj_files.sort()
252 self.assertEqual(['collection in FUSE project',
253 'pipeline instance in FUSE project.pipelineInstance',
254 'pipeline template in FUSE project.pipelineTemplate'
257 # Double check that we can open and read objects in this folder as a file,
258 # and that its contents are what we expect.
259 pipeline_template_path = os.path.join(
263 'pipeline template in FUSE project.pipelineTemplate')
264 with open(pipeline_template_path) as f:
266 self.assertEqual("pipeline template in FUSE project", j['name'])
268 # check mtime on template
269 st = os.stat(pipeline_template_path)
271 mtime = st.st_mtime_ns / 1000000000
272 except AttributeError:
274 self.assertEqual(mtime, 1397493304)
276 # check mtime on collection
277 st = os.stat(os.path.join(
280 'collection #1 owned by FUSE'))
282 mtime = st.st_mtime_ns / 1000000000
283 except AttributeError:
285 self.assertEqual(mtime, 1391448174)
288 class FuseHomeTest(MountTestBase):
290 self.make_mount(fuse.ProjectDirectory,
291 project_object=self.api.users().current().execute())
293 d1 = llfuse.listdir(self.mounttmp)
294 self.assertIn('Unrestricted public data', d1)
296 d2 = llfuse.listdir(os.path.join(self.mounttmp, 'Unrestricted public data'))
297 public_project = run_test_server.fixture('groups')[
298 'anonymously_accessible_project']
301 for name, item in run_test_server.fixture('collections').iteritems():
302 if 'name' not in item:
304 elif item['owner_uuid'] == public_project['uuid']:
305 self.assertIn(item['name'], d2)
308 # Artificial assumption here: there is no public
309 # collection fixture with the same name as a
310 # non-public collection.
311 self.assertNotIn(item['name'], d2)
313 self.assertNotEqual(0, found_in)
314 self.assertNotEqual(0, found_not_in)
316 d3 = llfuse.listdir(os.path.join(self.mounttmp, 'Unrestricted public data', 'GNU General Public License, version 3'))
317 self.assertEqual(["GNU_General_Public_License,_version_3.pdf"], d3)
320 def fuseModifyFileTestHelperReadStartContents(mounttmp):
321 class Test(unittest.TestCase):
323 d1 = llfuse.listdir(mounttmp)
324 self.assertEqual(["file1.txt"], d1)
325 with open(os.path.join(mounttmp, "file1.txt")) as f:
326 self.assertEqual("blub", f.read())
329 def fuseModifyFileTestHelperReadEndContents(mounttmp):
330 class Test(unittest.TestCase):
332 d1 = llfuse.listdir(mounttmp)
333 self.assertEqual(["file1.txt"], d1)
334 with open(os.path.join(mounttmp, "file1.txt")) as f:
335 self.assertEqual("plnp", f.read())
338 class FuseModifyFileTest(MountTestBase):
340 collection = arvados.collection.Collection(api_client=self.api)
341 with collection.open("file1.txt", "w") as f:
344 collection.save_new()
346 m = self.make_mount(fuse.CollectionDirectory)
348 m.new_collection(collection.api_response(), collection)
350 self.pool.apply(fuseModifyFileTestHelperReadStartContents, (self.mounttmp,))
352 with collection.open("file1.txt", "w") as f:
355 self.pool.apply(fuseModifyFileTestHelperReadEndContents, (self.mounttmp,))
358 class FuseAddFileToCollectionTest(MountTestBase):
360 collection = arvados.collection.Collection(api_client=self.api)
361 with collection.open("file1.txt", "w") as f:
364 collection.save_new()
366 m = self.make_mount(fuse.CollectionDirectory)
368 m.new_collection(collection.api_response(), collection)
370 d1 = llfuse.listdir(self.mounttmp)
371 self.assertEqual(["file1.txt"], d1)
373 with collection.open("file2.txt", "w") as f:
376 d1 = llfuse.listdir(self.mounttmp)
377 self.assertEqual(["file1.txt", "file2.txt"], sorted(d1))
380 class FuseRemoveFileFromCollectionTest(MountTestBase):
382 collection = arvados.collection.Collection(api_client=self.api)
383 with collection.open("file1.txt", "w") as f:
386 with collection.open("file2.txt", "w") as f:
389 collection.save_new()
391 m = self.make_mount(fuse.CollectionDirectory)
393 m.new_collection(collection.api_response(), collection)
395 d1 = llfuse.listdir(self.mounttmp)
396 self.assertEqual(["file1.txt", "file2.txt"], sorted(d1))
398 collection.remove("file2.txt")
400 d1 = llfuse.listdir(self.mounttmp)
401 self.assertEqual(["file1.txt"], d1)
404 def fuseCreateFileTestHelper(mounttmp):
405 class Test(unittest.TestCase):
407 with open(os.path.join(mounttmp, "file1.txt"), "w") as f:
411 class FuseCreateFileTest(MountTestBase):
413 collection = arvados.collection.Collection(api_client=self.api)
414 collection.save_new()
416 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
417 self.assertEqual(collection2["manifest_text"], "")
419 collection.save_new()
421 m = self.make_mount(fuse.CollectionDirectory)
423 m.new_collection(collection.api_response(), collection)
424 self.assertTrue(m.writable())
426 self.assertNotIn("file1.txt", collection)
428 self.pool.apply(fuseCreateFileTestHelper, (self.mounttmp,))
430 self.assertIn("file1.txt", collection)
432 d1 = llfuse.listdir(self.mounttmp)
433 self.assertEqual(["file1.txt"], d1)
435 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
436 self.assertRegexpMatches(collection2["manifest_text"],
437 r'\. d41d8cd98f00b204e9800998ecf8427e\+0\+A\S+ 0:0:file1\.txt$')
440 def fuseWriteFileTestHelperWriteFile(mounttmp):
441 class Test(unittest.TestCase):
443 with open(os.path.join(mounttmp, "file1.txt"), "w") as f:
444 f.write("Hello world!")
447 def fuseWriteFileTestHelperReadFile(mounttmp):
448 class Test(unittest.TestCase):
450 with open(os.path.join(mounttmp, "file1.txt"), "r") as f:
451 self.assertEqual(f.read(), "Hello world!")
454 class FuseWriteFileTest(MountTestBase):
456 collection = arvados.collection.Collection(api_client=self.api)
457 collection.save_new()
459 m = self.make_mount(fuse.CollectionDirectory)
461 m.new_collection(collection.api_response(), collection)
462 self.assertTrue(m.writable())
464 self.assertNotIn("file1.txt", collection)
466 self.assertEqual(0, self.operations.write_counter.get())
467 self.pool.apply(fuseWriteFileTestHelperWriteFile, (self.mounttmp,))
468 self.assertEqual(12, self.operations.write_counter.get())
470 with collection.open("file1.txt") as f:
471 self.assertEqual(f.read(), "Hello world!")
473 self.assertEqual(0, self.operations.read_counter.get())
474 self.pool.apply(fuseWriteFileTestHelperReadFile, (self.mounttmp,))
475 self.assertEqual(12, self.operations.read_counter.get())
477 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
478 self.assertRegexpMatches(collection2["manifest_text"],
479 r'\. 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$')
482 def fuseUpdateFileTestHelper(mounttmp):
483 class Test(unittest.TestCase):
485 with open(os.path.join(mounttmp, "file1.txt"), "w") as f:
486 f.write("Hello world!")
488 with open(os.path.join(mounttmp, "file1.txt"), "r+") as f:
490 self.assertEqual(fr, "Hello world!")
492 f.write("Hola mundo!")
495 self.assertEqual(fr, "Hola mundo!!")
497 with open(os.path.join(mounttmp, "file1.txt"), "r") as f:
498 self.assertEqual(f.read(), "Hola mundo!!")
502 class FuseUpdateFileTest(MountTestBase):
504 collection = arvados.collection.Collection(api_client=self.api)
505 collection.save_new()
507 m = self.make_mount(fuse.CollectionDirectory)
509 m.new_collection(collection.api_response(), collection)
510 self.assertTrue(m.writable())
512 # See note in MountTestBase.setUp
513 self.pool.apply(fuseUpdateFileTestHelper, (self.mounttmp,))
515 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
516 self.assertRegexpMatches(collection2["manifest_text"],
517 r'\. daaef200ebb921e011e3ae922dd3266b\+11\+A\S+ 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:11:file1\.txt 22:1:file1\.txt$')
520 def fuseMkdirTestHelper(mounttmp):
521 class Test(unittest.TestCase):
523 with self.assertRaises(IOError):
524 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
525 f.write("Hello world!")
527 os.mkdir(os.path.join(mounttmp, "testdir"))
529 with self.assertRaises(OSError):
530 os.mkdir(os.path.join(mounttmp, "testdir"))
532 d1 = llfuse.listdir(mounttmp)
533 self.assertEqual(["testdir"], d1)
535 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
536 f.write("Hello world!")
538 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
539 self.assertEqual(["file1.txt"], d1)
543 class FuseMkdirTest(MountTestBase):
545 collection = arvados.collection.Collection(api_client=self.api)
546 collection.save_new()
548 m = self.make_mount(fuse.CollectionDirectory)
550 m.new_collection(collection.api_response(), collection)
551 self.assertTrue(m.writable())
553 self.pool.apply(fuseMkdirTestHelper, (self.mounttmp,))
555 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
556 self.assertRegexpMatches(collection2["manifest_text"],
557 r'\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$')
560 def fuseRmTestHelperWriteFile(mounttmp):
561 class Test(unittest.TestCase):
563 os.mkdir(os.path.join(mounttmp, "testdir"))
565 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
566 f.write("Hello world!")
570 def fuseRmTestHelperDeleteFile(mounttmp):
571 class Test(unittest.TestCase):
573 # Can't delete because it's not empty
574 with self.assertRaises(OSError):
575 os.rmdir(os.path.join(mounttmp, "testdir"))
577 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
578 self.assertEqual(["file1.txt"], d1)
581 os.remove(os.path.join(mounttmp, "testdir", "file1.txt"))
583 # Make sure it's empty
584 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
585 self.assertEqual([], d1)
587 # Try to delete it again
588 with self.assertRaises(OSError):
589 os.remove(os.path.join(mounttmp, "testdir", "file1.txt"))
593 def fuseRmTestHelperRmdir(mounttmp):
594 class Test(unittest.TestCase):
596 # Should be able to delete now that it is empty
597 os.rmdir(os.path.join(mounttmp, "testdir"))
599 # Make sure it's empty
600 d1 = llfuse.listdir(os.path.join(mounttmp))
601 self.assertEqual([], d1)
603 # Try to delete it again
604 with self.assertRaises(OSError):
605 os.rmdir(os.path.join(mounttmp, "testdir"))
609 class FuseRmTest(MountTestBase):
611 collection = arvados.collection.Collection(api_client=self.api)
612 collection.save_new()
614 m = self.make_mount(fuse.CollectionDirectory)
616 m.new_collection(collection.api_response(), collection)
617 self.assertTrue(m.writable())
619 self.pool.apply(fuseRmTestHelperWriteFile, (self.mounttmp,))
622 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
623 self.assertRegexpMatches(collection2["manifest_text"],
624 r'\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$')
625 self.pool.apply(fuseRmTestHelperDeleteFile, (self.mounttmp,))
627 # Can't have empty directories :-( so manifest will be empty.
628 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
629 self.assertEqual(collection2["manifest_text"], "")
631 self.pool.apply(fuseRmTestHelperRmdir, (self.mounttmp,))
633 # manifest should be empty now.
634 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
635 self.assertEqual(collection2["manifest_text"], "")
638 def fuseMvFileTestHelperWriteFile(mounttmp):
639 class Test(unittest.TestCase):
641 os.mkdir(os.path.join(mounttmp, "testdir"))
643 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
644 f.write("Hello world!")
648 def fuseMvFileTestHelperMoveFile(mounttmp):
649 class Test(unittest.TestCase):
651 d1 = llfuse.listdir(os.path.join(mounttmp))
652 self.assertEqual(["testdir"], d1)
653 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
654 self.assertEqual(["file1.txt"], d1)
656 os.rename(os.path.join(mounttmp, "testdir", "file1.txt"), os.path.join(mounttmp, "file1.txt"))
658 d1 = llfuse.listdir(os.path.join(mounttmp))
659 self.assertEqual(["file1.txt", "testdir"], sorted(d1))
660 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
661 self.assertEqual([], d1)
665 class FuseMvFileTest(MountTestBase):
667 collection = arvados.collection.Collection(api_client=self.api)
668 collection.save_new()
670 m = self.make_mount(fuse.CollectionDirectory)
672 m.new_collection(collection.api_response(), collection)
673 self.assertTrue(m.writable())
675 self.pool.apply(fuseMvFileTestHelperWriteFile, (self.mounttmp,))
678 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
679 self.assertRegexpMatches(collection2["manifest_text"],
680 r'\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$')
682 self.pool.apply(fuseMvFileTestHelperMoveFile, (self.mounttmp,))
684 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
685 self.assertRegexpMatches(collection2["manifest_text"],
686 r'\. 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$')
689 def fuseRenameTestHelper(mounttmp):
690 class Test(unittest.TestCase):
692 os.mkdir(os.path.join(mounttmp, "testdir"))
694 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
695 f.write("Hello world!")
699 class FuseRenameTest(MountTestBase):
701 collection = arvados.collection.Collection(api_client=self.api)
702 collection.save_new()
704 m = self.make_mount(fuse.CollectionDirectory)
706 m.new_collection(collection.api_response(), collection)
707 self.assertTrue(m.writable())
709 self.pool.apply(fuseRenameTestHelper, (self.mounttmp,))
712 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
713 self.assertRegexpMatches(collection2["manifest_text"],
714 r'\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$')
716 d1 = llfuse.listdir(os.path.join(self.mounttmp))
717 self.assertEqual(["testdir"], d1)
718 d1 = llfuse.listdir(os.path.join(self.mounttmp, "testdir"))
719 self.assertEqual(["file1.txt"], d1)
721 os.rename(os.path.join(self.mounttmp, "testdir"), os.path.join(self.mounttmp, "testdir2"))
723 d1 = llfuse.listdir(os.path.join(self.mounttmp))
724 self.assertEqual(["testdir2"], sorted(d1))
725 d1 = llfuse.listdir(os.path.join(self.mounttmp, "testdir2"))
726 self.assertEqual(["file1.txt"], d1)
728 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
729 self.assertRegexpMatches(collection2["manifest_text"],
730 r'\./testdir2 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$')
733 class FuseUpdateFromEventTest(MountTestBase):
735 collection = arvados.collection.Collection(api_client=self.api)
736 collection.save_new()
738 m = self.make_mount(fuse.CollectionDirectory)
740 m.new_collection(collection.api_response(), collection)
742 self.operations.listen_for_events()
744 d1 = llfuse.listdir(os.path.join(self.mounttmp))
745 self.assertEqual([], sorted(d1))
747 with arvados.collection.Collection(collection.manifest_locator(), api_client=self.api) as collection2:
748 with collection2.open("file1.txt", "w") as f:
751 for attempt in AssertWithTimeout(10):
752 attempt(self.assertEqual, ["file1.txt"], llfuse.listdir(os.path.join(self.mounttmp)))
755 def fuseFileConflictTestHelper(mounttmp):
756 class Test(unittest.TestCase):
758 with open(os.path.join(mounttmp, "file1.txt"), "w") as f:
761 d1 = sorted(llfuse.listdir(os.path.join(mounttmp)))
762 self.assertEqual(len(d1), 2)
764 with open(os.path.join(mounttmp, "file1.txt"), "r") as f:
765 self.assertEqual(f.read(), "bar")
767 self.assertRegexpMatches(d1[1],
768 r'file1\.txt~\d\d\d\d\d\d\d\d-\d\d\d\d\d\d~conflict~')
770 with open(os.path.join(mounttmp, d1[1]), "r") as f:
771 self.assertEqual(f.read(), "foo")
775 class FuseFileConflictTest(MountTestBase):
777 collection = arvados.collection.Collection(api_client=self.api)
778 collection.save_new()
780 m = self.make_mount(fuse.CollectionDirectory)
782 m.new_collection(collection.api_response(), collection)
784 d1 = llfuse.listdir(os.path.join(self.mounttmp))
785 self.assertEqual([], sorted(d1))
787 with arvados.collection.Collection(collection.manifest_locator(), api_client=self.api) as collection2:
788 with collection2.open("file1.txt", "w") as f:
791 # See note in MountTestBase.setUp
792 self.pool.apply(fuseFileConflictTestHelper, (self.mounttmp,))
795 def fuseUnlinkOpenFileTest(mounttmp):
796 class Test(unittest.TestCase):
798 with open(os.path.join(mounttmp, "file1.txt"), "w+") as f:
801 d1 = llfuse.listdir(os.path.join(mounttmp))
802 self.assertEqual(["file1.txt"], sorted(d1))
804 os.remove(os.path.join(mounttmp, "file1.txt"))
806 d1 = llfuse.listdir(os.path.join(mounttmp))
807 self.assertEqual([], sorted(d1))
810 self.assertEqual(f.read(), "foo")
814 self.assertEqual(f.read(), "foobar")
818 class FuseUnlinkOpenFileTest(MountTestBase):
820 collection = arvados.collection.Collection(api_client=self.api)
821 collection.save_new()
823 m = self.make_mount(fuse.CollectionDirectory)
825 m.new_collection(collection.api_response(), collection)
827 # See note in MountTestBase.setUp
828 self.pool.apply(fuseUnlinkOpenFileTest, (self.mounttmp,))
830 self.assertEqual(collection.manifest_text(), "")
833 def fuseMvFileBetweenCollectionsTest1(mounttmp, uuid1, uuid2):
834 class Test(unittest.TestCase):
836 with open(os.path.join(mounttmp, uuid1, "file1.txt"), "w") as f:
837 f.write("Hello world!")
839 d1 = os.listdir(os.path.join(mounttmp, uuid1))
840 self.assertEqual(["file1.txt"], sorted(d1))
841 d1 = os.listdir(os.path.join(mounttmp, uuid2))
842 self.assertEqual([], sorted(d1))
846 def fuseMvFileBetweenCollectionsTest2(mounttmp, uuid1, uuid2):
847 class Test(unittest.TestCase):
849 os.rename(os.path.join(mounttmp, uuid1, "file1.txt"), os.path.join(mounttmp, uuid2, "file2.txt"))
851 d1 = os.listdir(os.path.join(mounttmp, uuid1))
852 self.assertEqual([], sorted(d1))
853 d1 = os.listdir(os.path.join(mounttmp, uuid2))
854 self.assertEqual(["file2.txt"], sorted(d1))
858 class FuseMvFileBetweenCollectionsTest(MountTestBase):
860 collection1 = arvados.collection.Collection(api_client=self.api)
861 collection1.save_new()
863 collection2 = arvados.collection.Collection(api_client=self.api)
864 collection2.save_new()
866 m = self.make_mount(fuse.MagicDirectory)
868 # See note in MountTestBase.setUp
869 self.pool.apply(fuseMvFileBetweenCollectionsTest1, (self.mounttmp,
870 collection1.manifest_locator(),
871 collection2.manifest_locator()))
876 self.assertRegexpMatches(collection1.manifest_text(), r"\. 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$")
877 self.assertEqual(collection2.manifest_text(), "")
879 self.pool.apply(fuseMvFileBetweenCollectionsTest2, (self.mounttmp,
880 collection1.manifest_locator(),
881 collection2.manifest_locator()))
886 self.assertEqual(collection1.manifest_text(), "")
887 self.assertRegexpMatches(collection2.manifest_text(), r"\. 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file2\.txt$")
889 collection1.stop_threads()
890 collection2.stop_threads()
893 def fuseMvDirBetweenCollectionsTest1(mounttmp, uuid1, uuid2):
894 class Test(unittest.TestCase):
896 os.mkdir(os.path.join(mounttmp, uuid1, "testdir"))
897 with open(os.path.join(mounttmp, uuid1, "testdir", "file1.txt"), "w") as f:
898 f.write("Hello world!")
900 d1 = os.listdir(os.path.join(mounttmp, uuid1))
901 self.assertEqual(["testdir"], sorted(d1))
902 d1 = os.listdir(os.path.join(mounttmp, uuid1, "testdir"))
903 self.assertEqual(["file1.txt"], sorted(d1))
905 d1 = os.listdir(os.path.join(mounttmp, uuid2))
906 self.assertEqual([], sorted(d1))
911 def fuseMvDirBetweenCollectionsTest2(mounttmp, uuid1, uuid2):
912 class Test(unittest.TestCase):
914 os.rename(os.path.join(mounttmp, uuid1, "testdir"), os.path.join(mounttmp, uuid2, "testdir2"))
916 d1 = os.listdir(os.path.join(mounttmp, uuid1))
917 self.assertEqual([], sorted(d1))
919 d1 = os.listdir(os.path.join(mounttmp, uuid2))
920 self.assertEqual(["testdir2"], sorted(d1))
921 d1 = os.listdir(os.path.join(mounttmp, uuid2, "testdir2"))
922 self.assertEqual(["file1.txt"], sorted(d1))
924 with open(os.path.join(mounttmp, uuid2, "testdir2", "file1.txt"), "r") as f:
925 self.assertEqual(f.read(), "Hello world!")
929 class FuseMvDirBetweenCollectionsTest(MountTestBase):
931 collection1 = arvados.collection.Collection(api_client=self.api)
932 collection1.save_new()
934 collection2 = arvados.collection.Collection(api_client=self.api)
935 collection2.save_new()
937 m = self.make_mount(fuse.MagicDirectory)
939 # See note in MountTestBase.setUp
940 self.pool.apply(fuseMvDirBetweenCollectionsTest1, (self.mounttmp,
941 collection1.manifest_locator(),
942 collection2.manifest_locator()))
947 self.assertRegexpMatches(collection1.manifest_text(), r"\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$")
948 self.assertEqual(collection2.manifest_text(), "")
950 self.pool.apply(fuseMvDirBetweenCollectionsTest2, (self.mounttmp,
951 collection1.manifest_locator(),
952 collection2.manifest_locator()))
957 self.assertEqual(collection1.manifest_text(), "")
958 self.assertRegexpMatches(collection2.manifest_text(), r"\./testdir2 86fb269d190d2c85f6e0468ceca42a20\+12\+A\S+ 0:12:file1\.txt$")
960 collection1.stop_threads()
961 collection2.stop_threads()
963 def fuseProjectMkdirTestHelper1(mounttmp):
964 class Test(unittest.TestCase):
966 os.mkdir(os.path.join(mounttmp, "testcollection"))
967 with self.assertRaises(OSError):
968 os.mkdir(os.path.join(mounttmp, "testcollection"))
971 def fuseProjectMkdirTestHelper2(mounttmp):
972 class Test(unittest.TestCase):
974 with open(os.path.join(mounttmp, "testcollection", "file1.txt"), "w") as f:
975 f.write("Hello world!")
976 with self.assertRaises(OSError):
977 os.rmdir(os.path.join(mounttmp, "testcollection"))
978 os.remove(os.path.join(mounttmp, "testcollection", "file1.txt"))
979 with self.assertRaises(OSError):
980 os.remove(os.path.join(mounttmp, "testcollection"))
981 os.rmdir(os.path.join(mounttmp, "testcollection"))
984 class FuseProjectMkdirRmdirTest(MountTestBase):
986 self.make_mount(fuse.ProjectDirectory,
987 project_object=self.api.users().current().execute())
989 d1 = llfuse.listdir(self.mounttmp)
990 self.assertNotIn('testcollection', d1)
992 self.pool.apply(fuseProjectMkdirTestHelper1, (self.mounttmp,))
994 d1 = llfuse.listdir(self.mounttmp)
995 self.assertIn('testcollection', d1)
997 self.pool.apply(fuseProjectMkdirTestHelper2, (self.mounttmp,))
999 d1 = llfuse.listdir(self.mounttmp)
1000 self.assertNotIn('testcollection', d1)
1003 def fuseProjectMvTestHelper1(mounttmp):
1004 class Test(unittest.TestCase):
1006 d1 = llfuse.listdir(mounttmp)
1007 self.assertNotIn('testcollection', d1)
1009 os.mkdir(os.path.join(mounttmp, "testcollection"))
1011 d1 = llfuse.listdir(mounttmp)
1012 self.assertIn('testcollection', d1)
1014 with self.assertRaises(OSError):
1015 os.rename(os.path.join(mounttmp, "testcollection"), os.path.join(mounttmp, 'Unrestricted public data'))
1017 os.rename(os.path.join(mounttmp, "testcollection"), os.path.join(mounttmp, 'Unrestricted public data', 'testcollection'))
1019 d1 = llfuse.listdir(mounttmp)
1020 self.assertNotIn('testcollection', d1)
1022 d1 = llfuse.listdir(os.path.join(mounttmp, 'Unrestricted public data'))
1023 self.assertIn('testcollection', d1)
1027 class FuseProjectMvTest(MountTestBase):
1029 self.make_mount(fuse.ProjectDirectory,
1030 project_object=self.api.users().current().execute())
1032 self.pool.apply(fuseProjectMvTestHelper1, (self.mounttmp,))
1035 def fuseFsyncTestHelper(mounttmp, k):
1036 class Test(unittest.TestCase):
1038 fd = os.open(os.path.join(mounttmp, k), os.O_RDONLY)
1044 class FuseFsyncTest(FuseMagicTest):
1046 self.make_mount(fuse.MagicDirectory)
1047 self.pool.apply(fuseFsyncTestHelper, (self.mounttmp, self.testcollection))
1050 class MagicDirApiError(FuseMagicTest):
1052 api = mock.MagicMock()
1053 super(MagicDirApiError, self).setUp(api=api)
1054 api.collections().get().execute.side_effect = iter([Exception('API fail'), {"manifest_text": self.test_manifest}])
1055 api.keep.get.side_effect = Exception('Keep fail')
1058 self.make_mount(fuse.MagicDirectory)
1060 self.operations.inodes.inode_cache.cap = 1
1061 self.operations.inodes.inode_cache.min_entries = 2
1063 with self.assertRaises(OSError):
1064 llfuse.listdir(os.path.join(self.mounttmp, self.testcollection))
1066 llfuse.listdir(os.path.join(self.mounttmp, self.testcollection))
1069 class FuseUnitTest(unittest.TestCase):
1070 def test_sanitize_filename(self):
1089 for f in acceptable:
1090 self.assertEqual(f, fuse.sanitize_filename(f))
1091 for f in unacceptable:
1092 self.assertNotEqual(f, fuse.sanitize_filename(f))
1093 # The sanitized filename should be the same length, though.
1094 self.assertEqual(len(f), len(fuse.sanitize_filename(f)))
1096 self.assertEqual("_", fuse.sanitize_filename(""))
1097 self.assertEqual("_", fuse.sanitize_filename("."))
1098 self.assertEqual("__", fuse.sanitize_filename(".."))
1101 class FuseMagicTestPDHOnly(MountTestBase):
1102 def setUp(self, api=None):
1103 super(FuseMagicTestPDHOnly, self).setUp(api=api)
1105 cw = arvados.CollectionWriter()
1107 cw.start_new_file('thing1.txt')
1110 self.testcollection = cw.finish()
1111 self.test_manifest = cw.manifest_text()
1112 created = self.api.collections().create(body={"manifest_text":self.test_manifest}).execute()
1113 self.testcollectionuuid = str(created['uuid'])
1115 def verify_pdh_only(self, pdh_only=False, skip_pdh_only=False):
1116 if skip_pdh_only is True:
1117 self.make_mount(fuse.MagicDirectory) # in this case, the default by_id applies
1119 self.make_mount(fuse.MagicDirectory, pdh_only=pdh_only)
1121 mount_ls = llfuse.listdir(self.mounttmp)
1122 self.assertIn('README', mount_ls)
1123 self.assertFalse(any(arvados.util.keep_locator_pattern.match(fn) or
1124 arvados.util.uuid_pattern.match(fn)
1125 for fn in mount_ls),
1126 "new FUSE MagicDirectory lists Collection")
1128 # look up using pdh should succeed in all cases
1129 self.assertDirContents(self.testcollection, ['thing1.txt'])
1130 self.assertDirContents(os.path.join('by_id', self.testcollection),
1132 mount_ls = llfuse.listdir(self.mounttmp)
1133 self.assertIn('README', mount_ls)
1134 self.assertIn(self.testcollection, mount_ls)
1135 self.assertIn(self.testcollection,
1136 llfuse.listdir(os.path.join(self.mounttmp, 'by_id')))
1139 files[os.path.join(self.mounttmp, self.testcollection, 'thing1.txt')] = 'data 1'
1141 for k, v in files.items():
1142 with open(os.path.join(self.mounttmp, k)) as f:
1143 self.assertEqual(v, f.read())
1145 # look up using uuid should fail when pdh_only is set
1146 if pdh_only is True:
1147 with self.assertRaises(OSError):
1148 self.assertDirContents(os.path.join('by_id', self.testcollectionuuid),
1151 self.assertDirContents(os.path.join('by_id', self.testcollectionuuid),
1154 def test_with_pdh_only_true(self):
1155 self.verify_pdh_only(pdh_only=True)
1157 def test_with_pdh_only_false(self):
1158 self.verify_pdh_only(pdh_only=False)
1160 def test_with_default_by_id(self):
1161 self.verify_pdh_only(skip_pdh_only=True)