7751: Test mount arguments.
authorTom Clegg <tom@curoverse.com>
Fri, 20 Nov 2015 08:38:10 +0000 (03:38 -0500)
committerTom Clegg <tom@curoverse.com>
Wed, 25 Nov 2015 15:44:59 +0000 (10:44 -0500)
services/fuse/arvados_fuse/command.py
services/fuse/arvados_fuse/fusedir.py
services/fuse/tests/integration_test.py
services/fuse/tests/test_command_args.py [new file with mode: 0644]

index e9d8bb58ef8edb0577f598c7003a8f5e04f99339..ba7411169da5d59ad489f5904fd4c9bd3b0b6961 100644 (file)
@@ -187,16 +187,31 @@ class Mount(object):
         dir_args = [llfuse.ROOT_INODE, self.operations.inodes, self.api, self.args.retries]
         mount_readme = False
 
-        if self.args.mode is not None and (
-                self.args.mount_by_id or
-                self.args.mount_by_pdh or
-                self.args.mount_by_tag or
-                self.args.mount_home or
-                self.args.mount_shared or
-                self.args.mount_tmp or
-                self.args.mount_collection):
-            sys.exit("Cannot combine '{}' mode with custom --mount-* options.".
-                     format(self.args.mode))
+        if self.args.collection is not None:
+            # Set up the request handler with the collection at the root
+            self.args.mode = 'collection'
+            dir_class = CollectionDirectory
+            dir_args.append(self.args.collection)
+        elif self.args.project is not None:
+            self.args.mode = 'project'
+            dir_class = ProjectDirectory
+            dir_args.append(
+                self.api.groups().get(uuid=self.args.project).execute(
+                    num_retries=self.args.retries))
+
+        if (self.args.mount_by_id or
+            self.args.mount_by_pdh or
+            self.args.mount_by_tag or
+            self.args.mount_home or
+            self.args.mount_shared or
+            self.args.mount_tmp):
+            if self.args.mode is not None:
+                sys.exit(
+                    "Cannot combine '{}' mode with custom --mount-* options.".
+                    format(self.args.mode))
+        elif self.args.mode is None:
+            # If no --mount-custom or custom mount args, --all is the default
+            self.args.mode = 'all'
 
         if self.args.mode in ['by_id', 'by_pdh']:
             # Set up the request handler with the 'magic directory' at the root
@@ -217,15 +232,6 @@ class Mount(object):
             self.args.mount_home = ['home']
             self.args.mount_shared = ['shared']
             mount_readme = True
-        elif self.args.collection is not None:
-            # Set up the request handler with the collection at the root
-            dir_class = CollectionDirectory
-            dir_args.append(self.args.collection)
-        elif self.args.project is not None:
-            dir_class = ProjectDirectory
-            dir_args.append(
-                self.api.groups().get(uuid=self.args.project).execute(
-                    num_retries=self.args.retries))
 
         if dir_class is not None:
             self.operations.inodes.add_entry(dir_class(*dir_args))
@@ -252,7 +258,7 @@ class Mount(object):
             text = self._readme_text(
                 arvados.config.get('ARVADOS_API_HOST'),
                 usr['email'])
-            self._add_mount(e, StringFile(e.inode, text, now))
+            self._add_mount(e, 'README', StringFile(e.inode, text, now))
 
     def _add_mount(self, tld, name, ent):
         if name in ['', '.', '..'] or '/' in name:
@@ -271,6 +277,7 @@ From here, the following directories are available:
   by_tag/    Access to Keep collections organized by tag.
   home/      The contents of your home project.
   shared/    Projects shared with you.
+
 '''.format(api_host, user_email)
 
     def _run_exec(self):
index 21961a56f41d8776133173565edfad030c46444c..04c2d5064234b7e535dabebd7a164d1526be0381 100644 (file)
@@ -556,12 +556,13 @@ class MagicDirectory(Directory):
     README_TEXT = """
 This directory provides access to Arvados collections as subdirectories listed
 by uuid (in the form 'zzzzz-4zz18-1234567890abcde') or portable data hash (in
-the form '1234567890abcdefghijklmnopqrstuv+123').
+the form '1234567890abcdef0123456789abcdef+123').
 
 Note that this directory will appear empty until you attempt to access a
 specific collection subdirectory (such as trying to 'cd' into it), at which
 point the collection will actually be looked up on the server and the directory
 will appear if it exists.
+
 """.lstrip()
 
     def __init__(self, parent_inode, inodes, api, num_retries, pdh_only=False):
index 9652709e5dd3a23313ffe33388414258d34f0815..faa4a55065945d907109b8994470ccccb2c5904d 100644 (file)
@@ -47,7 +47,7 @@ class IntegrationTest(unittest.TestCase):
 
     def setUp(self):
         self.mnt = tempfile.mkdtemp()
-        run_test_server.authorize_with("admin")
+        run_test_server.authorize_with('active')
         self.api = arvados.safeapi.ThreadSafeApiCache(arvados.config.settings())
 
     def tearDown(self):
diff --git a/services/fuse/tests/test_command_args.py b/services/fuse/tests/test_command_args.py
new file mode 100644 (file)
index 0000000..62987cc
--- /dev/null
@@ -0,0 +1,176 @@
+import arvados
+import arvados_fuse
+import arvados_fuse.command
+import functools
+import json
+import llfuse
+import logging
+import os
+import run_test_server
+import tempfile
+import unittest
+
+def noexit(func):
+    """If argparse or arvados_fuse tries to exit, fail the test instead"""
+    class SystemExitCaught(StandardError):
+        pass
+    @functools.wraps(func)
+    def wrapper(*args, **kwargs):
+        try:
+            return func(*args, **kwargs)
+        except SystemExit:
+            raise SystemExitCaught
+    return wrapper
+
+class MountArgsTest(unittest.TestCase):
+    def setUp(self):
+        self.mntdir = tempfile.mkdtemp()
+        run_test_server.authorize_with('active')
+
+    def tearDown(self):
+        os.rmdir(self.mntdir)
+
+    def lookup(self, mnt, *path):
+        ent = mnt.operations.inodes[llfuse.ROOT_INODE]
+        for p in path:
+            ent = ent[p]
+        return ent
+
+    def check_ent_type(self, cls, *path):
+        ent = self.lookup(self.mnt, *path)
+        self.assertEqual(ent.__class__, cls)
+        return ent
+
+    @noexit
+    def test_default_all(self):
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--foreground', self.mntdir])
+        self.assertEqual(args.mode, None)
+        self.mnt = arvados_fuse.command.Mount(args)
+        e = self.check_ent_type(arvados_fuse.ProjectDirectory, 'home')
+        self.assertEqual(e.project_object['uuid'],
+                         run_test_server.fixture('users')['active']['uuid'])
+        e = self.check_ent_type(arvados_fuse.MagicDirectory, 'by_id')
+
+        e = self.check_ent_type(arvados_fuse.StringFile, 'README')
+        readme = e.readfrom(0, -1)
+        self.assertRegexpMatches(readme, r'active-user@arvados\.local')
+        self.assertRegexpMatches(readme, r'\n$')
+
+        e = self.check_ent_type(arvados_fuse.StringFile, 'by_id', 'README')
+        txt = e.readfrom(0, -1)
+        self.assertRegexpMatches(txt, r'portable data hash')
+        self.assertRegexpMatches(txt, r'\n$')
+
+    @noexit
+    def test_by_id(self):
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--by-id',
+            '--foreground', self.mntdir])
+        self.assertEqual(args.mode, 'by_id')
+        self.mnt = arvados_fuse.command.Mount(args)
+        e = self.check_ent_type(arvados_fuse.MagicDirectory)
+        self.assertEqual(e.pdh_only, False)
+
+    @noexit
+    def test_by_pdh(self):
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--by-pdh',
+            '--foreground', self.mntdir])
+        self.assertEqual(args.mode, 'by_pdh')
+        self.mnt = arvados_fuse.command.Mount(args)
+        e = self.check_ent_type(arvados_fuse.MagicDirectory)
+        self.assertEqual(e.pdh_only, True)
+
+    @noexit
+    def test_by_tag(self):
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--by-tag',
+            '--foreground', self.mntdir])
+        self.assertEqual(args.mode, 'by_tag')
+        self.mnt = arvados_fuse.command.Mount(args)
+        e = self.check_ent_type(arvados_fuse.TagsDirectory)
+
+    @noexit
+    def test_collection(self, id_type='uuid'):
+        c = run_test_server.fixture('collections')['public_text_file']
+        cid = c[id_type]
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--collection', cid,
+            '--foreground', self.mntdir])
+        self.mnt = arvados_fuse.command.Mount(args)
+        e = self.check_ent_type(arvados_fuse.CollectionDirectory)
+        self.assertEqual(e.collection_locator, cid)
+
+    def test_collection_pdh(self):
+        self.test_collection('portable_data_hash')
+
+    @noexit
+    def test_home(self):
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--home',
+            '--foreground', self.mntdir])
+        self.assertEqual(args.mode, 'home')
+        self.mnt = arvados_fuse.command.Mount(args)
+        e = self.check_ent_type(arvados_fuse.ProjectDirectory)
+        self.assertEqual(e.project_object['uuid'],
+                         run_test_server.fixture('users')['active']['uuid'])
+
+    def test_mutually_exclusive_args(self):
+        cid = run_test_server.fixture('collections')['public_text_file']['uuid']
+        gid = run_test_server.fixture('groups')['aproject']['uuid']
+        for badargs in [
+                ['--mount-tmp', 'foo', '--collection', cid],
+                ['--mount-tmp', 'foo', '--project', gid],
+                ['--collection', cid, '--project', gid],
+                ['--by-id', '--project', gid],
+                ['--mount-tmp', 'foo', '--by-id'],
+        ]:
+            with self.assertRaises(SystemExit):
+                args = arvados_fuse.command.ArgumentParser().parse_args(
+                    badargs + ['--foreground', self.mntdir])
+                arvados_fuse.command.Mount(args)
+    @noexit
+    def test_project(self):
+        uuid = run_test_server.fixture('groups')['aproject']['uuid']
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--project', uuid,
+            '--foreground', self.mntdir])
+        self.mnt = arvados_fuse.command.Mount(args)
+        e = self.check_ent_type(arvados_fuse.ProjectDirectory)
+        self.assertEqual(e.project_object['uuid'], uuid)
+
+    @noexit
+    def test_shared(self):
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--shared',
+            '--foreground', self.mntdir])
+        self.assertEqual(args.mode, 'shared')
+        self.mnt = arvados_fuse.command.Mount(args)
+        e = self.check_ent_type(arvados_fuse.SharedDirectory)
+        self.assertEqual(e.current_user['uuid'],
+                         run_test_server.fixture('users')['active']['uuid'])
+
+    @noexit
+    def test_custom(self):
+        args = arvados_fuse.command.ArgumentParser().parse_args([
+            '--mount-tmp', 'foo',
+            '--mount-tmp', 'bar',
+            '--mount-home', 'my_home',
+            '--foreground', self.mntdir])
+        self.assertEqual(args.mode, None)
+        self.mnt = arvados_fuse.command.Mount(args)
+        self.check_ent_type(arvados_fuse.Directory)
+        self.check_ent_type(arvados_fuse.TmpCollectionDirectory, 'foo')
+        self.check_ent_type(arvados_fuse.TmpCollectionDirectory, 'bar')
+        e = self.check_ent_type(arvados_fuse.ProjectDirectory, 'my_home')
+        self.assertEqual(e.project_object['uuid'],
+                         run_test_server.fixture('users')['active']['uuid'])
+
+    def test_custom_unsupported_layouts(self):
+        for name in ['.', '..', '', 'foo/bar', '/foo']:
+            with self.assertRaises(SystemExit):
+                args = arvados_fuse.command.ArgumentParser().parse_args([
+                    '--mount-tmp', name,
+                    '--foreground', self.mntdir])
+                arvados_fuse.command.Mount(args)