X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/bf234475965f5908355435b246ac696c35d54556..62c3ba8319265118432f33ea98df116253b3e785:/services/fuse/tests/test_command_args.py diff --git a/services/fuse/tests/test_command_args.py b/services/fuse/tests/test_command_args.py index 8f040bc180..b08ab19335 100644 --- a/services/fuse/tests/test_command_args.py +++ b/services/fuse/tests/test_command_args.py @@ -1,20 +1,30 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + +from __future__ import absolute_import +from __future__ import print_function +from six import assertRegex import arvados import arvados_fuse import arvados_fuse.command import contextlib import functools +import io import json import llfuse import logging +import mock import os -import run_test_server +from . import run_test_server import sys import tempfile import unittest +import resource def noexit(func): """If argparse or arvados_fuse tries to exit, fail the test instead""" - class SystemExitCaught(StandardError): + class SystemExitCaught(Exception): pass @functools.wraps(func) def wrapper(*args, **kwargs): @@ -26,11 +36,12 @@ def noexit(func): @contextlib.contextmanager def nostderr(): - orig, sys.stderr = sys.stderr, open(os.devnull, 'w') - try: - yield - finally: - sys.stderr = orig + with open(os.devnull, 'w') as dn: + orig, sys.stderr = sys.stderr, dn + try: + yield + finally: + sys.stderr = orig class MountArgsTest(unittest.TestCase): @@ -47,6 +58,14 @@ class MountArgsTest(unittest.TestCase): ent = ent[p] return ent + @contextlib.contextmanager + def stderrMatches(self, stderr): + orig, sys.stderr = sys.stderr, stderr + try: + yield + finally: + sys.stderr = orig + def check_ent_type(self, cls, *path): ent = self.lookup(self.mnt, *path) self.assertEqual(ent.__class__, cls) @@ -64,14 +83,14 @@ class MountArgsTest(unittest.TestCase): 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$') + readme = e.readfrom(0, -1).decode() + assertRegex(self, readme, r'active-user@arvados\.local') + assertRegex(self, 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$') + txt = e.readfrom(0, -1).decode() + assertRegex(self, txt, r'portable data hash') + assertRegex(self, txt, r'\n$') @noexit def test_by_id(self): @@ -82,6 +101,7 @@ class MountArgsTest(unittest.TestCase): self.mnt = arvados_fuse.command.Mount(args) e = self.check_ent_type(arvados_fuse.MagicDirectory) self.assertEqual(e.pdh_only, False) + self.assertEqual(True, self.mnt.listen_for_events) @noexit def test_by_pdh(self): @@ -92,6 +112,7 @@ class MountArgsTest(unittest.TestCase): self.mnt = arvados_fuse.command.Mount(args) e = self.check_ent_type(arvados_fuse.MagicDirectory) self.assertEqual(e.pdh_only, True) + self.assertEqual(False, self.mnt.listen_for_events) @noexit def test_by_tag(self): @@ -101,6 +122,7 @@ class MountArgsTest(unittest.TestCase): self.assertEqual(args.mode, 'by_tag') self.mnt = arvados_fuse.command.Mount(args) e = self.check_ent_type(arvados_fuse.TagsDirectory) + self.assertEqual(True, self.mnt.listen_for_events) @noexit def test_collection(self, id_type='uuid'): @@ -112,6 +134,7 @@ class MountArgsTest(unittest.TestCase): self.mnt = arvados_fuse.command.Mount(args) e = self.check_ent_type(arvados_fuse.CollectionDirectory) self.assertEqual(e.collection_locator, cid) + self.assertEqual(id_type == 'uuid', self.mnt.listen_for_events) def test_collection_pdh(self): self.test_collection('portable_data_hash') @@ -126,6 +149,7 @@ class MountArgsTest(unittest.TestCase): e = self.check_ent_type(arvados_fuse.ProjectDirectory) self.assertEqual(e.project_object['uuid'], run_test_server.fixture('users')['active']['uuid']) + self.assertEqual(True, self.mnt.listen_for_events) def test_mutually_exclusive_args(self): cid = run_test_server.fixture('collections')['public_text_file']['uuid'] @@ -162,9 +186,41 @@ class MountArgsTest(unittest.TestCase): e = self.check_ent_type(arvados_fuse.SharedDirectory) self.assertEqual(e.current_user['uuid'], run_test_server.fixture('users')['active']['uuid']) + self.assertEqual(True, self.mnt.listen_for_events) + + def test_version_argument(self): + # The argparse version action prints to stderr in Python 2 and stdout + # in Python 3.4 and up. Write both to the same stream so the test can pass + # in both cases. + origerr = sys.stderr + origout = sys.stdout + sys.stderr = io.StringIO() + sys.stdout = sys.stderr + + with self.assertRaises(SystemExit): + args = arvados_fuse.command.ArgumentParser().parse_args(['--version']) + assertRegex(self, sys.stdout.getvalue(), "[0-9]+\.[0-9]+\.[0-9]+") + sys.stderr.close() + sys.stderr = origerr + sys.stdout = origout + + @noexit + @mock.patch('arvados.events.subscribe') + def test_disable_event_listening(self, mock_subscribe): + args = arvados_fuse.command.ArgumentParser().parse_args([ + '--disable-event-listening', + '--by-id', + '--foreground', self.mntdir]) + self.mnt = arvados_fuse.command.Mount(args) + self.assertEqual(True, self.mnt.listen_for_events) + self.assertEqual(True, self.mnt.args.disable_event_listening) + with self.mnt: + pass + self.assertEqual(0, mock_subscribe.call_count) @noexit - def test_custom(self): + @mock.patch('arvados.events.subscribe') + def test_custom(self, mock_subscribe): args = arvados_fuse.command.ArgumentParser().parse_args([ '--mount-tmp', 'foo', '--mount-tmp', 'bar', @@ -178,6 +234,24 @@ class MountArgsTest(unittest.TestCase): e = self.check_ent_type(arvados_fuse.ProjectDirectory, 'my_home') self.assertEqual(e.project_object['uuid'], run_test_server.fixture('users')['active']['uuid']) + self.assertEqual(True, self.mnt.listen_for_events) + with self.mnt: + pass + self.assertEqual(1, mock_subscribe.call_count) + + @noexit + @mock.patch('arvados.events.subscribe') + def test_custom_no_listen(self, mock_subscribe): + args = arvados_fuse.command.ArgumentParser().parse_args([ + '--mount-by-pdh', 'pdh', + '--mount-tmp', 'foo', + '--mount-tmp', 'bar', + '--foreground', self.mntdir]) + self.mnt = arvados_fuse.command.Mount(args) + self.assertEqual(False, self.mnt.listen_for_events) + with self.mnt: + pass + self.assertEqual(0, mock_subscribe.call_count) def test_custom_unsupported_layouts(self): for name in ['.', '..', '', 'foo/bar', '/foo']: @@ -188,6 +262,50 @@ class MountArgsTest(unittest.TestCase): '--foreground', self.mntdir]) arvados_fuse.command.Mount(args) + @noexit + @mock.patch('resource.setrlimit') + @mock.patch('resource.getrlimit') + def test_default_file_cache(self, getrlimit, setrlimit): + args = arvados_fuse.command.ArgumentParser().parse_args([ + '--foreground', self.mntdir]) + self.assertEqual(args.mode, None) + getrlimit.return_value = (1024, 1048576) + self.mnt = arvados_fuse.command.Mount(args) + setrlimit.assert_called_with(resource.RLIMIT_NOFILE, (10240, 1048576)) + + @noexit + @mock.patch('resource.setrlimit') + @mock.patch('resource.getrlimit') + def test_small_file_cache(self, getrlimit, setrlimit): + args = arvados_fuse.command.ArgumentParser().parse_args([ + '--foreground', '--file-cache=256000000', self.mntdir]) + self.assertEqual(args.mode, None) + getrlimit.return_value = (1024, 1048576) + self.mnt = arvados_fuse.command.Mount(args) + setrlimit.assert_not_called() + + @noexit + @mock.patch('resource.setrlimit') + @mock.patch('resource.getrlimit') + def test_large_file_cache(self, getrlimit, setrlimit): + args = arvados_fuse.command.ArgumentParser().parse_args([ + '--foreground', '--file-cache=256000000000', self.mntdir]) + self.assertEqual(args.mode, None) + getrlimit.return_value = (1024, 1048576) + self.mnt = arvados_fuse.command.Mount(args) + setrlimit.assert_called_with(resource.RLIMIT_NOFILE, (30517, 1048576)) + + @noexit + @mock.patch('resource.setrlimit') + @mock.patch('resource.getrlimit') + def test_file_cache_hard_limit(self, getrlimit, setrlimit): + args = arvados_fuse.command.ArgumentParser().parse_args([ + '--foreground', '--file-cache=256000000000', self.mntdir]) + self.assertEqual(args.mode, None) + getrlimit.return_value = (1024, 2048) + self.mnt = arvados_fuse.command.Mount(args) + setrlimit.assert_called_with(resource.RLIMIT_NOFILE, (2048, 2048)) + class MountErrorTest(unittest.TestCase): def setUp(self): self.mntdir = tempfile.mkdtemp() @@ -205,21 +323,31 @@ class MountErrorTest(unittest.TestCase): def test_no_token(self): del arvados.config._settings["ARVADOS_API_TOKEN"] arvados.config._settings = {} - with self.assertRaises(SystemExit): + with self.assertRaises(SystemExit) as ex: args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir]) arvados_fuse.command.Mount(args, logger=self.logger).run() + self.assertEqual(1, ex.exception.code) def test_no_host(self): del arvados.config._settings["ARVADOS_API_HOST"] - with self.assertRaises(SystemExit): + with self.assertRaises(SystemExit) as ex: args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir]) arvados_fuse.command.Mount(args, logger=self.logger).run() + self.assertEqual(1, ex.exception.code) def test_bogus_host(self): - arvados.config._settings["ARVADOS_API_HOST"] = "example.null" - with self.assertRaises(SystemExit): + arvados.config._settings["ARVADOS_API_HOST"] = "100::" + with self.assertRaises(SystemExit) as ex, mock.patch('time.sleep'): args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir]) arvados_fuse.command.Mount(args, logger=self.logger).run() + self.assertEqual(1, ex.exception.code) + + def test_bogus_token(self): + arvados.config._settings["ARVADOS_API_TOKEN"] = "zzzzzzzzzzzzz" + with self.assertRaises(SystemExit) as ex: + args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir]) + arvados_fuse.command.Mount(args, logger=self.logger).run() + self.assertEqual(1, ex.exception.code) def test_bogus_mount_dir(self): # All FUSE errors in llfuse.init() are raised as RuntimeError @@ -234,18 +362,21 @@ class MountErrorTest(unittest.TestCase): # The user specified --allow-other but user_allow_other is not set # in /etc/fuse.conf os.rmdir(self.mntdir) - with self.assertRaises(SystemExit): + with self.assertRaises(SystemExit) as ex: args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir]) arvados_fuse.command.Mount(args, logger=self.logger).run() + self.assertEqual(1, ex.exception.code) def test_unreadable_collection(self): - with self.assertRaises(SystemExit): + with self.assertRaises(SystemExit) as ex: args = arvados_fuse.command.ArgumentParser().parse_args([ "--collection", "zzzzz-4zz18-zzzzzzzzzzzzzzz", self.mntdir]) arvados_fuse.command.Mount(args, logger=self.logger).run() + self.assertEqual(1, ex.exception.code) def test_unreadable_project(self): - with self.assertRaises(SystemExit): + with self.assertRaises(SystemExit) as ex: args = arvados_fuse.command.ArgumentParser().parse_args([ "--project", "zzzzz-j7d0g-zzzzzzzzzzzzzzz", self.mntdir]) arvados_fuse.command.Mount(args, logger=self.logger).run() + self.assertEqual(1, ex.exception.code)