summaryrefslogtreecommitdiff
path: root/src/mailman/commands/tests/test_cli_shell.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/commands/tests/test_cli_shell.py')
-rw-r--r--src/mailman/commands/tests/test_cli_shell.py173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/mailman/commands/tests/test_cli_shell.py b/src/mailman/commands/tests/test_cli_shell.py
new file mode 100644
index 000000000..ffcf43803
--- /dev/null
+++ b/src/mailman/commands/tests/test_cli_shell.py
@@ -0,0 +1,173 @@
+# Copyright (C) 2016-2017 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Test the withlist/shell command."""
+
+import os
+import unittest
+
+from click.testing import CliRunner
+from contextlib import ExitStack
+from mailman.app.lifecycle import create_list
+from mailman.commands.cli_withlist import shell
+from mailman.config import config
+from mailman.interfaces.usermanager import IUserManager
+from mailman.testing.helpers import configuration
+from mailman.testing.layers import ConfigLayer
+from mailman.utilities.modules import hacked_sys_modules
+from unittest.mock import MagicMock, patch
+
+try:
+ import readline # noqa: F401
+ has_readline = True
+except ImportError:
+ has_readline = False
+
+
+class TestShell(unittest.TestCase):
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._command = CliRunner()
+
+ def test_namespace(self):
+ with patch('mailman.commands.cli_withlist.start_python') as mock:
+ self._command.invoke(shell, ('--interactive',))
+ self.assertEqual(mock.call_count, 1)
+ # Don't test that all names are available, just a few choice ones.
+ positional, keywords = mock.call_args
+ namespace = positional[0]
+ self.assertIn('getUtility', namespace)
+ self.assertIn('IArchiver', namespace)
+ self.assertEqual(namespace['IUserManager'], IUserManager)
+
+ @configuration('shell', banner='my banner')
+ def test_banner(self):
+ with patch('mailman.commands.cli_withlist.interact') as mock:
+ self._command.invoke(shell, ('--interactive',))
+ self.assertEqual(mock.call_count, 1)
+ positional, keywords = mock.call_args
+ self.assertEqual(keywords['banner'], 'my banner\n')
+
+ @unittest.skipUnless(has_readline, 'readline module is not available')
+ @configuration('shell', history_file='$var_dir/history.py')
+ def test_history_file(self):
+ with patch('mailman.commands.cli_withlist.interact'):
+ self._command.invoke(shell, ('--interactive',))
+ history_file = os.path.join(config.VAR_DIR, 'history.py')
+ self.assertTrue(os.path.exists(history_file))
+
+ @configuration('shell', use_ipython='yes')
+ def test_start_ipython4(self):
+ mock = MagicMock()
+ with hacked_sys_modules('IPython.terminal.embed', mock):
+ self._command.invoke(shell, ('--interactive',))
+ posargs, kws = mock.InteractiveShellEmbed.instance().mainloop.call_args
+ self.assertEqual(
+ kws['display_banner'], 'Welcome to the GNU Mailman shell\n')
+
+ @configuration('shell', use_ipython='yes')
+ def test_start_ipython1(self):
+ mock = MagicMock()
+ with hacked_sys_modules('IPython.frontend.terminal.embed', mock):
+ self._command.invoke(shell, ('--interactive',))
+ posargs, kws = mock.InteractiveShellEmbed.instance.call_args
+ self.assertEqual(
+ kws['banner1'], 'Welcome to the GNU Mailman shell\n')
+
+ @configuration('shell', use_ipython='debug')
+ def test_start_ipython_debug(self):
+ mock = MagicMock()
+ with hacked_sys_modules('IPython.terminal.embed', mock):
+ self._command.invoke(shell, ('--interactive',))
+ posargs, kws = mock.InteractiveShellEmbed.instance().mainloop.call_args
+ self.assertEqual(
+ kws['display_banner'], 'Welcome to the GNU Mailman shell\n')
+
+ @configuration('shell', use_ipython='oops')
+ def test_start_ipython_invalid(self):
+ mock = MagicMock()
+ with hacked_sys_modules('IPython.terminal.embed', mock):
+ results = self._command.invoke(shell, ('--interactive',))
+ self.assertEqual(
+ results.output,
+ 'Invalid value for [shell]use_python: oops\n')
+ # mainloop() never got called.
+ self.assertIsNone(
+ mock.InteractiveShellEmbed.instance().mainloop.call_args)
+
+ @configuration('shell', use_ipython='yes')
+ def test_start_ipython_uninstalled(self):
+ with ExitStack() as resources:
+ # Pretend iPython isn't available at all.
+ resources.enter_context(patch(
+ 'mailman.commands.cli_withlist.start_ipython1',
+ return_value=None))
+ resources.enter_context(patch(
+ 'mailman.commands.cli_withlist.start_ipython4',
+ return_value=None))
+ results = self._command.invoke(shell, ('--interactive',))
+ self.assertEqual(
+ results.output,
+ 'ipython is not available, set use_ipython to no\n')
+
+ def test_regex_without_run(self):
+ results = self._command.invoke(shell, ('-l', '^.*example.com'))
+ self.assertEqual(results.exit_code, 2)
+ self.assertEqual(
+ results.output,
+ 'Usage: shell [OPTIONS] [RUN_ARGS]...\n\n'
+ 'Error: Regular expression requires --run\n')
+
+ def test_listspec_without_run(self):
+ create_list('ant@example.com')
+ mock = MagicMock()
+ with ExitStack() as resources:
+ resources.enter_context(
+ hacked_sys_modules('IPython.terminal.embed', mock))
+ interactive_mock = resources.enter_context(patch(
+ 'mailman.commands.cli_withlist.do_interactive'))
+ self._command.invoke(shell, ('-l', 'ant.example.com'))
+ posargs, kws = interactive_mock.call_args
+ self.assertEqual(
+ posargs[1],
+ "The variable 'm' is the ant.example.com mailing list")
+
+ def test_listspec_without_run_no_such_list(self):
+ results = self._command.invoke(shell, ('-l', 'ant.example.com'))
+ self.assertEqual(results.exit_code, 2)
+ self.assertEqual(
+ results.output,
+ 'Usage: shell [OPTIONS] [RUN_ARGS]...\n\n'
+ 'Error: No such list: ant.example.com\n')
+
+ def test_run_without_listspec(self):
+ results = self._command.invoke(shell, ('--run', 'something'))
+ self.assertEqual(results.exit_code, 2)
+ self.assertEqual(
+ results.output,
+ 'Usage: shell [OPTIONS] [RUN_ARGS]...\n\n'
+ 'Error: --run requires a mailing list\n')
+
+ def test_run_bogus_listspec(self):
+ results = self._command.invoke(
+ shell, ('-l', 'bee.example.com', '--run', 'something'))
+ self.assertEqual(results.exit_code, 2)
+ self.assertEqual(
+ results.output,
+ 'Usage: shell [OPTIONS] [RUN_ARGS]...\n\n'
+ 'Error: No such list: bee.example.com\n')