3 import arvados_fuse.command
11 import run_test_server
17 """If argparse or arvados_fuse tries to exit, fail the test instead"""
18 class SystemExitCaught(StandardError):
20 @functools.wraps(func)
21 def wrapper(*args, **kwargs):
23 return func(*args, **kwargs)
25 raise SystemExitCaught
28 @contextlib.contextmanager
30 orig, sys.stderr = sys.stderr, open(os.devnull, 'w')
37 class MountArgsTest(unittest.TestCase):
39 self.mntdir = tempfile.mkdtemp()
40 run_test_server.authorize_with('active')
45 def lookup(self, mnt, *path):
46 ent = mnt.operations.inodes[llfuse.ROOT_INODE]
51 def check_ent_type(self, cls, *path):
52 ent = self.lookup(self.mnt, *path)
53 self.assertEqual(ent.__class__, cls)
57 def test_default_all(self):
58 args = arvados_fuse.command.ArgumentParser().parse_args([
59 '--foreground', self.mntdir])
60 self.assertEqual(args.mode, None)
61 self.mnt = arvados_fuse.command.Mount(args)
62 e = self.check_ent_type(arvados_fuse.ProjectDirectory, 'home')
63 self.assertEqual(e.project_object['uuid'],
64 run_test_server.fixture('users')['active']['uuid'])
65 e = self.check_ent_type(arvados_fuse.MagicDirectory, 'by_id')
67 e = self.check_ent_type(arvados_fuse.StringFile, 'README')
68 readme = e.readfrom(0, -1)
69 self.assertRegexpMatches(readme, r'active-user@arvados\.local')
70 self.assertRegexpMatches(readme, r'\n$')
72 e = self.check_ent_type(arvados_fuse.StringFile, 'by_id', 'README')
73 txt = e.readfrom(0, -1)
74 self.assertRegexpMatches(txt, r'portable data hash')
75 self.assertRegexpMatches(txt, r'\n$')
79 args = arvados_fuse.command.ArgumentParser().parse_args([
81 '--foreground', self.mntdir])
82 self.assertEqual(args.mode, 'by_id')
83 self.mnt = arvados_fuse.command.Mount(args)
84 e = self.check_ent_type(arvados_fuse.MagicDirectory)
85 self.assertEqual(e.pdh_only, False)
86 self.assertEqual(True, self.mnt.listen_for_events)
89 def test_by_pdh(self):
90 args = arvados_fuse.command.ArgumentParser().parse_args([
92 '--foreground', self.mntdir])
93 self.assertEqual(args.mode, 'by_pdh')
94 self.mnt = arvados_fuse.command.Mount(args)
95 e = self.check_ent_type(arvados_fuse.MagicDirectory)
96 self.assertEqual(e.pdh_only, True)
97 self.assertEqual(False, self.mnt.listen_for_events)
100 def test_by_tag(self):
101 args = arvados_fuse.command.ArgumentParser().parse_args([
103 '--foreground', self.mntdir])
104 self.assertEqual(args.mode, 'by_tag')
105 self.mnt = arvados_fuse.command.Mount(args)
106 e = self.check_ent_type(arvados_fuse.TagsDirectory)
107 self.assertEqual(True, self.mnt.listen_for_events)
110 def test_collection(self, id_type='uuid'):
111 c = run_test_server.fixture('collections')['public_text_file']
113 args = arvados_fuse.command.ArgumentParser().parse_args([
115 '--foreground', self.mntdir])
116 self.mnt = arvados_fuse.command.Mount(args)
117 e = self.check_ent_type(arvados_fuse.CollectionDirectory)
118 self.assertEqual(e.collection_locator, cid)
119 self.assertEqual(id_type == 'uuid', self.mnt.listen_for_events)
121 def test_collection_pdh(self):
122 self.test_collection('portable_data_hash')
126 args = arvados_fuse.command.ArgumentParser().parse_args([
128 '--foreground', self.mntdir])
129 self.assertEqual(args.mode, 'home')
130 self.mnt = arvados_fuse.command.Mount(args)
131 e = self.check_ent_type(arvados_fuse.ProjectDirectory)
132 self.assertEqual(e.project_object['uuid'],
133 run_test_server.fixture('users')['active']['uuid'])
134 self.assertEqual(True, self.mnt.listen_for_events)
136 def test_mutually_exclusive_args(self):
137 cid = run_test_server.fixture('collections')['public_text_file']['uuid']
138 gid = run_test_server.fixture('groups')['aproject']['uuid']
140 ['--mount-tmp', 'foo', '--collection', cid],
141 ['--mount-tmp', 'foo', '--project', gid],
142 ['--collection', cid, '--project', gid],
143 ['--by-id', '--project', gid],
144 ['--mount-tmp', 'foo', '--by-id'],
147 with self.assertRaises(SystemExit):
148 args = arvados_fuse.command.ArgumentParser().parse_args(
149 badargs + ['--foreground', self.mntdir])
150 arvados_fuse.command.Mount(args)
152 def test_project(self):
153 uuid = run_test_server.fixture('groups')['aproject']['uuid']
154 args = arvados_fuse.command.ArgumentParser().parse_args([
156 '--foreground', self.mntdir])
157 self.mnt = arvados_fuse.command.Mount(args)
158 e = self.check_ent_type(arvados_fuse.ProjectDirectory)
159 self.assertEqual(e.project_object['uuid'], uuid)
162 def test_shared(self):
163 args = arvados_fuse.command.ArgumentParser().parse_args([
165 '--foreground', self.mntdir])
166 self.assertEqual(args.mode, 'shared')
167 self.mnt = arvados_fuse.command.Mount(args)
168 e = self.check_ent_type(arvados_fuse.SharedDirectory)
169 self.assertEqual(e.current_user['uuid'],
170 run_test_server.fixture('users')['active']['uuid'])
171 self.assertEqual(True, self.mnt.listen_for_events)
174 @mock.patch('arvados.events.subscribe')
175 def test_custom(self, mock_subscribe):
176 args = arvados_fuse.command.ArgumentParser().parse_args([
177 '--mount-tmp', 'foo',
178 '--mount-tmp', 'bar',
179 '--mount-home', 'my_home',
180 '--foreground', self.mntdir])
181 self.assertEqual(args.mode, None)
182 self.mnt = arvados_fuse.command.Mount(args)
183 self.check_ent_type(arvados_fuse.Directory)
184 self.check_ent_type(arvados_fuse.TmpCollectionDirectory, 'foo')
185 self.check_ent_type(arvados_fuse.TmpCollectionDirectory, 'bar')
186 e = self.check_ent_type(arvados_fuse.ProjectDirectory, 'my_home')
187 self.assertEqual(e.project_object['uuid'],
188 run_test_server.fixture('users')['active']['uuid'])
189 self.assertEqual(True, self.mnt.listen_for_events)
192 self.assertEqual(1, mock_subscribe.call_count)
195 @mock.patch('arvados.events.subscribe')
196 def test_custom_no_listen(self, mock_subscribe):
197 args = arvados_fuse.command.ArgumentParser().parse_args([
198 '--mount-by-pdh', 'pdh',
199 '--mount-tmp', 'foo',
200 '--mount-tmp', 'bar',
201 '--foreground', self.mntdir])
202 self.mnt = arvados_fuse.command.Mount(args)
203 self.assertEqual(False, self.mnt.listen_for_events)
206 self.assertEqual(0, mock_subscribe.call_count)
208 def test_custom_unsupported_layouts(self):
209 for name in ['.', '..', '', 'foo/bar', '/foo']:
211 with self.assertRaises(SystemExit):
212 args = arvados_fuse.command.ArgumentParser().parse_args([
214 '--foreground', self.mntdir])
215 arvados_fuse.command.Mount(args)
217 class MountErrorTest(unittest.TestCase):
219 self.mntdir = tempfile.mkdtemp()
220 run_test_server.run()
221 run_test_server.authorize_with("active")
222 self.logger = logging.getLogger("null")
223 self.logger.setLevel(logging.CRITICAL+1)
226 if os.path.exists(self.mntdir):
227 # If the directory was not unmounted, this will raise an exception.
228 os.rmdir(self.mntdir)
229 run_test_server.reset()
231 def test_no_token(self):
232 del arvados.config._settings["ARVADOS_API_TOKEN"]
233 arvados.config._settings = {}
234 with self.assertRaises(SystemExit) as ex:
235 args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
236 arvados_fuse.command.Mount(args, logger=self.logger).run()
237 self.assertEqual(1, ex.exception.code)
239 def test_no_host(self):
240 del arvados.config._settings["ARVADOS_API_HOST"]
241 with self.assertRaises(SystemExit) as ex:
242 args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
243 arvados_fuse.command.Mount(args, logger=self.logger).run()
244 self.assertEqual(1, ex.exception.code)
246 def test_bogus_host(self):
247 arvados.config._settings["ARVADOS_API_HOST"] = "100::"
248 with self.assertRaises(SystemExit) as ex:
249 args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
250 arvados_fuse.command.Mount(args, logger=self.logger).run()
251 self.assertEqual(1, ex.exception.code)
253 def test_bogus_token(self):
254 arvados.config._settings["ARVADOS_API_TOKEN"] = "zzzzzzzzzzzzz"
255 with self.assertRaises(SystemExit) as ex:
256 args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
257 arvados_fuse.command.Mount(args, logger=self.logger).run()
258 self.assertEqual(1, ex.exception.code)
260 def test_bogus_mount_dir(self):
261 # All FUSE errors in llfuse.init() are raised as RuntimeError
262 # An easy error to trigger is to supply a nonexistent mount point,
265 # Other possible errors that also raise RuntimeError (but are much
266 # harder to test automatically because they depend on operating
267 # system configuration):
269 # The user doesn't have permission to use FUSE
270 # The user specified --allow-other but user_allow_other is not set
272 os.rmdir(self.mntdir)
273 with self.assertRaises(SystemExit) as ex:
274 args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
275 arvados_fuse.command.Mount(args, logger=self.logger).run()
276 self.assertEqual(1, ex.exception.code)
278 def test_unreadable_collection(self):
279 with self.assertRaises(SystemExit) as ex:
280 args = arvados_fuse.command.ArgumentParser().parse_args([
281 "--collection", "zzzzz-4zz18-zzzzzzzzzzzzzzz", self.mntdir])
282 arvados_fuse.command.Mount(args, logger=self.logger).run()
283 self.assertEqual(1, ex.exception.code)
285 def test_unreadable_project(self):
286 with self.assertRaises(SystemExit) as ex:
287 args = arvados_fuse.command.ArgumentParser().parse_args([
288 "--project", "zzzzz-j7d0g-zzzzzzzzzzzzzzz", self.mntdir])
289 arvados_fuse.command.Mount(args, logger=self.logger).run()
290 self.assertEqual(1, ex.exception.code)