3 import arvados_fuse as fuse
16 import multiprocessing
17 import run_test_server
19 logger = logging.getLogger('arvados.arv-mount')
21 class MountTestBase(unittest.TestCase):
23 # The underlying C implementation of open() makes a fstat() syscall
24 # with the GIL still held. When the GETATTR message comes back to
25 # llfuse (which in these tests is in the same interpreter process) it
26 # can't acquire the GIL, so it can't service the fstat() call, so it
27 # deadlocks. The workaround is to run some of our test code in a
28 # separate process. Forturnately the multiprocessing module makes this
30 self.pool = multiprocessing.Pool(1)
32 self.keeptmp = tempfile.mkdtemp()
33 os.environ['KEEP_LOCAL_STORE'] = self.keeptmp
34 self.mounttmp = tempfile.mkdtemp()
36 run_test_server.authorize_with("admin")
37 self.api = arvados.safeapi.ThreadSafeApiCache(arvados.config.settings())
39 def make_mount(self, root_class, **root_kwargs):
40 self.operations = fuse.Operations(os.getuid(), os.getgid())
41 self.operations.inodes.add_entry(root_class(
42 llfuse.ROOT_INODE, self.operations.inodes, self.api, 0, **root_kwargs))
43 llfuse.init(self.operations, self.mounttmp, [])
44 threading.Thread(None, llfuse.main).start()
45 # wait until the driver is finished initializing
46 self.operations.initlock.wait()
47 return self.operations.inodes[llfuse.ROOT_INODE]
53 # llfuse.close is buggy, so use fusermount instead.
54 #llfuse.close(unmount=True)
57 while (count < 9 and success != 0):
58 success = subprocess.call(["fusermount", "-u", self.mounttmp])
62 os.rmdir(self.mounttmp)
63 shutil.rmtree(self.keeptmp)
64 run_test_server.reset()
66 def assertDirContents(self, subdir, expect_content):
69 path = os.path.join(path, subdir)
70 self.assertEqual(sorted(expect_content), sorted(llfuse.listdir(path)))
73 class FuseMountTest(MountTestBase):
75 super(FuseMountTest, self).setUp()
77 cw = arvados.CollectionWriter()
79 cw.start_new_file('thing1.txt')
81 cw.start_new_file('thing2.txt')
83 cw.start_new_stream('dir1')
85 cw.start_new_file('thing3.txt')
87 cw.start_new_file('thing4.txt')
90 cw.start_new_stream('dir2')
91 cw.start_new_file('thing5.txt')
93 cw.start_new_file('thing6.txt')
96 cw.start_new_stream('dir2/dir3')
97 cw.start_new_file('thing7.txt')
100 cw.start_new_file('thing8.txt')
103 cw.start_new_stream('edgecases')
104 for f in ":/./../.../-/*/\x01\\/ ".split("/"):
108 for f in ":/../.../-/*/\x01\\/ ".split("/"):
109 cw.start_new_stream('edgecases/dirs/' + f)
110 cw.start_new_file('x/x')
113 self.testcollection = cw.finish()
114 self.api.collections().create(body={"manifest_text":cw.manifest_text()}).execute()
117 self.make_mount(fuse.CollectionDirectory, collection_record=self.testcollection)
119 self.assertDirContents(None, ['thing1.txt', 'thing2.txt',
120 'edgecases', 'dir1', 'dir2'])
121 self.assertDirContents('dir1', ['thing3.txt', 'thing4.txt'])
122 self.assertDirContents('dir2', ['thing5.txt', 'thing6.txt', 'dir3'])
123 self.assertDirContents('dir2/dir3', ['thing7.txt', 'thing8.txt'])
124 self.assertDirContents('edgecases',
125 "dirs/:/_/__/.../-/*/\x01\\/ ".split("/"))
126 self.assertDirContents('edgecases/dirs',
127 ":/__/.../-/*/\x01\\/ ".split("/"))
129 files = {'thing1.txt': 'data 1',
130 'thing2.txt': 'data 2',
131 'dir1/thing3.txt': 'data 3',
132 'dir1/thing4.txt': 'data 4',
133 'dir2/thing5.txt': 'data 5',
134 'dir2/thing6.txt': 'data 6',
135 'dir2/dir3/thing7.txt': 'data 7',
136 'dir2/dir3/thing8.txt': 'data 8'}
138 for k, v in files.items():
139 with open(os.path.join(self.mounttmp, k)) as f:
140 self.assertEqual(v, f.read())
143 class FuseNoAPITest(MountTestBase):
145 super(FuseNoAPITest, self).setUp()
146 keep = arvados.keep.KeepClient(local_store=self.keeptmp)
147 self.file_data = "API-free text\n"
148 self.file_loc = keep.put(self.file_data)
149 self.coll_loc = keep.put(". {} 0:{}:api-free.txt\n".format(
150 self.file_loc, len(self.file_data)))
153 self.make_mount(fuse.MagicDirectory)
154 self.assertDirContents(self.coll_loc, ['api-free.txt'])
155 with open(os.path.join(
156 self.mounttmp, self.coll_loc, 'api-free.txt')) as keep_file:
157 actual = keep_file.read(-1)
158 self.assertEqual(self.file_data, actual)
161 class FuseMagicTest(MountTestBase):
163 super(FuseMagicTest, self).setUp()
165 cw = arvados.CollectionWriter()
167 cw.start_new_file('thing1.txt')
170 self.testcollection = cw.finish()
171 self.api.collections().create(body={"manifest_text":cw.manifest_text()}).execute()
174 self.make_mount(fuse.MagicDirectory)
176 mount_ls = llfuse.listdir(self.mounttmp)
177 self.assertIn('README', mount_ls)
178 self.assertFalse(any(arvados.util.keep_locator_pattern.match(fn) or
179 arvados.util.uuid_pattern.match(fn)
181 "new FUSE MagicDirectory lists Collection")
182 self.assertDirContents(self.testcollection, ['thing1.txt'])
183 self.assertDirContents(os.path.join('by_id', self.testcollection),
185 mount_ls = llfuse.listdir(self.mounttmp)
186 self.assertIn('README', mount_ls)
187 self.assertIn(self.testcollection, mount_ls)
188 self.assertIn(self.testcollection,
189 llfuse.listdir(os.path.join(self.mounttmp, 'by_id')))
192 files[os.path.join(self.mounttmp, self.testcollection, 'thing1.txt')] = 'data 1'
194 for k, v in files.items():
195 with open(os.path.join(self.mounttmp, k)) as f:
196 self.assertEqual(v, f.read())
199 class FuseTagsTest(MountTestBase):
201 self.make_mount(fuse.TagsDirectory)
203 d1 = llfuse.listdir(self.mounttmp)
205 self.assertEqual(['foo_tag'], d1)
207 d2 = llfuse.listdir(os.path.join(self.mounttmp, 'foo_tag'))
209 self.assertEqual(['zzzzz-4zz18-fy296fx3hot09f7'], d2)
211 d3 = llfuse.listdir(os.path.join(self.mounttmp, 'foo_tag', 'zzzzz-4zz18-fy296fx3hot09f7'))
213 self.assertEqual(['foo'], d3)
216 class FuseTagsUpdateTest(MountTestBase):
217 def tag_collection(self, coll_uuid, tag_name):
218 return self.api.links().create(
219 body={'link': {'head_uuid': coll_uuid,
225 self.make_mount(fuse.TagsDirectory, poll_time=1)
227 self.assertIn('foo_tag', llfuse.listdir(self.mounttmp))
229 bar_uuid = run_test_server.fixture('collections')['bar_file']['uuid']
230 self.tag_collection(bar_uuid, 'fuse_test_tag')
232 self.assertIn('fuse_test_tag', llfuse.listdir(self.mounttmp))
233 self.assertDirContents('fuse_test_tag', [bar_uuid])
235 baz_uuid = run_test_server.fixture('collections')['baz_file']['uuid']
236 l = self.tag_collection(baz_uuid, 'fuse_test_tag')
238 self.assertDirContents('fuse_test_tag', [bar_uuid, baz_uuid])
240 self.api.links().delete(uuid=l['uuid']).execute()
242 self.assertDirContents('fuse_test_tag', [bar_uuid])
245 class FuseSharedTest(MountTestBase):
247 self.make_mount(fuse.SharedDirectory,
248 exclude=self.api.users().current().execute()['uuid'])
250 # shared_dirs is a list of the directories exposed
251 # by fuse.SharedDirectory (i.e. any object visible
252 # to the current user)
253 shared_dirs = llfuse.listdir(self.mounttmp)
255 self.assertIn('FUSE User', shared_dirs)
257 # fuse_user_objs is a list of the objects owned by the FUSE
258 # test user (which present as files in the 'FUSE User'
260 fuse_user_objs = llfuse.listdir(os.path.join(self.mounttmp, 'FUSE User'))
261 fuse_user_objs.sort()
262 self.assertEqual(['FUSE Test Project', # project owned by user
263 'collection #1 owned by FUSE', # collection owned by user
264 'collection #2 owned by FUSE', # collection owned by user
265 'pipeline instance owned by FUSE.pipelineInstance', # pipeline instance owned by user
268 # test_proj_files is a list of the files in the FUSE Test Project.
269 test_proj_files = llfuse.listdir(os.path.join(self.mounttmp, 'FUSE User', 'FUSE Test Project'))
270 test_proj_files.sort()
271 self.assertEqual(['collection in FUSE project',
272 'pipeline instance in FUSE project.pipelineInstance',
273 'pipeline template in FUSE project.pipelineTemplate'
276 # Double check that we can open and read objects in this folder as a file,
277 # and that its contents are what we expect.
278 pipeline_template_path = os.path.join(
282 'pipeline template in FUSE project.pipelineTemplate')
283 with open(pipeline_template_path) as f:
285 self.assertEqual("pipeline template in FUSE project", j['name'])
287 # check mtime on template
288 st = os.stat(pipeline_template_path)
289 self.assertEqual(st.st_mtime, 1397493304)
291 # check mtime on collection
292 st = os.stat(os.path.join(
295 'collection #1 owned by FUSE'))
296 self.assertEqual(st.st_mtime, 1391448174)
299 class FuseHomeTest(MountTestBase):
301 self.make_mount(fuse.ProjectDirectory,
302 project_object=self.api.users().current().execute())
304 d1 = llfuse.listdir(self.mounttmp)
305 self.assertIn('Unrestricted public data', d1)
307 d2 = llfuse.listdir(os.path.join(self.mounttmp, 'Unrestricted public data'))
308 public_project = run_test_server.fixture('groups')[
309 'anonymously_accessible_project']
312 for name, item in run_test_server.fixture('collections').iteritems():
313 if 'name' not in item:
315 elif item['owner_uuid'] == public_project['uuid']:
316 self.assertIn(item['name'], d2)
319 # Artificial assumption here: there is no public
320 # collection fixture with the same name as a
321 # non-public collection.
322 self.assertNotIn(item['name'], d2)
324 self.assertNotEqual(0, found_in)
325 self.assertNotEqual(0, found_not_in)
327 d3 = llfuse.listdir(os.path.join(self.mounttmp, 'Unrestricted public data', 'GNU General Public License, version 3'))
328 self.assertEqual(["GNU_General_Public_License,_version_3.pdf"], d3)
331 def fuseModifyFileTestHelper1(mounttmp):
332 class Test(unittest.TestCase):
334 d1 = llfuse.listdir(mounttmp)
335 self.assertEqual(["file1.txt"], d1)
336 with open(os.path.join(mounttmp, "file1.txt")) as f:
337 self.assertEqual("blub", f.read())
340 def fuseModifyFileTestHelper2(mounttmp):
341 class Test(unittest.TestCase):
343 d1 = llfuse.listdir(mounttmp)
344 self.assertEqual(["file1.txt"], d1)
345 with open(os.path.join(mounttmp, "file1.txt")) as f:
346 self.assertEqual("plnp", f.read())
349 class FuseModifyFileTest(MountTestBase):
351 collection = arvados.collection.Collection(api_client=self.api)
352 with collection.open("file1.txt", "w") as f:
355 collection.save_new()
357 m = self.make_mount(fuse.CollectionDirectory)
359 m.new_collection(collection.api_response(), collection)
361 self.pool.apply(fuseModifyFileTestHelper1, (self.mounttmp,))
363 with collection.open("file1.txt", "w") as f:
366 self.pool.apply(fuseModifyFileTestHelper2, (self.mounttmp,))
369 class FuseAddFileToCollectionTest(MountTestBase):
371 collection = arvados.collection.Collection(api_client=self.api)
372 with collection.open("file1.txt", "w") as f:
375 collection.save_new()
377 m = self.make_mount(fuse.CollectionDirectory)
379 m.new_collection(collection.api_response(), collection)
381 d1 = llfuse.listdir(self.mounttmp)
382 self.assertEqual(["file1.txt"], d1)
384 with collection.open("file2.txt", "w") as f:
387 d1 = llfuse.listdir(self.mounttmp)
388 self.assertEqual(["file1.txt", "file2.txt"], sorted(d1))
391 class FuseRemoveFileFromCollectionTest(MountTestBase):
393 collection = arvados.collection.Collection(api_client=self.api)
394 with collection.open("file1.txt", "w") as f:
397 with collection.open("file2.txt", "w") as f:
400 collection.save_new()
402 m = self.make_mount(fuse.CollectionDirectory)
404 m.new_collection(collection.api_response(), collection)
406 d1 = llfuse.listdir(self.mounttmp)
407 self.assertEqual(["file1.txt", "file2.txt"], sorted(d1))
409 collection.remove("file2.txt")
411 d1 = llfuse.listdir(self.mounttmp)
412 self.assertEqual(["file1.txt"], d1)
415 def fuseCreateFileTestHelper(mounttmp):
416 class Test(unittest.TestCase):
418 with open(os.path.join(mounttmp, "file1.txt"), "w") as f:
422 class FuseCreateFileTest(MountTestBase):
424 collection = arvados.collection.Collection(api_client=self.api)
425 collection.save_new()
427 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
428 self.assertEqual(collection2["manifest_text"], "")
430 collection.save_new()
432 m = self.make_mount(fuse.CollectionDirectory)
434 m.new_collection(collection.api_response(), collection)
435 self.assertTrue(m.writable())
437 self.assertNotIn("file1.txt", collection)
439 self.pool.apply(fuseCreateFileTestHelper, (self.mounttmp,))
441 self.assertIn("file1.txt", collection)
443 d1 = llfuse.listdir(self.mounttmp)
444 self.assertEqual(["file1.txt"], d1)
446 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
447 self.assertRegexpMatches(collection2["manifest_text"],
448 r'\. d41d8cd98f00b204e9800998ecf8427e\+0\+A[a-f0-9]{40}@[a-f0-9]{8} 0:0:file1\.txt$')
451 def fuseWriteFileTestHelper1(mounttmp):
452 class Test(unittest.TestCase):
454 with open(os.path.join(mounttmp, "file1.txt"), "w") as f:
455 f.write("Hello world!")
458 def fuseWriteFileTestHelper2(mounttmp):
459 class Test(unittest.TestCase):
461 with open(os.path.join(mounttmp, "file1.txt"), "r") as f:
462 self.assertEqual(f.read(), "Hello world!")
465 class FuseWriteFileTest(MountTestBase):
467 collection = arvados.collection.Collection(api_client=self.api)
468 collection.save_new()
470 m = self.make_mount(fuse.CollectionDirectory)
472 m.new_collection(collection.api_response(), collection)
473 self.assertTrue(m.writable())
475 self.assertNotIn("file1.txt", collection)
477 self.pool.apply(fuseWriteFileTestHelper1, (self.mounttmp,))
479 with collection.open("file1.txt") as f:
480 self.assertEqual(f.read(), "Hello world!")
482 self.pool.apply(fuseWriteFileTestHelper2, (self.mounttmp,))
484 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
485 self.assertRegexpMatches(collection2["manifest_text"],
486 r'\. 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$')
489 def fuseUpdateFileTestHelper(mounttmp):
490 class Test(unittest.TestCase):
492 with open(os.path.join(mounttmp, "file1.txt"), "w") as f:
493 f.write("Hello world!")
495 with open(os.path.join(mounttmp, "file1.txt"), "r+") as f:
497 self.assertEqual(fr, "Hello world!")
499 f.write("Hola mundo!")
502 self.assertEqual(fr, "Hola mundo!!")
504 with open(os.path.join(mounttmp, "file1.txt"), "r") as f:
505 self.assertEqual(f.read(), "Hola mundo!!")
509 class FuseUpdateFileTest(MountTestBase):
511 collection = arvados.collection.Collection(api_client=self.api)
512 collection.save_new()
514 m = self.make_mount(fuse.CollectionDirectory)
516 m.new_collection(collection.api_response(), collection)
517 self.assertTrue(m.writable())
519 # See note in FuseWriteFileTest
520 self.pool.apply(fuseUpdateFileTestHelper, (self.mounttmp,))
522 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
523 self.assertRegexpMatches(collection2["manifest_text"],
524 r'\. daaef200ebb921e011e3ae922dd3266b\+11\+A[a-f0-9]{40}@[a-f0-9]{8} 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:11:file1\.txt 22:1:file1\.txt$')
527 def fuseMkdirTestHelper(mounttmp):
528 class Test(unittest.TestCase):
530 with self.assertRaises(IOError):
531 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
532 f.write("Hello world!")
534 os.mkdir(os.path.join(mounttmp, "testdir"))
536 with self.assertRaises(OSError):
537 os.mkdir(os.path.join(mounttmp, "testdir"))
539 d1 = llfuse.listdir(mounttmp)
540 self.assertEqual(["testdir"], d1)
542 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
543 f.write("Hello world!")
545 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
546 self.assertEqual(["file1.txt"], d1)
550 class FuseMkdirTest(MountTestBase):
552 collection = arvados.collection.Collection(api_client=self.api)
553 collection.save_new()
555 m = self.make_mount(fuse.CollectionDirectory)
557 m.new_collection(collection.api_response(), collection)
558 self.assertTrue(m.writable())
560 self.pool.apply(fuseMkdirTestHelper, (self.mounttmp,))
562 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
563 self.assertRegexpMatches(collection2["manifest_text"],
564 r'\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$')
567 def fuseRmTestHelper1(mounttmp):
568 class Test(unittest.TestCase):
570 os.mkdir(os.path.join(mounttmp, "testdir"))
572 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
573 f.write("Hello world!")
577 def fuseRmTestHelper2(mounttmp):
578 class Test(unittest.TestCase):
580 # Can't delete because it's not empty
581 with self.assertRaises(OSError):
582 os.rmdir(os.path.join(mounttmp, "testdir"))
584 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
585 self.assertEqual(["file1.txt"], d1)
588 os.remove(os.path.join(mounttmp, "testdir", "file1.txt"))
590 # Make sure it's empty
591 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
592 self.assertEqual([], d1)
594 # Try to delete it again
595 with self.assertRaises(OSError):
596 os.remove(os.path.join(mounttmp, "testdir", "file1.txt"))
600 def fuseRmTestHelper3(mounttmp):
601 class Test(unittest.TestCase):
603 # Should be able to delete now that it is empty
604 os.rmdir(os.path.join(mounttmp, "testdir"))
606 # Make sure it's empty
607 d1 = llfuse.listdir(os.path.join(mounttmp))
608 self.assertEqual([], d1)
610 # Try to delete it again
611 with self.assertRaises(OSError):
612 os.rmdir(os.path.join(mounttmp, "testdir"))
616 class FuseRmTest(MountTestBase):
618 collection = arvados.collection.Collection(api_client=self.api)
619 collection.save_new()
621 m = self.make_mount(fuse.CollectionDirectory)
623 m.new_collection(collection.api_response(), collection)
624 self.assertTrue(m.writable())
626 self.pool.apply(fuseRmTestHelper1, (self.mounttmp,))
629 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
630 self.assertRegexpMatches(collection2["manifest_text"],
631 r'\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$')
632 self.pool.apply(fuseRmTestHelper2, (self.mounttmp,))
634 # Can't have empty directories :-( so manifest will be empty.
635 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
636 self.assertEqual(collection2["manifest_text"], "")
638 self.pool.apply(fuseRmTestHelper3, (self.mounttmp,))
640 # manifest should be empty now.
641 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
642 self.assertEqual(collection2["manifest_text"], "")
645 def fuseMvFileTestHelper1(mounttmp):
646 class Test(unittest.TestCase):
648 os.mkdir(os.path.join(mounttmp, "testdir"))
650 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
651 f.write("Hello world!")
655 def fuseMvFileTestHelper2(mounttmp):
656 class Test(unittest.TestCase):
658 d1 = llfuse.listdir(os.path.join(mounttmp))
659 self.assertEqual(["testdir"], d1)
660 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
661 self.assertEqual(["file1.txt"], d1)
663 os.rename(os.path.join(mounttmp, "testdir", "file1.txt"), os.path.join(mounttmp, "file1.txt"))
665 d1 = llfuse.listdir(os.path.join(mounttmp))
666 self.assertEqual(["file1.txt", "testdir"], sorted(d1))
667 d1 = llfuse.listdir(os.path.join(mounttmp, "testdir"))
668 self.assertEqual([], d1)
672 class FuseMvFileTest(MountTestBase):
674 collection = arvados.collection.Collection(api_client=self.api)
675 collection.save_new()
677 m = self.make_mount(fuse.CollectionDirectory)
679 m.new_collection(collection.api_response(), collection)
680 self.assertTrue(m.writable())
682 self.pool.apply(fuseMvFileTestHelper1, (self.mounttmp,))
685 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
686 self.assertRegexpMatches(collection2["manifest_text"],
687 r'\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$')
689 self.pool.apply(fuseMvFileTestHelper2, (self.mounttmp,))
691 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
692 self.assertRegexpMatches(collection2["manifest_text"],
693 r'\. 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$')
696 def fuseRenameTestHelper(mounttmp):
697 class Test(unittest.TestCase):
699 os.mkdir(os.path.join(mounttmp, "testdir"))
701 with open(os.path.join(mounttmp, "testdir", "file1.txt"), "w") as f:
702 f.write("Hello world!")
706 class FuseRenameTest(MountTestBase):
708 collection = arvados.collection.Collection(api_client=self.api)
709 collection.save_new()
711 m = self.make_mount(fuse.CollectionDirectory)
713 m.new_collection(collection.api_response(), collection)
714 self.assertTrue(m.writable())
716 self.pool.apply(fuseRenameTestHelper, (self.mounttmp,))
719 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
720 self.assertRegexpMatches(collection2["manifest_text"],
721 r'\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$')
723 d1 = llfuse.listdir(os.path.join(self.mounttmp))
724 self.assertEqual(["testdir"], d1)
725 d1 = llfuse.listdir(os.path.join(self.mounttmp, "testdir"))
726 self.assertEqual(["file1.txt"], d1)
728 os.rename(os.path.join(self.mounttmp, "testdir"), os.path.join(self.mounttmp, "testdir2"))
730 d1 = llfuse.listdir(os.path.join(self.mounttmp))
731 self.assertEqual(["testdir2"], sorted(d1))
732 d1 = llfuse.listdir(os.path.join(self.mounttmp, "testdir2"))
733 self.assertEqual(["file1.txt"], d1)
735 collection2 = self.api.collections().get(uuid=collection.manifest_locator()).execute()
736 self.assertRegexpMatches(collection2["manifest_text"],
737 r'\./testdir2 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$')
740 class FuseUpdateFromEventTest(MountTestBase):
742 arvados.logger.setLevel(logging.DEBUG)
744 collection = arvados.collection.Collection(api_client=self.api)
745 collection.save_new()
747 m = self.make_mount(fuse.CollectionDirectory)
749 m.new_collection(collection.api_response(), collection)
751 self.operations.listen_for_events(self.api)
753 d1 = llfuse.listdir(os.path.join(self.mounttmp))
754 self.assertEqual([], sorted(d1))
756 with arvados.collection.Collection(collection.manifest_locator(), api_client=self.api) as collection2:
757 with collection2.open("file1.txt", "w") as f:
762 # should show up via event bus notify
764 d1 = llfuse.listdir(os.path.join(self.mounttmp))
765 self.assertEqual(["file1.txt"], sorted(d1))
768 def fuseFileConflictTestHelper(mounttmp):
769 class Test(unittest.TestCase):
771 with open(os.path.join(mounttmp, "file1.txt"), "w") as f:
774 d1 = sorted(llfuse.listdir(os.path.join(mounttmp)))
775 self.assertEqual(len(d1), 2)
777 with open(os.path.join(mounttmp, "file1.txt"), "r") as f:
778 self.assertEqual(f.read(), "bar")
780 self.assertRegexpMatches(d1[1],
781 r'file1\.txt~conflict-\d\d\d\d-\d\d-\d\d-\d\d:\d\d:\d\d~')
783 with open(os.path.join(mounttmp, d1[1]), "r") as f:
784 self.assertEqual(f.read(), "foo")
788 class FuseFileConflictTest(MountTestBase):
790 collection = arvados.collection.Collection(api_client=self.api)
791 collection.save_new()
793 m = self.make_mount(fuse.CollectionDirectory)
795 m.new_collection(collection.api_response(), collection)
797 d1 = llfuse.listdir(os.path.join(self.mounttmp))
798 self.assertEqual([], sorted(d1))
800 with arvados.collection.Collection(collection.manifest_locator(), api_client=self.api) as collection2:
801 with collection2.open("file1.txt", "w") as f:
804 # See comment in FuseWriteFileTest
805 self.pool.apply(fuseFileConflictTestHelper, (self.mounttmp,))
808 def fuseUnlinkOpenFileTest(mounttmp):
809 class Test(unittest.TestCase):
811 with open(os.path.join(mounttmp, "file1.txt"), "w+") as f:
814 d1 = llfuse.listdir(os.path.join(mounttmp))
815 self.assertEqual(["file1.txt"], sorted(d1))
817 os.remove(os.path.join(mounttmp, "file1.txt"))
819 d1 = llfuse.listdir(os.path.join(mounttmp))
820 self.assertEqual([], sorted(d1))
823 self.assertEqual(f.read(), "foo")
827 self.assertEqual(f.read(), "foobar")
831 class FuseUnlinkOpenFileTest(MountTestBase):
833 collection = arvados.collection.Collection(api_client=self.api)
834 collection.save_new()
836 m = self.make_mount(fuse.CollectionDirectory)
838 m.new_collection(collection.api_response(), collection)
840 # See comment in FuseWriteFileTest
841 self.pool.apply(fuseUnlinkOpenFileTest, (self.mounttmp,))
843 self.assertEqual(collection.manifest_text(), "")
846 def fuseMvFileBetweenCollectionsTest1(mounttmp, uuid1, uuid2):
847 class Test(unittest.TestCase):
849 with open(os.path.join(mounttmp, uuid1, "file1.txt"), "w") as f:
850 f.write("Hello world!")
852 d1 = os.listdir(os.path.join(mounttmp, uuid1))
853 self.assertEqual(["file1.txt"], sorted(d1))
854 d1 = os.listdir(os.path.join(mounttmp, uuid2))
855 self.assertEqual([], sorted(d1))
859 def fuseMvFileBetweenCollectionsTest2(mounttmp, uuid1, uuid2):
860 class Test(unittest.TestCase):
862 os.rename(os.path.join(mounttmp, uuid1, "file1.txt"), os.path.join(mounttmp, uuid2, "file2.txt"))
864 d1 = os.listdir(os.path.join(mounttmp, uuid1))
865 self.assertEqual([], sorted(d1))
866 d1 = os.listdir(os.path.join(mounttmp, uuid2))
867 self.assertEqual(["file2.txt"], sorted(d1))
871 class FuseMvFileBetweenCollectionsTest(MountTestBase):
873 collection1 = arvados.collection.Collection(api_client=self.api)
874 collection1.save_new()
876 collection2 = arvados.collection.Collection(api_client=self.api)
877 collection2.save_new()
879 m = self.make_mount(fuse.MagicDirectory)
881 # See comment in FuseWriteFileTest
882 self.pool.apply(fuseMvFileBetweenCollectionsTest1, (self.mounttmp,
883 collection1.manifest_locator(),
884 collection2.manifest_locator()))
889 self.assertRegexpMatches(collection1.manifest_text(), r"\. 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$")
890 self.assertEqual(collection2.manifest_text(), "")
892 self.pool.apply(fuseMvFileBetweenCollectionsTest2, (self.mounttmp,
893 collection1.manifest_locator(),
894 collection2.manifest_locator()))
899 self.assertEqual(collection1.manifest_text(), "")
900 self.assertRegexpMatches(collection2.manifest_text(), r"\. 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file2\.txt$")
903 def fuseMvDirBetweenCollectionsTest1(mounttmp, uuid1, uuid2):
904 class Test(unittest.TestCase):
906 os.mkdir(os.path.join(mounttmp, uuid1, "testdir"))
907 with open(os.path.join(mounttmp, uuid1, "testdir", "file1.txt"), "w") as f:
908 f.write("Hello world!")
910 d1 = os.listdir(os.path.join(mounttmp, uuid1))
911 self.assertEqual(["testdir"], sorted(d1))
912 d1 = os.listdir(os.path.join(mounttmp, uuid1, "testdir"))
913 self.assertEqual(["file1.txt"], sorted(d1))
915 d1 = os.listdir(os.path.join(mounttmp, uuid2))
916 self.assertEqual([], sorted(d1))
921 def fuseMvDirBetweenCollectionsTest2(mounttmp, uuid1, uuid2):
922 class Test(unittest.TestCase):
924 os.rename(os.path.join(mounttmp, uuid1, "testdir"), os.path.join(mounttmp, uuid2, "testdir2"))
926 d1 = os.listdir(os.path.join(mounttmp, uuid1))
927 self.assertEqual([], sorted(d1))
929 d1 = os.listdir(os.path.join(mounttmp, uuid2))
930 self.assertEqual(["testdir2"], sorted(d1))
931 d1 = os.listdir(os.path.join(mounttmp, uuid2, "testdir2"))
932 self.assertEqual(["file1.txt"], sorted(d1))
934 with open(os.path.join(mounttmp, uuid2, "testdir2", "file1.txt"), "r") as f:
935 self.assertEqual(f.read(), "Hello world!")
939 class FuseMvDirBetweenCollectionsTest(MountTestBase):
941 collection1 = arvados.collection.Collection(api_client=self.api)
942 collection1.save_new()
944 collection2 = arvados.collection.Collection(api_client=self.api)
945 collection2.save_new()
947 m = self.make_mount(fuse.MagicDirectory)
949 # See comment in FuseWriteFileTest
950 self.pool.apply(fuseMvDirBetweenCollectionsTest1, (self.mounttmp,
951 collection1.manifest_locator(),
952 collection2.manifest_locator()))
957 self.assertRegexpMatches(collection1.manifest_text(), r"\./testdir 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$")
958 self.assertEqual(collection2.manifest_text(), "")
960 self.pool.apply(fuseMvDirBetweenCollectionsTest2, (self.mounttmp,
961 collection1.manifest_locator(),
962 collection2.manifest_locator()))
967 self.assertEqual(collection1.manifest_text(), "")
968 self.assertRegexpMatches(collection2.manifest_text(), r"\./testdir2 86fb269d190d2c85f6e0468ceca42a20\+12\+A[a-f0-9]{40}@[a-f0-9]{8} 0:12:file1\.txt$")
971 def fuseProjectMkdirTestHelper1(mounttmp):
972 class Test(unittest.TestCase):
974 os.mkdir(os.path.join(mounttmp, "testcollection"))
975 with self.assertRaises(OSError):
976 os.mkdir(os.path.join(mounttmp, "testcollection"))
979 def fuseProjectMkdirTestHelper2(mounttmp):
980 class Test(unittest.TestCase):
982 with open(os.path.join(mounttmp, "testcollection", "file1.txt"), "w") as f:
983 f.write("Hello world!")
984 with self.assertRaises(OSError):
985 os.rmdir(os.path.join(mounttmp, "testcollection"))
986 os.remove(os.path.join(mounttmp, "testcollection", "file1.txt"))
987 with self.assertRaises(OSError):
988 os.remove(os.path.join(mounttmp, "testcollection"))
989 os.rmdir(os.path.join(mounttmp, "testcollection"))
992 class FuseProjectMkdirRmdirTest(MountTestBase):
994 self.make_mount(fuse.ProjectDirectory,
995 project_object=self.api.users().current().execute())
997 d1 = llfuse.listdir(self.mounttmp)
998 self.assertNotIn('testcollection', d1)
1000 self.pool.apply(fuseProjectMkdirTestHelper1, (self.mounttmp,))
1002 d1 = llfuse.listdir(self.mounttmp)
1003 self.assertIn('testcollection', d1)
1005 self.pool.apply(fuseProjectMkdirTestHelper2, (self.mounttmp,))
1007 d1 = llfuse.listdir(self.mounttmp)
1008 self.assertNotIn('testcollection', d1)
1011 def fuseProjectMvTestHelper1(mounttmp):
1012 class Test(unittest.TestCase):
1014 d1 = llfuse.listdir(mounttmp)
1015 self.assertNotIn('testcollection', d1)
1017 os.mkdir(os.path.join(mounttmp, "testcollection"))
1019 d1 = llfuse.listdir(mounttmp)
1020 self.assertIn('testcollection', d1)
1022 with self.assertRaises(OSError):
1023 os.rename(os.path.join(mounttmp, "testcollection"), os.path.join(mounttmp, 'Unrestricted public data'))
1025 os.rename(os.path.join(mounttmp, "testcollection"), os.path.join(mounttmp, 'Unrestricted public data', 'testcollection'))
1027 d1 = llfuse.listdir(mounttmp)
1028 self.assertNotIn('testcollection', d1)
1030 d1 = llfuse.listdir(os.path.join(mounttmp, 'Unrestricted public data'))
1031 self.assertIn('testcollection', d1)
1035 class FuseProjectMvTest(MountTestBase):
1037 self.make_mount(fuse.ProjectDirectory,
1038 project_object=self.api.users().current().execute())
1040 self.pool.apply(fuseProjectMvTestHelper1, (self.mounttmp,))
1043 class FuseUnitTest(unittest.TestCase):
1044 def test_sanitize_filename(self):
1063 for f in acceptable:
1064 self.assertEqual(f, fuse.sanitize_filename(f))
1065 for f in unacceptable:
1066 self.assertNotEqual(f, fuse.sanitize_filename(f))
1067 # The sanitized filename should be the same length, though.
1068 self.assertEqual(len(f), len(fuse.sanitize_filename(f)))
1070 self.assertEqual("_", fuse.sanitize_filename(""))
1071 self.assertEqual("_", fuse.sanitize_filename("."))
1072 self.assertEqual("__", fuse.sanitize_filename(".."))