| import contextlib |
| import os |
| import sys |
| |
| if sys.version_info[:2] == (2, 6): # pragma: no cover |
| import unittest2 as unittest |
| else: # pragma: no cover |
| import unittest |
| |
| from waitress import runner |
| |
| |
| class Test_match(unittest.TestCase): |
| def test_empty(self): |
| self.assertRaisesRegex( |
| ValueError, "^Malformed application ''$", runner.match, "" |
| ) |
| |
| def test_module_only(self): |
| self.assertRaisesRegex( |
| ValueError, r"^Malformed application 'foo\.bar'$", runner.match, "foo.bar" |
| ) |
| |
| def test_bad_module(self): |
| self.assertRaisesRegex( |
| ValueError, |
| r"^Malformed application 'foo#bar:barney'$", |
| runner.match, |
| "foo#bar:barney", |
| ) |
| |
| def test_module_obj(self): |
| self.assertTupleEqual( |
| runner.match("foo.bar:fred.barney"), ("foo.bar", "fred.barney") |
| ) |
| |
| |
| class Test_resolve(unittest.TestCase): |
| def test_bad_module(self): |
| self.assertRaises( |
| ImportError, runner.resolve, "nonexistent", "nonexistent_function" |
| ) |
| |
| def test_nonexistent_function(self): |
| self.assertRaisesRegex( |
| AttributeError, |
| r"has no attribute 'nonexistent_function'", |
| runner.resolve, |
| "os.path", |
| "nonexistent_function", |
| ) |
| |
| def test_simple_happy_path(self): |
| from os.path import exists |
| |
| self.assertIs(runner.resolve("os.path", "exists"), exists) |
| |
| def test_complex_happy_path(self): |
| # Ensure we can recursively resolve object attributes if necessary. |
| self.assertEqual(runner.resolve("os.path", "exists.__name__"), "exists") |
| |
| |
| class Test_run(unittest.TestCase): |
| def match_output(self, argv, code, regex): |
| argv = ["waitress-serve"] + argv |
| with capture() as captured: |
| self.assertEqual(runner.run(argv=argv), code) |
| self.assertRegex(captured.getvalue(), regex) |
| captured.close() |
| |
| def test_bad(self): |
| self.match_output(["--bad-opt"], 1, "^Error: option --bad-opt not recognized") |
| |
| def test_help(self): |
| self.match_output(["--help"], 0, "^Usage:\n\n waitress-serve") |
| |
| def test_no_app(self): |
| self.match_output([], 1, "^Error: Specify one application only") |
| |
| def test_multiple_apps_app(self): |
| self.match_output(["a:a", "b:b"], 1, "^Error: Specify one application only") |
| |
| def test_bad_apps_app(self): |
| self.match_output(["a"], 1, "^Error: Malformed application 'a'") |
| |
| def test_bad_app_module(self): |
| self.match_output(["nonexistent:a"], 1, "^Error: Bad module 'nonexistent'") |
| |
| self.match_output( |
| ["nonexistent:a"], |
| 1, |
| ( |
| r"There was an exception \((ImportError|ModuleNotFoundError)\) " |
| "importing your module.\n\nIt had these arguments: \n" |
| "1. No module named '?nonexistent'?" |
| ), |
| ) |
| |
| def test_cwd_added_to_path(self): |
| def null_serve(app, **kw): |
| pass |
| |
| sys_path = sys.path |
| current_dir = os.getcwd() |
| try: |
| os.chdir(os.path.dirname(__file__)) |
| argv = [ |
| "waitress-serve", |
| "fixtureapps.runner:app", |
| ] |
| self.assertEqual(runner.run(argv=argv, _serve=null_serve), 0) |
| finally: |
| sys.path = sys_path |
| os.chdir(current_dir) |
| |
| def test_bad_app_object(self): |
| self.match_output( |
| ["tests.fixtureapps.runner:a"], 1, "^Error: Bad object name 'a'" |
| ) |
| |
| def test_simple_call(self): |
| from tests.fixtureapps import runner as _apps |
| |
| def check_server(app, **kw): |
| self.assertIs(app, _apps.app) |
| self.assertDictEqual(kw, {"port": "80"}) |
| |
| argv = [ |
| "waitress-serve", |
| "--port=80", |
| "tests.fixtureapps.runner:app", |
| ] |
| self.assertEqual(runner.run(argv=argv, _serve=check_server), 0) |
| |
| def test_returned_app(self): |
| from tests.fixtureapps import runner as _apps |
| |
| def check_server(app, **kw): |
| self.assertIs(app, _apps.app) |
| self.assertDictEqual(kw, {"port": "80"}) |
| |
| argv = [ |
| "waitress-serve", |
| "--port=80", |
| "--call", |
| "tests.fixtureapps.runner:returns_app", |
| ] |
| self.assertEqual(runner.run(argv=argv, _serve=check_server), 0) |
| |
| |
| class Test_helper(unittest.TestCase): |
| def test_exception_logging(self): |
| from waitress.runner import show_exception |
| |
| regex = ( |
| r"There was an exception \(ImportError\) importing your module." |
| r"\n\nIt had these arguments: \n1. My reason" |
| ) |
| |
| with capture() as captured: |
| try: |
| raise ImportError("My reason") |
| except ImportError: |
| self.assertEqual(show_exception(sys.stderr), None) |
| self.assertRegex(captured.getvalue(), regex) |
| captured.close() |
| |
| regex = ( |
| r"There was an exception \(ImportError\) importing your module." |
| r"\n\nIt had no arguments." |
| ) |
| |
| with capture() as captured: |
| try: |
| raise ImportError |
| except ImportError: |
| self.assertEqual(show_exception(sys.stderr), None) |
| self.assertRegex(captured.getvalue(), regex) |
| captured.close() |
| |
| |
| @contextlib.contextmanager |
| def capture(): |
| from io import StringIO |
| |
| fd = StringIO() |
| sys.stdout = fd |
| sys.stderr = fd |
| yield fd |
| sys.stdout = sys.__stdout__ |
| sys.stderr = sys.__stderr__ |