From 10738c3fe22d2c46669630e55e465c5c8a84c77c Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Thu, 20 Aug 2020 15:53:20 +0100 Subject: Tests: default tmpfs in rootfs. --- test/test_go_isolation.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'test') diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index 61d39617..76434f62 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -327,6 +327,26 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson(url='/?file=/bin/sh')['body'] self.assertEqual(obj['FileExists'], False, 'file should not exists') + def test_go_isolation_rootfs_default_tmpfs(self): + if not self.isolation_key('unprivileged_userns_clone'): + print('unprivileged clone is not available') + raise unittest.SkipTest() + + if not self.isolation_key('mnt'): + print('mnt namespace is not supported') + raise unittest.SkipTest() + + isolation = { + 'namespaces': {'mount': True, 'credential': True}, + 'rootfs': self.testdir, + } + + self.load('ns_inspect', isolation=isolation) + + obj = self.getjson(url='/?file=/tmp')['body'] + + self.assertEqual(obj['FileExists'], True, 'app has /tmp') + if __name__ == '__main__': TestGoIsolation.main() -- cgit From 244ffb2829cfbac26e013988474184d6050504fe Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Tue, 25 Aug 2020 13:48:33 +0100 Subject: Tests: PHP extension mounts. --- test/php/list-extensions/index.php | 11 ++++++++ test/php/list-extensions/php.ini | 1 + test/test_php_isolation.py | 54 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 test/php/list-extensions/index.php create mode 100644 test/php/list-extensions/php.ini (limited to 'test') diff --git a/test/php/list-extensions/index.php b/test/php/list-extensions/index.php new file mode 100644 index 00000000..d6eb40d0 --- /dev/null +++ b/test/php/list-extensions/index.php @@ -0,0 +1,11 @@ + diff --git a/test/php/list-extensions/php.ini b/test/php/list-extensions/php.ini new file mode 100644 index 00000000..5848a0f2 --- /dev/null +++ b/test/php/list-extensions/php.ini @@ -0,0 +1 @@ +extension=json.so diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index 1b70ef02..abaf70a2 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -52,6 +52,60 @@ class TestPHPIsolation(TestApplicationPHP): self.assertEqual(self.get()['status'], 200, 'empty rootfs') + def test_php_isolation_rootfs_extensions(self): + isolation_features = self.available['features']['isolation'].keys() + + if not self.is_su: + if 'user' not in isolation_features: + print('requires unprivileged userns or root') + raise unittest.SkipTest() + + if not 'unprivileged_userns_clone' in isolation_features: + print('requires unprivileged userns or root') + raise unittest.SkipTest() + + if 'mnt' not in isolation_features: + print('requires mnt ns') + raise unittest.SkipTest() + + isolation = { + 'rootfs': self.current_dir, + 'namespaces': { + 'credential': not self.is_su, + 'mount': not self.is_su, + }, + } + + self.load('list-extensions', isolation=isolation) + + self.assertIn( + 'success', + self.conf( + '"/php/list-extensions"', 'applications/list-extensions/root' + ), + ) + + self.assertIn( + 'success', + self.conf( + {'file': '/php/list-extensions/php.ini'}, + 'applications/list-extensions/options', + ), + ) + + self.assertIn( + 'success', + self.conf( + '"/php/list-extensions"', + 'applications/list-extensions/working_directory', + ), + ) + + extensions = self.getjson()['body'] + + self.assertIn('json', extensions, 'json in extensions list') + self.assertIn('unit', extensions, 'unit in extensions list') + if __name__ == '__main__': TestPHPIsolation.main() -- cgit From d1bdaf98ba15cdba62e1f2ecb83c37e08728682c Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Tue, 25 Aug 2020 15:27:51 +0100 Subject: Tests: disable of language_deps. --- test/test_php_isolation.py | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'test') diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index abaf70a2..3004a7b8 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -107,5 +107,74 @@ class TestPHPIsolation(TestApplicationPHP): self.assertIn('unit', extensions, 'unit in extensions list') + def test_php_isolation_rootfs_no_language_libs(self): + isolation_features = self.available['features']['isolation'].keys() + + if not self.is_su: + if 'user' not in isolation_features: + print('requires unprivileged userns or root') + raise unittest.SkipTest() + + if not 'unprivileged_userns_clone' in isolation_features: + print('requires unprivileged userns or root') + raise unittest.SkipTest() + + if 'mnt' not in isolation_features: + print('requires mnt ns') + raise unittest.SkipTest() + + isolation = { + 'rootfs': self.current_dir, + 'automount': {'language_deps': False}, + 'namespaces': { + 'credential': not self.is_su, + 'mount': not self.is_su, + }, + } + + self.load('list-extensions', isolation=isolation) + + self.assertIn( + 'success', + self.conf( + '"/php/list-extensions"', 'applications/list-extensions/root' + ), + ) + + self.assertIn( + 'success', + self.conf( + {'file': '/php/list-extensions/php.ini'}, + 'applications/list-extensions/options', + ), + ) + + self.assertIn( + 'success', + self.conf( + '"/php/list-extensions"', + 'applications/list-extensions/working_directory', + ), + ) + + extensions = self.getjson()['body'] + + self.assertIn('unit', extensions, 'unit in extensions list') + self.assertNotIn('json', extensions, 'json not in extensions list') + + self.assertIn( + 'success', + self.conf( + {'language_deps': True}, + 'applications/list-extensions/isolation/automount', + ), + ) + + extensions = self.getjson()['body'] + + self.assertIn('unit', extensions, 'unit in extensions list 2') + self.assertIn('json', extensions, 'json in extensions list 2') + + if __name__ == '__main__': TestPHPIsolation.main() -- cgit From df374057f7a42808d9482a8cac82111f24a104fa Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 31 Aug 2020 03:14:02 +0100 Subject: Tests: $host varaible test. Also added few tests for $uri and minor style fixes. --- test/test_variables.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/test/test_variables.py b/test/test_variables.py index 805c5144..fb481be5 100644 --- a/test/test_variables.py +++ b/test/test_variables.py @@ -16,10 +16,11 @@ class TestVariables(TestApplicationProto): "GET": [{"action": {"return": 201}}], "POST": [{"action": {"return": 202}}], "3": [{"action": {"return": 203}}], - "4": [{"action": {"return": 204}}], + "4*": [{"action": {"return": 204}}], "blahGET}": [{"action": {"return": 205}}], "5GET": [{"action": {"return": 206}}], "GETGET": [{"action": {"return": 207}}], + "localhost": [{"action": {"return": 208}}], }, }, ), @@ -27,10 +28,7 @@ class TestVariables(TestApplicationProto): ) def conf_routes(self, routes): - self.assertIn( - 'success', - self.conf(routes, 'listeners/*:7080/pass') - ) + self.assertIn('success', self.conf(routes, 'listeners/*:7080/pass')) def test_variables_method(self): self.assertEqual(self.get()['status'], 201, 'method GET') @@ -40,7 +38,26 @@ class TestVariables(TestApplicationProto): self.conf_routes("\"routes$uri\"") self.assertEqual(self.get(url='/3')['status'], 203, 'uri') - self.assertEqual(self.get(url='/4')['status'], 204, 'uri 2') + self.assertEqual(self.get(url='/4*')['status'], 204, 'uri 2') + self.assertEqual(self.get(url='/4%2A')['status'], 204, 'uri 3') + + def test_variables_host(self): + self.conf_routes("\"routes/$host\"") + + def check_host(host, status=208): + self.assertEqual( + self.get(headers={'Host': host, 'Connection': 'close'})[ + 'status' + ], + status, + ) + + check_host('localhost') + check_host('localhost.') + check_host('localhost:7080') + check_host('.localhost', 404) + check_host('www.localhost', 404) + check_host('localhost1', 404) def test_variables_many(self): self.conf_routes("\"routes$uri$method\"") @@ -69,7 +86,7 @@ class TestVariables(TestApplicationProto): self.assertEqual(self.post()['status'], 202) self.conf_routes("\"routes${uri}\"") - self.assertEqual(self.get(url='/4')['status'], 204) + self.assertEqual(self.get(url='/4*')['status'], 204) self.conf_routes("\"routes/blah$method}\"") self.assertEqual(self.get()['status'], 205) -- cgit From d5e915934066c77a59d211efafca10c117b73d05 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 16 Sep 2020 21:31:15 +0100 Subject: Tests: migrated to the pytest. --- test/conftest.py | 299 ++++++ test/run.py | 19 - test/test_access_log.py | 160 ++- test/test_configuration.py | 418 +++----- test/test_go_application.py | 113 +- test/test_go_isolation.py | 175 ++- test/test_go_isolation_rootfs.py | 22 +- test/test_http_header.py | 294 +++--- test/test_java_application.py | 1311 ++++++++++------------- test/test_java_isolation_rootfs.py | 61 +- test/test_java_websockets.py | 225 ++-- test/test_node_application.py | 251 ++--- test/test_node_websockets.py | 227 ++-- test/test_perl_application.py | 189 ++-- test/test_php_application.py | 495 ++++----- test/test_php_basic.py | 150 +-- test/test_php_isolation.py | 154 +-- test/test_php_targets.py | 192 ++-- test/test_proxy.py | 417 +++----- test/test_proxy_chunked.py | 135 ++- test/test_python_application.py | 514 ++++----- test/test_python_basic.py | 154 +-- test/test_python_environment.py | 108 +- test/test_python_isolation.py | 76 +- test/test_python_isolation_chroot.py | 62 +- test/test_python_procman.py | 136 +-- test/test_respawn.py | 45 +- test/test_return.py | 140 ++- test/test_routing.py | 1877 ++++++++++++++------------------- test/test_routing_tls.py | 48 +- test/test_ruby_application.py | 275 +++-- test/test_ruby_isolation.py | 54 +- test/test_settings.py | 61 +- test/test_share_fallback.py | 125 +-- test/test_static.py | 529 ++++------ test/test_tls.py | 398 ++++--- test/test_upstreams_rr.py | 594 +++++------ test/test_usr1.py | 76 +- test/test_variables.py | 89 +- test/unit/applications/lang/go.py | 23 +- test/unit/applications/lang/java.py | 10 +- test/unit/applications/lang/node.py | 13 +- test/unit/applications/lang/perl.py | 3 +- test/unit/applications/lang/php.py | 3 +- test/unit/applications/lang/python.py | 12 +- test/unit/applications/lang/ruby.py | 3 +- test/unit/applications/proto.py | 18 +- test/unit/applications/tls.py | 23 +- test/unit/applications/websockets.py | 14 +- test/unit/control.py | 2 +- test/unit/feature/isolation.py | 4 +- test/unit/http.py | 32 +- test/unit/main.py | 269 +---- 53 files changed, 4776 insertions(+), 6321 deletions(-) create mode 100644 test/conftest.py delete mode 100755 test/run.py (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 00000000..8683a023 --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,299 @@ +import fcntl +import os +import platform +import pytest +import signal +import stat +import subprocess +import sys +import re +import tempfile +import time + + +def pytest_addoption(parser): + parser.addoption( + "--detailed", + default=False, + action="store_true", + help="Detailed output for tests", + ) + parser.addoption( + "--print_log", + default=False, + action="store_true", + help="Print unit.log to stdout in case of errors", + ) + parser.addoption( + "--save_log", + default=False, + action="store_true", + help="Save unit.log after the test execution", + ) + parser.addoption( + "--unsafe", + default=False, + action="store_true", + help="Run unsafe tests", + ) + + +unit_instance = {} +option = None + + +def pytest_configure(config): + global option + option = config.option + + option.generated_tests = {} + option.current_dir = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.pardir) + ) + option.test_dir = option.current_dir + '/test' + option.architecture = platform.architecture()[0] + option.system = platform.system() + + # set stdout to non-blocking + + if option.detailed or option.print_log: + fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, 0) + + +def pytest_generate_tests(metafunc): + cls = metafunc.cls + if not hasattr(cls, 'application_type'): + return + + type = cls.application_type + + # take available module from option and generate tests for each version + + for module in cls.prerequisites['modules']: + if module in option.available['modules']: + prereq_version = cls.prerequisites['modules'][module] + available_versions = option.available['modules'][module] + + if prereq_version == 'all': + metafunc.fixturenames.append('tmp_ct') + metafunc.parametrize('tmp_ct', range(len(available_versions))) + + for i in range(len(available_versions)): + version = available_versions[i] + option.generated_tests[ + metafunc.function.__name__ + '[{}]'.format(i) + ] = (type + ' ' + version) + elif prereq_version == 'any': + option.generated_tests[metafunc.function.__name__] = ( + type + ' ' + available_versions[0] + ) + else: + for version in available_versions: + if version.startswith(prereq_version): + option.generated_tests[metafunc.function.__name__] = ( + type + ' ' + version + ) + + +def pytest_sessionstart(session): + option.available = {'modules': {}, 'features': {}} + + unit = unit_run() + + # read unit.log + + for i in range(50): + with open(unit['temp_dir'] + '/unit.log', 'r') as f: + log = f.read() + m = re.search('controller started', log) + + if m is None: + time.sleep(0.1) + else: + break + + if m is None: + _print_log() + exit("Unit is writing log too long") + + # discover available modules from unit.log + + for module in re.findall(r'module: ([a-zA-Z]+) (.*) ".*"$', log, re.M): + if module[0] not in option.available['modules']: + option.available['modules'][module[0]] = [module[1]] + else: + option.available['modules'][module[0]].append(module[1]) + + unit_stop() + + +def setup_method(self): + option.skip_alerts = [ + r'read signalfd\(4\) failed', + r'sendmsg.+failed', + r'recvmsg.+failed', + ] + option.skip_sanitizer = False + +def unit_run(): + global unit_instance + build_dir = option.current_dir + '/build' + unitd = build_dir + '/unitd' + + if not os.path.isfile(unitd): + exit('Could not find unit') + + temp_dir = tempfile.mkdtemp(prefix='unit-test-') + public_dir(temp_dir) + + if oct(stat.S_IMODE(os.stat(build_dir).st_mode)) != '0o777': + public_dir(build_dir) + + os.mkdir(temp_dir + '/state') + + with open(temp_dir + '/unit.log', 'w') as log: + unit_instance['process'] = subprocess.Popen( + [ + unitd, + '--no-daemon', + '--modules', + build_dir, + '--state', + temp_dir + '/state', + '--pid', + temp_dir + '/unit.pid', + '--log', + temp_dir + '/unit.log', + '--control', + 'unix:' + temp_dir + '/control.unit.sock', + '--tmp', + temp_dir, + ], + stderr=log, + ) + + if not waitforfiles(temp_dir + '/control.unit.sock'): + _print_log() + exit('Could not start unit') + + # dumb (TODO: remove) + option.skip_alerts = [ + r'read signalfd\(4\) failed', + r'sendmsg.+failed', + r'recvmsg.+failed', + ] + option.skip_sanitizer = False + + unit_instance['temp_dir'] = temp_dir + unit_instance['log'] = temp_dir + '/unit.log' + unit_instance['control_sock'] = temp_dir + '/control.unit.sock' + unit_instance['unitd'] = unitd + + return unit_instance + + +def unit_stop(): + p = unit_instance['process'] + + if p.poll() is not None: + return + + p.send_signal(signal.SIGQUIT) + + try: + retcode = p.wait(15) + if retcode: + return 'Child process terminated with code ' + str(retcode) + except: + p.kill() + return 'Could not terminate unit' + + +def public_dir(path): + os.chmod(path, 0o777) + + for root, dirs, files in os.walk(path): + for d in dirs: + os.chmod(os.path.join(root, d), 0o777) + for f in files: + os.chmod(os.path.join(root, f), 0o777) + +def waitforfiles(*files): + for i in range(50): + wait = False + ret = False + + for f in files: + if not os.path.exists(f): + wait = True + break + + if wait: + time.sleep(0.1) + + else: + ret = True + break + + return ret + + +def skip_alert(*alerts): + option.skip_alerts.extend(alerts) + + +def _check_alerts(log): + found = False + + alerts = re.findall(r'.+\[alert\].+', log) + + if alerts: + print('All alerts/sanitizer errors found in log:') + [print(alert) for alert in alerts] + found = True + + if option.skip_alerts: + for skip in option.skip_alerts: + alerts = [al for al in alerts if re.search(skip, al) is None] + + if alerts: + _print_log(log) + assert not alerts, 'alert(s)' + + if not option.skip_sanitizer: + sanitizer_errors = re.findall('.+Sanitizer.+', log) + + if sanitizer_errors: + _print_log(log) + assert not sanitizer_errors, 'sanitizer error(s)' + + if found: + print('skipped.') + + +def _print_log(data=None): + unit_log = unit_instance['log'] + + print('Path to unit.log:\n' + unit_log + '\n') + + if option.print_log: + os.set_blocking(sys.stdout.fileno(), True) + sys.stdout.flush() + + if data is None: + with open(unit_log, 'r', encoding='utf-8', errors='ignore') as f: + shutil.copyfileobj(f, sys.stdout) + else: + sys.stdout.write(data) + + +@pytest.fixture +def is_unsafe(request): + return request.config.getoption("--unsafe") + +@pytest.fixture +def is_su(request): + return os.geteuid() == 0 + +def pytest_sessionfinish(session): + unit_stop() diff --git a/test/run.py b/test/run.py deleted file mode 100755 index 384663f9..00000000 --- a/test/run.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python3 -import os -import sys -import unittest - -if __name__ == '__main__': - loader = unittest.TestLoader() - suite = unittest.TestSuite() - - this_dir = os.path.dirname(__file__) - tests = loader.discover(start_dir=this_dir) - suite.addTests(tests) - - runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=3) - result = runner.run(suite) - - ret = not (len(result.failures) == len(result.errors) == 0) - - sys.exit(ret) diff --git a/test/test_access_log.py b/test/test_access_log.py index 3ef8f7a0..010c56c2 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -1,5 +1,5 @@ +import pytest import time -import unittest from unit.applications.lang.python import TestApplicationPython @@ -10,11 +10,9 @@ class TestAccessLog(TestApplicationPython): def load(self, script): super().load(script) - self.assertIn( - 'success', - self.conf('"' + self.testdir + '/access.log"', 'access_log'), - 'access_log configure', - ) + assert 'success' in self.conf( + '"' + self.temp_dir + '/access.log"', 'access_log' + ), 'access_log configure' def wait_for_record(self, pattern, name='access.log'): return super().wait_for_record(pattern, name) @@ -22,7 +20,7 @@ class TestAccessLog(TestApplicationPython): def test_access_log_keepalive(self): self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' (resp, sock) = self.post( headers={ @@ -35,9 +33,9 @@ class TestAccessLog(TestApplicationPython): read_timeout=1, ) - self.assertIsNotNone( - self.wait_for_record(r'"POST / HTTP/1.1" 200 5'), 'keepalive 1' - ) + assert ( + self.wait_for_record(r'"POST / HTTP/1.1" 200 5') is not None + ), 'keepalive 1' resp = self.post( headers={ @@ -51,9 +49,9 @@ class TestAccessLog(TestApplicationPython): self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"POST / HTTP/1.1" 200 10'), 'keepalive 2' - ) + assert ( + self.wait_for_record(r'"POST / HTTP/1.1" 200 10') is not None + ), 'keepalive 2' def test_access_log_pipeline(self): self.load('empty') @@ -79,18 +77,18 @@ Connection: close self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"'), - 'pipeline 1', - ) - self.assertIsNotNone( - self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-2" "-"'), - 'pipeline 2', - ) - self.assertIsNotNone( - self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-3" "-"'), - 'pipeline 3', - ) + assert ( + self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"') + is not None + ), 'pipeline 1' + assert ( + self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-2" "-"') + is not None + ), 'pipeline 2' + assert ( + self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-3" "-"') + is not None + ), 'pipeline 3' def test_access_log_ipv6(self): self.load('empty') @@ -101,17 +99,17 @@ Connection: close self.stop() - self.assertIsNotNone( + assert ( self.wait_for_record( r'::1 - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"' - ), - 'ipv6', - ) + ) + is not None + ), 'ipv6' def test_access_log_unix(self): self.load('empty') - addr = self.testdir + '/sock' + addr = self.temp_dir + '/sock' self.conf( {"unix:" + addr: {"pass": "applications/empty"}}, 'listeners' @@ -121,12 +119,12 @@ Connection: close self.stop() - self.assertIsNotNone( + assert ( self.wait_for_record( r'unix: - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"' - ), - 'unix', - ) + ) + is not None + ), 'unix' def test_access_log_referer(self): self.load('empty') @@ -141,12 +139,10 @@ Connection: close self.stop() - self.assertIsNotNone( - self.wait_for_record( - r'"GET / HTTP/1.1" 200 0 "referer-value" "-"' - ), - 'referer', - ) + assert ( + self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "referer-value" "-"') + is not None + ), 'referer' def test_access_log_user_agent(self): self.load('empty') @@ -161,12 +157,12 @@ Connection: close self.stop() - self.assertIsNotNone( + assert ( self.wait_for_record( r'"GET / HTTP/1.1" 200 0 "-" "user-agent-value"' - ), - 'user agent', - ) + ) + is not None + ), 'user agent' def test_access_log_http10(self): self.load('empty') @@ -175,14 +171,14 @@ Connection: close self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GET / HTTP/1.0" 200 0 "-" "-"'), 'http 1.0' - ) + assert ( + self.wait_for_record(r'"GET / HTTP/1.0" 200 0 "-" "-"') is not None + ), 'http 1.0' def test_access_log_partial(self): self.load('empty') - self.assertEqual(self.post()['status'], 200, 'init') + assert self.post()['status'] == 200, 'init' resp = self.http(b"""GE""", raw=True, read_timeout=1) @@ -190,27 +186,27 @@ Connection: close self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GE" 400 0 "-" "-"'), 'partial' - ) + assert ( + self.wait_for_record(r'"GE" 400 0 "-" "-"') is not None + ), 'partial' def test_access_log_partial_2(self): self.load('empty') - self.assertEqual(self.post()['status'], 200, 'init') + assert self.post()['status'] == 200, 'init' self.http(b"""GET /\n""", raw=True) self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GET /" 400 \d+ "-" "-"'), 'partial 2' - ) + assert ( + self.wait_for_record(r'"GET /" 400 \d+ "-" "-"') is not None + ), 'partial 2' def test_access_log_partial_3(self): self.load('empty') - self.assertEqual(self.post()['status'], 200, 'init') + assert self.post()['status'] == 200, 'init' resp = self.http(b"""GET / HTTP/1.1""", raw=True, read_timeout=1) @@ -218,14 +214,14 @@ Connection: close self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GET /" 400 0 "-" "-"'), 'partial 3' - ) + assert ( + self.wait_for_record(r'"GET /" 400 0 "-" "-"') is not None + ), 'partial 3' def test_access_log_partial_4(self): self.load('empty') - self.assertEqual(self.post()['status'], 200, 'init') + assert self.post()['status'] == 200, 'init' resp = self.http(b"""GET / HTTP/1.1\n""", raw=True, read_timeout=1) @@ -233,25 +229,24 @@ Connection: close self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GET / HTTP/1.1" 400 0 "-" "-"'), - 'partial 4', - ) + assert ( + self.wait_for_record(r'"GET / HTTP/1.1" 400 0 "-" "-"') is not None + ), 'partial 4' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_access_log_partial_5(self): self.load('empty') - self.assertEqual(self.post()['status'], 200, 'init') + assert self.post()['status'] == 200, 'init' self.get(headers={'Connection': 'close'}) self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GET / HTTP/1.1" 400 \d+ "-" "-"'), - 'partial 5', - ) + assert ( + self.wait_for_record(r'"GET / HTTP/1.1" 400 \d+ "-" "-"') + is not None + ), 'partial 5' def test_access_log_get_parameters(self): self.load('empty') @@ -260,12 +255,12 @@ Connection: close self.stop() - self.assertIsNotNone( + assert ( self.wait_for_record( r'"GET /\?blah&var=val HTTP/1.1" 200 0 "-" "-"' - ), - 'get parameters', - ) + ) + is not None + ), 'get parameters' def test_access_log_delete(self): self.load('empty') @@ -276,25 +271,20 @@ Connection: close self.stop() - self.assertIsNone( - self.search_in_log(r'/delete', 'access.log'), 'delete' - ) + assert self.search_in_log(r'/delete', 'access.log') is None, 'delete' def test_access_log_change(self): self.load('empty') self.get() - self.conf('"' + self.testdir + '/new.log"', 'access_log') + self.conf('"' + self.temp_dir + '/new.log"', 'access_log') self.get() self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log'), - 'change', - ) - -if __name__ == '__main__': - TestAccessLog.main() + assert ( + self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log') + is not None + ), 'change' diff --git a/test/test_configuration.py b/test/test_configuration.py index 0b0c9c78..07b8d522 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -1,22 +1,21 @@ -import unittest +import pytest from unit.control import TestControl +from conftest import skip_alert class TestConfiguration(TestControl): prerequisites = {'modules': {'python': 'any'}} def test_json_empty(self): - self.assertIn('error', self.conf(''), 'empty') + assert 'error' in self.conf(''), 'empty' def test_json_leading_zero(self): - self.assertIn('error', self.conf('00'), 'leading zero') + assert 'error' in self.conf('00'), 'leading zero' def test_json_unicode(self): - self.assertIn( - 'success', - self.conf( - b""" + assert 'success' in self.conf( + b""" { "ap\u0070": { "type": "\u0070ython", @@ -26,50 +25,36 @@ class TestConfiguration(TestControl): } } """, - 'applications', - ), - 'unicode', - ) + 'applications', + ), 'unicode' + + assert self.conf_get('applications') == { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, 'unicode get' - self.assertDictEqual( - self.conf_get('applications'), + def test_json_unicode_2(self): + assert 'success' in self.conf( { - "app": { + "приложение": { "type": "python", "processes": {"spare": 0}, "path": "/app", "module": "wsgi", } }, - 'unicode get', - ) + 'applications', + ), 'unicode 2' - def test_json_unicode_2(self): - self.assertIn( - 'success', - self.conf( - { - "приложение": { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - 'applications', - ), - 'unicode 2', - ) - - self.assertIn( - 'приложение', self.conf_get('applications'), 'unicode 2 get' - ) + assert 'приложение' in self.conf_get('applications'), 'unicode 2 get' def test_json_unicode_number(self): - self.assertIn( - 'error', - self.conf( - b""" + assert 'error' in self.conf( + b""" { "app": { "type": "python", @@ -79,16 +64,12 @@ class TestConfiguration(TestControl): } } """, - 'applications', - ), - 'unicode number', - ) + 'applications', + ), 'unicode number' def test_json_utf8_bom(self): - self.assertIn( - 'success', - self.conf( - b"""\xEF\xBB\xBF + assert 'success' in self.conf( + b"""\xEF\xBB\xBF { "app": { "type": "python", @@ -98,16 +79,12 @@ class TestConfiguration(TestControl): } } """, - 'applications', - ), - 'UTF-8 BOM', - ) + 'applications', + ), 'UTF-8 BOM' def test_json_comment_single_line(self): - self.assertIn( - 'success', - self.conf( - b""" + assert 'success' in self.conf( + b""" // this is bridge { "//app": { @@ -121,16 +98,12 @@ class TestConfiguration(TestControl): } // end of json \xEF\t """, - 'applications', - ), - 'single line comments', - ) + 'applications', + ), 'single line comments' def test_json_comment_multi_line(self): - self.assertIn( - 'success', - self.conf( - b""" + assert 'success' in self.conf( + b""" /* this is bridge */ { "/*app": { @@ -148,41 +121,31 @@ class TestConfiguration(TestControl): } /* end of json \xEF\t\b */ """, - 'applications', - ), - 'multi line comments', - ) + 'applications', + ), 'multi line comments' def test_json_comment_invalid(self): - self.assertIn('error', self.conf(b'/{}', 'applications'), 'slash') - self.assertIn('error', self.conf(b'//{}', 'applications'), 'comment') - self.assertIn('error', self.conf(b'{} /', 'applications'), 'slash end') - self.assertIn( - 'error', self.conf(b'/*{}', 'applications'), 'slash star' - ) - self.assertIn( - 'error', self.conf(b'{} /*', 'applications'), 'slash star end' - ) + assert 'error' in self.conf(b'/{}', 'applications'), 'slash' + assert 'error' in self.conf(b'//{}', 'applications'), 'comment' + assert 'error' in self.conf(b'{} /', 'applications'), 'slash end' + assert 'error' in self.conf(b'/*{}', 'applications'), 'slash star' + assert 'error' in self.conf(b'{} /*', 'applications'), 'slash star end' def test_applications_open_brace(self): - self.assertIn('error', self.conf('{', 'applications'), 'open brace') + assert 'error' in self.conf('{', 'applications'), 'open brace' def test_applications_string(self): - self.assertIn('error', self.conf('"{}"', 'applications'), 'string') + assert 'error' in self.conf('"{}"', 'applications'), 'string' - @unittest.skip('not yet, unsafe') + @pytest.mark.skip('not yet, unsafe') def test_applications_type_only(self): - self.assertIn( - 'error', - self.conf({"app": {"type": "python"}}, 'applications'), - 'type only', - ) + assert 'error' in self.conf( + {"app": {"type": "python"}}, 'applications' + ), 'type only' def test_applications_miss_quote(self): - self.assertIn( - 'error', - self.conf( - """ + assert 'error' in self.conf( + """ { app": { "type": "python", @@ -192,16 +155,12 @@ class TestConfiguration(TestControl): } } """, - 'applications', - ), - 'miss quote', - ) + 'applications', + ), 'miss quote' def test_applications_miss_colon(self): - self.assertIn( - 'error', - self.conf( - """ + assert 'error' in self.conf( + """ { "app" { "type": "python", @@ -211,16 +170,12 @@ class TestConfiguration(TestControl): } } """, - 'applications', - ), - 'miss colon', - ) + 'applications', + ), 'miss colon' def test_applications_miss_comma(self): - self.assertIn( - 'error', - self.conf( - """ + assert 'error' in self.conf( + """ { "app": { "type": "python" @@ -230,144 +185,117 @@ class TestConfiguration(TestControl): } } """, - 'applications', - ), - 'miss comma', - ) + 'applications', + ), 'miss comma' def test_applications_skip_spaces(self): - self.assertIn( - 'success', self.conf(b'{ \n\r\t}', 'applications'), 'skip spaces' - ) + assert 'success' in self.conf( + b'{ \n\r\t}', 'applications' + ), 'skip spaces' def test_applications_relative_path(self): - self.assertIn( - 'success', - self.conf( - { - "app": { - "type": "python", - "processes": {"spare": 0}, - "path": "../app", - "module": "wsgi", - } - }, - 'applications', - ), - 'relative path', - ) + assert 'success' in self.conf( + { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "../app", + "module": "wsgi", + } + }, + 'applications', + ), 'relative path' - @unittest.skip('not yet, unsafe') + @pytest.mark.skip('not yet, unsafe') def test_listeners_empty(self): - self.assertIn( - 'error', self.conf({"*:7080": {}}, 'listeners'), 'listener empty' - ) + assert 'error' in self.conf( + {"*:7080": {}}, 'listeners' + ), 'listener empty' def test_listeners_no_app(self): - self.assertIn( - 'error', - self.conf({"*:7080": {"pass": "applications/app"}}, 'listeners'), - 'listeners no app', - ) + assert 'error' in self.conf( + {"*:7080": {"pass": "applications/app"}}, 'listeners' + ), 'listeners no app' def test_listeners_wildcard(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "applications/app"}}, - "applications": { - "app": { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - } - ), - 'listeners wildcard', - ) + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "applications/app"}}, + "applications": { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + } + ), 'listeners wildcard' def test_listeners_explicit(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": {"127.0.0.1:7080": {"pass": "applications/app"}}, - "applications": { - "app": { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - } - ), - 'explicit', - ) + assert 'success' in self.conf( + { + "listeners": {"127.0.0.1:7080": {"pass": "applications/app"}}, + "applications": { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + } + ), 'explicit' def test_listeners_explicit_ipv6(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": {"[::1]:7080": {"pass": "applications/app"}}, - "applications": { - "app": { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - } - ), - 'explicit ipv6', - ) + assert 'success' in self.conf( + { + "listeners": {"[::1]:7080": {"pass": "applications/app"}}, + "applications": { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + } + ), 'explicit ipv6' - @unittest.skip('not yet, unsafe') + @pytest.mark.skip('not yet, unsafe') def test_listeners_no_port(self): - self.assertIn( - 'error', - self.conf( - { - "listeners": {"127.0.0.1": {"pass": "applications/app"}}, - "applications": { - "app": { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - } - ), - 'no port', - ) + assert 'error' in self.conf( + { + "listeners": {"127.0.0.1": {"pass": "applications/app"}}, + "applications": { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + } + ), 'no port' def test_json_application_name_large(self): name = "X" * 1024 * 1024 - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "applications/" + name}}, - "applications": { - name: { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - } - ), + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "applications/" + name}}, + "applications": { + name: { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + } ) - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_json_application_many(self): apps = 999 @@ -388,7 +316,7 @@ class TestConfiguration(TestControl): }, } - self.assertIn('success', self.conf(conf)) + assert 'success' in self.conf(conf) def test_json_application_many2(self): conf = { @@ -407,35 +335,21 @@ class TestConfiguration(TestControl): "listeners": {"*:7080": {"pass": "applications/app-1"}}, } - self.assertIn('success', self.conf(conf)) - - def test_unprivileged_user_error(self): - self.skip_alerts.extend( - [ - r'cannot set user "root"', - r'failed to apply new conf', - ] - ) - if self.is_su: - print('unprivileged tests, skip this') - raise unittest.SkipTest() - - self.assertIn( - 'error', - self.conf( - { - "app": { - "type": "external", - "processes": 1, - "executable": "/app", - "user": "root", - } - }, - 'applications', - ), - 'setting user', - ) + assert 'success' in self.conf(conf) + def test_unprivileged_user_error(self, is_su): + skip_alert(r'cannot set user "root"', r'failed to apply new conf') + if is_su: + pytest.skip('unprivileged tests') -if __name__ == '__main__': - TestConfiguration.main() + assert 'error' in self.conf( + { + "app": { + "type": "external", + "processes": 1, + "executable": "/app", + "user": "root", + } + }, + 'applications', + ), 'setting user' diff --git a/test/test_go_application.py b/test/test_go_application.py index b9b78e2b..828a8e6e 100644 --- a/test/test_go_application.py +++ b/test/test_go_application.py @@ -1,4 +1,5 @@ from unit.applications.lang.go import TestApplicationGo +import re class TestGoApplication(TestApplicationGo): @@ -19,44 +20,38 @@ class TestGoApplication(TestApplicationGo): body=body, ) - self.assertEqual(resp['status'], 200, 'status') + assert resp['status'] == 200, 'status' headers = resp['headers'] header_server = headers.pop('Server') - self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header') + assert re.search(r'Unit/[\d\.]+', header_server), 'server header' date = headers.pop('Date') - self.assertEqual(date[-4:], ' GMT', 'date header timezone') - self.assertLess( - abs(self.date_to_sec_epoch(date) - self.sec_epoch()), - 5, - 'date header', - ) - - self.assertDictEqual( - headers, - { - 'Content-Length': str(len(body)), - 'Content-Type': 'text/html', - 'Request-Method': 'POST', - 'Request-Uri': '/', - 'Http-Host': 'localhost', - 'Server-Protocol': 'HTTP/1.1', - 'Server-Protocol-Major': '1', - 'Server-Protocol-Minor': '1', - 'Custom-Header': 'blah', - 'Connection': 'close', - }, - 'headers', - ) - self.assertEqual(resp['body'], body, 'body') + assert date[-4:] == ' GMT', 'date header timezone' + assert ( + abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5 + ), 'date header' + + assert headers == { + 'Content-Length': str(len(body)), + 'Content-Type': 'text/html', + 'Request-Method': 'POST', + 'Request-Uri': '/', + 'Http-Host': 'localhost', + 'Server-Protocol': 'HTTP/1.1', + 'Server-Protocol-Major': '1', + 'Server-Protocol-Minor': '1', + 'Custom-Header': 'blah', + 'Connection': 'close', + }, 'headers' + assert resp['body'] == body, 'body' def test_go_application_get_variables(self): self.load('get_variables') resp = self.get(url='/?var1=val1&var2=&var3') - self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'GET variables') - self.assertEqual(resp['headers']['X-Var-2'], '', 'GET variables 2') - self.assertEqual(resp['headers']['X-Var-3'], '', 'GET variables 3') + assert resp['headers']['X-Var-1'] == 'val1', 'GET variables' + assert resp['headers']['X-Var-2'] == '', 'GET variables 2' + assert resp['headers']['X-Var-3'] == '', 'GET variables 3' def test_go_application_post_variables(self): self.load('post_variables') @@ -70,24 +65,24 @@ class TestGoApplication(TestApplicationGo): body='var1=val1&var2=&var3', ) - self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'POST variables') - self.assertEqual(resp['headers']['X-Var-2'], '', 'POST variables 2') - self.assertEqual(resp['headers']['X-Var-3'], '', 'POST variables 3') + assert resp['headers']['X-Var-1'] == 'val1', 'POST variables' + assert resp['headers']['X-Var-2'] == '', 'POST variables 2' + assert resp['headers']['X-Var-3'] == '', 'POST variables 3' def test_go_application_404(self): self.load('404') resp = self.get() - self.assertEqual(resp['status'], 404, '404 status') - self.assertRegex( - resp['body'], r'404 Not Found', '404 body' - ) + assert resp['status'] == 404, '404 status' + assert re.search( + r'404 Not Found', resp['body'] + ), '404 body' def test_go_keepalive_body(self): self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' body = '0123456789' * 500 (resp, sock) = self.post( @@ -101,7 +96,7 @@ class TestGoApplication(TestApplicationGo): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'keep-alive 1') + assert resp['body'] == body, 'keep-alive 1' body = '0123456789' resp = self.post( @@ -114,7 +109,7 @@ class TestGoApplication(TestApplicationGo): body=body, ) - self.assertEqual(resp['body'], body, 'keep-alive 2') + assert resp['body'] == body, 'keep-alive 2' def test_go_application_cookies(self): self.load('cookies') @@ -127,28 +122,24 @@ class TestGoApplication(TestApplicationGo): } ) - self.assertEqual(resp['headers']['X-Cookie-1'], 'val1', 'cookie 1') - self.assertEqual(resp['headers']['X-Cookie-2'], 'val2', 'cookie 2') + assert resp['headers']['X-Cookie-1'] == 'val1', 'cookie 1' + assert resp['headers']['X-Cookie-2'] == 'val2', 'cookie 2' def test_go_application_command_line_arguments_type(self): self.load('command_line_arguments') - self.assertIn( - 'error', + assert 'error' in \ self.conf( '' "a b c", 'applications/command_line_arguments/arguments' - ), - 'arguments type', - ) + ), \ + 'arguments type' def test_go_application_command_line_arguments_0(self): self.load('command_line_arguments') - self.assertEqual( - self.get()['headers']['X-Arg-0'], - self.conf_get('applications/command_line_arguments/executable'), - 'argument 0', - ) + assert self.get()['headers']['X-Arg-0'] == self.conf_get( + 'applications/command_line_arguments/executable' + ), 'argument 0' def test_go_application_command_line_arguments(self): self.load('command_line_arguments') @@ -162,9 +153,9 @@ class TestGoApplication(TestApplicationGo): 'applications/command_line_arguments/arguments', ) - self.assertEqual( - self.get()['body'], arg1 + ',' + arg2 + ',' + arg3, 'arguments' - ) + assert ( + self.get()['body'] == arg1 + ',' + arg2 + ',' + arg3 + ), 'arguments' def test_go_application_command_line_arguments_change(self): self.load('command_line_arguments') @@ -173,18 +164,14 @@ class TestGoApplication(TestApplicationGo): self.conf('["0", "a", "$", ""]', args_path) - self.assertEqual(self.get()['body'], '0,a,$,', 'arguments') + assert self.get()['body'] == '0,a,$,', 'arguments' self.conf('["-1", "b", "%"]', args_path) - self.assertEqual(self.get()['body'], '-1,b,%', 'arguments change') + assert self.get()['body'] == '-1,b,%', 'arguments change' self.conf('[]', args_path) - self.assertEqual( - self.get()['headers']['Content-Length'], '0', 'arguments empty' - ) - - -if __name__ == '__main__': - TestGoApplication.main() + assert ( + self.get()['headers']['Content-Length'] == '0' + ), 'arguments empty' diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index 76434f62..bcfdd015 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -1,21 +1,21 @@ import grp +import os import pwd -import unittest +import pytest from unit.applications.lang.go import TestApplicationGo from unit.feature.isolation import TestFeatureIsolation - class TestGoIsolation(TestApplicationGo): prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']} isolation = TestFeatureIsolation() @classmethod - def setUpClass(cls, complete_check=True): - unit = super().setUpClass(complete_check=False) + def setup_class(cls, complete_check=True): + unit = super().setup_class(complete_check=False) - TestFeatureIsolation().check(cls.available, unit.testdir) + TestFeatureIsolation().check(cls.available, unit.temp_dir) return unit if not complete_check else unit.complete() @@ -41,24 +41,20 @@ class TestGoIsolation(TestApplicationGo): for ns, ns_value in self.available['features']['isolation'].items(): if ns.upper() in obj['NS']: - self.assertEqual( - obj['NS'][ns.upper()], ns_value, '%s match' % ns - ) + assert obj['NS'][ns.upper()] == ns_value, '%s match' % ns - def test_isolation_unpriv_user(self): + def test_isolation_unpriv_user(self, is_su): if not self.isolation_key('unprivileged_userns_clone'): - print('unprivileged clone is not available') - raise unittest.SkipTest() + pytest.skip('unprivileged clone is not available') - if self.is_su: - print('privileged tests, skip this') - raise unittest.SkipTest() + if is_su: + pytest.skip('privileged tests, skip this') self.load('ns_inspect') obj = self.getjson()['body'] - self.assertEqual(obj['UID'], self.uid, 'uid match') - self.assertEqual(obj['GID'], self.gid, 'gid match') + assert obj['UID'] == os.geteuid(), 'uid match' + assert obj['GID'] == os.getegid(), 'gid match' self.load('ns_inspect', isolation={'namespaces': {'credential': True}}) @@ -67,8 +63,8 @@ class TestGoIsolation(TestApplicationGo): nobody_uid, nogroup_gid, nogroup = self.unpriv_creds() # unprivileged unit map itself to nobody in the container by default - self.assertEqual(obj['UID'], nobody_uid, 'uid of nobody') - self.assertEqual(obj['GID'], nogroup_gid, 'gid of %s' % nogroup) + assert obj['UID'] == nobody_uid, 'uid of nobody' + assert obj['GID'] == nogroup_gid, 'gid of %s' % nogroup self.load( 'ns_inspect', @@ -78,8 +74,8 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson()['body'] - self.assertEqual(obj['UID'], 0, 'uid match user=root') - self.assertEqual(obj['GID'], 0, 'gid match user=root') + assert obj['UID'] == 0, 'uid match user=root' + assert obj['GID'] == 0, 'gid match user=root' self.load( 'ns_inspect', @@ -90,10 +86,8 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson()['body'] - self.assertEqual(obj['UID'], 0, 'uid match user=root group=nogroup') - self.assertEqual( - obj['GID'], nogroup_gid, 'gid match user=root group=nogroup' - ) + assert obj['UID'] == 0, 'uid match user=root group=nogroup' + assert obj['GID'] == nogroup_gid, 'gid match user=root group=nogroup' self.load( 'ns_inspect', @@ -101,20 +95,19 @@ class TestGoIsolation(TestApplicationGo): group='root', isolation={ 'namespaces': {'credential': True}, - 'uidmap': [{'container': 0, 'host': self.uid, 'size': 1}], - 'gidmap': [{'container': 0, 'host': self.gid, 'size': 1}], + 'uidmap': [{'container': 0, 'host': os.geteuid(), 'size': 1}], + 'gidmap': [{'container': 0, 'host': os.getegid(), 'size': 1}], }, ) obj = self.getjson()['body'] - self.assertEqual(obj['UID'], 0, 'uid match uidmap') - self.assertEqual(obj['GID'], 0, 'gid match gidmap') + assert obj['UID'] == 0, 'uid match uidmap' + assert obj['GID'] == 0, 'gid match gidmap' - def test_isolation_priv_user(self): - if not self.is_su: - print('unprivileged tests, skip this') - raise unittest.SkipTest() + def test_isolation_priv_user(self, is_su): + if not is_su: + pytest.skip('unprivileged tests, skip this') self.load('ns_inspect') @@ -122,16 +115,16 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson()['body'] - self.assertEqual(obj['UID'], nobody_uid, 'uid match') - self.assertEqual(obj['GID'], nogroup_gid, 'gid match') + assert obj['UID'] == nobody_uid, 'uid match' + assert obj['GID'] == nogroup_gid, 'gid match' self.load('ns_inspect', isolation={'namespaces': {'credential': True}}) obj = self.getjson()['body'] # privileged unit map app creds in the container by default - self.assertEqual(obj['UID'], nobody_uid, 'uid nobody') - self.assertEqual(obj['GID'], nogroup_gid, 'gid nobody') + assert obj['UID'] == nobody_uid, 'uid nobody' + assert obj['GID'] == nogroup_gid, 'gid nobody' self.load( 'ns_inspect', @@ -141,8 +134,8 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson()['body'] - self.assertEqual(obj['UID'], 0, 'uid nobody user=root') - self.assertEqual(obj['GID'], 0, 'gid nobody user=root') + assert obj['UID'] == 0, 'uid nobody user=root' + assert obj['GID'] == 0, 'gid nobody user=root' self.load( 'ns_inspect', @@ -153,10 +146,8 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson()['body'] - self.assertEqual(obj['UID'], 0, 'uid match user=root group=nogroup') - self.assertEqual( - obj['GID'], nogroup_gid, 'gid match user=root group=nogroup' - ) + assert obj['UID'] == 0, 'uid match user=root group=nogroup' + assert obj['GID'] == nogroup_gid, 'gid match user=root group=nogroup' self.load( 'ns_inspect', @@ -171,8 +162,8 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson()['body'] - self.assertEqual(obj['UID'], 0, 'uid match uidmap user=root') - self.assertEqual(obj['GID'], 0, 'gid match gidmap user=root') + assert obj['UID'] == 0, 'uid match uidmap user=root' + assert obj['GID'] == 0, 'gid match gidmap user=root' # map 65535 uids self.load( @@ -188,21 +179,15 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson()['body'] - self.assertEqual( - obj['UID'], nobody_uid, 'uid match uidmap user=nobody' - ) - self.assertEqual( - obj['GID'], nogroup_gid, 'gid match uidmap user=nobody' - ) + assert obj['UID'] == nobody_uid, 'uid match uidmap user=nobody' + assert obj['GID'] == nogroup_gid, 'gid match uidmap user=nobody' def test_isolation_mnt(self): if not self.isolation_key('mnt'): - print('mnt namespace is not supported') - raise unittest.SkipTest() + pytest.skip('mnt namespace is not supported') if not self.isolation_key('unprivileged_userns_clone'): - print('unprivileged clone is not available') - raise unittest.SkipTest() + pytest.skip('unprivileged clone is not available') self.load( 'ns_inspect', @@ -218,27 +203,20 @@ class TestGoIsolation(TestApplicationGo): for ns in allns: if ns.upper() in obj['NS']: - self.assertEqual( - obj['NS'][ns.upper()], - self.available['features']['isolation'][ns], - '%s match' % ns, - ) - - self.assertNotEqual( - obj['NS']['MNT'], self.isolation.getns('mnt'), 'mnt set' - ) - self.assertNotEqual( - obj['NS']['USER'], self.isolation.getns('user'), 'user set' - ) + assert ( + obj['NS'][ns.upper()] + == self.available['features']['isolation'][ns] + ), ('%s match' % ns) + + assert obj['NS']['MNT'] != self.isolation.getns('mnt'), 'mnt set' + assert obj['NS']['USER'] != self.isolation.getns('user'), 'user set' - def test_isolation_pid(self): + def test_isolation_pid(self, is_su): if not self.isolation_key('pid'): - print('pid namespace is not supported') - raise unittest.SkipTest() + pytest.skip('pid namespace is not supported') - if not (self.is_su or self.isolation_key('unprivileged_userns_clone')): - print('requires root or unprivileged_userns_clone') - raise unittest.SkipTest() + if not (is_su or self.isolation_key('unprivileged_userns_clone')): + pytest.skip('requires root or unprivileged_userns_clone') self.load( 'ns_inspect', @@ -247,7 +225,7 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson()['body'] - self.assertEqual(obj['PID'], 1, 'pid of container is 1') + assert obj['PID'] == 1, 'pid of container is 1' def test_isolation_namespace_false(self): self.load('ns_inspect') @@ -275,78 +253,67 @@ class TestGoIsolation(TestApplicationGo): for ns in allns: if ns.upper() in obj['NS']: - self.assertEqual( - obj['NS'][ns.upper()], - self.available['features']['isolation'][ns], - '%s match' % ns, - ) + assert ( + obj['NS'][ns.upper()] + == self.available['features']['isolation'][ns] + ), ('%s match' % ns) def test_go_isolation_rootfs_container(self): if not self.isolation_key('unprivileged_userns_clone'): - print('unprivileged clone is not available') - raise unittest.SkipTest() + pytest.skip('unprivileged clone is not available') if not self.isolation_key('mnt'): - print('mnt namespace is not supported') - raise unittest.SkipTest() + pytest.skip('mnt namespace is not supported') isolation = { 'namespaces': {'mount': True, 'credential': True}, - 'rootfs': self.testdir, + 'rootfs': self.temp_dir, } self.load('ns_inspect', isolation=isolation) obj = self.getjson(url='/?file=/go/app')['body'] - self.assertEqual(obj['FileExists'], True, 'app relative to rootfs') + assert obj['FileExists'] == True, 'app relative to rootfs' obj = self.getjson(url='/?file=/bin/sh')['body'] - self.assertEqual(obj['FileExists'], False, 'file should not exists') + assert obj['FileExists'] == False, 'file should not exists' - def test_go_isolation_rootfs_container_priv(self): - if not self.is_su: - print("requires root") - raise unittest.SkipTest() + def test_go_isolation_rootfs_container_priv(self, is_su): + if not is_su: + pytest.skip('requires root') if not self.isolation_key('mnt'): - print('mnt namespace is not supported') - raise unittest.SkipTest() + pytest.skip('mnt namespace is not supported') isolation = { 'namespaces': {'mount': True}, - 'rootfs': self.testdir, + 'rootfs': self.temp_dir, } self.load('ns_inspect', isolation=isolation) obj = self.getjson(url='/?file=/go/app')['body'] - self.assertEqual(obj['FileExists'], True, 'app relative to rootfs') + assert obj['FileExists'] == True, 'app relative to rootfs' obj = self.getjson(url='/?file=/bin/sh')['body'] - self.assertEqual(obj['FileExists'], False, 'file should not exists') + assert obj['FileExists'] == False, 'file should not exists' def test_go_isolation_rootfs_default_tmpfs(self): if not self.isolation_key('unprivileged_userns_clone'): - print('unprivileged clone is not available') - raise unittest.SkipTest() + pytest.skip('unprivileged clone is not available') if not self.isolation_key('mnt'): - print('mnt namespace is not supported') - raise unittest.SkipTest() + pytest.skip('mnt namespace is not supported') isolation = { 'namespaces': {'mount': True, 'credential': True}, - 'rootfs': self.testdir, + 'rootfs': self.temp_dir, } self.load('ns_inspect', isolation=isolation) obj = self.getjson(url='/?file=/tmp')['body'] - self.assertEqual(obj['FileExists'], True, 'app has /tmp') - - -if __name__ == '__main__': - TestGoIsolation.main() + assert obj['FileExists'] == True, 'app has /tmp' diff --git a/test/test_go_isolation_rootfs.py b/test/test_go_isolation_rootfs.py index 0039ff87..68891cd6 100644 --- a/test/test_go_isolation_rootfs.py +++ b/test/test_go_isolation_rootfs.py @@ -1,5 +1,5 @@ import os -import unittest +import pytest from unit.applications.lang.go import TestApplicationGo @@ -7,28 +7,22 @@ from unit.applications.lang.go import TestApplicationGo class TestGoIsolationRootfs(TestApplicationGo): prerequisites = {'modules': {'go': 'all'}} - def test_go_isolation_rootfs_chroot(self): - if not self.is_su: - print("requires root") - raise unittest.SkipTest() + def test_go_isolation_rootfs_chroot(self, is_su): + if not is_su: + pytest.skip('requires root') if os.uname().sysname == 'Darwin': - print('chroot tests not supported on OSX') - raise unittest.SkipTest() + pytest.skip('chroot tests not supported on OSX') isolation = { - 'rootfs': self.testdir, + 'rootfs': self.temp_dir, } self.load('ns_inspect', isolation=isolation) obj = self.getjson(url='/?file=/go/app')['body'] - self.assertEqual(obj['FileExists'], True, 'app relative to rootfs') + assert obj['FileExists'] == True, 'app relative to rootfs' obj = self.getjson(url='/?file=/bin/sh')['body'] - self.assertEqual(obj['FileExists'], False, 'file should not exists') - - -if __name__ == '__main__': - TestGoIsolationRootfs.main() + assert obj['FileExists'] == False, 'file should not exists' diff --git a/test/test_http_header.py b/test/test_http_header.py index ea4520c1..8c1e211b 100644 --- a/test/test_http_header.py +++ b/test/test_http_header.py @@ -1,4 +1,4 @@ -import unittest +import pytest from unit.applications.lang.python import TestApplicationPython @@ -17,12 +17,10 @@ class TestHTTPHeader(TestApplicationPython): } ) - self.assertEqual(resp['status'], 200, 'value leading sp status') - self.assertEqual( - resp['headers']['Custom-Header'], - ',', - 'value leading sp custom header', - ) + assert resp['status'] == 200, 'value leading sp status' + assert ( + resp['headers']['Custom-Header'] == ',' + ), 'value leading sp custom header' def test_http_header_value_leading_htab(self): self.load('custom_header') @@ -35,12 +33,10 @@ class TestHTTPHeader(TestApplicationPython): } ) - self.assertEqual(resp['status'], 200, 'value leading htab status') - self.assertEqual( - resp['headers']['Custom-Header'], - ',', - 'value leading htab custom header', - ) + assert resp['status'] == 200, 'value leading htab status' + assert ( + resp['headers']['Custom-Header'] == ',' + ), 'value leading htab custom header' def test_http_header_value_trailing_sp(self): self.load('custom_header') @@ -53,12 +49,10 @@ class TestHTTPHeader(TestApplicationPython): } ) - self.assertEqual(resp['status'], 200, 'value trailing sp status') - self.assertEqual( - resp['headers']['Custom-Header'], - ',', - 'value trailing sp custom header', - ) + assert resp['status'] == 200, 'value trailing sp status' + assert ( + resp['headers']['Custom-Header'] == ',' + ), 'value trailing sp custom header' def test_http_header_value_trailing_htab(self): self.load('custom_header') @@ -71,12 +65,10 @@ class TestHTTPHeader(TestApplicationPython): } ) - self.assertEqual(resp['status'], 200, 'value trailing htab status') - self.assertEqual( - resp['headers']['Custom-Header'], - ',', - 'value trailing htab custom header', - ) + assert resp['status'] == 200, 'value trailing htab status' + assert ( + resp['headers']['Custom-Header'] == ',' + ), 'value trailing htab custom header' def test_http_header_value_both_sp(self): self.load('custom_header') @@ -89,12 +81,10 @@ class TestHTTPHeader(TestApplicationPython): } ) - self.assertEqual(resp['status'], 200, 'value both sp status') - self.assertEqual( - resp['headers']['Custom-Header'], - ',', - 'value both sp custom header', - ) + assert resp['status'] == 200, 'value both sp status' + assert ( + resp['headers']['Custom-Header'] == ',' + ), 'value both sp custom header' def test_http_header_value_both_htab(self): self.load('custom_header') @@ -107,12 +97,10 @@ class TestHTTPHeader(TestApplicationPython): } ) - self.assertEqual(resp['status'], 200, 'value both htab status') - self.assertEqual( - resp['headers']['Custom-Header'], - ',', - 'value both htab custom header', - ) + assert resp['status'] == 200, 'value both htab status' + assert ( + resp['headers']['Custom-Header'] == ',' + ), 'value both htab custom header' def test_http_header_value_chars(self): self.load('custom_header') @@ -125,12 +113,11 @@ class TestHTTPHeader(TestApplicationPython): } ) - self.assertEqual(resp['status'], 200, 'value chars status') - self.assertEqual( - resp['headers']['Custom-Header'], - '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~', - 'value chars custom header', - ) + assert resp['status'] == 200, 'value chars status' + assert ( + resp['headers']['Custom-Header'] + == '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~' + ), 'value chars custom header' def test_http_header_value_chars_edge(self): self.load('custom_header') @@ -146,10 +133,8 @@ Connection: close encoding='latin1', ) - self.assertEqual(resp['status'], 200, 'value chars edge status') - self.assertEqual( - resp['headers']['Custom-Header'], '\xFF', 'value chars edge' - ) + assert resp['status'] == 200, 'value chars edge status' + assert resp['headers']['Custom-Header'] == '\xFF', 'value chars edge' def test_http_header_value_chars_below(self): self.load('custom_header') @@ -164,7 +149,7 @@ Connection: close raw=True, ) - self.assertEqual(resp['status'], 400, 'value chars below') + assert resp['status'] == 400, 'value chars below' def test_http_header_field_leading_sp(self): self.load('empty') @@ -177,7 +162,7 @@ Connection: close } ) - self.assertEqual(resp['status'], 400, 'field leading sp') + assert resp['status'] == 400, 'field leading sp' def test_http_header_field_leading_htab(self): self.load('empty') @@ -190,7 +175,7 @@ Connection: close } ) - self.assertEqual(resp['status'], 400, 'field leading htab') + assert resp['status'] == 400, 'field leading htab' def test_http_header_field_trailing_sp(self): self.load('empty') @@ -203,7 +188,7 @@ Connection: close } ) - self.assertEqual(resp['status'], 400, 'field trailing sp') + assert resp['status'] == 400, 'field trailing sp' def test_http_header_field_trailing_htab(self): self.load('empty') @@ -216,12 +201,12 @@ Connection: close } ) - self.assertEqual(resp['status'], 400, 'field trailing htab') + assert resp['status'] == 400, 'field trailing htab' def test_http_header_content_length_big(self): self.load('empty') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -229,15 +214,14 @@ Connection: close 'Connection': 'close', }, body='X' * 1000, - )['status'], - 400, - 'Content-Length big', - ) + )['status'] + == 400 + ), 'Content-Length big' def test_http_header_content_length_negative(self): self.load('empty') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -245,15 +229,14 @@ Connection: close 'Connection': 'close', }, body='X' * 1000, - )['status'], - 400, - 'Content-Length negative', - ) + )['status'] + == 400 + ), 'Content-Length negative' def test_http_header_content_length_text(self): self.load('empty') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -261,15 +244,14 @@ Connection: close 'Connection': 'close', }, body='X' * 1000, - )['status'], - 400, - 'Content-Length text', - ) + )['status'] + == 400 + ), 'Content-Length text' def test_http_header_content_length_multiple_values(self): self.load('empty') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -277,15 +259,14 @@ Connection: close 'Connection': 'close', }, body='X' * 1000, - )['status'], - 400, - 'Content-Length multiple value', - ) + )['status'] + == 400 + ), 'Content-Length multiple value' def test_http_header_content_length_multiple_fields(self): self.load('empty') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -293,39 +274,35 @@ Connection: close 'Connection': 'close', }, body='X' * 1000, - )['status'], - 400, - 'Content-Length multiple fields', - ) + )['status'] + == 400 + ), 'Content-Length multiple fields' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_http_header_host_absent(self): self.load('host') resp = self.get(headers={'Connection': 'close'}) - self.assertEqual(resp['status'], 400, 'Host absent status') + assert resp['status'] == 400, 'Host absent status' def test_http_header_host_empty(self): self.load('host') resp = self.get(headers={'Host': '', 'Connection': 'close'}) - self.assertEqual(resp['status'], 200, 'Host empty status') - self.assertNotEqual( - resp['headers']['X-Server-Name'], '', 'Host empty SERVER_NAME' - ) + assert resp['status'] == 200, 'Host empty status' + assert resp['headers']['X-Server-Name'] != '', 'Host empty SERVER_NAME' def test_http_header_host_big(self): self.load('empty') - self.assertEqual( + assert ( self.get(headers={'Host': 'X' * 10000, 'Connection': 'close'})[ 'status' - ], - 431, - 'Host big', - ) + ] + == 431 + ), 'Host big' def test_http_header_host_port(self): self.load('host') @@ -334,17 +311,13 @@ Connection: close headers={'Host': 'exmaple.com:7080', 'Connection': 'close'} ) - self.assertEqual(resp['status'], 200, 'Host port status') - self.assertEqual( - resp['headers']['X-Server-Name'], - 'exmaple.com', - 'Host port SERVER_NAME', - ) - self.assertEqual( - resp['headers']['X-Http-Host'], - 'exmaple.com:7080', - 'Host port HTTP_HOST', - ) + assert resp['status'] == 200, 'Host port status' + assert ( + resp['headers']['X-Server-Name'] == 'exmaple.com' + ), 'Host port SERVER_NAME' + assert ( + resp['headers']['X-Http-Host'] == 'exmaple.com:7080' + ), 'Host port HTTP_HOST' def test_http_header_host_port_empty(self): self.load('host') @@ -353,63 +326,49 @@ Connection: close headers={'Host': 'exmaple.com:', 'Connection': 'close'} ) - self.assertEqual(resp['status'], 200, 'Host port empty status') - self.assertEqual( - resp['headers']['X-Server-Name'], - 'exmaple.com', - 'Host port empty SERVER_NAME', - ) - self.assertEqual( - resp['headers']['X-Http-Host'], - 'exmaple.com:', - 'Host port empty HTTP_HOST', - ) + assert resp['status'] == 200, 'Host port empty status' + assert ( + resp['headers']['X-Server-Name'] == 'exmaple.com' + ), 'Host port empty SERVER_NAME' + assert ( + resp['headers']['X-Http-Host'] == 'exmaple.com:' + ), 'Host port empty HTTP_HOST' def test_http_header_host_literal(self): self.load('host') resp = self.get(headers={'Host': '127.0.0.1', 'Connection': 'close'}) - self.assertEqual(resp['status'], 200, 'Host literal status') - self.assertEqual( - resp['headers']['X-Server-Name'], - '127.0.0.1', - 'Host literal SERVER_NAME', - ) + assert resp['status'] == 200, 'Host literal status' + assert ( + resp['headers']['X-Server-Name'] == '127.0.0.1' + ), 'Host literal SERVER_NAME' def test_http_header_host_literal_ipv6(self): self.load('host') resp = self.get(headers={'Host': '[::1]:7080', 'Connection': 'close'}) - self.assertEqual(resp['status'], 200, 'Host literal ipv6 status') - self.assertEqual( - resp['headers']['X-Server-Name'], - '[::1]', - 'Host literal ipv6 SERVER_NAME', - ) - self.assertEqual( - resp['headers']['X-Http-Host'], - '[::1]:7080', - 'Host literal ipv6 HTTP_HOST', - ) + assert resp['status'] == 200, 'Host literal ipv6 status' + assert ( + resp['headers']['X-Server-Name'] == '[::1]' + ), 'Host literal ipv6 SERVER_NAME' + assert ( + resp['headers']['X-Http-Host'] == '[::1]:7080' + ), 'Host literal ipv6 HTTP_HOST' def test_http_header_host_trailing_period(self): self.load('host') resp = self.get(headers={'Host': '127.0.0.1.', 'Connection': 'close'}) - self.assertEqual(resp['status'], 200, 'Host trailing period status') - self.assertEqual( - resp['headers']['X-Server-Name'], - '127.0.0.1', - 'Host trailing period SERVER_NAME', - ) - self.assertEqual( - resp['headers']['X-Http-Host'], - '127.0.0.1.', - 'Host trailing period HTTP_HOST', - ) + assert resp['status'] == 200, 'Host trailing period status' + assert ( + resp['headers']['X-Server-Name'] == '127.0.0.1' + ), 'Host trailing period SERVER_NAME' + assert ( + resp['headers']['X-Http-Host'] == '127.0.0.1.' + ), 'Host trailing period HTTP_HOST' def test_http_header_host_trailing_period_2(self): self.load('host') @@ -418,66 +377,53 @@ Connection: close headers={'Host': 'EXAMPLE.COM.', 'Connection': 'close'} ) - self.assertEqual(resp['status'], 200, 'Host trailing period 2 status') - self.assertEqual( - resp['headers']['X-Server-Name'], - 'example.com', - 'Host trailing period 2 SERVER_NAME', - ) - self.assertEqual( - resp['headers']['X-Http-Host'], - 'EXAMPLE.COM.', - 'Host trailing period 2 HTTP_HOST', - ) + assert resp['status'] == 200, 'Host trailing period 2 status' + assert ( + resp['headers']['X-Server-Name'] == 'example.com' + ), 'Host trailing period 2 SERVER_NAME' + assert ( + resp['headers']['X-Http-Host'] == 'EXAMPLE.COM.' + ), 'Host trailing period 2 HTTP_HOST' def test_http_header_host_case_insensitive(self): self.load('host') resp = self.get(headers={'Host': 'EXAMPLE.COM', 'Connection': 'close'}) - self.assertEqual(resp['status'], 200, 'Host case insensitive') - self.assertEqual( - resp['headers']['X-Server-Name'], - 'example.com', - 'Host case insensitive SERVER_NAME', - ) + assert resp['status'] == 200, 'Host case insensitive' + assert ( + resp['headers']['X-Server-Name'] == 'example.com' + ), 'Host case insensitive SERVER_NAME' def test_http_header_host_double_dot(self): self.load('empty') - self.assertEqual( + assert ( self.get(headers={'Host': '127.0.0..1', 'Connection': 'close'})[ 'status' - ], - 400, - 'Host double dot', - ) + ] + == 400 + ), 'Host double dot' def test_http_header_host_slash(self): self.load('empty') - self.assertEqual( + assert ( self.get(headers={'Host': '/localhost', 'Connection': 'close'})[ 'status' - ], - 400, - 'Host slash', - ) + ] + == 400 + ), 'Host slash' def test_http_header_host_multiple_fields(self): self.load('empty') - self.assertEqual( + assert ( self.get( headers={ 'Host': ['localhost', 'example.com'], 'Connection': 'close', } - )['status'], - 400, - 'Host multiple fields', - ) - - -if __name__ == '__main__': - TestHTTPHeader.main() + )['status'] + == 400 + ), 'Host multiple fields' diff --git a/test/test_java_application.py b/test/test_java_application.py index 0cb18c25..a2bd3d44 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -1,54 +1,44 @@ import io import os +import re import time from unit.applications.lang.java import TestApplicationJava - +from conftest import option, public_dir, skip_alert class TestJavaApplication(TestApplicationJava): prerequisites = {'modules': {'java': 'all'}} def test_java_conf_error(self): - self.skip_alerts.extend( - [ - r'realpath.*failed', - r'failed to apply new conf', - r'application setup failed', - ] - ) - self.assertIn( - 'error', - self.conf( - { - "listeners": {"*:7080": {"pass": "applications/app"}}, - "applications": { - "app": { - "type": "java", - "processes": 1, - "working_directory": self.current_dir - + "/java/empty", - "webapp": self.testdir + "/java", - "unit_jars": self.testdir + "/no_such_dir", - } - }, - } - ), - 'conf error', - ) + skip_alert( + r'realpath.*failed', + r'failed to apply new conf', + r'application setup failed', + ) + assert 'error' in self.conf( + { + "listeners": {"*:7080": {"pass": "applications/app"}}, + "applications": { + "app": { + "type": "java", + "processes": 1, + "working_directory": option.test_dir + "/java/empty", + "webapp": self.temp_dir + "/java", + "unit_jars": self.temp_dir + "/no_such_dir", + } + }, + } + ), 'conf error' def test_java_war(self): self.load('empty_war') - self.assertIn( - 'success', - self.conf( - '"' + self.testdir + '/java/empty.war"', - '/config/applications/empty_war/webapp', - ), - 'configure war', - ) + assert 'success' in self.conf( + '"' + self.temp_dir + '/java/empty.war"', + '/config/applications/empty_war/webapp', + ), 'configure war' - self.assertEqual(self.get()['status'], 200, 'war') + assert self.get()['status'] == 200, 'war' def test_java_application_cookies(self): self.load('cookies') @@ -61,22 +51,20 @@ class TestJavaApplication(TestApplicationJava): } )['headers'] - self.assertEqual(headers['X-Cookie-1'], 'val1', 'cookie 1') - self.assertEqual(headers['X-Cookie-2'], 'val2', 'cookie 2') + assert headers['X-Cookie-1'] == 'val1', 'cookie 1' + assert headers['X-Cookie-2'] == 'val2', 'cookie 2' def test_java_application_filter(self): self.load('filter') headers = self.get()['headers'] - self.assertEqual(headers['X-Filter-Before'], '1', 'filter before') - self.assertEqual(headers['X-Filter-After'], '1', 'filter after') + assert headers['X-Filter-Before'] == '1', 'filter before' + assert headers['X-Filter-After'] == '1', 'filter after' - self.assertEqual( - self.get(url='/test')['headers']['X-Filter-After'], - '0', - 'filter after 2', - ) + assert ( + self.get(url='/test')['headers']['X-Filter-After'] == '0' + ), 'filter after 2' def test_java_application_get_variables(self): self.load('get_params') @@ -85,21 +73,17 @@ class TestJavaApplication(TestApplicationJava): 'headers' ] - self.assertEqual(headers['X-Var-1'], 'val1', 'GET variables') - self.assertEqual(headers['X-Var-2'], 'true', 'GET variables 2') - self.assertEqual(headers['X-Var-3'], 'false', 'GET variables 3') + assert headers['X-Var-1'] == 'val1', 'GET variables' + assert headers['X-Var-2'] == 'true', 'GET variables 2' + assert headers['X-Var-3'] == 'false', 'GET variables 3' - self.assertEqual( - headers['X-Param-Names'], 'var4 var2 var1 ', 'getParameterNames' - ) - self.assertEqual( - headers['X-Param-Values'], 'val4 foo ', 'getParameterValues' - ) - self.assertEqual( - headers['X-Param-Map'], - 'var2= var1=val1 var4=val4,foo ', - 'getParameterMap', - ) + assert ( + headers['X-Param-Names'] == 'var4 var2 var1 ' + ), 'getParameterNames' + assert headers['X-Param-Values'] == 'val4 foo ', 'getParameterValues' + assert ( + headers['X-Param-Map'] == 'var2= var1=val1 var4=val4,foo ' + ), 'getParameterMap' def test_java_application_post_variables(self): self.load('post_params') @@ -113,9 +97,9 @@ class TestJavaApplication(TestApplicationJava): body='var1=val1&var2=', )['headers'] - self.assertEqual(headers['X-Var-1'], 'val1', 'POST variables') - self.assertEqual(headers['X-Var-2'], 'true', 'POST variables 2') - self.assertEqual(headers['X-Var-3'], 'false', 'POST variables 3') + assert headers['X-Var-1'] == 'val1', 'POST variables' + assert headers['X-Var-2'] == 'true', 'POST variables 2' + assert headers['X-Var-3'] == 'false', 'POST variables 3' def test_java_application_session(self): self.load('session') @@ -123,8 +107,8 @@ class TestJavaApplication(TestApplicationJava): headers = self.get(url='/?var1=val1')['headers'] session_id = headers['X-Session-Id'] - self.assertEqual(headers['X-Var-1'], 'null', 'variable empty') - self.assertEqual(headers['X-Session-New'], 'true', 'session create') + assert headers['X-Var-1'] == 'null', 'variable empty' + assert headers['X-Session-New'] == 'true', 'session create' headers = self.get( headers={ @@ -135,36 +119,33 @@ class TestJavaApplication(TestApplicationJava): url='/?var1=val2', )['headers'] - self.assertEqual(headers['X-Var-1'], 'val1', 'variable') - self.assertEqual(headers['X-Session-New'], 'false', 'session resume') - self.assertEqual( - session_id, headers['X-Session-Id'], 'session same id' - ) + assert headers['X-Var-1'] == 'val1', 'variable' + assert headers['X-Session-New'] == 'false', 'session resume' + assert session_id == headers['X-Session-Id'], 'session same id' def test_java_application_session_active(self): self.load('session_inactive') - resp = self.get(headers={ - 'X-Interval': '4', - 'Host': 'localhost', - 'Connection': 'close', - }) + resp = self.get( + headers={ + 'X-Interval': '4', + 'Host': 'localhost', + 'Connection': 'close', + } + ) session_id = resp['headers']['X-Session-Id'] - self.assertEqual(resp['status'], 200, 'session init') - self.assertEqual( - resp['headers']['X-Session-Interval'], '4', 'session interval' - ) - self.assertLess( + assert resp['status'] == 200, 'session init' + assert resp['headers']['X-Session-Interval'] == '4', 'session interval' + assert ( abs( self.date_to_sec_epoch( resp['headers']['X-Session-Last-Access-Time'] ) - self.sec_epoch() - ), - 5, - 'session last access time', - ) + ) + < 5 + ), 'session last access time' time.sleep(1) @@ -176,9 +157,7 @@ class TestJavaApplication(TestApplicationJava): } ) - self.assertEqual( - resp['headers']['X-Session-Id'], session_id, 'session active' - ) + assert resp['headers']['X-Session-Id'] == session_id, 'session active' session_id = resp['headers']['X-Session-Id'] @@ -192,9 +171,9 @@ class TestJavaApplication(TestApplicationJava): } ) - self.assertEqual( - resp['headers']['X-Session-Id'], session_id, 'session active 2' - ) + assert ( + resp['headers']['X-Session-Id'] == session_id + ), 'session active 2' time.sleep(2) @@ -206,18 +185,20 @@ class TestJavaApplication(TestApplicationJava): } ) - self.assertEqual( - resp['headers']['X-Session-Id'], session_id, 'session active 3' - ) + assert ( + resp['headers']['X-Session-Id'] == session_id + ), 'session active 3' def test_java_application_session_inactive(self): self.load('session_inactive') - resp = self.get(headers={ - 'X-Interval': '1', - 'Host': 'localhost', - 'Connection': 'close', - }) + resp = self.get( + headers={ + 'X-Interval': '1', + 'Host': 'localhost', + 'Connection': 'close', + } + ) session_id = resp['headers']['X-Session-Id'] time.sleep(3) @@ -230,9 +211,9 @@ class TestJavaApplication(TestApplicationJava): } ) - self.assertNotEqual( - resp['headers']['X-Session-Id'], session_id, 'session inactive' - ) + assert ( + resp['headers']['X-Session-Id'] != session_id + ), 'session inactive' def test_java_application_session_invalidate(self): self.load('session_invalidate') @@ -248,9 +229,9 @@ class TestJavaApplication(TestApplicationJava): } ) - self.assertNotEqual( - resp['headers']['X-Session-Id'], session_id, 'session invalidate' - ) + assert ( + resp['headers']['X-Session-Id'] != session_id + ), 'session invalidate' def test_java_application_session_listeners(self): self.load('session_listeners') @@ -258,10 +239,8 @@ class TestJavaApplication(TestApplicationJava): headers = self.get(url='/test?var1=val1')['headers'] session_id = headers['X-Session-Id'] - self.assertEqual( - headers['X-Session-Created'], session_id, 'session create' - ) - self.assertEqual(headers['X-Attr-Added'], 'var1=val1', 'attribute add') + assert headers['X-Session-Created'] == session_id, 'session create' + assert headers['X-Attr-Added'] == 'var1=val1', 'attribute add' headers = self.get( headers={ @@ -272,12 +251,8 @@ class TestJavaApplication(TestApplicationJava): url='/?var1=val2', )['headers'] - self.assertEqual( - session_id, headers['X-Session-Id'], 'session same id' - ) - self.assertEqual( - headers['X-Attr-Replaced'], 'var1=val1', 'attribute replace' - ) + assert session_id == headers['X-Session-Id'], 'session same id' + assert headers['X-Attr-Replaced'] == 'var1=val1', 'attribute replace' headers = self.get( headers={ @@ -288,289 +263,219 @@ class TestJavaApplication(TestApplicationJava): url='/', )['headers'] - self.assertEqual( - session_id, headers['X-Session-Id'], 'session same id' - ) - self.assertEqual( - headers['X-Attr-Removed'], 'var1=val2', 'attribute remove' - ) + assert session_id == headers['X-Session-Id'], 'session same id' + assert headers['X-Attr-Removed'] == 'var1=val2', 'attribute remove' def test_java_application_jsp(self): self.load('jsp') headers = self.get(url='/index.jsp')['headers'] - self.assertEqual(headers['X-Unit-JSP'], 'ok', 'JSP Ok header') + assert headers['X-Unit-JSP'] == 'ok', 'JSP Ok header' def test_java_application_url_pattern(self): self.load('url_pattern') headers = self.get(url='/foo/bar/index.html')['headers'] - self.assertEqual(headers['X-Id'], 'servlet1', '#1 Servlet1 request') - self.assertEqual( - headers['X-Request-URI'], '/foo/bar/index.html', '#1 request URI' - ) - self.assertEqual( - headers['X-Servlet-Path'], '/foo/bar', '#1 servlet path' - ) - self.assertEqual(headers['X-Path-Info'], '/index.html', '#1 path info') + assert headers['X-Id'] == 'servlet1', '#1 Servlet1 request' + assert ( + headers['X-Request-URI'] == '/foo/bar/index.html' + ), '#1 request URI' + assert headers['X-Servlet-Path'] == '/foo/bar', '#1 servlet path' + assert headers['X-Path-Info'] == '/index.html', '#1 path info' headers = self.get(url='/foo/bar/index.bop')['headers'] - self.assertEqual(headers['X-Id'], 'servlet1', '#2 Servlet1 request') - self.assertEqual( - headers['X-Request-URI'], '/foo/bar/index.bop', '#2 request URI' - ) - self.assertEqual( - headers['X-Servlet-Path'], '/foo/bar', '#2 servlet path' - ) - self.assertEqual(headers['X-Path-Info'], '/index.bop', '#2 path info') + assert headers['X-Id'] == 'servlet1', '#2 Servlet1 request' + assert ( + headers['X-Request-URI'] == '/foo/bar/index.bop' + ), '#2 request URI' + assert headers['X-Servlet-Path'] == '/foo/bar', '#2 servlet path' + assert headers['X-Path-Info'] == '/index.bop', '#2 path info' headers = self.get(url='/baz')['headers'] - self.assertEqual(headers['X-Id'], 'servlet2', '#3 Servlet2 request') - self.assertEqual(headers['X-Request-URI'], '/baz', '#3 request URI') - self.assertEqual(headers['X-Servlet-Path'], '/baz', '#3 servlet path') - self.assertEqual(headers['X-Path-Info'], 'null', '#3 path info') + assert headers['X-Id'] == 'servlet2', '#3 Servlet2 request' + assert headers['X-Request-URI'] == '/baz', '#3 request URI' + assert headers['X-Servlet-Path'] == '/baz', '#3 servlet path' + assert headers['X-Path-Info'] == 'null', '#3 path info' headers = self.get(url='/baz/index.html')['headers'] - self.assertEqual(headers['X-Id'], 'servlet2', '#4 Servlet2 request') - self.assertEqual( - headers['X-Request-URI'], '/baz/index.html', '#4 request URI' - ) - self.assertEqual(headers['X-Servlet-Path'], '/baz', '#4 servlet path') - self.assertEqual(headers['X-Path-Info'], '/index.html', '#4 path info') + assert headers['X-Id'] == 'servlet2', '#4 Servlet2 request' + assert headers['X-Request-URI'] == '/baz/index.html', '#4 request URI' + assert headers['X-Servlet-Path'] == '/baz', '#4 servlet path' + assert headers['X-Path-Info'] == '/index.html', '#4 path info' headers = self.get(url='/catalog')['headers'] - self.assertEqual(headers['X-Id'], 'servlet3', '#5 Servlet3 request') - self.assertEqual( - headers['X-Request-URI'], '/catalog', '#5 request URI' - ) - self.assertEqual( - headers['X-Servlet-Path'], '/catalog', '#5 servlet path' - ) - self.assertEqual(headers['X-Path-Info'], 'null', '#5 path info') + assert headers['X-Id'] == 'servlet3', '#5 Servlet3 request' + assert headers['X-Request-URI'] == '/catalog', '#5 request URI' + assert headers['X-Servlet-Path'] == '/catalog', '#5 servlet path' + assert headers['X-Path-Info'] == 'null', '#5 path info' headers = self.get(url='/catalog/index.html')['headers'] - self.assertEqual(headers['X-Id'], 'default', '#6 default request') - self.assertEqual( - headers['X-Request-URI'], '/catalog/index.html', '#6 request URI' - ) - self.assertEqual( - headers['X-Servlet-Path'], '/catalog/index.html', '#6 servlet path' - ) - self.assertEqual(headers['X-Path-Info'], 'null', '#6 path info') + assert headers['X-Id'] == 'default', '#6 default request' + assert ( + headers['X-Request-URI'] == '/catalog/index.html' + ), '#6 request URI' + assert ( + headers['X-Servlet-Path'] == '/catalog/index.html' + ), '#6 servlet path' + assert headers['X-Path-Info'] == 'null', '#6 path info' headers = self.get(url='/catalog/racecar.bop')['headers'] - self.assertEqual(headers['X-Id'], 'servlet4', '#7 servlet4 request') - self.assertEqual( - headers['X-Request-URI'], '/catalog/racecar.bop', '#7 request URI' - ) - self.assertEqual( - headers['X-Servlet-Path'], - '/catalog/racecar.bop', - '#7 servlet path', - ) - self.assertEqual(headers['X-Path-Info'], 'null', '#7 path info') + assert headers['X-Id'] == 'servlet4', '#7 servlet4 request' + assert ( + headers['X-Request-URI'] == '/catalog/racecar.bop' + ), '#7 request URI' + assert ( + headers['X-Servlet-Path'] == '/catalog/racecar.bop' + ), '#7 servlet path' + assert headers['X-Path-Info'] == 'null', '#7 path info' headers = self.get(url='/index.bop')['headers'] - self.assertEqual(headers['X-Id'], 'servlet4', '#8 servlet4 request') - self.assertEqual( - headers['X-Request-URI'], '/index.bop', '#8 request URI' - ) - self.assertEqual( - headers['X-Servlet-Path'], '/index.bop', '#8 servlet path' - ) - self.assertEqual(headers['X-Path-Info'], 'null', '#8 path info') + assert headers['X-Id'] == 'servlet4', '#8 servlet4 request' + assert headers['X-Request-URI'] == '/index.bop', '#8 request URI' + assert headers['X-Servlet-Path'] == '/index.bop', '#8 servlet path' + assert headers['X-Path-Info'] == 'null', '#8 path info' headers = self.get(url='/foo/baz')['headers'] - self.assertEqual(headers['X-Id'], 'servlet0', '#9 servlet0 request') - self.assertEqual( - headers['X-Request-URI'], '/foo/baz', '#9 request URI' - ) - self.assertEqual(headers['X-Servlet-Path'], '/foo', '#9 servlet path') - self.assertEqual(headers['X-Path-Info'], '/baz', '#9 path info') + assert headers['X-Id'] == 'servlet0', '#9 servlet0 request' + assert headers['X-Request-URI'] == '/foo/baz', '#9 request URI' + assert headers['X-Servlet-Path'] == '/foo', '#9 servlet path' + assert headers['X-Path-Info'] == '/baz', '#9 path info' headers = self.get()['headers'] - self.assertEqual(headers['X-Id'], 'default', '#10 default request') - self.assertEqual(headers['X-Request-URI'], '/', '#10 request URI') - self.assertEqual(headers['X-Servlet-Path'], '/', '#10 servlet path') - self.assertEqual(headers['X-Path-Info'], 'null', '#10 path info') + assert headers['X-Id'] == 'default', '#10 default request' + assert headers['X-Request-URI'] == '/', '#10 request URI' + assert headers['X-Servlet-Path'] == '/', '#10 servlet path' + assert headers['X-Path-Info'] == 'null', '#10 path info' headers = self.get(url='/index.bop/')['headers'] - self.assertEqual(headers['X-Id'], 'default', '#11 default request') - self.assertEqual( - headers['X-Request-URI'], '/index.bop/', '#11 request URI' - ) - self.assertEqual( - headers['X-Servlet-Path'], '/index.bop/', '#11 servlet path' - ) - self.assertEqual(headers['X-Path-Info'], 'null', '#11 path info') + assert headers['X-Id'] == 'default', '#11 default request' + assert headers['X-Request-URI'] == '/index.bop/', '#11 request URI' + assert headers['X-Servlet-Path'] == '/index.bop/', '#11 servlet path' + assert headers['X-Path-Info'] == 'null', '#11 path info' def test_java_application_header(self): self.load('header') headers = self.get()['headers'] - self.assertEqual( - headers['X-Set-Utf8-Value'], '????', 'set Utf8 header value' - ) - self.assertEqual( - headers['X-Set-Utf8-Name-???'], 'x', 'set Utf8 header name' - ) - self.assertEqual( - headers['X-Add-Utf8-Value'], '????', 'add Utf8 header value' - ) - self.assertEqual( - headers['X-Add-Utf8-Name-???'], 'y', 'add Utf8 header name' - ) - self.assertEqual(headers['X-Add-Test'], 'v1', 'add null header') - self.assertEqual('X-Set-Test1' in headers, False, 'set null header') - self.assertEqual(headers['X-Set-Test2'], '', 'set empty header') + assert headers['X-Set-Utf8-Value'] == '????', 'set Utf8 header value' + assert headers['X-Set-Utf8-Name-???'] == 'x', 'set Utf8 header name' + assert headers['X-Add-Utf8-Value'] == '????', 'add Utf8 header value' + assert headers['X-Add-Utf8-Name-???'] == 'y', 'add Utf8 header name' + assert headers['X-Add-Test'] == 'v1', 'add null header' + assert ('X-Set-Test1' in headers) == False, 'set null header' + assert headers['X-Set-Test2'] == '', 'set empty header' def test_java_application_content_type(self): self.load('content_type') headers = self.get(url='/1')['headers'] - self.assertEqual( - headers['Content-Type'], - 'text/plain;charset=utf-8', - '#1 Content-Type header', - ) - self.assertEqual( - headers['X-Content-Type'], - 'text/plain;charset=utf-8', - '#1 response Content-Type', - ) - self.assertEqual( - headers['X-Character-Encoding'], 'utf-8', '#1 response charset' - ) + assert ( + headers['Content-Type'] == 'text/plain;charset=utf-8' + ), '#1 Content-Type header' + assert ( + headers['X-Content-Type'] == 'text/plain;charset=utf-8' + ), '#1 response Content-Type' + assert ( + headers['X-Character-Encoding'] == 'utf-8' + ), '#1 response charset' headers = self.get(url='/2')['headers'] - self.assertEqual( - headers['Content-Type'], - 'text/plain;charset=iso-8859-1', - '#2 Content-Type header', - ) - self.assertEqual( - headers['X-Content-Type'], - 'text/plain;charset=iso-8859-1', - '#2 response Content-Type', - ) - self.assertEqual( - headers['X-Character-Encoding'], - 'iso-8859-1', - '#2 response charset', - ) + assert ( + headers['Content-Type'] == 'text/plain;charset=iso-8859-1' + ), '#2 Content-Type header' + assert ( + headers['X-Content-Type'] == 'text/plain;charset=iso-8859-1' + ), '#2 response Content-Type' + assert ( + headers['X-Character-Encoding'] == 'iso-8859-1' + ), '#2 response charset' headers = self.get(url='/3')['headers'] - self.assertEqual( - headers['Content-Type'], - 'text/plain;charset=windows-1251', - '#3 Content-Type header', - ) - self.assertEqual( - headers['X-Content-Type'], - 'text/plain;charset=windows-1251', - '#3 response Content-Type', - ) - self.assertEqual( - headers['X-Character-Encoding'], - 'windows-1251', - '#3 response charset', - ) + assert ( + headers['Content-Type'] == 'text/plain;charset=windows-1251' + ), '#3 Content-Type header' + assert ( + headers['X-Content-Type'] == 'text/plain;charset=windows-1251' + ), '#3 response Content-Type' + assert ( + headers['X-Character-Encoding'] == 'windows-1251' + ), '#3 response charset' headers = self.get(url='/4')['headers'] - self.assertEqual( - headers['Content-Type'], - 'text/plain;charset=windows-1251', - '#4 Content-Type header', - ) - self.assertEqual( - headers['X-Content-Type'], - 'text/plain;charset=windows-1251', - '#4 response Content-Type', - ) - self.assertEqual( - headers['X-Character-Encoding'], - 'windows-1251', - '#4 response charset', - ) + assert ( + headers['Content-Type'] == 'text/plain;charset=windows-1251' + ), '#4 Content-Type header' + assert ( + headers['X-Content-Type'] == 'text/plain;charset=windows-1251' + ), '#4 response Content-Type' + assert ( + headers['X-Character-Encoding'] == 'windows-1251' + ), '#4 response charset' headers = self.get(url='/5')['headers'] - self.assertEqual( - headers['Content-Type'], - 'text/plain;charset=iso-8859-1', - '#5 Content-Type header', - ) - self.assertEqual( - headers['X-Content-Type'], - 'text/plain;charset=iso-8859-1', - '#5 response Content-Type', - ) - self.assertEqual( - headers['X-Character-Encoding'], - 'iso-8859-1', - '#5 response charset', - ) + assert ( + headers['Content-Type'] == 'text/plain;charset=iso-8859-1' + ), '#5 Content-Type header' + assert ( + headers['X-Content-Type'] == 'text/plain;charset=iso-8859-1' + ), '#5 response Content-Type' + assert ( + headers['X-Character-Encoding'] == 'iso-8859-1' + ), '#5 response charset' headers = self.get(url='/6')['headers'] - self.assertEqual( - 'Content-Type' in headers, False, '#6 no Content-Type header' - ) - self.assertEqual( - 'X-Content-Type' in headers, False, '#6 no response Content-Type' - ) - self.assertEqual( - headers['X-Character-Encoding'], 'utf-8', '#6 response charset' - ) + assert ( + 'Content-Type' in headers + ) == False, '#6 no Content-Type header' + assert ( + 'X-Content-Type' in headers + ) == False, '#6 no response Content-Type' + assert ( + headers['X-Character-Encoding'] == 'utf-8' + ), '#6 response charset' headers = self.get(url='/7')['headers'] - self.assertEqual( - headers['Content-Type'], - 'text/plain;charset=utf-8', - '#7 Content-Type header', - ) - self.assertEqual( - headers['X-Content-Type'], - 'text/plain;charset=utf-8', - '#7 response Content-Type', - ) - self.assertEqual( - headers['X-Character-Encoding'], 'utf-8', '#7 response charset' - ) + assert ( + headers['Content-Type'] == 'text/plain;charset=utf-8' + ), '#7 Content-Type header' + assert ( + headers['X-Content-Type'] == 'text/plain;charset=utf-8' + ), '#7 response Content-Type' + assert ( + headers['X-Character-Encoding'] == 'utf-8' + ), '#7 response charset' headers = self.get(url='/8')['headers'] - self.assertEqual( - headers['Content-Type'], - 'text/html;charset=utf-8', - '#8 Content-Type header', - ) - self.assertEqual( - headers['X-Content-Type'], - 'text/html;charset=utf-8', - '#8 response Content-Type', - ) - self.assertEqual( - headers['X-Character-Encoding'], 'utf-8', '#8 response charset' - ) + assert ( + headers['Content-Type'] == 'text/html;charset=utf-8' + ), '#8 Content-Type header' + assert ( + headers['X-Content-Type'] == 'text/html;charset=utf-8' + ), '#8 response Content-Type' + assert ( + headers['X-Character-Encoding'] == 'utf-8' + ), '#8 response charset' def test_java_application_welcome_files(self): self.load('welcome_files') @@ -579,126 +484,90 @@ class TestJavaApplication(TestApplicationJava): resp = self.get(url='/dir1') - self.assertEqual(resp['status'], 302, 'dir redirect expected') + assert resp['status'] == 302, 'dir redirect expected' resp = self.get(url='/dir1/') - self.assertEqual( - 'This is index.txt.' in resp['body'], True, 'dir1 index body' - ) - self.assertEqual( - resp['headers']['X-TXT-Filter'], '1', 'TXT Filter header' - ) + assert ( + 'This is index.txt.' in resp['body'] + ) == True, 'dir1 index body' + assert resp['headers']['X-TXT-Filter'] == '1', 'TXT Filter header' headers = self.get(url='/dir2/')['headers'] - self.assertEqual(headers['X-Unit-JSP'], 'ok', 'JSP Ok header') - self.assertEqual(headers['X-JSP-Filter'], '1', 'JSP Filter header') + assert headers['X-Unit-JSP'] == 'ok', 'JSP Ok header' + assert headers['X-JSP-Filter'] == '1', 'JSP Filter header' headers = self.get(url='/dir3/')['headers'] - self.assertEqual( - headers['X-App-Servlet'], '1', 'URL pattern overrides welcome file' - ) + assert ( + headers['X-App-Servlet'] == '1' + ), 'URL pattern overrides welcome file' headers = self.get(url='/dir4/')['headers'] - self.assertEqual( - 'X-App-Servlet' in headers, - False, - 'Static welcome file served first', - ) + assert ( + 'X-App-Servlet' in headers + ) == False, 'Static welcome file served first' headers = self.get(url='/dir5/')['headers'] - self.assertEqual( - headers['X-App-Servlet'], - '1', - 'Servlet for welcome file served when no static file found', - ) + assert ( + headers['X-App-Servlet'] == '1' + ), 'Servlet for welcome file served when no static file found' def test_java_application_request_listeners(self): self.load('request_listeners') headers = self.get(url='/test1')['headers'] - self.assertEqual( - headers['X-Request-Initialized'], - '/test1', - 'request initialized event', - ) - self.assertEqual( - headers['X-Request-Destroyed'], '', 'request destroyed event' - ) - self.assertEqual(headers['X-Attr-Added'], '', 'attribute added event') - self.assertEqual( - headers['X-Attr-Removed'], '', 'attribute removed event' - ) - self.assertEqual( - headers['X-Attr-Replaced'], '', 'attribute replaced event' - ) + assert ( + headers['X-Request-Initialized'] == '/test1' + ), 'request initialized event' + assert headers['X-Request-Destroyed'] == '', 'request destroyed event' + assert headers['X-Attr-Added'] == '', 'attribute added event' + assert headers['X-Attr-Removed'] == '', 'attribute removed event' + assert headers['X-Attr-Replaced'] == '', 'attribute replaced event' headers = self.get(url='/test2?var1=1')['headers'] - self.assertEqual( - headers['X-Request-Initialized'], - '/test2', - 'request initialized event', - ) - self.assertEqual( - headers['X-Request-Destroyed'], '/test1', 'request destroyed event' - ) - self.assertEqual( - headers['X-Attr-Added'], 'var=1;', 'attribute added event' - ) - self.assertEqual( - headers['X-Attr-Removed'], 'var=1;', 'attribute removed event' - ) - self.assertEqual( - headers['X-Attr-Replaced'], '', 'attribute replaced event' - ) + assert ( + headers['X-Request-Initialized'] == '/test2' + ), 'request initialized event' + assert ( + headers['X-Request-Destroyed'] == '/test1' + ), 'request destroyed event' + assert headers['X-Attr-Added'] == 'var=1;', 'attribute added event' + assert headers['X-Attr-Removed'] == 'var=1;', 'attribute removed event' + assert headers['X-Attr-Replaced'] == '', 'attribute replaced event' headers = self.get(url='/test3?var1=1&var2=2')['headers'] - self.assertEqual( - headers['X-Request-Initialized'], - '/test3', - 'request initialized event', - ) - self.assertEqual( - headers['X-Request-Destroyed'], '/test2', 'request destroyed event' - ) - self.assertEqual( - headers['X-Attr-Added'], 'var=1;', 'attribute added event' - ) - self.assertEqual( - headers['X-Attr-Removed'], 'var=2;', 'attribute removed event' - ) - self.assertEqual( - headers['X-Attr-Replaced'], 'var=1;', 'attribute replaced event' - ) + assert ( + headers['X-Request-Initialized'] == '/test3' + ), 'request initialized event' + assert ( + headers['X-Request-Destroyed'] == '/test2' + ), 'request destroyed event' + assert headers['X-Attr-Added'] == 'var=1;', 'attribute added event' + assert headers['X-Attr-Removed'] == 'var=2;', 'attribute removed event' + assert ( + headers['X-Attr-Replaced'] == 'var=1;' + ), 'attribute replaced event' headers = self.get(url='/test4?var1=1&var2=2&var3=3')['headers'] - self.assertEqual( - headers['X-Request-Initialized'], - '/test4', - 'request initialized event', - ) - self.assertEqual( - headers['X-Request-Destroyed'], '/test3', 'request destroyed event' - ) - self.assertEqual( - headers['X-Attr-Added'], 'var=1;', 'attribute added event' - ) - self.assertEqual( - headers['X-Attr-Removed'], '', 'attribute removed event' - ) - self.assertEqual( - headers['X-Attr-Replaced'], - 'var=1;var=2;', - 'attribute replaced event', - ) + assert ( + headers['X-Request-Initialized'] == '/test4' + ), 'request initialized event' + assert ( + headers['X-Request-Destroyed'] == '/test3' + ), 'request destroyed event' + assert headers['X-Attr-Added'] == 'var=1;', 'attribute added event' + assert headers['X-Attr-Removed'] == '', 'attribute removed event' + assert ( + headers['X-Attr-Replaced'] == 'var=1;var=2;' + ), 'attribute replaced event' def test_java_application_request_uri_forward(self): self.load('forward') @@ -708,105 +577,67 @@ class TestJavaApplication(TestApplicationJava): ) headers = resp['headers'] - self.assertEqual( - headers['X-REQUEST-Id'], 'fwd', 'initial request servlet mapping' - ) - self.assertEqual( - headers['X-Forward-To'], - '/data/test?uri=new_uri&a=2&b=3', - 'forwarding triggered', - ) - self.assertEqual( - headers['X-REQUEST-Param-uri'], - '/data/test?uri=new_uri&a=2&b=3', - 'original uri parameter', - ) - self.assertEqual( - headers['X-REQUEST-Param-a'], '1', 'original a parameter' - ) - self.assertEqual( - headers['X-REQUEST-Param-c'], '4', 'original c parameter' - ) - - self.assertEqual( - headers['X-FORWARD-Id'], 'data', 'forward request servlet mapping' - ) - self.assertEqual( - headers['X-FORWARD-Request-URI'], - '/data/test', - 'forward request uri', - ) - self.assertEqual( - headers['X-FORWARD-Servlet-Path'], - '/data', - 'forward request servlet path', - ) - self.assertEqual( - headers['X-FORWARD-Path-Info'], - '/test', - 'forward request path info', - ) - self.assertEqual( - headers['X-FORWARD-Query-String'], - 'uri=new_uri&a=2&b=3', - 'forward request query string', - ) - self.assertEqual( - headers['X-FORWARD-Param-uri'], - 'new_uri,/data/test?uri=new_uri&a=2&b=3', - 'forward uri parameter', - ) - self.assertEqual( - headers['X-FORWARD-Param-a'], '2,1', 'forward a parameter' - ) - self.assertEqual( - headers['X-FORWARD-Param-b'], '3', 'forward b parameter' - ) - self.assertEqual( - headers['X-FORWARD-Param-c'], '4', 'forward c parameter' - ) - - self.assertEqual( - headers['X-javax.servlet.forward.request_uri'], - '/fwd', - 'original request uri', - ) - self.assertEqual( - headers['X-javax.servlet.forward.context_path'], - '', - 'original request context path', - ) - self.assertEqual( - headers['X-javax.servlet.forward.servlet_path'], - '/fwd', - 'original request servlet path', - ) - self.assertEqual( - headers['X-javax.servlet.forward.path_info'], - 'null', - 'original request path info', - ) - self.assertEqual( - headers['X-javax.servlet.forward.query_string'], - 'uri=%2Fdata%2Ftest%3Furi%3Dnew_uri%26a%3D2%26b%3D3&a=1&c=4', - 'original request query', - ) - - self.assertEqual( - 'Before forwarding' in resp['body'], - False, - 'discarded data added before forward() call', - ) - self.assertEqual( - 'X-After-Forwarding' in headers, - False, - 'cannot add headers after forward() call', - ) - self.assertEqual( - 'After forwarding' in resp['body'], - False, - 'cannot add data after forward() call', - ) + assert ( + headers['X-REQUEST-Id'] == 'fwd' + ), 'initial request servlet mapping' + assert ( + headers['X-Forward-To'] == '/data/test?uri=new_uri&a=2&b=3' + ), 'forwarding triggered' + assert ( + headers['X-REQUEST-Param-uri'] == '/data/test?uri=new_uri&a=2&b=3' + ), 'original uri parameter' + assert headers['X-REQUEST-Param-a'] == '1', 'original a parameter' + assert headers['X-REQUEST-Param-c'] == '4', 'original c parameter' + + assert ( + headers['X-FORWARD-Id'] == 'data' + ), 'forward request servlet mapping' + assert ( + headers['X-FORWARD-Request-URI'] == '/data/test' + ), 'forward request uri' + assert ( + headers['X-FORWARD-Servlet-Path'] == '/data' + ), 'forward request servlet path' + assert ( + headers['X-FORWARD-Path-Info'] == '/test' + ), 'forward request path info' + assert ( + headers['X-FORWARD-Query-String'] == 'uri=new_uri&a=2&b=3' + ), 'forward request query string' + assert ( + headers['X-FORWARD-Param-uri'] + == 'new_uri,/data/test?uri=new_uri&a=2&b=3' + ), 'forward uri parameter' + assert headers['X-FORWARD-Param-a'] == '2,1', 'forward a parameter' + assert headers['X-FORWARD-Param-b'] == '3', 'forward b parameter' + assert headers['X-FORWARD-Param-c'] == '4', 'forward c parameter' + + assert ( + headers['X-javax.servlet.forward.request_uri'] == '/fwd' + ), 'original request uri' + assert ( + headers['X-javax.servlet.forward.context_path'] == '' + ), 'original request context path' + assert ( + headers['X-javax.servlet.forward.servlet_path'] == '/fwd' + ), 'original request servlet path' + assert ( + headers['X-javax.servlet.forward.path_info'] == 'null' + ), 'original request path info' + assert ( + headers['X-javax.servlet.forward.query_string'] + == 'uri=%2Fdata%2Ftest%3Furi%3Dnew_uri%26a%3D2%26b%3D3&a=1&c=4' + ), 'original request query' + + assert ( + 'Before forwarding' in resp['body'] + ) == False, 'discarded data added before forward() call' + assert ( + 'X-After-Forwarding' in headers + ) == False, 'cannot add headers after forward() call' + assert ( + 'After forwarding' in resp['body'] + ) == False, 'cannot add data after forward() call' def test_java_application_named_dispatcher_forward(self): self.load('forward') @@ -814,74 +645,52 @@ class TestJavaApplication(TestApplicationJava): resp = self.get(url='/fwd?disp=name&uri=data') headers = resp['headers'] - self.assertEqual( - headers['X-REQUEST-Id'], 'fwd', 'initial request servlet mapping' - ) - self.assertEqual( - headers['X-Forward-To'], 'data', 'forwarding triggered' - ) - - self.assertEqual( - headers['X-FORWARD-Id'], 'data', 'forward request servlet mapping' - ) - self.assertEqual( - headers['X-FORWARD-Request-URI'], '/fwd', 'forward request uri' - ) - self.assertEqual( - headers['X-FORWARD-Servlet-Path'], - '/fwd', - 'forward request servlet path', - ) - self.assertEqual( - headers['X-FORWARD-Path-Info'], 'null', 'forward request path info' - ) - self.assertEqual( - headers['X-FORWARD-Query-String'], - 'disp=name&uri=data', - 'forward request query string', - ) - - self.assertEqual( - headers['X-javax.servlet.forward.request_uri'], - 'null', - 'original request uri', - ) - self.assertEqual( - headers['X-javax.servlet.forward.context_path'], - 'null', - 'original request context path', - ) - self.assertEqual( - headers['X-javax.servlet.forward.servlet_path'], - 'null', - 'original request servlet path', - ) - self.assertEqual( - headers['X-javax.servlet.forward.path_info'], - 'null', - 'original request path info', - ) - self.assertEqual( - headers['X-javax.servlet.forward.query_string'], - 'null', - 'original request query', - ) - - self.assertEqual( - 'Before forwarding' in resp['body'], - False, - 'discarded data added before forward() call', - ) - self.assertEqual( - 'X-After-Forwarding' in headers, - False, - 'cannot add headers after forward() call', - ) - self.assertEqual( - 'After forwarding' in resp['body'], - False, - 'cannot add data after forward() call', - ) + assert ( + headers['X-REQUEST-Id'] == 'fwd' + ), 'initial request servlet mapping' + assert headers['X-Forward-To'] == 'data', 'forwarding triggered' + + assert ( + headers['X-FORWARD-Id'] == 'data' + ), 'forward request servlet mapping' + assert ( + headers['X-FORWARD-Request-URI'] == '/fwd' + ), 'forward request uri' + assert ( + headers['X-FORWARD-Servlet-Path'] == '/fwd' + ), 'forward request servlet path' + assert ( + headers['X-FORWARD-Path-Info'] == 'null' + ), 'forward request path info' + assert ( + headers['X-FORWARD-Query-String'] == 'disp=name&uri=data' + ), 'forward request query string' + + assert ( + headers['X-javax.servlet.forward.request_uri'] == 'null' + ), 'original request uri' + assert ( + headers['X-javax.servlet.forward.context_path'] == 'null' + ), 'original request context path' + assert ( + headers['X-javax.servlet.forward.servlet_path'] == 'null' + ), 'original request servlet path' + assert ( + headers['X-javax.servlet.forward.path_info'] == 'null' + ), 'original request path info' + assert ( + headers['X-javax.servlet.forward.query_string'] == 'null' + ), 'original request query' + + assert ( + 'Before forwarding' in resp['body'] + ) == False, 'discarded data added before forward() call' + assert ( + 'X-After-Forwarding' in headers + ) == False, 'cannot add headers after forward() call' + assert ( + 'After forwarding' in resp['body'] + ) == False, 'cannot add data after forward() call' def test_java_application_request_uri_include(self): self.load('include') @@ -890,55 +699,40 @@ class TestJavaApplication(TestApplicationJava): headers = resp['headers'] body = resp['body'] - self.assertEqual( - headers['X-REQUEST-Id'], 'inc', 'initial request servlet mapping' - ) - self.assertEqual( - headers['X-Include'], '/data/test', 'including triggered' - ) - - self.assertEqual( - 'X-INCLUDE-Id' in headers, - False, - 'unable to add headers in include request', - ) - - self.assertEqual( - 'javax.servlet.include.request_uri: /data/test' in body, - True, - 'include request uri', - ) - # self.assertEqual('javax.servlet.include.context_path: ' in body, - # 'include request context path') - self.assertEqual( - 'javax.servlet.include.servlet_path: /data' in body, - True, - 'include request servlet path', - ) - self.assertEqual( - 'javax.servlet.include.path_info: /test' in body, - True, - 'include request path info', - ) - self.assertEqual( - 'javax.servlet.include.query_string: null' in body, - True, - 'include request query', - ) - - self.assertEqual( - 'Before include' in body, - True, - 'preserve data added before include() call', - ) - self.assertEqual( - headers['X-After-Include'], - 'you-should-see-this', - 'add headers after include() call', - ) - self.assertEqual( - 'After include' in body, True, 'add data after include() call' - ) + assert ( + headers['X-REQUEST-Id'] == 'inc' + ), 'initial request servlet mapping' + assert headers['X-Include'] == '/data/test', 'including triggered' + + assert ( + 'X-INCLUDE-Id' in headers + ) == False, 'unable to add headers in include request' + + assert ( + 'javax.servlet.include.request_uri: /data/test' in body + ) == True, 'include request uri' + #assert ( + # 'javax.servlet.include.context_path: ' in body + #) == True, 'include request context path' + assert ( + 'javax.servlet.include.servlet_path: /data' in body + ) == True, 'include request servlet path' + assert ( + 'javax.servlet.include.path_info: /test' in body + ) == True, 'include request path info' + assert ( + 'javax.servlet.include.query_string: null' in body + ) == True, 'include request query' + + assert ( + 'Before include' in body + ) == True, 'preserve data added before include() call' + assert ( + headers['X-After-Include'] == 'you-should-see-this' + ), 'add headers after include() call' + assert ( + 'After include' in body + ) == True, 'add data after include() call' def test_java_application_named_dispatcher_include(self): self.load('include') @@ -947,144 +741,105 @@ class TestJavaApplication(TestApplicationJava): headers = resp['headers'] body = resp['body'] - self.assertEqual( - headers['X-REQUEST-Id'], 'inc', 'initial request servlet mapping' - ) - self.assertEqual(headers['X-Include'], 'data', 'including triggered') - - self.assertEqual( - 'X-INCLUDE-Id' in headers, - False, - 'unable to add headers in include request', - ) - - self.assertEqual( - 'javax.servlet.include.request_uri: null' in body, - True, - 'include request uri', - ) - # self.assertEqual('javax.servlet.include.context_path: null' in body, - # 'include request context path') - self.assertEqual( - 'javax.servlet.include.servlet_path: null' in body, - True, - 'include request servlet path', - ) - self.assertEqual( - 'javax.servlet.include.path_info: null' in body, - True, - 'include request path info', - ) - self.assertEqual( - 'javax.servlet.include.query_string: null' in body, - True, - 'include request query', - ) - - self.assertEqual( - 'Before include' in body, - True, - 'preserve data added before include() call', - ) - self.assertEqual( - headers['X-After-Include'], - 'you-should-see-this', - 'add headers after include() call', - ) - self.assertEqual( - 'After include' in body, True, 'add data after include() call' - ) + assert ( + headers['X-REQUEST-Id'] == 'inc' + ), 'initial request servlet mapping' + assert headers['X-Include'] == 'data', 'including triggered' + + assert ( + 'X-INCLUDE-Id' in headers + ) == False, 'unable to add headers in include request' + + assert ( + 'javax.servlet.include.request_uri: null' in body + ) == True, 'include request uri' + #assert ( + # 'javax.servlet.include.context_path: null' in body + #) == True, 'include request context path' + assert ( + 'javax.servlet.include.servlet_path: null' in body + ) == True, 'include request servlet path' + assert ( + 'javax.servlet.include.path_info: null' in body + ) == True, 'include request path info' + assert ( + 'javax.servlet.include.query_string: null' in body + ) == True, 'include request query' + + assert ( + 'Before include' in body + ) == True, 'preserve data added before include() call' + assert ( + headers['X-After-Include'] == 'you-should-see-this' + ), 'add headers after include() call' + assert ( + 'After include' in body + ) == True, 'add data after include() call' def test_java_application_path_translation(self): self.load('path_translation') headers = self.get(url='/pt/test?path=/')['headers'] - self.assertEqual( - headers['X-Servlet-Path'], '/pt', 'matched servlet path' - ) - self.assertEqual( - headers['X-Path-Info'], '/test', 'the rest of the path' - ) - self.assertEqual( - headers['X-Path-Translated'], - headers['X-Real-Path'] + headers['X-Path-Info'], - 'translated path is the app root + path info', - ) - self.assertEqual( - headers['X-Resource-Paths'].endswith('/WEB-INF/, /index.html]'), - True, - 'app root directory content', - ) - self.assertEqual( - headers['X-Resource-As-Stream'], - 'null', - 'no resource stream for root path', - ) + assert headers['X-Servlet-Path'] == '/pt', 'matched servlet path' + assert headers['X-Path-Info'] == '/test', 'the rest of the path' + assert ( + headers['X-Path-Translated'] + == headers['X-Real-Path'] + headers['X-Path-Info'] + ), 'translated path is the app root + path info' + assert ( + headers['X-Resource-Paths'].endswith('/WEB-INF/, /index.html]') + == True + ), 'app root directory content' + assert ( + headers['X-Resource-As-Stream'] == 'null' + ), 'no resource stream for root path' headers = self.get(url='/test?path=/none')['headers'] - self.assertEqual( - headers['X-Servlet-Path'], '/test', 'matched whole path' - ) - self.assertEqual( - headers['X-Path-Info'], - 'null', - 'the rest of the path is null, whole path matched', - ) - self.assertEqual( - headers['X-Path-Translated'], - 'null', - 'translated path is null because path info is null', - ) - self.assertEqual( - headers['X-Real-Path'].endswith('/none'), - True, - 'read path is not null', - ) - self.assertEqual( - headers['X-Resource-Paths'], 'null', 'no resource found' - ) - self.assertEqual( - headers['X-Resource-As-Stream'], 'null', 'no resource stream' - ) + assert headers['X-Servlet-Path'] == '/test', 'matched whole path' + assert ( + headers['X-Path-Info'] == 'null' + ), 'the rest of the path is null, whole path matched' + assert ( + headers['X-Path-Translated'] == 'null' + ), 'translated path is null because path info is null' + assert ( + headers['X-Real-Path'].endswith('/none') == True + ), 'read path is not null' + assert headers['X-Resource-Paths'] == 'null', 'no resource found' + assert headers['X-Resource-As-Stream'] == 'null', 'no resource stream' def test_java_application_query_string(self): self.load('query_string') - self.assertEqual( - self.get(url='/?a=b')['headers']['X-Query-String'], - 'a=b', - 'query string', - ) + assert ( + self.get(url='/?a=b')['headers']['X-Query-String'] == 'a=b' + ), 'query string' def test_java_application_query_empty(self): self.load('query_string') - self.assertEqual( - self.get(url='/?')['headers']['X-Query-String'], - '', - 'query string empty', - ) + assert ( + self.get(url='/?')['headers']['X-Query-String'] == '' + ), 'query string empty' def test_java_application_query_absent(self): self.load('query_string') - self.assertEqual( - self.get()['headers']['X-Query-String'], - 'null', - 'query string absent', - ) + assert ( + self.get()['headers']['X-Query-String'] == 'null' + ), 'query string absent' def test_java_application_empty(self): self.load('empty') - self.assertEqual(self.get()['status'], 200, 'empty') + assert self.get()['status'] == 200, 'empty' def test_java_application_keepalive_body(self): self.load('mirror') - self.assertEqual(self.post()['status'], 200, 'init') + assert self.post()['status'] == 200, 'init' body = '0123456789' * 500 (resp, sock) = self.post( @@ -1098,7 +853,7 @@ class TestJavaApplication(TestApplicationJava): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'keep-alive 1') + assert resp['body'] == body, 'keep-alive 1' body = '0123456789' resp = self.post( @@ -1111,22 +866,22 @@ class TestJavaApplication(TestApplicationJava): body=body, ) - self.assertEqual(resp['body'], body, 'keep-alive 2') + assert resp['body'] == body, 'keep-alive 2' def test_java_application_http_10(self): self.load('empty') - self.assertEqual(self.get(http_10=True)['status'], 200, 'HTTP 1.0') + assert self.get(http_10=True)['status'] == 200, 'HTTP 1.0' def test_java_application_no_method(self): self.load('empty') - self.assertEqual(self.post()['status'], 405, 'no method') + assert self.post()['status'] == 405, 'no method' def test_java_application_get_header(self): self.load('get_header') - self.assertEqual( + assert ( self.get( headers={ 'X-Header': 'blah', @@ -1134,15 +889,14 @@ class TestJavaApplication(TestApplicationJava): 'Host': 'localhost', 'Connection': 'close', } - )['headers']['X-Reply'], - 'blah', - 'get header', - ) + )['headers']['X-Reply'] + == 'blah' + ), 'get header' def test_java_application_get_header_empty(self): self.load('get_header') - self.assertNotIn('X-Reply', self.get()['headers'], 'get header empty') + assert 'X-Reply' not in self.get()['headers'], 'get header empty' def test_java_application_get_headers(self): self.load('get_headers') @@ -1156,32 +910,28 @@ class TestJavaApplication(TestApplicationJava): } )['headers'] - self.assertEqual(headers['X-Reply-0'], 'blah', 'get headers') - self.assertEqual(headers['X-Reply-1'], 'blah', 'get headers 2') + assert headers['X-Reply-0'] == 'blah', 'get headers' + assert headers['X-Reply-1'] == 'blah', 'get headers 2' def test_java_application_get_headers_empty(self): self.load('get_headers') - self.assertNotIn( - 'X-Reply-0', self.get()['headers'], 'get headers empty' - ) + assert 'X-Reply-0' not in self.get()['headers'], 'get headers empty' def test_java_application_get_header_names(self): self.load('get_header_names') headers = self.get()['headers'] - self.assertRegex( - headers['X-Reply-0'], r'(?:Host|Connection)', 'get header names' - ) - self.assertRegex( - headers['X-Reply-1'], r'(?:Host|Connection)', 'get header names 2' - ) - self.assertNotEqual( - headers['X-Reply-0'], - headers['X-Reply-1'], - 'get header names not equal', - ) + assert re.search( + r'(?:Host|Connection)', headers['X-Reply-0'] + ), 'get header names' + assert re.search( + r'(?:Host|Connection)', headers['X-Reply-1'] + ), 'get header names 2' + assert ( + headers['X-Reply-0'] != headers['X-Reply-1'] + ), 'get header names not equal' def test_java_application_header_int(self): self.load('header_int') @@ -1195,8 +945,8 @@ class TestJavaApplication(TestApplicationJava): } )['headers'] - self.assertEqual(headers['X-Set-Int'], '1', 'set int header') - self.assertEqual(headers['X-Get-Int'], '2', 'get int header') + assert headers['X-Set-Int'] == '1', 'set int header' + assert headers['X-Get-Int'] == '2', 'get int header' def test_java_application_header_date(self): self.load('header_date') @@ -1212,20 +962,18 @@ class TestJavaApplication(TestApplicationJava): } )['headers'] - self.assertEqual( - headers['X-Set-Date'], - 'Thu, 01 Jan 1970 00:00:01 GMT', - 'set date header', - ) - self.assertEqual(headers['X-Get-Date'], date, 'get date header') + assert ( + headers['X-Set-Date'] == 'Thu, 01 Jan 1970 00:00:01 GMT' + ), 'set date header' + assert headers['X-Get-Date'] == date, 'get date header' def test_java_application_multipart(self): self.load('multipart') reldst = '/uploads' - fulldst = self.testdir + reldst + fulldst = self.temp_dir + reldst os.mkdir(fulldst) - self.public_dir(fulldst) + public_dir(fulldst) fields = { 'file': { @@ -1252,16 +1000,13 @@ class TestJavaApplication(TestApplicationJava): body=body, ) - self.assertEqual(resp['status'], 200, 'multipart status') - self.assertRegex( - resp['body'], r'sample\.txt created', 'multipart body' - ) - self.assertIsNotNone( + assert resp['status'] == 200, 'multipart status' + assert re.search( + r'sample\.txt created', resp['body'] + ), 'multipart body' + assert ( self.search_in_log( r'^Data from sample file$', name=reldst + '/sample.txt' - ), - 'file created', - ) - -if __name__ == '__main__': - TestJavaApplication.main() + ) + is not None + ), 'file created' diff --git a/test/test_java_isolation_rootfs.py b/test/test_java_isolation_rootfs.py index 4d39bdc3..fa227469 100644 --- a/test/test_java_isolation_rootfs.py +++ b/test/test_java_isolation_rootfs.py @@ -1,6 +1,6 @@ import os import subprocess -import unittest +import pytest from unit.applications.lang.java import TestApplicationJava @@ -8,15 +8,15 @@ from unit.applications.lang.java import TestApplicationJava class TestJavaIsolationRootfs(TestApplicationJava): prerequisites = {'modules': {'java': 'all'}} - def setUp(self): - if not self.is_su: - return + def setup_method(self, is_su): + super().setup_method() - super().setUp() + if not is_su: + return - os.makedirs(self.testdir + '/jars') - os.makedirs(self.testdir + '/tmp') - os.chmod(self.testdir + '/tmp', 0o777) + os.makedirs(self.temp_dir + '/jars') + os.makedirs(self.temp_dir + '/tmp') + os.chmod(self.temp_dir + '/tmp', 0o777) try: process = subprocess.Popen( @@ -24,7 +24,7 @@ class TestJavaIsolationRootfs(TestApplicationJava): "mount", "--bind", self.pardir + "/build", - self.testdir + "/jars", + self.temp_dir + "/jars", ], stderr=subprocess.STDOUT, ) @@ -32,54 +32,45 @@ class TestJavaIsolationRootfs(TestApplicationJava): process.communicate() except: - self.fail('Cann\'t run mount process.') + pytest.fail('Cann\'t run mount process.') - def tearDown(self): - if not self.is_su: + def teardown_method(self, is_su): + if not is_su: return try: process = subprocess.Popen( - ["umount", "--lazy", self.testdir + "/jars"], + ["umount", "--lazy", self.temp_dir + "/jars"], stderr=subprocess.STDOUT, ) process.communicate() except: - self.fail('Cann\'t run mount process.') + pytest.fail('Cann\'t run mount process.') # super teardown must happen after unmount to avoid deletion of /build - super().tearDown() + super().teardown_method() - def test_java_isolation_rootfs_chroot_war(self): - if not self.is_su: - print('require root') - raise unittest.SkipTest() + def test_java_isolation_rootfs_chroot_war(self, is_su): + if not is_su: + pytest.skip('require root') isolation = { - 'rootfs': self.testdir, + 'rootfs': self.temp_dir, } self.load('empty_war', isolation=isolation) - self.assertIn( - 'success', - self.conf( - '"/"', '/config/applications/empty_war/working_directory', - ), + assert 'success' in self.conf( + '"/"', '/config/applications/empty_war/working_directory', ) - self.assertIn( - 'success', self.conf('"/jars"', 'applications/empty_war/unit_jars') + assert 'success' in self.conf( + '"/jars"', 'applications/empty_war/unit_jars' ) - self.assertIn( - 'success', - self.conf('"/java/empty.war"', 'applications/empty_war/webapp'), + assert 'success' in self.conf( + '"/java/empty.war"', 'applications/empty_war/webapp' ) - self.assertEqual(self.get()['status'], 200, 'war') - - -if __name__ == '__main__': - TestJavaIsolationRootfs.main() + assert self.get()['status'] == 200, 'war' diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index d78f7263..1bbefa1e 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -1,9 +1,10 @@ +import pytest import struct import time -import unittest from unit.applications.lang.java import TestApplicationJava from unit.applications.websockets import TestApplicationWebsocket +from conftest import option, skip_alert class TestJavaWebsockets(TestApplicationJava): @@ -11,23 +12,17 @@ class TestJavaWebsockets(TestApplicationJava): ws = TestApplicationWebsocket() - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - self.assertIn( - 'success', - self.conf( - {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' - ), - 'clear keepalive_interval', - ) + assert 'success' in self.conf( + {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' + ), 'clear keepalive_interval' - self.skip_alerts.extend( - [r'socket close\(\d+\) failed'] - ) + skip_alert(r'socket close\(\d+\) failed') def close_connection(self, sock): - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) @@ -36,9 +31,9 @@ class TestJavaWebsockets(TestApplicationJava): def check_close(self, sock, code=1000, no_close=False): frame = self.ws.frame_read(sock) - self.assertEqual(frame['fin'], True, 'close fin') - self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'close opcode') - self.assertEqual(frame['code'], code, 'close code') + assert frame['fin'] == True, 'close fin' + assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode' + assert frame['code'] == code, 'close code' if not no_close: sock.close() @@ -49,9 +44,9 @@ class TestJavaWebsockets(TestApplicationJava): else: data = frame['data'].decode('utf-8') - self.assertEqual(frame['fin'], fin, 'fin') - self.assertEqual(frame['opcode'], opcode, 'opcode') - self.assertEqual(data, payload, 'payload') + assert frame['fin'] == fin, 'fin' + assert frame['opcode'] == opcode, 'opcode' + assert data == payload, 'payload' def test_java_websockets_handshake(self): self.load('websockets_mirror') @@ -59,14 +54,12 @@ class TestJavaWebsockets(TestApplicationJava): resp, sock, key = self.ws.upgrade() sock.close() - self.assertEqual(resp['status'], 101, 'status') - self.assertEqual(resp['headers']['Upgrade'], 'websocket', 'upgrade') - self.assertEqual( - resp['headers']['Connection'], 'Upgrade', 'connection' - ) - self.assertEqual( - resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key' - ) + assert resp['status'] == 101, 'status' + assert resp['headers']['Upgrade'] == 'websocket', 'upgrade' + assert resp['headers']['Connection'] == 'Upgrade', 'connection' + assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept( + key + ), 'key' def test_java_websockets_mirror(self): self.load('websockets_mirror') @@ -78,12 +71,12 @@ class TestJavaWebsockets(TestApplicationJava): self.ws.frame_write(sock, self.ws.OP_TEXT, message) frame = self.ws.frame_read(sock) - self.assertEqual(message, frame['data'].decode('utf-8'), 'mirror') + assert message == frame['data'].decode('utf-8'), 'mirror' self.ws.frame_write(sock, self.ws.OP_TEXT, message) frame = self.ws.frame_read(sock) - self.assertEqual(message, frame['data'].decode('utf-8'), 'mirror 2') + assert message == frame['data'].decode('utf-8'), 'mirror 2' sock.close() @@ -98,8 +91,8 @@ class TestJavaWebsockets(TestApplicationJava): frame = self.ws.frame_read(sock) - self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'no mask opcode') - self.assertEqual(frame['code'], 1002, 'no mask close code') + assert frame['opcode'] == self.ws.OP_CLOSE, 'no mask opcode' + assert frame['code'] == 1002, 'no mask close code' sock.close() @@ -116,11 +109,9 @@ class TestJavaWebsockets(TestApplicationJava): frame = self.ws.frame_read(sock) - self.assertEqual( - message + ' ' + message, - frame['data'].decode('utf-8'), - 'mirror framing', - ) + assert message + ' ' + message == frame['data'].decode( + 'utf-8' + ), 'mirror framing' sock.close() @@ -136,20 +127,16 @@ class TestJavaWebsockets(TestApplicationJava): frame = self.ws.frame_read(sock) frame.pop('data') - self.assertDictEqual( - frame, - { - 'fin': True, - 'rsv1': False, - 'rsv2': False, - 'rsv3': False, - 'opcode': self.ws.OP_CLOSE, - 'mask': 0, - 'code': 1002, - 'reason': 'Fragmented control frame', - }, - 'close frame', - ) + assert frame == { + 'fin': True, + 'rsv1': False, + 'rsv2': False, + 'rsv3': False, + 'opcode': self.ws.OP_CLOSE, + 'mask': 0, + 'code': 1002, + 'reason': 'Fragmented control frame', + }, 'close frame' sock.close() @@ -168,13 +155,13 @@ class TestJavaWebsockets(TestApplicationJava): frame1 = self.ws.frame_read(sock1) frame2 = self.ws.frame_read(sock2) - self.assertEqual(message1, frame1['data'].decode('utf-8'), 'client 1') - self.assertEqual(message2, frame2['data'].decode('utf-8'), 'client 2') + assert message1 == frame1['data'].decode('utf-8'), 'client 1' + assert message2 == frame2['data'].decode('utf-8'), 'client 2' sock1.close() sock2.close() - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_java_websockets_handshake_upgrade_absent( self ): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1 @@ -190,7 +177,7 @@ class TestJavaWebsockets(TestApplicationJava): }, ) - self.assertEqual(resp['status'], 400, 'upgrade absent') + assert resp['status'] == 400, 'upgrade absent' def test_java_websockets_handshake_case_insensitive(self): self.load('websockets_mirror') @@ -207,9 +194,9 @@ class TestJavaWebsockets(TestApplicationJava): ) sock.close() - self.assertEqual(resp['status'], 101, 'status') + assert resp['status'] == 101, 'status' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_java_websockets_handshake_connection_absent(self): # FAIL self.load('websockets_mirror') @@ -223,7 +210,7 @@ class TestJavaWebsockets(TestApplicationJava): }, ) - self.assertEqual(resp['status'], 400, 'status') + assert resp['status'] == 400, 'status' def test_java_websockets_handshake_version_absent(self): self.load('websockets_mirror') @@ -238,9 +225,9 @@ class TestJavaWebsockets(TestApplicationJava): }, ) - self.assertEqual(resp['status'], 426, 'status') + assert resp['status'] == 426, 'status' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_java_websockets_handshake_key_invalid(self): self.load('websockets_mirror') @@ -255,7 +242,7 @@ class TestJavaWebsockets(TestApplicationJava): }, ) - self.assertEqual(resp['status'], 400, 'key length') + assert resp['status'] == 400, 'key length' key = self.ws.key() resp = self.get( @@ -269,9 +256,7 @@ class TestJavaWebsockets(TestApplicationJava): }, ) - self.assertEqual( - resp['status'], 400, 'key double' - ) # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1 + assert resp['status'] == 400, 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1 def test_java_websockets_handshake_method_invalid(self): self.load('websockets_mirror') @@ -287,7 +272,7 @@ class TestJavaWebsockets(TestApplicationJava): }, ) - self.assertEqual(resp['status'], 400, 'status') + assert resp['status'] == 400, 'status' def test_java_websockets_handshake_http_10(self): self.load('websockets_mirror') @@ -304,7 +289,7 @@ class TestJavaWebsockets(TestApplicationJava): http_10=True, ) - self.assertEqual(resp['status'], 400, 'status') + assert resp['status'] == 400, 'status' def test_java_websockets_handshake_uri_invalid(self): self.load('websockets_mirror') @@ -321,7 +306,7 @@ class TestJavaWebsockets(TestApplicationJava): url='!', ) - self.assertEqual(resp['status'], 400, 'status') + assert resp['status'] == 400, 'status' def test_java_websockets_protocol_absent(self): self.load('websockets_mirror') @@ -338,14 +323,12 @@ class TestJavaWebsockets(TestApplicationJava): ) sock.close() - self.assertEqual(resp['status'], 101, 'status') - self.assertEqual(resp['headers']['Upgrade'], 'websocket', 'upgrade') - self.assertEqual( - resp['headers']['Connection'], 'Upgrade', 'connection' - ) - self.assertEqual( - resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key' - ) + assert resp['status'] == 101, 'status' + assert resp['headers']['Upgrade'] == 'websocket', 'upgrade' + assert resp['headers']['Connection'] == 'Upgrade', 'connection' + assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept( + key + ), 'key' # autobahn-testsuite # @@ -442,12 +425,12 @@ class TestJavaWebsockets(TestApplicationJava): _, sock, _ = self.ws.upgrade() self.ws.frame_write(sock, self.ws.OP_PONG, '') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '2_7') + assert self.recvall(sock, read_timeout=0.1) == b'', '2_7' # 2_8 self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '2_8') + assert self.recvall(sock, read_timeout=0.1) == b'', '2_8' # 2_9 @@ -487,7 +470,7 @@ class TestJavaWebsockets(TestApplicationJava): self.close_connection(sock) - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_java_websockets_3_1__3_7(self): self.load('websockets_mirror') @@ -513,7 +496,7 @@ class TestJavaWebsockets(TestApplicationJava): self.check_close(sock, 1002, no_close=True) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty 3_2') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_2' sock.close() # 3_3 @@ -531,7 +514,7 @@ class TestJavaWebsockets(TestApplicationJava): self.check_close(sock, 1002, no_close=True) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty 3_3') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_3' sock.close() # 3_4 @@ -549,7 +532,7 @@ class TestJavaWebsockets(TestApplicationJava): self.check_close(sock, 1002, no_close=True) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty 3_4') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_4' sock.close() # 3_5 @@ -735,7 +718,7 @@ class TestJavaWebsockets(TestApplicationJava): # 5_4 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '5_4') + assert self.recvall(sock, read_timeout=0.1) == b'', '5_4' self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) frame = self.ws.frame_read(sock) @@ -772,7 +755,7 @@ class TestJavaWebsockets(TestApplicationJava): ping_payload = 'ping payload' self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '5_7') + assert self.recvall(sock, read_timeout=0.1) == b'', '5_7' self.ws.frame_write(sock, self.ws.OP_PING, ping_payload) @@ -956,7 +939,7 @@ class TestJavaWebsockets(TestApplicationJava): frame = self.ws.frame_read(sock) self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '5_20') + assert self.recvall(sock, read_timeout=0.1) == b'', '5_20' self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5') self.check_frame( @@ -1089,7 +1072,7 @@ class TestJavaWebsockets(TestApplicationJava): self.check_close(sock, no_close=True) self.ws.frame_write(sock, self.ws.OP_PING, '') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' sock.close() @@ -1101,7 +1084,7 @@ class TestJavaWebsockets(TestApplicationJava): self.check_close(sock, no_close=True) self.ws.frame_write(sock, self.ws.OP_TEXT, payload) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' sock.close() @@ -1114,7 +1097,7 @@ class TestJavaWebsockets(TestApplicationJava): self.check_close(sock, no_close=True) self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' sock.close() @@ -1129,7 +1112,7 @@ class TestJavaWebsockets(TestApplicationJava): self.recvall(sock, read_timeout=1) self.ws.frame_write(sock, self.ws.OP_PING, '') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' sock.close() @@ -1249,27 +1232,23 @@ class TestJavaWebsockets(TestApplicationJava): self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) self.check_close(sock, 1002) - def test_java_websockets_9_1_1__9_6_6(self): - if not self.unsafe: - self.skipTest("unsafe, long run") + def test_java_websockets_9_1_1__9_6_6(self, is_unsafe): + if not is_unsafe: + pytest.skip('unsafe, long run') self.load('websockets_mirror') - self.assertIn( - 'success', - self.conf( - { - 'http': { - 'websocket': { - 'max_frame_size': 33554432, - 'keepalive_interval': 0, - } + assert 'success' in self.conf( + { + 'http': { + 'websocket': { + 'max_frame_size': 33554432, + 'keepalive_interval': 0, } - }, - 'settings', - ), - 'increase max_frame_size and keepalive_interval', - ) + } + }, + 'settings', + ), 'increase max_frame_size and keepalive_interval' _, sock, _ = self.ws.upgrade() @@ -1310,7 +1289,7 @@ class TestJavaWebsockets(TestApplicationJava): check_payload(op_binary, 8 * 2 ** 20) # 9_2_5 check_payload(op_binary, 16 * 2 ** 20) # 9_2_6 - if self.system != 'Darwin' and self.system != 'FreeBSD': + if option.system != 'Darwin' and option.system != 'FreeBSD': check_message(op_text, 64) # 9_3_1 check_message(op_text, 256) # 9_3_2 check_message(op_text, 2 ** 10) # 9_3_3 @@ -1366,13 +1345,9 @@ class TestJavaWebsockets(TestApplicationJava): def test_java_websockets_max_frame_size(self): self.load('websockets_mirror') - self.assertIn( - 'success', - self.conf( - {'http': {'websocket': {'max_frame_size': 100}}}, 'settings' - ), - 'configure max_frame_size', - ) + assert 'success' in self.conf( + {'http': {'websocket': {'max_frame_size': 100}}}, 'settings' + ), 'configure max_frame_size' _, sock, _ = self.ws.upgrade() @@ -1392,13 +1367,9 @@ class TestJavaWebsockets(TestApplicationJava): def test_java_websockets_read_timeout(self): self.load('websockets_mirror') - self.assertIn( - 'success', - self.conf( - {'http': {'websocket': {'read_timeout': 5}}}, 'settings' - ), - 'configure read_timeout', - ) + assert 'success' in self.conf( + {'http': {'websocket': {'read_timeout': 5}}}, 'settings' + ), 'configure read_timeout' _, sock, _ = self.ws.upgrade() @@ -1412,13 +1383,9 @@ class TestJavaWebsockets(TestApplicationJava): def test_java_websockets_keepalive_interval(self): self.load('websockets_mirror') - self.assertIn( - 'success', - self.conf( - {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings' - ), - 'configure keepalive_interval', - ) + assert 'success' in self.conf( + {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings' + ), 'configure keepalive_interval' _, sock, _ = self.ws.upgrade() @@ -1431,7 +1398,3 @@ class TestJavaWebsockets(TestApplicationJava): self.check_frame(frame, True, self.ws.OP_PING, '') # PING frame sock.close() - - -if __name__ == '__main__': - TestJavaWebsockets.main() diff --git a/test/test_node_application.py b/test/test_node_application.py index e46cc6a1..c2b0ed69 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -1,6 +1,8 @@ -import unittest +import pytest +import re from unit.applications.lang.node import TestApplicationNode +from conftest import waitforfiles class TestNodeApplication(TestApplicationNode): @@ -10,16 +12,14 @@ class TestNodeApplication(TestApplicationNode): self.load('basic') resp = self.get() - self.assertEqual( - resp['headers']['Content-Type'], 'text/plain', 'basic header' - ) - self.assertEqual(resp['body'], 'Hello World\n', 'basic body') + assert resp['headers']['Content-Type'] == 'text/plain', 'basic header' + assert resp['body'] == 'Hello World\n', 'basic body' def test_node_application_seq(self): self.load('basic') - self.assertEqual(self.get()['status'], 200, 'seq') - self.assertEqual(self.get()['status'], 200, 'seq 2') + assert self.get()['status'] == 200, 'seq' + assert self.get()['status'] == 200, 'seq 2' def test_node_application_variables(self): self.load('variables') @@ -36,51 +36,44 @@ class TestNodeApplication(TestApplicationNode): body=body, ) - self.assertEqual(resp['status'], 200, 'status') + assert resp['status'] == 200, 'status' headers = resp['headers'] header_server = headers.pop('Server') - self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header') + assert re.search(r'Unit/[\d\.]+', header_server), 'server header' date = headers.pop('Date') - self.assertEqual(date[-4:], ' GMT', 'date header timezone') - self.assertLess( - abs(self.date_to_sec_epoch(date) - self.sec_epoch()), - 5, - 'date header', - ) + assert date[-4:] == ' GMT', 'date header timezone' + assert ( + abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5 + ), 'date header' raw_headers = headers.pop('Request-Raw-Headers') - self.assertRegex( - raw_headers, + assert re.search( r'^(?:Host|localhost|Content-Type|' 'text\/html|Custom-Header|blah|Content-Length|17|Connection|' 'close|,)+$', - 'raw headers', - ) - - self.assertDictEqual( - headers, - { - 'Connection': 'close', - 'Content-Length': str(len(body)), - 'Content-Type': 'text/html', - 'Request-Method': 'POST', - 'Request-Uri': '/', - 'Http-Host': 'localhost', - 'Server-Protocol': 'HTTP/1.1', - 'Custom-Header': 'blah', - }, - 'headers', - ) - self.assertEqual(resp['body'], body, 'body') + raw_headers, + ), 'raw headers' + + assert headers == { + 'Connection': 'close', + 'Content-Length': str(len(body)), + 'Content-Type': 'text/html', + 'Request-Method': 'POST', + 'Request-Uri': '/', + 'Http-Host': 'localhost', + 'Server-Protocol': 'HTTP/1.1', + 'Custom-Header': 'blah', + }, 'headers' + assert resp['body'] == body, 'body' def test_node_application_get_variables(self): self.load('get_variables') resp = self.get(url='/?var1=val1&var2=&var3') - self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'GET variables') - self.assertEqual(resp['headers']['X-Var-2'], '', 'GET variables 2') - self.assertEqual(resp['headers']['X-Var-3'], '', 'GET variables 3') + assert resp['headers']['X-Var-1'] == 'val1', 'GET variables' + assert resp['headers']['X-Var-2'] == '', 'GET variables 2' + assert resp['headers']['X-Var-3'] == '', 'GET variables 3' def test_node_application_post_variables(self): self.load('post_variables') @@ -94,24 +87,24 @@ class TestNodeApplication(TestApplicationNode): body='var1=val1&var2=&var3', ) - self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'POST variables') - self.assertEqual(resp['headers']['X-Var-2'], '', 'POST variables 2') - self.assertEqual(resp['headers']['X-Var-3'], '', 'POST variables 3') + assert resp['headers']['X-Var-1'] == 'val1', 'POST variables' + assert resp['headers']['X-Var-2'] == '', 'POST variables 2' + assert resp['headers']['X-Var-3'] == '', 'POST variables 3' def test_node_application_404(self): self.load('404') resp = self.get() - self.assertEqual(resp['status'], 404, '404 status') - self.assertRegex( - resp['body'], r'404 Not Found', '404 body' - ) + assert resp['status'] == 404, '404 status' + assert re.search( + r'404 Not Found', resp['body'] + ), '404 body' def test_node_keepalive_body(self): self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' body = '0123456789' * 500 (resp, sock) = self.post( @@ -125,7 +118,7 @@ class TestNodeApplication(TestApplicationNode): read_timeout=1, ) - self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1') + assert resp['body'] == '0123456789' * 500, 'keep-alive 1' body = '0123456789' resp = self.post( @@ -138,47 +131,34 @@ class TestNodeApplication(TestApplicationNode): body=body, ) - self.assertEqual(resp['body'], body, 'keep-alive 2') + assert resp['body'] == body, 'keep-alive 2' def test_node_application_write_buffer(self): self.load('write_buffer') - self.assertEqual( - self.get()['body'], 'buffer', 'write buffer' - ) + assert self.get()['body'] == 'buffer', 'write buffer' def test_node_application_write_callback(self): self.load('write_callback') - self.assertEqual( - self.get()['body'], - 'helloworld', - 'write callback order', - ) - self.assertTrue( - self.waitforfiles(self.testdir + '/node/callback'), - 'write callback', - ) + assert self.get()['body'] == 'helloworld', 'write callback order' + assert waitforfiles(self.temp_dir + '/node/callback'), 'write callback' def test_node_application_write_before_write_head(self): self.load('write_before_write_head') - self.assertEqual(self.get()['status'], 200, 'write before writeHead') + assert self.get()['status'] == 200, 'write before writeHead' def test_node_application_double_end(self): self.load('double_end') - self.assertEqual(self.get()['status'], 200, 'double end') - self.assertEqual(self.get()['status'], 200, 'double end 2') + assert self.get()['status'] == 200, 'double end' + assert self.get()['status'] == 200, 'double end 2' def test_node_application_write_return(self): self.load('write_return') - self.assertEqual( - self.get()['body'], - 'bodytrue', - 'write return', - ) + assert self.get()['body'] == 'bodytrue', 'write return' def test_node_application_remove_header(self): self.load('remove_header') @@ -190,69 +170,61 @@ class TestNodeApplication(TestApplicationNode): 'Connection': 'close', } ) - self.assertEqual(resp['headers']['Was-Header'], 'true', 'was header') - self.assertEqual(resp['headers']['Has-Header'], 'false', 'has header') - self.assertFalse('X-Header' in resp['headers'], 'remove header') + assert resp['headers']['Was-Header'] == 'true', 'was header' + assert resp['headers']['Has-Header'] == 'false', 'has header' + assert not ('X-Header' in resp['headers']), 'remove header' def test_node_application_remove_header_nonexisting(self): self.load('remove_header') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Remove': 'blah', 'Connection': 'close', } - )['headers']['Has-Header'], - 'true', - 'remove header nonexisting', - ) + )['headers']['Has-Header'] + == 'true' + ), 'remove header nonexisting' def test_node_application_update_header(self): self.load('update_header') - self.assertEqual( - self.get()['headers']['X-Header'], 'new', 'update header' - ) + assert self.get()['headers']['X-Header'] == 'new', 'update header' def test_node_application_set_header_array(self): self.load('set_header_array') - self.assertListEqual( - self.get()['headers']['Set-Cookie'], - ['tc=one,two,three', 'tc=four,five,six'], - 'set header array', - ) + assert self.get()['headers']['Set-Cookie'] == [ + 'tc=one,two,three', + 'tc=four,five,six', + ], 'set header array' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_node_application_status_message(self): self.load('status_message') - self.assertRegex( - self.get(raw_resp=True), r'200 blah', 'status message' - ) + assert re.search(r'200 blah', self.get(raw_resp=True)), 'status message' def test_node_application_get_header_type(self): self.load('get_header_type') - self.assertEqual( - self.get()['headers']['X-Type'], 'number', 'get header type' - ) + assert self.get()['headers']['X-Type'] == 'number', 'get header type' def test_node_application_header_name_case(self): self.load('header_name_case') headers = self.get()['headers'] - self.assertEqual(headers['X-HEADER'], '3', 'header value') - self.assertNotIn('X-Header', headers, 'insensitive') - self.assertNotIn('X-header', headers, 'insensitive 2') + assert headers['X-HEADER'] == '3', 'header value' + assert 'X-Header' not in headers, 'insensitive' + assert 'X-header' not in headers, 'insensitive 2' def test_node_application_promise_handler(self): self.load('promise_handler') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -260,19 +232,15 @@ class TestNodeApplication(TestApplicationNode): 'Connection': 'close', }, body='callback', - )['status'], - 200, - 'promise handler request', - ) - self.assertTrue( - self.waitforfiles(self.testdir + '/node/callback'), - 'promise handler', - ) + )['status'] + == 200 + ), 'promise handler request' + assert waitforfiles(self.temp_dir + '/node/callback'), 'promise handler' def test_node_application_promise_handler_write_after_end(self): self.load('promise_handler') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -281,15 +249,14 @@ class TestNodeApplication(TestApplicationNode): 'Connection': 'close', }, body='callback', - )['status'], - 200, - 'promise handler request write after end', - ) + )['status'] + == 200 + ), 'promise handler request write after end' def test_node_application_promise_end(self): self.load('promise_end') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -297,13 +264,10 @@ class TestNodeApplication(TestApplicationNode): 'Connection': 'close', }, body='end', - )['status'], - 200, - 'promise end request', - ) - self.assertTrue( - self.waitforfiles(self.testdir + '/node/callback'), 'promise end' - ) + )['status'] + == 200 + ), 'promise end request' + assert waitforfiles(self.temp_dir + '/node/callback'), 'promise end' def test_node_application_promise_multiple_calls(self): self.load('promise_handler') @@ -317,10 +281,9 @@ class TestNodeApplication(TestApplicationNode): body='callback1', ) - self.assertTrue( - self.waitforfiles(self.testdir + '/node/callback1'), - 'promise first call', - ) + assert waitforfiles( + self.temp_dir + '/node/callback1' + ), 'promise first call' self.post( headers={ @@ -331,65 +294,55 @@ class TestNodeApplication(TestApplicationNode): body='callback2', ) - self.assertTrue( - self.waitforfiles(self.testdir + '/node/callback2'), - 'promise second call', - ) + assert waitforfiles( + self.temp_dir + '/node/callback2' + ), 'promise second call' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_node_application_header_name_valid(self): self.load('header_name_valid') - self.assertNotIn('status', self.get(), 'header name valid') + assert 'status' not in self.get(), 'header name valid' def test_node_application_header_value_object(self): self.load('header_value_object') - self.assertIn('X-Header', self.get()['headers'], 'header value object') + assert 'X-Header' in self.get()['headers'], 'header value object' def test_node_application_get_header_names(self): self.load('get_header_names') - self.assertListEqual( - self.get()['headers']['X-Names'], - ['date', 'x-header'], - 'get header names', - ) + assert self.get()['headers']['X-Names'] == [ + 'date', + 'x-header', + ], 'get header names' def test_node_application_has_header(self): self.load('has_header') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Header': 'length', 'Connection': 'close', } - )['headers']['X-Has-Header'], - 'false', - 'has header length', - ) + )['headers']['X-Has-Header'] + == 'false' + ), 'has header length' - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Header': 'Date', 'Connection': 'close', } - )['headers']['X-Has-Header'], - 'false', - 'has header date', - ) + )['headers']['X-Has-Header'] + == 'false' + ), 'has header date' def test_node_application_write_multiple(self): self.load('write_multiple') - self.assertEqual( - self.get()['body'], 'writewrite2end', 'write multiple' - ) - - -if __name__ == '__main__': - TestNodeApplication.main() + assert self.get()['body'] == 'writewrite2end', 'write multiple' diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index 1928d8c9..5af2f6f3 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -1,9 +1,10 @@ +import pytest import struct import time -import unittest from unit.applications.lang.node import TestApplicationNode from unit.applications.websockets import TestApplicationWebsocket +from conftest import option, skip_alert class TestNodeWebsockets(TestApplicationNode): @@ -11,23 +12,17 @@ class TestNodeWebsockets(TestApplicationNode): ws = TestApplicationWebsocket() - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - self.assertIn( - 'success', - self.conf( - {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' - ), - 'clear keepalive_interval', - ) + assert 'success' in self.conf( + {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' + ), 'clear keepalive_interval' - self.skip_alerts.extend( - [r'socket close\(\d+\) failed'] - ) + skip_alert(r'socket close\(\d+\) failed') def close_connection(self, sock): - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) @@ -36,9 +31,9 @@ class TestNodeWebsockets(TestApplicationNode): def check_close(self, sock, code=1000, no_close=False): frame = self.ws.frame_read(sock) - self.assertEqual(frame['fin'], True, 'close fin') - self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'close opcode') - self.assertEqual(frame['code'], code, 'close code') + assert frame['fin'] == True, 'close fin' + assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode' + assert frame['code'] == code, 'close code' if not no_close: sock.close() @@ -49,9 +44,9 @@ class TestNodeWebsockets(TestApplicationNode): else: data = frame['data'].decode('utf-8') - self.assertEqual(frame['fin'], fin, 'fin') - self.assertEqual(frame['opcode'], opcode, 'opcode') - self.assertEqual(data, payload, 'payload') + assert frame['fin'] == fin, 'fin' + assert frame['opcode'] == opcode, 'opcode' + assert data == payload, 'payload' def test_node_websockets_handshake(self): self.load('websockets/mirror') @@ -59,14 +54,12 @@ class TestNodeWebsockets(TestApplicationNode): resp, sock, key = self.ws.upgrade() sock.close() - self.assertEqual(resp['status'], 101, 'status') - self.assertEqual(resp['headers']['Upgrade'], 'websocket', 'upgrade') - self.assertEqual( - resp['headers']['Connection'], 'Upgrade', 'connection' - ) - self.assertEqual( - resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key' - ) + assert resp['status'] == 101, 'status' + assert resp['headers']['Upgrade'] == 'websocket', 'upgrade' + assert resp['headers']['Connection'] == 'Upgrade', 'connection' + assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept( + key + ), 'key' def test_node_websockets_mirror(self): self.load('websockets/mirror') @@ -78,12 +71,12 @@ class TestNodeWebsockets(TestApplicationNode): self.ws.frame_write(sock, self.ws.OP_TEXT, message) frame = self.ws.frame_read(sock) - self.assertEqual(message, frame['data'].decode('utf-8'), 'mirror') + assert message == frame['data'].decode('utf-8'), 'mirror' self.ws.frame_write(sock, self.ws.OP_TEXT, message) frame = self.ws.frame_read(sock) - self.assertEqual(message, frame['data'].decode('utf-8'), 'mirror 2') + assert message == frame['data'].decode('utf-8'), 'mirror 2' sock.close() @@ -98,8 +91,8 @@ class TestNodeWebsockets(TestApplicationNode): frame = self.ws.frame_read(sock) - self.assertEqual(frame['opcode'], self.ws.OP_CLOSE, 'no mask opcode') - self.assertEqual(frame['code'], 1002, 'no mask close code') + assert frame['opcode'] == self.ws.OP_CLOSE, 'no mask opcode' + assert frame['code'] == 1002, 'no mask close code' sock.close() @@ -116,11 +109,9 @@ class TestNodeWebsockets(TestApplicationNode): frame = self.ws.frame_read(sock) - self.assertEqual( - message + ' ' + message, - frame['data'].decode('utf-8'), - 'mirror framing', - ) + assert message + ' ' + message == frame['data'].decode( + 'utf-8' + ), 'mirror framing' sock.close() @@ -136,20 +127,16 @@ class TestNodeWebsockets(TestApplicationNode): frame = self.ws.frame_read(sock) frame.pop('data') - self.assertDictEqual( - frame, - { - 'fin': True, - 'rsv1': False, - 'rsv2': False, - 'rsv3': False, - 'opcode': self.ws.OP_CLOSE, - 'mask': 0, - 'code': 1002, - 'reason': 'Fragmented control frame', - }, - 'close frame', - ) + assert frame == { + 'fin': True, + 'rsv1': False, + 'rsv2': False, + 'rsv3': False, + 'opcode': self.ws.OP_CLOSE, + 'mask': 0, + 'code': 1002, + 'reason': 'Fragmented control frame', + }, 'close frame' sock.close() @@ -168,7 +155,7 @@ class TestNodeWebsockets(TestApplicationNode): frame = self.ws.frame_read(sock) data += frame['data'].decode('utf-8') - self.assertEqual(message, data, 'large') + assert message == data, 'large' sock.close() @@ -187,13 +174,13 @@ class TestNodeWebsockets(TestApplicationNode): frame1 = self.ws.frame_read(sock1) frame2 = self.ws.frame_read(sock2) - self.assertEqual(message1, frame1['data'].decode('utf-8'), 'client 1') - self.assertEqual(message2, frame2['data'].decode('utf-8'), 'client 2') + assert message1 == frame1['data'].decode('utf-8'), 'client 1' + assert message2 == frame2['data'].decode('utf-8'), 'client 2' sock1.close() sock2.close() - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_node_websockets_handshake_upgrade_absent( self ): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1 @@ -209,7 +196,7 @@ class TestNodeWebsockets(TestApplicationNode): }, ) - self.assertEqual(resp['status'], 400, 'upgrade absent') + assert resp['status'] == 400, 'upgrade absent' def test_node_websockets_handshake_case_insensitive(self): self.load('websockets/mirror') @@ -226,9 +213,9 @@ class TestNodeWebsockets(TestApplicationNode): ) sock.close() - self.assertEqual(resp['status'], 101, 'status') + assert resp['status'] == 101, 'status' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_node_websockets_handshake_connection_absent(self): # FAIL self.load('websockets/mirror') @@ -242,7 +229,7 @@ class TestNodeWebsockets(TestApplicationNode): }, ) - self.assertEqual(resp['status'], 400, 'status') + assert resp['status'] == 400, 'status' def test_node_websockets_handshake_version_absent(self): self.load('websockets/mirror') @@ -257,9 +244,9 @@ class TestNodeWebsockets(TestApplicationNode): }, ) - self.assertEqual(resp['status'], 426, 'status') + assert resp['status'] == 426, 'status' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_node_websockets_handshake_key_invalid(self): self.load('websockets/mirror') @@ -274,7 +261,7 @@ class TestNodeWebsockets(TestApplicationNode): }, ) - self.assertEqual(resp['status'], 400, 'key length') + assert resp['status'] == 400, 'key length' key = self.ws.key() resp = self.get( @@ -288,9 +275,7 @@ class TestNodeWebsockets(TestApplicationNode): }, ) - self.assertEqual( - resp['status'], 400, 'key double' - ) # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1 + assert resp['status'] == 400, 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1 def test_node_websockets_handshake_method_invalid(self): self.load('websockets/mirror') @@ -306,7 +291,7 @@ class TestNodeWebsockets(TestApplicationNode): }, ) - self.assertEqual(resp['status'], 400, 'status') + assert resp['status'] == 400, 'status' def test_node_websockets_handshake_http_10(self): self.load('websockets/mirror') @@ -323,7 +308,7 @@ class TestNodeWebsockets(TestApplicationNode): http_10=True, ) - self.assertEqual(resp['status'], 400, 'status') + assert resp['status'] == 400, 'status' def test_node_websockets_handshake_uri_invalid(self): self.load('websockets/mirror') @@ -340,7 +325,7 @@ class TestNodeWebsockets(TestApplicationNode): url='!', ) - self.assertEqual(resp['status'], 400, 'status') + assert resp['status'] == 400, 'status' def test_node_websockets_protocol_absent(self): self.load('websockets/mirror') @@ -357,14 +342,12 @@ class TestNodeWebsockets(TestApplicationNode): ) sock.close() - self.assertEqual(resp['status'], 101, 'status') - self.assertEqual(resp['headers']['Upgrade'], 'websocket', 'upgrade') - self.assertEqual( - resp['headers']['Connection'], 'Upgrade', 'connection' - ) - self.assertEqual( - resp['headers']['Sec-WebSocket-Accept'], self.ws.accept(key), 'key' - ) + assert resp['status'] == 101, 'status' + assert resp['headers']['Upgrade'] == 'websocket', 'upgrade' + assert resp['headers']['Connection'] == 'Upgrade', 'connection' + assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept( + key + ), 'key' # autobahn-testsuite # @@ -461,12 +444,12 @@ class TestNodeWebsockets(TestApplicationNode): _, sock, _ = self.ws.upgrade() self.ws.frame_write(sock, self.ws.OP_PONG, '') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '2_7') + assert self.recvall(sock, read_timeout=0.1) == b'', '2_7' # 2_8 self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '2_8') + assert self.recvall(sock, read_timeout=0.1) == b'', '2_8' # 2_9 @@ -506,7 +489,7 @@ class TestNodeWebsockets(TestApplicationNode): self.close_connection(sock) - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_node_websockets_3_1__3_7(self): self.load('websockets/mirror') @@ -532,7 +515,7 @@ class TestNodeWebsockets(TestApplicationNode): self.check_close(sock, 1002, no_close=True) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty 3_2') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_2' sock.close() # 3_3 @@ -550,7 +533,7 @@ class TestNodeWebsockets(TestApplicationNode): self.check_close(sock, 1002, no_close=True) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty 3_3') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_3' sock.close() # 3_4 @@ -568,7 +551,7 @@ class TestNodeWebsockets(TestApplicationNode): self.check_close(sock, 1002, no_close=True) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty 3_4') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_4' sock.close() # 3_5 @@ -754,7 +737,7 @@ class TestNodeWebsockets(TestApplicationNode): # 5_4 self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '5_4') + assert self.recvall(sock, read_timeout=0.1) == b'', '5_4' self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) frame = self.ws.frame_read(sock) @@ -791,7 +774,7 @@ class TestNodeWebsockets(TestApplicationNode): ping_payload = 'ping payload' self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '5_7') + assert self.recvall(sock, read_timeout=0.1) == b'', '5_7' self.ws.frame_write(sock, self.ws.OP_PING, ping_payload) @@ -975,7 +958,7 @@ class TestNodeWebsockets(TestApplicationNode): frame = self.ws.frame_read(sock) self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', '5_20') + assert self.recvall(sock, read_timeout=0.1) == b'', '5_20' self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5') self.check_frame( @@ -1108,7 +1091,7 @@ class TestNodeWebsockets(TestApplicationNode): self.check_close(sock, no_close=True) self.ws.frame_write(sock, self.ws.OP_PING, '') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' sock.close() @@ -1120,7 +1103,7 @@ class TestNodeWebsockets(TestApplicationNode): self.check_close(sock, no_close=True) self.ws.frame_write(sock, self.ws.OP_TEXT, payload) - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' sock.close() @@ -1133,7 +1116,7 @@ class TestNodeWebsockets(TestApplicationNode): self.check_close(sock, no_close=True) self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' sock.close() @@ -1148,7 +1131,7 @@ class TestNodeWebsockets(TestApplicationNode): self.recvall(sock, read_timeout=1) self.ws.frame_write(sock, self.ws.OP_PING, '') - self.assertEqual(self.recvall(sock, read_timeout=0.1), b'', 'empty soc') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' sock.close() @@ -1268,27 +1251,23 @@ class TestNodeWebsockets(TestApplicationNode): self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) self.check_close(sock, 1002) - def test_node_websockets_9_1_1__9_6_6(self): - if not self.unsafe: - self.skipTest("unsafe, long run") + def test_node_websockets_9_1_1__9_6_6(self, is_unsafe): + if not is_unsafe: + pytest.skip('unsafe, long run') self.load('websockets/mirror') - self.assertIn( - 'success', - self.conf( - { - 'http': { - 'websocket': { - 'max_frame_size': 33554432, - 'keepalive_interval': 0, - } + assert 'success' in self.conf( + { + 'http': { + 'websocket': { + 'max_frame_size': 33554432, + 'keepalive_interval': 0, } - }, - 'settings', - ), - 'increase max_frame_size and keepalive_interval', - ) + } + }, + 'settings', + ), 'increase max_frame_size and keepalive_interval' _, sock, _ = self.ws.upgrade() @@ -1329,7 +1308,7 @@ class TestNodeWebsockets(TestApplicationNode): check_payload(op_binary, 8 * 2 ** 20) # 9_2_5 check_payload(op_binary, 16 * 2 ** 20) # 9_2_6 - if self.system != 'Darwin' and self.system != 'FreeBSD': + if option.system != 'Darwin' and option.system != 'FreeBSD': check_message(op_text, 64) # 9_3_1 check_message(op_text, 256) # 9_3_2 check_message(op_text, 2 ** 10) # 9_3_3 @@ -1385,13 +1364,9 @@ class TestNodeWebsockets(TestApplicationNode): def test_node_websockets_max_frame_size(self): self.load('websockets/mirror') - self.assertIn( - 'success', - self.conf( - {'http': {'websocket': {'max_frame_size': 100}}}, 'settings' - ), - 'configure max_frame_size', - ) + assert 'success' in self.conf( + {'http': {'websocket': {'max_frame_size': 100}}}, 'settings' + ), 'configure max_frame_size' _, sock, _ = self.ws.upgrade() @@ -1411,13 +1386,9 @@ class TestNodeWebsockets(TestApplicationNode): def test_node_websockets_read_timeout(self): self.load('websockets/mirror') - self.assertIn( - 'success', - self.conf( - {'http': {'websocket': {'read_timeout': 5}}}, 'settings' - ), - 'configure read_timeout', - ) + assert 'success' in self.conf( + {'http': {'websocket': {'read_timeout': 5}}}, 'settings' + ), 'configure read_timeout' _, sock, _ = self.ws.upgrade() @@ -1431,13 +1402,9 @@ class TestNodeWebsockets(TestApplicationNode): def test_node_websockets_keepalive_interval(self): self.load('websockets/mirror') - self.assertIn( - 'success', - self.conf( - {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings' - ), - 'configure keepalive_interval', - ) + assert 'success' in self.conf( + {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings' + ), 'configure keepalive_interval' _, sock, _ = self.ws.upgrade() @@ -1450,7 +1417,3 @@ class TestNodeWebsockets(TestApplicationNode): self.check_frame(frame, True, self.ws.OP_PING, '') # PING frame sock.close() - - -if __name__ == '__main__': - TestNodeWebsockets.main() diff --git a/test/test_perl_application.py b/test/test_perl_application.py index dbf6abf7..bb63eceb 100644 --- a/test/test_perl_application.py +++ b/test/test_perl_application.py @@ -1,6 +1,8 @@ -import unittest +import pytest +import re from unit.applications.lang.perl import TestApplicationPerl +from conftest import skip_alert class TestPerlApplication(TestApplicationPerl): @@ -21,149 +23,130 @@ class TestPerlApplication(TestApplicationPerl): body=body, ) - self.assertEqual(resp['status'], 200, 'status') + assert resp['status'] == 200, 'status' headers = resp['headers'] header_server = headers.pop('Server') - self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header') - self.assertEqual( - headers.pop('Server-Software'), - header_server, - 'server software header', - ) + assert re.search(r'Unit/[\d\.]+', header_server), 'server header' + assert ( + headers.pop('Server-Software') == header_server + ), 'server software header' date = headers.pop('Date') - self.assertEqual(date[-4:], ' GMT', 'date header timezone') - self.assertLess( - abs(self.date_to_sec_epoch(date) - self.sec_epoch()), - 5, - 'date header', - ) - - self.assertDictEqual( - headers, - { - 'Connection': 'close', - 'Content-Length': str(len(body)), - 'Content-Type': 'text/html', - 'Request-Method': 'POST', - 'Request-Uri': '/', - 'Http-Host': 'localhost', - 'Server-Protocol': 'HTTP/1.1', - 'Custom-Header': 'blah', - 'Psgi-Version': '11', - 'Psgi-Url-Scheme': 'http', - 'Psgi-Multithread': '', - 'Psgi-Multiprocess': '1', - 'Psgi-Run-Once': '', - 'Psgi-Nonblocking': '', - 'Psgi-Streaming': '1', - }, - 'headers', - ) - self.assertEqual(resp['body'], body, 'body') + assert date[-4:] == ' GMT', 'date header timezone' + assert ( + abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5 + ), 'date header' + + assert headers == { + 'Connection': 'close', + 'Content-Length': str(len(body)), + 'Content-Type': 'text/html', + 'Request-Method': 'POST', + 'Request-Uri': '/', + 'Http-Host': 'localhost', + 'Server-Protocol': 'HTTP/1.1', + 'Custom-Header': 'blah', + 'Psgi-Version': '11', + 'Psgi-Url-Scheme': 'http', + 'Psgi-Multithread': '', + 'Psgi-Multiprocess': '1', + 'Psgi-Run-Once': '', + 'Psgi-Nonblocking': '', + 'Psgi-Streaming': '1', + }, 'headers' + assert resp['body'] == body, 'body' def test_perl_application_query_string(self): self.load('query_string') resp = self.get(url='/?var1=val1&var2=val2') - self.assertEqual( - resp['headers']['Query-String'], - 'var1=val1&var2=val2', - 'Query-String header', - ) + assert ( + resp['headers']['Query-String'] == 'var1=val1&var2=val2' + ), 'Query-String header' def test_perl_application_query_string_empty(self): self.load('query_string') resp = self.get(url='/?') - self.assertEqual(resp['status'], 200, 'query string empty status') - self.assertEqual( - resp['headers']['Query-String'], '', 'query string empty' - ) + assert resp['status'] == 200, 'query string empty status' + assert resp['headers']['Query-String'] == '', 'query string empty' def test_perl_application_query_string_absent(self): self.load('query_string') resp = self.get() - self.assertEqual(resp['status'], 200, 'query string absent status') - self.assertEqual( - resp['headers']['Query-String'], '', 'query string absent' - ) + assert resp['status'] == 200, 'query string absent status' + assert resp['headers']['Query-String'] == '', 'query string absent' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_perl_application_server_port(self): self.load('server_port') - self.assertEqual( - self.get()['headers']['Server-Port'], '7080', 'Server-Port header' - ) + assert ( + self.get()['headers']['Server-Port'] == '7080' + ), 'Server-Port header' def test_perl_application_input_read_empty(self): self.load('input_read_empty') - self.assertEqual(self.get()['body'], '', 'read empty') + assert self.get()['body'] == '', 'read empty' def test_perl_application_input_read_parts(self): self.load('input_read_parts') - self.assertEqual( - self.post(body='0123456789')['body'], - '0123456789', - 'input read parts', - ) + assert ( + self.post(body='0123456789')['body'] == '0123456789' + ), 'input read parts' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_perl_application_input_read_offset(self): self.load('input_read_offset') - self.assertEqual( - self.post(body='0123456789')['body'], '4567', 'read offset' - ) + assert self.post(body='0123456789')['body'] == '4567', 'read offset' def test_perl_application_input_copy(self): self.load('input_copy') body = '0123456789' - self.assertEqual(self.post(body=body)['body'], body, 'input copy') + assert self.post(body=body)['body'] == body, 'input copy' def test_perl_application_errors_print(self): self.load('errors_print') - self.assertEqual(self.get()['body'], '1', 'errors result') + assert self.get()['body'] == '1', 'errors result' self.stop() - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+Error in application'), - 'errors print', - ) + assert ( + self.wait_for_record(r'\[error\].+Error in application') + is not None + ), 'errors print' def test_perl_application_header_equal_names(self): self.load('header_equal_names') - self.assertListEqual( - self.get()['headers']['Set-Cookie'], - ['tc=one,two,three', 'tc=four,five,six'], - 'header equal names', - ) + assert self.get()['headers']['Set-Cookie'] == [ + 'tc=one,two,three', + 'tc=four,five,six', + ], 'header equal names' def test_perl_application_header_pairs(self): self.load('header_pairs') - self.assertEqual(self.get()['headers']['blah'], 'blah', 'header pairs') + assert self.get()['headers']['blah'] == 'blah', 'header pairs' def test_perl_application_body_empty(self): self.load('body_empty') - self.assertEqual(self.get()['body'], '', 'body empty') + assert self.get()['body'] == '', 'body empty' def test_perl_application_body_array(self): self.load('body_array') - self.assertEqual(self.get()['body'], '0123456789', 'body array') + assert self.get()['body'] == '0123456789', 'body array' def test_perl_application_body_large(self): self.load('variables') @@ -172,31 +155,29 @@ class TestPerlApplication(TestApplicationPerl): resp = self.post(body=body)['body'] - self.assertEqual(resp, body, 'body large') + assert resp == body, 'body large' def test_perl_application_body_io_empty(self): self.load('body_io_empty') - self.assertEqual(self.get()['status'], 200, 'body io empty') + assert self.get()['status'] == 200, 'body io empty' def test_perl_application_body_io_file(self): self.load('body_io_file') - self.assertEqual(self.get()['body'], 'body\n', 'body io file') + assert self.get()['body'] == 'body\n', 'body io file' - @unittest.skip('not yet, unsafe') + @pytest.mark.skip('not yet') def test_perl_application_syntax_error(self): - self.skip_alerts.extend( - [r'PSGI: Failed to parse script'] - ) + skip_alert(r'PSGI: Failed to parse script') self.load('syntax_error') - self.assertEqual(self.get()['status'], 500, 'syntax error') + assert self.get()['status'] == 500, 'syntax error' def test_perl_keepalive_body(self): self.load('variables') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' body = '0123456789' * 500 (resp, sock) = self.post( @@ -210,7 +191,7 @@ class TestPerlApplication(TestApplicationPerl): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'keep-alive 1') + assert resp['body'] == body, 'keep-alive 1' body = '0123456789' resp = self.post( @@ -223,39 +204,35 @@ class TestPerlApplication(TestApplicationPerl): body=body, ) - self.assertEqual(resp['body'], body, 'keep-alive 2') + assert resp['body'] == body, 'keep-alive 2' def test_perl_body_io_fake(self): self.load('body_io_fake') - self.assertEqual(self.get()['body'], '21', 'body io fake') + assert self.get()['body'] == '21', 'body io fake' - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+IOFake getline\(\) \$\/ is \d+'), - 'body io fake $/ value', - ) + assert ( + self.wait_for_record(r'\[error\].+IOFake getline\(\) \$\/ is \d+') + is not None + ), 'body io fake $/ value' - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+IOFake close\(\) called'), - 'body io fake close', - ) + assert ( + self.wait_for_record(r'\[error\].+IOFake close\(\) called') + is not None + ), 'body io fake close' def test_perl_delayed_response(self): self.load('delayed_response') resp = self.get() - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], 'Hello World!', 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == 'Hello World!', 'body' def test_perl_streaming_body(self): self.load('streaming_body') resp = self.get() - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], 'Hello World!', 'body') - - -if __name__ == '__main__': - TestPerlApplication.main() + assert resp['status'] == 200, 'status' + assert resp['body'] == 'Hello World!', 'body' diff --git a/test/test_php_application.py b/test/test_php_application.py index d8bfade2..18a5c085 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -1,10 +1,11 @@ import os +import pytest import re import shutil import time -import unittest from unit.applications.lang.php import TestApplicationPHP +from conftest import option class TestPHPApplication(TestApplicationPHP): prerequisites = {'modules': {'php': 'all'}} @@ -12,30 +13,21 @@ class TestPHPApplication(TestApplicationPHP): def before_disable_functions(self): body = self.get()['body'] - self.assertRegex(body, r'time: \d+', 'disable_functions before time') - self.assertRegex(body, r'exec: \/\w+', 'disable_functions before exec') + assert re.search(r'time: \d+', body), 'disable_functions before time' + assert re.search(r'exec: \/\w+', body), 'disable_functions before exec' def set_opcache(self, app, val): - self.assertIn( - 'success', - self.conf( - { - "admin": { - "opcache.enable": val, - "opcache.enable_cli": val, - }, - }, - 'applications/' + app + '/options', - ), + assert 'success' in self.conf( + {"admin": {"opcache.enable": val, "opcache.enable_cli": val,},}, + 'applications/' + app + '/options', ) opcache = self.get()['headers']['X-OPcache'] if not opcache or opcache == '-1': - print('opcache is not supported') - raise unittest.SkipTest() + pytest.skip('opcache is not supported') - self.assertEqual(opcache, val, 'opcache value') + assert opcache == val, 'opcache value' def test_php_application_variables(self): self.load('variables') @@ -50,140 +42,122 @@ class TestPHPApplication(TestApplicationPHP): 'Connection': 'close', }, body=body, - url='/index.php/blah?var=val' + url='/index.php/blah?var=val', ) - self.assertEqual(resp['status'], 200, 'status') + assert resp['status'] == 200, 'status' headers = resp['headers'] header_server = headers.pop('Server') - self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header') - self.assertEqual( - headers.pop('Server-Software'), - header_server, - 'server software header', - ) + assert re.search(r'Unit/[\d\.]+', header_server), 'server header' + assert ( + headers.pop('Server-Software') == header_server + ), 'server software header' date = headers.pop('Date') - self.assertEqual(date[-4:], ' GMT', 'date header timezone') - self.assertLess( - abs(self.date_to_sec_epoch(date) - self.sec_epoch()), - 5, - 'date header', - ) + assert date[-4:] == ' GMT', 'date header timezone' + assert ( + abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5 + ), 'date header' if 'X-Powered-By' in headers: headers.pop('X-Powered-By') headers.pop('Content-type') - self.assertDictEqual( - headers, - { - 'Connection': 'close', - 'Content-Length': str(len(body)), - 'Request-Method': 'POST', - 'Path-Info': '/blah', - 'Request-Uri': '/index.php/blah?var=val', - 'Http-Host': 'localhost', - 'Server-Protocol': 'HTTP/1.1', - 'Custom-Header': 'blah', - }, - 'headers', - ) - self.assertEqual(resp['body'], body, 'body') + assert headers == { + 'Connection': 'close', + 'Content-Length': str(len(body)), + 'Request-Method': 'POST', + 'Path-Info': '/blah', + 'Request-Uri': '/index.php/blah?var=val', + 'Http-Host': 'localhost', + 'Server-Protocol': 'HTTP/1.1', + 'Custom-Header': 'blah', + }, 'headers' + assert resp['body'] == body, 'body' def test_php_application_query_string(self): self.load('query_string') resp = self.get(url='/?var1=val1&var2=val2') - self.assertEqual( - resp['headers']['Query-String'], - 'var1=val1&var2=val2', - 'query string', - ) + assert ( + resp['headers']['Query-String'] == 'var1=val1&var2=val2' + ), 'query string' def test_php_application_query_string_empty(self): self.load('query_string') resp = self.get(url='/?') - self.assertEqual(resp['status'], 200, 'query string empty status') - self.assertEqual( - resp['headers']['Query-String'], '', 'query string empty' - ) + assert resp['status'] == 200, 'query string empty status' + assert resp['headers']['Query-String'] == '', 'query string empty' def test_php_application_query_string_absent(self): self.load('query_string') resp = self.get() - self.assertEqual(resp['status'], 200, 'query string absent status') - self.assertEqual( - resp['headers']['Query-String'], '', 'query string absent' - ) + assert resp['status'] == 200, 'query string absent status' + assert resp['headers']['Query-String'] == '', 'query string absent' def test_php_application_phpinfo(self): self.load('phpinfo') resp = self.get() - self.assertEqual(resp['status'], 200, 'status') - self.assertNotEqual(resp['body'], '', 'body not empty') + assert resp['status'] == 200, 'status' + assert resp['body'] != '', 'body not empty' def test_php_application_header_status(self): self.load('header') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'Connection': 'close', 'X-Header': 'HTTP/1.1 404 Not Found', } - )['status'], - 404, - 'status', - ) + )['status'] + == 404 + ), 'status' - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'Connection': 'close', 'X-Header': 'http/1.1 404 Not Found', } - )['status'], - 404, - 'status case insensitive', - ) + )['status'] + == 404 + ), 'status case insensitive' - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'Connection': 'close', 'X-Header': 'HTTP/ 404 Not Found', } - )['status'], - 404, - 'status version empty', - ) - + )['status'] + == 404 + ), 'status version empty' def test_php_application_404(self): self.load('404') resp = self.get() - self.assertEqual(resp['status'], 404, '404 status') - self.assertRegex( - resp['body'], r'404 Not Found', '404 body' - ) + assert resp['status'] == 404, '404 status' + assert re.search( + r'404 Not Found', resp['body'] + ), '404 body' def test_php_application_keepalive_body(self): self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' body = '0123456789' * 500 (resp, sock) = self.post( @@ -197,7 +171,7 @@ class TestPHPApplication(TestApplicationPHP): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'keep-alive 1') + assert resp['body'] == body, 'keep-alive 1' body = '0123456789' resp = self.post( @@ -210,22 +184,22 @@ class TestPHPApplication(TestApplicationPHP): body=body, ) - self.assertEqual(resp['body'], body, 'keep-alive 2') + assert resp['body'] == body, 'keep-alive 2' def test_php_application_conditional(self): self.load('conditional') - self.assertRegex(self.get()['body'], r'True', 'conditional true') - self.assertRegex(self.post()['body'], r'False', 'conditional false') + assert re.search(r'True', self.get()['body']), 'conditional true' + assert re.search(r'False', self.post()['body']), 'conditional false' def test_php_application_get_variables(self): self.load('get_variables') resp = self.get(url='/?var1=val1&var2=&var3') - self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'GET variables') - self.assertEqual(resp['headers']['X-Var-2'], '1', 'GET variables 2') - self.assertEqual(resp['headers']['X-Var-3'], '1', 'GET variables 3') - self.assertEqual(resp['headers']['X-Var-4'], '', 'GET variables 4') + assert resp['headers']['X-Var-1'] == 'val1', 'GET variables' + assert resp['headers']['X-Var-2'] == '1', 'GET variables 2' + assert resp['headers']['X-Var-3'] == '1', 'GET variables 3' + assert resp['headers']['X-Var-4'] == '', 'GET variables 4' def test_php_application_post_variables(self): self.load('post_variables') @@ -238,9 +212,9 @@ class TestPHPApplication(TestApplicationPHP): }, body='var1=val1&var2=', ) - self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'POST variables') - self.assertEqual(resp['headers']['X-Var-2'], '1', 'POST variables 2') - self.assertEqual(resp['headers']['X-Var-3'], '', 'POST variables 3') + assert resp['headers']['X-Var-1'] == 'val1', 'POST variables' + assert resp['headers']['X-Var-2'] == '1', 'POST variables 2' + assert resp['headers']['X-Var-3'] == '', 'POST variables 3' def test_php_application_cookies(self): self.load('cookies') @@ -253,41 +227,32 @@ class TestPHPApplication(TestApplicationPHP): } ) - self.assertEqual(resp['headers']['X-Cookie-1'], 'val', 'cookie') - self.assertEqual(resp['headers']['X-Cookie-2'], 'val2', 'cookie') + assert resp['headers']['X-Cookie-1'] == 'val', 'cookie' + assert resp['headers']['X-Cookie-2'] == 'val2', 'cookie' def test_php_application_ini_precision(self): self.load('ini_precision') - self.assertNotEqual( - self.get()['headers']['X-Precision'], '4', 'ini value default' - ) + assert self.get()['headers']['X-Precision'] != '4', 'ini value default' self.conf( {"file": "ini/php.ini"}, 'applications/ini_precision/options' ) - self.assertEqual( - self.get()['headers']['X-File'], - self.current_dir + '/php/ini_precision/ini/php.ini', - 'ini file', - ) - self.assertEqual( - self.get()['headers']['X-Precision'], '4', 'ini value' - ) + assert ( + self.get()['headers']['X-File'] + == option.test_dir + '/php/ini_precision/ini/php.ini' + ), 'ini file' + assert self.get()['headers']['X-Precision'] == '4', 'ini value' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_php_application_ini_admin_user(self): self.load('ini_precision') - self.assertIn( - 'error', - self.conf( - {"user": {"precision": "4"}, "admin": {"precision": "5"}}, - 'applications/ini_precision/options', - ), - 'ini admin user', - ) + assert 'error' in self.conf( + {"user": {"precision": "4"}, "admin": {"precision": "5"}}, + 'applications/ini_precision/options', + ), 'ini admin user' def test_php_application_ini_admin(self): self.load('ini_precision') @@ -297,9 +262,7 @@ class TestPHPApplication(TestApplicationPHP): 'applications/ini_precision/options', ) - self.assertEqual( - self.get()['headers']['X-Precision'], '5', 'ini value admin' - ) + assert self.get()['headers']['X-Precision'] == '5', 'ini value admin' def test_php_application_ini_user(self): self.load('ini_precision') @@ -309,9 +272,7 @@ class TestPHPApplication(TestApplicationPHP): 'applications/ini_precision/options', ) - self.assertEqual( - self.get()['headers']['X-Precision'], '5', 'ini value user' - ) + assert self.get()['headers']['X-Precision'] == '5', 'ini value user' def test_php_application_ini_user_2(self): self.load('ini_precision') @@ -320,17 +281,13 @@ class TestPHPApplication(TestApplicationPHP): {"file": "ini/php.ini"}, 'applications/ini_precision/options' ) - self.assertEqual( - self.get()['headers']['X-Precision'], '4', 'ini user file' - ) + assert self.get()['headers']['X-Precision'] == '4', 'ini user file' self.conf( {"precision": "5"}, 'applications/ini_precision/options/user' ) - self.assertEqual( - self.get()['headers']['X-Precision'], '5', 'ini value user' - ) + assert self.get()['headers']['X-Precision'] == '5', 'ini value user' def test_php_application_ini_set_admin(self): self.load('ini_precision') @@ -339,11 +296,9 @@ class TestPHPApplication(TestApplicationPHP): {"admin": {"precision": "5"}}, 'applications/ini_precision/options' ) - self.assertEqual( - self.get(url='/?precision=6')['headers']['X-Precision'], - '5', - 'ini set admin', - ) + assert ( + self.get(url='/?precision=6')['headers']['X-Precision'] == '5' + ), 'ini set admin' def test_php_application_ini_set_user(self): self.load('ini_precision') @@ -352,11 +307,9 @@ class TestPHPApplication(TestApplicationPHP): {"user": {"precision": "5"}}, 'applications/ini_precision/options' ) - self.assertEqual( - self.get(url='/?precision=6')['headers']['X-Precision'], - '6', - 'ini set user', - ) + assert ( + self.get(url='/?precision=6')['headers']['X-Precision'] == '6' + ), 'ini set user' def test_php_application_ini_repeat(self): self.load('ini_precision') @@ -365,13 +318,9 @@ class TestPHPApplication(TestApplicationPHP): {"user": {"precision": "5"}}, 'applications/ini_precision/options' ) - self.assertEqual( - self.get()['headers']['X-Precision'], '5', 'ini value' - ) + assert self.get()['headers']['X-Precision'] == '5', 'ini value' - self.assertEqual( - self.get()['headers']['X-Precision'], '5', 'ini value repeat' - ) + assert self.get()['headers']['X-Precision'] == '5', 'ini value repeat' def test_php_application_disable_functions_exec(self): self.load('time_exec') @@ -385,8 +334,8 @@ class TestPHPApplication(TestApplicationPHP): body = self.get()['body'] - self.assertRegex(body, r'time: \d+', 'disable_functions time') - self.assertNotRegex(body, r'exec: \/\w+', 'disable_functions exec') + assert re.search(r'time: \d+', body), 'disable_functions time' + assert not re.search(r'exec: \/\w+', body), 'disable_functions exec' def test_php_application_disable_functions_comma(self): self.load('time_exec') @@ -400,10 +349,12 @@ class TestPHPApplication(TestApplicationPHP): body = self.get()['body'] - self.assertNotRegex(body, r'time: \d+', 'disable_functions comma time') - self.assertNotRegex( - body, r'exec: \/\w+', 'disable_functions comma exec' - ) + assert not re.search( + r'time: \d+', body + ), 'disable_functions comma time' + assert not re.search( + r'exec: \/\w+', body + ), 'disable_functions comma exec' def test_php_application_disable_functions_space(self): self.load('time_exec') @@ -417,10 +368,12 @@ class TestPHPApplication(TestApplicationPHP): body = self.get()['body'] - self.assertNotRegex(body, r'time: \d+', 'disable_functions space time') - self.assertNotRegex( - body, r'exec: \/\w+', 'disable_functions space exec' - ) + assert not re.search( + r'time: \d+', body + ), 'disable_functions space time' + assert not re.search( + r'exec: \/\w+', body + ), 'disable_functions space exec' def test_php_application_disable_functions_user(self): self.load('time_exec') @@ -434,10 +387,10 @@ class TestPHPApplication(TestApplicationPHP): body = self.get()['body'] - self.assertRegex(body, r'time: \d+', 'disable_functions user time') - self.assertNotRegex( - body, r'exec: \/\w+', 'disable_functions user exec' - ) + assert re.search(r'time: \d+', body), 'disable_functions user time' + assert not re.search( + r'exec: \/\w+', body + ), 'disable_functions user exec' def test_php_application_disable_functions_nonexistent(self): self.load('time_exec') @@ -451,187 +404,165 @@ class TestPHPApplication(TestApplicationPHP): body = self.get()['body'] - self.assertRegex( - body, r'time: \d+', 'disable_functions nonexistent time' - ) - self.assertRegex( - body, r'exec: \/\w+', 'disable_functions nonexistent exec' - ) + assert re.search( + r'time: \d+', body + ), 'disable_functions nonexistent time' + assert re.search( + r'exec: \/\w+', body + ), 'disable_functions nonexistent exec' def test_php_application_disable_classes(self): self.load('date_time') - self.assertRegex( - self.get()['body'], r'012345', 'disable_classes before' - ) + assert re.search( + r'012345', self.get()['body'] + ), 'disable_classes before' self.conf( {"admin": {"disable_classes": "DateTime"}}, 'applications/date_time/options', ) - self.assertNotRegex( - self.get()['body'], r'012345', 'disable_classes before' - ) + assert not re.search( + r'012345', self.get()['body'] + ), 'disable_classes before' def test_php_application_disable_classes_user(self): self.load('date_time') - self.assertRegex( - self.get()['body'], r'012345', 'disable_classes before' - ) + assert re.search( + r'012345', self.get()['body'] + ), 'disable_classes before' self.conf( {"user": {"disable_classes": "DateTime"}}, 'applications/date_time/options', ) - self.assertNotRegex( - self.get()['body'], r'012345', 'disable_classes before' - ) + assert not re.search( + r'012345', self.get()['body'] + ), 'disable_classes before' def test_php_application_error_log(self): self.load('error_log') - self.assertEqual(self.get()['status'], 200, 'status') + assert self.get()['status'] == 200, 'status' time.sleep(1) - self.assertEqual(self.get()['status'], 200, 'status 2') + assert self.get()['status'] == 200, 'status 2' self.stop() pattern = r'\d{4}\/\d\d\/\d\d\s\d\d:.+\[notice\].+Error in application' - self.assertIsNotNone(self.wait_for_record(pattern), 'errors print') + assert self.wait_for_record(pattern) is not None, 'errors print' - with open(self.testdir + '/unit.log', 'r', errors='ignore') as f: + with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f: errs = re.findall(pattern, f.read()) - self.assertEqual(len(errs), 2, 'error_log count') + assert len(errs) == 2, 'error_log count' date = errs[0].split('[')[0] date2 = errs[1].split('[')[0] - self.assertNotEqual(date, date2, 'date diff') + assert date != date2, 'date diff' def test_php_application_script(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "applications/script"}}, - "applications": { - "script": { - "type": "php", - "processes": {"spare": 0}, - "root": self.current_dir + "/php/script", - "script": "phpinfo.php", - } - }, - } - ), - 'configure script', - ) + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "applications/script"}}, + "applications": { + "script": { + "type": "php", + "processes": {"spare": 0}, + "root": option.test_dir + "/php/script", + "script": "phpinfo.php", + } + }, + } + ), 'configure script' resp = self.get() - self.assertEqual(resp['status'], 200, 'status') - self.assertNotEqual(resp['body'], '', 'body not empty') + assert resp['status'] == 200, 'status' + assert resp['body'] != '', 'body not empty' def test_php_application_index_default(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "applications/phpinfo"}}, - "applications": { - "phpinfo": { - "type": "php", - "processes": {"spare": 0}, - "root": self.current_dir + "/php/phpinfo", - } - }, - } - ), - 'configure index default', - ) + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "applications/phpinfo"}}, + "applications": { + "phpinfo": { + "type": "php", + "processes": {"spare": 0}, + "root": option.test_dir + "/php/phpinfo", + } + }, + } + ), 'configure index default' resp = self.get() - self.assertEqual(resp['status'], 200, 'status') - self.assertNotEqual(resp['body'], '', 'body not empty') + assert resp['status'] == 200, 'status' + assert resp['body'] != '', 'body not empty' def test_php_application_extension_check(self): self.load('phpinfo') - self.assertNotEqual( - self.get(url='/index.wrong')['status'], 200, 'status' - ) + assert self.get(url='/index.wrong')['status'] != 200, 'status' - new_root = self.testdir + "/php" + new_root = self.temp_dir + "/php" os.mkdir(new_root) - shutil.copy(self.current_dir + '/php/phpinfo/index.wrong', new_root) - - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "applications/phpinfo"}}, - "applications": { - "phpinfo": { - "type": "php", - "processes": {"spare": 0}, - "root": new_root, - "working_directory": new_root, - } - }, - } - ), - 'configure new root', - ) + shutil.copy(option.test_dir + '/php/phpinfo/index.wrong', new_root) + + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "applications/phpinfo"}}, + "applications": { + "phpinfo": { + "type": "php", + "processes": {"spare": 0}, + "root": new_root, + "working_directory": new_root, + } + }, + } + ), 'configure new root' resp = self.get() - self.assertNotEqual( - str(resp['status']) + resp['body'], '200', 'status new root' - ) + assert str(resp['status']) + resp['body'] != '200', 'status new root' def run_php_application_cwd_root_tests(self): - self.assertIn( - 'success', self.conf_delete('applications/cwd/working_directory') + assert 'success' in self.conf_delete( + 'applications/cwd/working_directory' ) - script_cwd = self.current_dir + '/php/cwd' + script_cwd = option.test_dir + '/php/cwd' resp = self.get() - self.assertEqual(resp['status'], 200, 'status ok') - self.assertEqual(resp['body'], script_cwd, 'default cwd') - - self.assertIn( - 'success', - self.conf( - '"' + self.current_dir + '"', - 'applications/cwd/working_directory', - ), + assert resp['status'] == 200, 'status ok' + assert resp['body'] == script_cwd, 'default cwd' + + assert 'success' in self.conf( + '"' + option.test_dir + '"', 'applications/cwd/working_directory', ) resp = self.get() - self.assertEqual(resp['status'], 200, 'status ok') - self.assertEqual(resp['body'], script_cwd, 'wdir cwd') + assert resp['status'] == 200, 'status ok' + assert resp['body'] == script_cwd, 'wdir cwd' resp = self.get(url='/?chdir=/') - self.assertEqual(resp['status'], 200, 'status ok') - self.assertEqual(resp['body'], '/', 'cwd after chdir') + assert resp['status'] == 200, 'status ok' + assert resp['body'] == '/', 'cwd after chdir' # cwd must be restored resp = self.get() - self.assertEqual(resp['status'], 200, 'status ok') - self.assertEqual(resp['body'], script_cwd, 'cwd restored') + assert resp['status'] == 200, 'status ok' + assert resp['body'] == script_cwd, 'cwd restored' resp = self.get(url='/subdir/') - self.assertEqual( - resp['body'], script_cwd + '/subdir', 'cwd subdir', - ) + assert resp['body'] == script_cwd + '/subdir', 'cwd subdir' def test_php_application_cwd_root(self): self.load('cwd') @@ -650,26 +581,20 @@ class TestPHPApplication(TestApplicationPHP): def run_php_application_cwd_script_tests(self): self.load('cwd') - script_cwd = self.current_dir + '/php/cwd' + script_cwd = option.test_dir + '/php/cwd' - self.assertIn( - 'success', self.conf_delete('applications/cwd/working_directory') + assert 'success' in self.conf_delete( + 'applications/cwd/working_directory' ) - self.assertIn( - 'success', self.conf('"index.php"', 'applications/cwd/script') - ) + assert 'success' in self.conf('"index.php"', 'applications/cwd/script') - self.assertEqual( - self.get()['body'], script_cwd, 'default cwd', - ) + assert self.get()['body'] == script_cwd, 'default cwd' - self.assertEqual( - self.get(url='/?chdir=/')['body'], '/', 'cwd after chdir', - ) + assert self.get(url='/?chdir=/')['body'] == '/', 'cwd after chdir' # cwd must be restored - self.assertEqual(self.get()['body'], script_cwd, 'cwd restored') + assert self.get()['body'] == script_cwd, 'cwd restored' def test_php_application_cwd_script(self): self.load('cwd') @@ -688,14 +613,10 @@ class TestPHPApplication(TestApplicationPHP): def test_php_application_path_relative(self): self.load('open') - self.assertEqual(self.get()['body'], 'test', 'relative path') - - self.assertNotEqual( - self.get(url='/?chdir=/')['body'], 'test', 'relative path w/ chdir' - ) - - self.assertEqual(self.get()['body'], 'test', 'relative path 2') + assert self.get()['body'] == 'test', 'relative path' + assert ( + self.get(url='/?chdir=/')['body'] != 'test' + ), 'relative path w/ chdir' -if __name__ == '__main__': - TestPHPApplication.main() + assert self.get()['body'] == 'test', 'relative path 2' diff --git a/test/test_php_basic.py b/test/test_php_basic.py index 16483c4a..1420ec21 100644 --- a/test/test_php_basic.py +++ b/test/test_php_basic.py @@ -23,133 +23,97 @@ class TestPHPBasic(TestControl): conf = self.conf_get() - self.assertEqual(conf['listeners'], {}, 'listeners') - self.assertEqual( - conf['applications'], - { - "app": { - "type": "php", - "processes": {"spare": 0}, - "root": "/app", - "index": "index.php", - } - }, - 'applications', - ) - - self.assertEqual( - self.conf_get('applications'), - { - "app": { - "type": "php", - "processes": {"spare": 0}, - "root": "/app", - "index": "index.php", - } - }, - 'applications prefix', - ) - - self.assertEqual( - self.conf_get('applications/app'), - { + assert conf['listeners'] == {}, 'listeners' + assert conf['applications'] == { + "app": { "type": "php", "processes": {"spare": 0}, "root": "/app", "index": "index.php", - }, - 'applications prefix 2', - ) + } + }, 'applications' - self.assertEqual(self.conf_get('applications/app/type'), 'php', 'type') - self.assertEqual( - self.conf_get('applications/app/processes/spare'), - 0, - 'spare processes', - ) + assert self.conf_get('applications') == { + "app": { + "type": "php", + "processes": {"spare": 0}, + "root": "/app", + "index": "index.php", + } + }, 'applications prefix' + + assert self.conf_get('applications/app') == { + "type": "php", + "processes": {"spare": 0}, + "root": "/app", + "index": "index.php", + }, 'applications prefix 2' + + assert self.conf_get('applications/app/type') == 'php', 'type' + assert ( + self.conf_get('applications/app/processes/spare') == 0 + ), 'spare processes' def test_php_get_listeners(self): self.conf(self.conf_basic) - self.assertEqual( - self.conf_get()['listeners'], - {"*:7080": {"pass": "applications/app"}}, - 'listeners', - ) + assert self.conf_get()['listeners'] == { + "*:7080": {"pass": "applications/app"} + }, 'listeners' - self.assertEqual( - self.conf_get('listeners'), - {"*:7080": {"pass": "applications/app"}}, - 'listeners prefix', - ) + assert self.conf_get('listeners') == { + "*:7080": {"pass": "applications/app"} + }, 'listeners prefix' - self.assertEqual( - self.conf_get('listeners/*:7080'), - {"pass": "applications/app"}, - 'listeners prefix 2', - ) + assert self.conf_get('listeners/*:7080') == { + "pass": "applications/app" + }, 'listeners prefix 2' def test_php_change_listener(self): self.conf(self.conf_basic) self.conf({"*:7081": {"pass": "applications/app"}}, 'listeners') - self.assertEqual( - self.conf_get('listeners'), - {"*:7081": {"pass": "applications/app"}}, - 'change listener', - ) + assert self.conf_get('listeners') == { + "*:7081": {"pass": "applications/app"} + }, 'change listener' def test_php_add_listener(self): self.conf(self.conf_basic) self.conf({"pass": "applications/app"}, 'listeners/*:7082') - self.assertEqual( - self.conf_get('listeners'), - { - "*:7080": {"pass": "applications/app"}, - "*:7082": {"pass": "applications/app"}, - }, - 'add listener', - ) + assert self.conf_get('listeners') == { + "*:7080": {"pass": "applications/app"}, + "*:7082": {"pass": "applications/app"}, + }, 'add listener' def test_php_change_application(self): self.conf(self.conf_basic) self.conf('30', 'applications/app/processes/max') - self.assertEqual( - self.conf_get('applications/app/processes/max'), - 30, - 'change application max', - ) + assert ( + self.conf_get('applications/app/processes/max') == 30 + ), 'change application max' self.conf('"/www"', 'applications/app/root') - self.assertEqual( - self.conf_get('applications/app/root'), - '/www', - 'change application root', - ) + assert ( + self.conf_get('applications/app/root') == '/www' + ), 'change application root' def test_php_delete(self): self.conf(self.conf_basic) - self.assertIn('error', self.conf_delete('applications/app')) - self.assertIn('success', self.conf_delete('listeners/*:7080')) - self.assertIn('success', self.conf_delete('applications/app')) - self.assertIn('error', self.conf_delete('applications/app')) + assert 'error' in self.conf_delete('applications/app') + assert 'success' in self.conf_delete('listeners/*:7080') + assert 'success' in self.conf_delete('applications/app') + assert 'error' in self.conf_delete('applications/app') def test_php_delete_blocks(self): self.conf(self.conf_basic) - self.assertIn('success', self.conf_delete('listeners')) - self.assertIn('success', self.conf_delete('applications')) - - self.assertIn('success', self.conf(self.conf_app, 'applications')) - self.assertIn( - 'success', - self.conf({"*:7081": {"pass": "applications/app"}}, 'listeners'), - 'applications restore', - ) - + assert 'success' in self.conf_delete('listeners') + assert 'success' in self.conf_delete('applications') -if __name__ == '__main__': - TestPHPBasic.main() + assert 'success' in self.conf(self.conf_app, 'applications') + assert 'success' in self.conf( + {"*:7081": {"pass": "applications/app"}}, 'listeners' + ), 'applications restore' diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index 3004a7b8..f4170f1b 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -1,7 +1,8 @@ -import unittest +import pytest from unit.applications.lang.php import TestApplicationPHP from unit.feature.isolation import TestFeatureIsolation +from conftest import option class TestPHPIsolation(TestApplicationPHP): @@ -10,171 +11,128 @@ class TestPHPIsolation(TestApplicationPHP): isolation = TestFeatureIsolation() @classmethod - def setUpClass(cls, complete_check=True): - unit = super().setUpClass(complete_check=False) + def setup_class(cls, complete_check=True): + unit = super().setup_class(complete_check=False) - TestFeatureIsolation().check(cls.available, unit.testdir) + TestFeatureIsolation().check(cls.available, unit.temp_dir) return unit if not complete_check else unit.complete() - def test_php_isolation_rootfs(self): + def test_php_isolation_rootfs(self, is_su): isolation_features = self.available['features']['isolation'].keys() if 'mnt' not in isolation_features: - print('requires mnt ns') - raise unittest.SkipTest() + pytest.skip('requires mnt ns') - if not self.is_su: + if not is_su: if 'user' not in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') if not 'unprivileged_userns_clone' in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') isolation = { - 'namespaces': {'credential': not self.is_su, 'mount': True}, - 'rootfs': self.current_dir, + 'namespaces': {'credential': not is_su, 'mount': True}, + 'rootfs': option.test_dir, } self.load('phpinfo', isolation=isolation) - self.assertIn( - 'success', self.conf('"/php/phpinfo"', 'applications/phpinfo/root') + assert 'success' in self.conf( + '"/php/phpinfo"', 'applications/phpinfo/root' ) - self.assertIn( - 'success', - self.conf( - '"/php/phpinfo"', 'applications/phpinfo/working_directory' - ), + assert 'success' in self.conf( + '"/php/phpinfo"', 'applications/phpinfo/working_directory' ) - self.assertEqual(self.get()['status'], 200, 'empty rootfs') + assert self.get()['status'] == 200, 'empty rootfs' - def test_php_isolation_rootfs_extensions(self): + def test_php_isolation_rootfs_extensions(self, is_su): isolation_features = self.available['features']['isolation'].keys() - if not self.is_su: + if not is_su: if 'user' not in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') if not 'unprivileged_userns_clone' in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') if 'mnt' not in isolation_features: - print('requires mnt ns') - raise unittest.SkipTest() + pytest.skip('requires mnt ns') isolation = { - 'rootfs': self.current_dir, - 'namespaces': { - 'credential': not self.is_su, - 'mount': not self.is_su, - }, + 'rootfs': option.test_dir, + 'namespaces': {'credential': not is_su, 'mount': not is_su}, } self.load('list-extensions', isolation=isolation) - self.assertIn( - 'success', - self.conf( - '"/php/list-extensions"', 'applications/list-extensions/root' - ), + assert 'success' in self.conf( + '"/php/list-extensions"', 'applications/list-extensions/root' ) - self.assertIn( - 'success', - self.conf( - {'file': '/php/list-extensions/php.ini'}, - 'applications/list-extensions/options', - ), + assert 'success' in self.conf( + {'file': '/php/list-extensions/php.ini'}, + 'applications/list-extensions/options', ) - self.assertIn( - 'success', - self.conf( - '"/php/list-extensions"', - 'applications/list-extensions/working_directory', - ), + assert 'success' in self.conf( + '"/php/list-extensions"', + 'applications/list-extensions/working_directory', ) extensions = self.getjson()['body'] - self.assertIn('json', extensions, 'json in extensions list') - self.assertIn('unit', extensions, 'unit in extensions list') + assert 'json' in extensions, 'json in extensions list' + assert 'unit' in extensions, 'unit in extensions list' - - def test_php_isolation_rootfs_no_language_libs(self): + def test_php_isolation_rootfs_no_language_libs(self, is_su): isolation_features = self.available['features']['isolation'].keys() - if not self.is_su: + if not is_su: if 'user' not in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') if not 'unprivileged_userns_clone' in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') if 'mnt' not in isolation_features: - print('requires mnt ns') - raise unittest.SkipTest() + pytest.skip('requires mnt ns') isolation = { - 'rootfs': self.current_dir, + 'rootfs': option.test_dir, 'automount': {'language_deps': False}, - 'namespaces': { - 'credential': not self.is_su, - 'mount': not self.is_su, - }, + 'namespaces': {'credential': not is_su, 'mount': not is_su}, } self.load('list-extensions', isolation=isolation) - self.assertIn( - 'success', - self.conf( - '"/php/list-extensions"', 'applications/list-extensions/root' - ), + assert 'success' in self.conf( + '"/php/list-extensions"', 'applications/list-extensions/root' ) - self.assertIn( - 'success', - self.conf( - {'file': '/php/list-extensions/php.ini'}, - 'applications/list-extensions/options', - ), + assert 'success' in self.conf( + {'file': '/php/list-extensions/php.ini'}, + 'applications/list-extensions/options', ) - self.assertIn( - 'success', - self.conf( - '"/php/list-extensions"', - 'applications/list-extensions/working_directory', - ), + assert 'success' in self.conf( + '"/php/list-extensions"', + 'applications/list-extensions/working_directory', ) extensions = self.getjson()['body'] - self.assertIn('unit', extensions, 'unit in extensions list') - self.assertNotIn('json', extensions, 'json not in extensions list') + assert 'unit' in extensions, 'unit in extensions list' + assert 'json' not in extensions, 'json not in extensions list' - self.assertIn( - 'success', - self.conf( - {'language_deps': True}, - 'applications/list-extensions/isolation/automount', - ), + assert 'success' in self.conf( + {'language_deps': True}, + 'applications/list-extensions/isolation/automount', ) extensions = self.getjson()['body'] - self.assertIn('unit', extensions, 'unit in extensions list 2') - self.assertIn('json', extensions, 'json in extensions list 2') - + assert 'unit' in extensions, 'unit in extensions list 2' + assert 'json' in extensions, 'json in extensions list 2' -if __name__ == '__main__': - TestPHPIsolation.main() diff --git a/test/test_php_targets.py b/test/test_php_targets.py index 0657554a..2eadf071 100644 --- a/test/test_php_targets.py +++ b/test/test_php_targets.py @@ -1,128 +1,98 @@ from unit.applications.lang.php import TestApplicationPHP +from conftest import option + class TestPHPTargets(TestApplicationPHP): prerequisites = {'modules': {'php': 'any'}} def test_php_application_targets(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "routes"}}, - "routes": [ - { - "match": {"uri": "/1"}, - "action": {"pass": "applications/targets/1"}, - }, - { - "match": {"uri": "/2"}, - "action": {"pass": "applications/targets/2"}, - }, - {"action": {"pass": "applications/targets/default"}}, - ], - "applications": { + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes"}}, + "routes": [ + { + "match": {"uri": "/1"}, + "action": {"pass": "applications/targets/1"}, + }, + { + "match": {"uri": "/2"}, + "action": {"pass": "applications/targets/2"}, + }, + {"action": {"pass": "applications/targets/default"}}, + ], + "applications": { + "targets": { + "type": "php", + "processes": {"spare": 0}, "targets": { - "type": "php", - "processes": {"spare": 0}, - "targets": { - "1": { - "script": "1.php", - "root": self.current_dir + "/php/targets", - }, - "2": { - "script": "2.php", - "root": self.current_dir - + "/php/targets/2", - }, - "default": { - "index": "index.php", - "root": self.current_dir + "/php/targets", - }, + "1": { + "script": "1.php", + "root": option.test_dir + "/php/targets", }, - } - }, - } - ), + "2": { + "script": "2.php", + "root": option.test_dir + "/php/targets/2", + }, + "default": { + "index": "index.php", + "root": option.test_dir + "/php/targets", + }, + }, + } + }, + } ) - self.assertEqual(self.get(url='/1')['body'], '1') - self.assertEqual(self.get(url='/2')['body'], '2') - self.assertEqual(self.get(url='/blah')['status'], 503) # TODO 404 - self.assertEqual(self.get(url='/')['body'], 'index') + assert self.get(url='/1')['body'] == '1' + assert self.get(url='/2')['body'] == '2' + assert self.get(url='/blah')['status'] == 503 # TODO 404 + assert self.get(url='/')['body'] == 'index' - self.assertIn( - 'success', - self.conf( - "\"1.php\"", 'applications/targets/targets/default/index' - ), - 'change targets index', - ) - self.assertEqual(self.get(url='/')['body'], '1') + assert 'success' in self.conf( + "\"1.php\"", 'applications/targets/targets/default/index' + ), 'change targets index' + assert self.get(url='/')['body'] == '1' - self.assertIn( - 'success', - self.conf_delete('applications/targets/targets/default/index'), - 'remove targets index', - ) - self.assertEqual(self.get(url='/')['body'], 'index') + assert 'success' in self.conf_delete( + 'applications/targets/targets/default/index' + ), 'remove targets index' + assert self.get(url='/')['body'] == 'index' def test_php_application_targets_error(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "applications/targets/default"} - }, - "applications": { + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "applications/targets/default"} + }, + "applications": { + "targets": { + "type": "php", + "processes": {"spare": 0}, "targets": { - "type": "php", - "processes": {"spare": 0}, - "targets": { - "default": { - "index": "index.php", - "root": self.current_dir + "/php/targets", - }, + "default": { + "index": "index.php", + "root": option.test_dir + "/php/targets", }, - } - }, - } - ), - 'initial configuration', - ) - self.assertEqual(self.get()['status'], 200) - - self.assertIn( - 'error', - self.conf( - {"pass": "applications/targets/blah"}, 'listeners/*:7080' - ), - 'invalid targets pass', - ) - self.assertIn( - 'error', - self.conf( - '"' + self.current_dir + '/php/targets\"', - 'applications/targets/root', - ), - 'invalid root', - ) - self.assertIn( - 'error', - self.conf('"index.php"', 'applications/targets/index'), - 'invalid index', - ) - self.assertIn( - 'error', - self.conf('"index.php"', 'applications/targets/script'), - 'invalid script', - ) - self.assertIn( - 'error', - self.conf_delete('applications/targets/default/root'), - 'root remove', - ) - + }, + } + }, + } + ), 'initial configuration' + assert self.get()['status'] == 200 -if __name__ == '__main__': - TestPHPTargets.main() + assert 'error' in self.conf( + {"pass": "applications/targets/blah"}, 'listeners/*:7080' + ), 'invalid targets pass' + assert 'error' in self.conf( + '"' + option.test_dir + '/php/targets\"', + 'applications/targets/root', + ), 'invalid root' + assert 'error' in self.conf( + '"index.php"', 'applications/targets/index' + ), 'invalid index' + assert 'error' in self.conf( + '"index.php"', 'applications/targets/script' + ), 'invalid script' + assert 'error' in self.conf_delete( + 'applications/targets/default/root' + ), 'root remove' diff --git a/test/test_proxy.py b/test/test_proxy.py index feec1ac4..1476670c 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -1,9 +1,10 @@ +import pytest import re import socket import time -import unittest from unit.applications.lang.python import TestApplicationPython +from conftest import option, skip_alert class TestProxy(TestApplicationPython): @@ -42,7 +43,7 @@ Content-Length: 10 to_send = req - m = re.search('X-Len: (\d+)', data) + m = re.search(r'X-Len: (\d+)', data) if m: to_send += b'X' * int(m.group(1)) @@ -56,145 +57,127 @@ Content-Length: 10 def post_http10(self, *args, **kwargs): return self.post(*args, http_10=True, **kwargs) - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() self.run_process(self.run_server, self.SERVER_PORT) self.waitforsocket(self.SERVER_PORT) - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "routes"}, - "*:7081": {"pass": "applications/mirror"}, + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": {"pass": "applications/mirror"}, + }, + "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "applications": { + "mirror": { + "type": "python", + "processes": {"spare": 0}, + "path": option.test_dir + "/python/mirror", + "working_directory": option.test_dir + + "/python/mirror", + "module": "wsgi", }, - "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], - "applications": { - "mirror": { - "type": "python", - "processes": {"spare": 0}, - "path": self.current_dir + "/python/mirror", - "working_directory": self.current_dir - + "/python/mirror", - "module": "wsgi", - }, - "custom_header": { - "type": "python", - "processes": {"spare": 0}, - "path": self.current_dir + "/python/custom_header", - "working_directory": self.current_dir - + "/python/custom_header", - "module": "wsgi", - }, - "delayed": { - "type": "python", - "processes": {"spare": 0}, - "path": self.current_dir + "/python/delayed", - "working_directory": self.current_dir - + "/python/delayed", - "module": "wsgi", - }, + "custom_header": { + "type": "python", + "processes": {"spare": 0}, + "path": option.test_dir + "/python/custom_header", + "working_directory": option.test_dir + + "/python/custom_header", + "module": "wsgi", }, - } - ), - 'proxy initial configuration', - ) + "delayed": { + "type": "python", + "processes": {"spare": 0}, + "path": option.test_dir + "/python/delayed", + "working_directory": option.test_dir + + "/python/delayed", + "module": "wsgi", + }, + }, + } + ), 'proxy initial configuration' def test_proxy_http10(self): for _ in range(10): - self.assertEqual(self.get_http10()['status'], 200, 'status') + assert self.get_http10()['status'] == 200, 'status' def test_proxy_chain(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "routes/first"}, - "*:7081": {"pass": "routes/second"}, - "*:7082": {"pass": "routes/third"}, - "*:7083": {"pass": "routes/fourth"}, - "*:7084": {"pass": "routes/fifth"}, - "*:7085": {"pass": "applications/mirror"}, - }, - "routes": { - "first": [ - {"action": {"proxy": "http://127.0.0.1:7081"}} - ], - "second": [ - {"action": {"proxy": "http://127.0.0.1:7082"}} - ], - "third": [ - {"action": {"proxy": "http://127.0.0.1:7083"}} - ], - "fourth": [ - {"action": {"proxy": "http://127.0.0.1:7084"}} - ], - "fifth": [ - {"action": {"proxy": "http://127.0.0.1:7085"}} - ], - }, - "applications": { - "mirror": { - "type": "python", - "processes": {"spare": 0}, - "path": self.current_dir + "/python/mirror", - "working_directory": self.current_dir - + "/python/mirror", - "module": "wsgi", - } - }, - } - ), - 'proxy chain configuration', - ) + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "routes/first"}, + "*:7081": {"pass": "routes/second"}, + "*:7082": {"pass": "routes/third"}, + "*:7083": {"pass": "routes/fourth"}, + "*:7084": {"pass": "routes/fifth"}, + "*:7085": {"pass": "applications/mirror"}, + }, + "routes": { + "first": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "second": [{"action": {"proxy": "http://127.0.0.1:7082"}}], + "third": [{"action": {"proxy": "http://127.0.0.1:7083"}}], + "fourth": [{"action": {"proxy": "http://127.0.0.1:7084"}}], + "fifth": [{"action": {"proxy": "http://127.0.0.1:7085"}}], + }, + "applications": { + "mirror": { + "type": "python", + "processes": {"spare": 0}, + "path": option.test_dir + "/python/mirror", + "working_directory": option.test_dir + + "/python/mirror", + "module": "wsgi", + } + }, + } + ), 'proxy chain configuration' - self.assertEqual(self.get_http10()['status'], 200, 'status') + assert self.get_http10()['status'] == 200, 'status' def test_proxy_body(self): payload = '0123456789' for _ in range(10): resp = self.post_http10(body=payload) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], payload, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' payload = 'X' * 4096 for _ in range(10): resp = self.post_http10(body=payload) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], payload, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' payload = 'X' * 4097 for _ in range(10): resp = self.post_http10(body=payload) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], payload, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' payload = 'X' * 4096 * 256 for _ in range(10): resp = self.post_http10(body=payload, read_buffer_size=4096 * 128) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], payload, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' payload = 'X' * 4096 * 257 for _ in range(10): resp = self.post_http10(body=payload, read_buffer_size=4096 * 128) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], payload, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' self.conf({'http': {'max_body_size': 32 * 1024 * 1024}}, 'settings') payload = '0123456789abcdef' * 32 * 64 * 1024 resp = self.post_http10(body=payload, read_buffer_size=1024 * 1024) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], payload, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == payload, 'body' def test_proxy_parallel(self): payload = 'X' * 4096 * 257 @@ -216,62 +199,53 @@ Content-Length: 10 resp = self._resp_to_dict(resp) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], payload + str(i), 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == payload + str(i), 'body' def test_proxy_header(self): - self.assertIn( - 'success', - self.conf( - {"pass": "applications/custom_header"}, 'listeners/*:7081' - ), - 'custom_header configure', - ) + assert 'success' in self.conf( + {"pass": "applications/custom_header"}, 'listeners/*:7081' + ), 'custom_header configure' header_value = 'blah' - self.assertEqual( + assert ( self.get_http10( headers={'Host': 'localhost', 'Custom-Header': header_value} - )['headers']['Custom-Header'], - header_value, - 'custom header', - ) + )['headers']['Custom-Header'] + == header_value + ), 'custom header' header_value = '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~' - self.assertEqual( + assert ( self.get_http10( headers={'Host': 'localhost', 'Custom-Header': header_value} - )['headers']['Custom-Header'], - header_value, - 'custom header 2', - ) + )['headers']['Custom-Header'] + == header_value + ), 'custom header 2' header_value = 'X' * 4096 - self.assertEqual( + assert ( self.get_http10( headers={'Host': 'localhost', 'Custom-Header': header_value} - )['headers']['Custom-Header'], - header_value, - 'custom header 3', - ) + )['headers']['Custom-Header'] + == header_value + ), 'custom header 3' header_value = 'X' * 8191 - self.assertEqual( + assert ( self.get_http10( headers={'Host': 'localhost', 'Custom-Header': header_value} - )['headers']['Custom-Header'], - header_value, - 'custom header 4', - ) + )['headers']['Custom-Header'] + == header_value + ), 'custom header 4' header_value = 'X' * 8192 - self.assertEqual( + assert ( self.get_http10( headers={'Host': 'localhost', 'Custom-Header': header_value} - )['status'], - 431, - 'custom header 5', - ) + )['status'] + == 431 + ), 'custom header 5' def test_proxy_fragmented(self): _, sock = self.http( @@ -286,9 +260,9 @@ Content-Length: 10 sock.sendall("t\r\n\r\n".encode()) - self.assertRegex( - self.recvall(sock).decode(), '200 OK', 'fragmented send' - ) + assert re.search( + '200 OK', self.recvall(sock).decode() + ), 'fragmented send' sock.close() def test_proxy_fragmented_close(self): @@ -328,8 +302,8 @@ Content-Length: 10 resp = self._resp_to_dict(self.recvall(sock).decode()) sock.close() - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], "X" * 30000, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == "X" * 30000, 'body' def test_proxy_fragmented_body_close(self): _, sock = self.http( @@ -349,70 +323,48 @@ Content-Length: 10 sock.close() def test_proxy_nowhere(self): - self.assertIn( - 'success', - self.conf( - [{"action": {"proxy": "http://127.0.0.1:7082"}}], 'routes' - ), - 'proxy path changed', - ) + assert 'success' in self.conf( + [{"action": {"proxy": "http://127.0.0.1:7082"}}], 'routes' + ), 'proxy path changed' - self.assertEqual(self.get_http10()['status'], 502, 'status') + assert self.get_http10()['status'] == 502, 'status' def test_proxy_ipv6(self): - self.assertIn( - 'success', - self.conf( - { - "*:7080": {"pass": "routes"}, - "[::1]:7081": {'application': 'mirror'}, - }, - 'listeners', - ), - 'add ipv6 listener configure', - ) + assert 'success' in self.conf( + { + "*:7080": {"pass": "routes"}, + "[::1]:7081": {'application': 'mirror'}, + }, + 'listeners', + ), 'add ipv6 listener configure' - self.assertIn( - 'success', - self.conf([{"action": {"proxy": "http://[::1]:7081"}}], 'routes'), - 'proxy ipv6 configure', - ) + assert 'success' in self.conf( + [{"action": {"proxy": "http://[::1]:7081"}}], 'routes' + ), 'proxy ipv6 configure' - self.assertEqual(self.get_http10()['status'], 200, 'status') + assert self.get_http10()['status'] == 200, 'status' def test_proxy_unix(self): - addr = self.testdir + '/sock' + addr = self.temp_dir + '/sock' - self.assertIn( - 'success', - self.conf( - { - "*:7080": {"pass": "routes"}, - "unix:" + addr: {'application': 'mirror'}, - }, - 'listeners', - ), - 'add unix listener configure', - ) + assert 'success' in self.conf( + { + "*:7080": {"pass": "routes"}, + "unix:" + addr: {'application': 'mirror'}, + }, + 'listeners', + ), 'add unix listener configure' - self.assertIn( - 'success', - self.conf( - [{"action": {"proxy": 'http://unix:' + addr}}], 'routes' - ), - 'proxy unix configure', - ) + assert 'success' in self.conf( + [{"action": {"proxy": 'http://unix:' + addr}}], 'routes' + ), 'proxy unix configure' - self.assertEqual(self.get_http10()['status'], 200, 'status') + assert self.get_http10()['status'] == 200, 'status' def test_proxy_delayed(self): - self.assertIn( - 'success', - self.conf( - {"pass": "applications/delayed"}, 'listeners/*:7081' - ), - 'delayed configure', - ) + assert 'success' in self.conf( + {"pass": "applications/delayed"}, 'listeners/*:7081' + ), 'delayed configure' body = '0123456789' * 1000 resp = self.post_http10( @@ -426,8 +378,8 @@ Content-Length: 10 body=body, ) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], body, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == body, 'body' resp = self.post_http10( headers={ @@ -440,17 +392,13 @@ Content-Length: 10 body=body, ) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], body, 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == body, 'body' def test_proxy_delayed_close(self): - self.assertIn( - 'success', - self.conf( - {"pass": "applications/delayed"}, 'listeners/*:7081' - ), - 'delayed configure', - ) + assert 'success' in self.conf( + {"pass": "applications/delayed"}, 'listeners/*:7081' + ), 'delayed configure' _, sock = self.post_http10( headers={ @@ -465,9 +413,7 @@ Content-Length: 10 no_recv=True, ) - self.assertRegex( - sock.recv(100).decode(), '200 OK', 'first' - ) + assert re.search('200 OK', sock.recv(100).decode()), 'first' sock.close() _, sock = self.post_http10( @@ -483,51 +429,42 @@ Content-Length: 10 no_recv=True, ) - self.assertRegex( - sock.recv(100).decode(), '200 OK', 'second' - ) + assert re.search('200 OK', sock.recv(100).decode()), 'second' sock.close() - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_proxy_content_length(self): - self.assertIn( - 'success', - self.conf( - [ - { - "action": { - "proxy": "http://127.0.0.1:" - + str(self.SERVER_PORT) - } + assert 'success' in self.conf( + [ + { + "action": { + "proxy": "http://127.0.0.1:" + str(self.SERVER_PORT) } - ], - 'routes', - ), - 'proxy backend configure', - ) + } + ], + 'routes', + ), 'proxy backend configure' resp = self.get_http10() - self.assertEqual(len(resp['body']), 0, 'body lt Content-Length 0') + assert len(resp['body']) == 0, 'body lt Content-Length 0' resp = self.get_http10(headers={'Host': 'localhost', 'X-Len': '5'}) - self.assertEqual(len(resp['body']), 5, 'body lt Content-Length 5') + assert len(resp['body']) == 5, 'body lt Content-Length 5' resp = self.get_http10(headers={'Host': 'localhost', 'X-Len': '9'}) - self.assertEqual(len(resp['body']), 9, 'body lt Content-Length 9') + assert len(resp['body']) == 9, 'body lt Content-Length 9' resp = self.get_http10(headers={'Host': 'localhost', 'X-Len': '11'}) - self.assertEqual(len(resp['body']), 10, 'body gt Content-Length 11') + assert len(resp['body']) == 10, 'body gt Content-Length 11' resp = self.get_http10(headers={'Host': 'localhost', 'X-Len': '15'}) - self.assertEqual(len(resp['body']), 10, 'body gt Content-Length 15') + assert len(resp['body']) == 10, 'body gt Content-Length 15' def test_proxy_invalid(self): def check_proxy(proxy): - self.assertIn( - 'error', - self.conf([{"action": {"proxy": proxy}}], 'routes'), - 'proxy invalid', - ) + assert 'error' in \ + self.conf([{"action": {"proxy": proxy}}], 'routes'), \ + 'proxy invalid' check_proxy('blah') check_proxy('/blah') @@ -544,12 +481,10 @@ Content-Length: 10 check_proxy('http://[::7080') def test_proxy_loop(self): - self.skip_alerts.extend( - [ - r'socket.*failed', - r'accept.*failed', - r'new connections are not accepted', - ] + skip_alert( + r'socket.*failed', + r'accept.*failed', + r'new connections are not accepted', ) self.conf( { @@ -563,9 +498,8 @@ Content-Length: 10 "mirror": { "type": "python", "processes": {"spare": 0}, - "path": self.current_dir + "/python/mirror", - "working_directory": self.current_dir - + "/python/mirror", + "path": option.test_dir + "/python/mirror", + "working_directory": option.test_dir + "/python/mirror", "module": "wsgi", }, }, @@ -574,6 +508,3 @@ Content-Length: 10 self.get_http10(no_recv=True) self.get_http10(read_timeout=1) - -if __name__ == '__main__': - TestProxy.main() diff --git a/test/test_proxy_chunked.py b/test/test_proxy_chunked.py index f344b69a..93746703 100644 --- a/test/test_proxy_chunked.py +++ b/test/test_proxy_chunked.py @@ -12,7 +12,7 @@ class TestProxyChunked(TestApplicationPython): SERVER_PORT = 7999 @staticmethod - def run_server(server_port, testdir): + def run_server(server_port, temp_dir): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) @@ -81,68 +81,62 @@ class TestProxyChunked(TestApplicationPython): def get_http10(self, *args, **kwargs): return self.get(*args, http_10=True, **kwargs) - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - self.run_process(self.run_server, self.SERVER_PORT, self.testdir) + self.run_process(self.run_server, self.SERVER_PORT, self.temp_dir) self.waitforsocket(self.SERVER_PORT) - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "routes"},}, - "routes": [ - { - "action": { - "proxy": "http://127.0.0.1:" - + str(self.SERVER_PORT) - } + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes"},}, + "routes": [ + { + "action": { + "proxy": "http://127.0.0.1:" + + str(self.SERVER_PORT) } - ], - } - ), - 'proxy initial configuration', - ) + } + ], + } + ), 'proxy initial configuration' def test_proxy_chunked(self): for _ in range(10): - self.assertEqual( - self.get_http10(body='\r\n\r\n0\r\n\r\n')['status'], 200 - ) + assert self.get_http10(body='\r\n\r\n0\r\n\r\n')['status'] == 200 def test_proxy_chunked_body(self): part = '0123456789abcdef' - self.assertEqual( + assert ( self.get_http10(body=self.chunks([('1000', part + ' X 256')]))[ 'body' - ], - part * 256, + ] + == part * 256 ) - self.assertEqual( + assert ( self.get_http10(body=self.chunks([('100000', part + ' X 65536')]))[ 'body' - ], - part * 65536, + ] + == part * 65536 ) - self.assertEqual( + assert ( self.get_http10( body=self.chunks([('1000000', part + ' X 1048576')]), read_buffer_size=4096 * 4096, - )['body'], - part * 1048576, + )['body'] + == part * 1048576 ) - self.assertEqual( + assert ( self.get_http10( body=self.chunks( [('1000', part + ' X 256'), ('1000', part + ' X 256')] ) - )['body'], - part * 256 * 2, + )['body'] + == part * 256 * 2 ) - self.assertEqual( + assert ( self.get_http10( body=self.chunks( [ @@ -150,10 +144,10 @@ class TestProxyChunked(TestApplicationPython): ('100000', part + ' X 65536'), ] ) - )['body'], - part * 65536 * 2, + )['body'] + == part * 65536 * 2 ) - self.assertEqual( + assert ( self.get_http10( body=self.chunks( [ @@ -162,42 +156,40 @@ class TestProxyChunked(TestApplicationPython): ] ), read_buffer_size=4096 * 4096, - )['body'], - part * 1048576 * 2, + )['body'] + == part * 1048576 * 2 ) def test_proxy_chunked_fragmented(self): part = '0123456789abcdef' - self.assertEqual( + assert ( self.get_http10( body=self.chunks( [('1', hex(i % 16)[2:]) for i in range(4096)] ), - )['body'], - part * 256, + )['body'] + == part * 256 ) def test_proxy_chunked_send(self): - self.assertEqual( - self.get_http10(body='\r\n\r\n@0@\r\n\r\n')['status'], 200 - ) - self.assertEqual( + assert self.get_http10(body='\r\n\r\n@0@\r\n\r\n')['status'] == 200 + assert ( self.get_http10( body='\r@\n\r\n2\r@\na@b\r\n2\r\ncd@\r\n0\r@\n\r\n' - )['body'], - 'abcd', + )['body'] + == 'abcd' ) - self.assertEqual( + assert ( self.get_http10( body='\r\n\r\n2\r#\na#b\r\n##2\r\n#cd\r\n0\r\n#\r#\n' - )['body'], - 'abcd', + )['body'] + == 'abcd' ) def test_proxy_chunked_invalid(self): def check_invalid(body): - self.assertNotEqual(self.get_http10(body=body)['status'], 200) + assert self.get_http10(body=body)['status'] != 200 check_invalid('\r\n\r0') check_invalid('\r\n\r\n\r0') @@ -209,41 +201,38 @@ class TestProxyChunked(TestApplicationPython): check_invalid('\r\n\r\n0\r\nX') resp = self.get_http10(body='\r\n\r\n65#\r\nA X 100') - self.assertEqual(resp['status'], 200, 'incomplete chunk status') - self.assertNotEqual(resp['body'][-5:], '0\r\n\r\n', 'incomplete chunk') + assert resp['status'] == 200, 'incomplete chunk status' + assert resp['body'][-5:] != '0\r\n\r\n', 'incomplete chunk' resp = self.get_http10(body='\r\n\r\n64#\r\nA X 100') - self.assertEqual(resp['status'], 200, 'no zero chunk status') - self.assertNotEqual(resp['body'][-5:], '0\r\n\r\n', 'no zero chunk') + assert resp['status'] == 200, 'no zero chunk status' + assert resp['body'][-5:] != '0\r\n\r\n', 'no zero chunk' - self.assertEqual( - self.get_http10(body='\r\n\r\n80000000\r\nA X 100')['status'], 200, + assert ( + self.get_http10(body='\r\n\r\n80000000\r\nA X 100')['status'] + == 200 ) - self.assertEqual( + assert ( self.get_http10(body='\r\n\r\n10000000000000000\r\nA X 100')[ 'status' - ], - 502, + ] + == 502 ) - self.assertGreaterEqual( + assert ( len( self.get_http10( body='\r\n\r\n1000000\r\nA X 1048576\r\n1000000\r\nA X 100', read_buffer_size=4096 * 4096, )['body'] - ), - 1048576, + ) + >= 1048576 ) - self.assertGreaterEqual( + assert ( len( self.get_http10( body='\r\n\r\n1000000\r\nA X 1048576\r\nXXX\r\nA X 100', read_buffer_size=4096 * 4096, )['body'] - ), - 1048576, + ) + >= 1048576 ) - - -if __name__ == '__main__': - TestProxyChunked.main() diff --git a/test/test_python_application.py b/test/test_python_application.py index 4b8983ff..d1079116 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -1,17 +1,18 @@ import grp +import pytest import pwd import re import time -import unittest from unit.applications.lang.python import TestApplicationPython +from conftest import skip_alert class TestPythonApplication(TestApplicationPython): prerequisites = {'modules': {'python': 'all'}} def findall(self, pattern): - with open(self.testdir + '/unit.log', 'r', errors='ignore') as f: + with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f: return re.findall(pattern, f.read()) def test_python_application_variables(self): @@ -29,135 +30,109 @@ class TestPythonApplication(TestApplicationPython): body=body, ) - self.assertEqual(resp['status'], 200, 'status') + assert resp['status'] == 200, 'status' headers = resp['headers'] header_server = headers.pop('Server') - self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header') - self.assertEqual( - headers.pop('Server-Software'), - header_server, - 'server software header', - ) + assert re.search(r'Unit/[\d\.]+', header_server), 'server header' + assert ( + headers.pop('Server-Software') == header_server + ), 'server software header' date = headers.pop('Date') - self.assertEqual(date[-4:], ' GMT', 'date header timezone') - self.assertLess( - abs(self.date_to_sec_epoch(date) - self.sec_epoch()), - 5, - 'date header', - ) + assert date[-4:] == ' GMT', 'date header timezone' + assert ( + abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5 + ), 'date header' - self.assertDictEqual( - headers, - { - 'Connection': 'close', - 'Content-Length': str(len(body)), - 'Content-Type': 'text/html', - 'Request-Method': 'POST', - 'Request-Uri': '/', - 'Http-Host': 'localhost', - 'Server-Protocol': 'HTTP/1.1', - 'Custom-Header': 'blah', - 'Wsgi-Version': '(1, 0)', - 'Wsgi-Url-Scheme': 'http', - 'Wsgi-Multithread': 'False', - 'Wsgi-Multiprocess': 'True', - 'Wsgi-Run-Once': 'False', - }, - 'headers', - ) - self.assertEqual(resp['body'], body, 'body') + assert headers == { + 'Connection': 'close', + 'Content-Length': str(len(body)), + 'Content-Type': 'text/html', + 'Request-Method': 'POST', + 'Request-Uri': '/', + 'Http-Host': 'localhost', + 'Server-Protocol': 'HTTP/1.1', + 'Custom-Header': 'blah', + 'Wsgi-Version': '(1, 0)', + 'Wsgi-Url-Scheme': 'http', + 'Wsgi-Multithread': 'False', + 'Wsgi-Multiprocess': 'True', + 'Wsgi-Run-Once': 'False', + }, 'headers' + assert resp['body'] == body, 'body' def test_python_application_query_string(self): self.load('query_string') resp = self.get(url='/?var1=val1&var2=val2') - self.assertEqual( - resp['headers']['Query-String'], - 'var1=val1&var2=val2', - 'Query-String header', - ) + assert ( + resp['headers']['Query-String'] == 'var1=val1&var2=val2' + ), 'Query-String header' def test_python_application_query_string_space(self): self.load('query_string') resp = self.get(url='/ ?var1=val1&var2=val2') - self.assertEqual( - resp['headers']['Query-String'], - 'var1=val1&var2=val2', - 'Query-String space', - ) + assert ( + resp['headers']['Query-String'] == 'var1=val1&var2=val2' + ), 'Query-String space' resp = self.get(url='/ %20?var1=val1&var2=val2') - self.assertEqual( - resp['headers']['Query-String'], - 'var1=val1&var2=val2', - 'Query-String space 2', - ) + assert ( + resp['headers']['Query-String'] == 'var1=val1&var2=val2' + ), 'Query-String space 2' resp = self.get(url='/ %20 ?var1=val1&var2=val2') - self.assertEqual( - resp['headers']['Query-String'], - 'var1=val1&var2=val2', - 'Query-String space 3', - ) + assert ( + resp['headers']['Query-String'] == 'var1=val1&var2=val2' + ), 'Query-String space 3' resp = self.get(url='/blah %20 blah? var1= val1 & var2=val2') - self.assertEqual( - resp['headers']['Query-String'], - ' var1= val1 & var2=val2', - 'Query-String space 4', - ) + assert ( + resp['headers']['Query-String'] == ' var1= val1 & var2=val2' + ), 'Query-String space 4' def test_python_application_query_string_empty(self): self.load('query_string') resp = self.get(url='/?') - self.assertEqual(resp['status'], 200, 'query string empty status') - self.assertEqual( - resp['headers']['Query-String'], '', 'query string empty' - ) + assert resp['status'] == 200, 'query string empty status' + assert resp['headers']['Query-String'] == '', 'query string empty' def test_python_application_query_string_absent(self): self.load('query_string') resp = self.get() - self.assertEqual(resp['status'], 200, 'query string absent status') - self.assertEqual( - resp['headers']['Query-String'], '', 'query string absent' - ) + assert resp['status'] == 200, 'query string absent status' + assert resp['headers']['Query-String'] == '', 'query string absent' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_python_application_server_port(self): self.load('server_port') - self.assertEqual( - self.get()['headers']['Server-Port'], '7080', 'Server-Port header' - ) + assert ( + self.get()['headers']['Server-Port'] == '7080' + ), 'Server-Port header' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_python_application_working_directory_invalid(self): self.load('empty') - self.assertIn( - 'success', - self.conf('"/blah"', 'applications/empty/working_directory'), - 'configure invalid working_directory', - ) + assert 'success' in self.conf( + '"/blah"', 'applications/empty/working_directory' + ), 'configure invalid working_directory' - self.assertEqual(self.get()['status'], 500, 'status') + assert self.get()['status'] == 500, 'status' def test_python_application_204_transfer_encoding(self): self.load('204_no_content') - self.assertNotIn( - 'Transfer-Encoding', - self.get()['headers'], - '204 header transfer encoding', - ) + assert ( + 'Transfer-Encoding' not in self.get()['headers'] + ), '204 header transfer encoding' def test_python_application_ctx_iter_atexit(self): self.load('ctx_iter_atexit') @@ -171,21 +146,21 @@ class TestPythonApplication(TestApplicationPython): body='0123456789', ) - self.assertEqual(resp['status'], 200, 'ctx iter status') - self.assertEqual(resp['body'], '0123456789', 'ctx iter body') + assert resp['status'] == 200, 'ctx iter status' + assert resp['body'] == '0123456789', 'ctx iter body' self.conf({"listeners": {}, "applications": {}}) self.stop() - self.assertIsNotNone( - self.wait_for_record(r'RuntimeError'), 'ctx iter atexit' - ) + assert ( + self.wait_for_record(r'RuntimeError') is not None + ), 'ctx iter atexit' def test_python_keepalive_body(self): self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' body = '0123456789' * 500 (resp, sock) = self.post( @@ -199,7 +174,7 @@ class TestPythonApplication(TestApplicationPython): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'keep-alive 1') + assert resp['body'] == body, 'keep-alive 1' body = '0123456789' resp = self.post( @@ -212,19 +187,17 @@ class TestPythonApplication(TestApplicationPython): body=body, ) - self.assertEqual(resp['body'], body, 'keep-alive 2') + assert resp['body'] == body, 'keep-alive 2' def test_python_keepalive_reconfigure(self): - self.skip_alerts.extend( - [ - r'pthread_mutex.+failed', - r'failed to apply', - r'process \d+ exited on signal', - ] + skip_alert( + r'pthread_mutex.+failed', + r'failed to apply', + r'process \d+ exited on signal', ) self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' body = '0123456789' conns = 3 @@ -242,12 +215,10 @@ class TestPythonApplication(TestApplicationPython): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'keep-alive open') - self.assertIn( - 'success', - self.conf(str(i + 1), 'applications/mirror/processes'), - 'reconfigure', - ) + assert resp['body'] == body, 'keep-alive open' + assert 'success' in self.conf( + str(i + 1), 'applications/mirror/processes' + ), 'reconfigure' socks.append(sock) @@ -264,12 +235,10 @@ class TestPythonApplication(TestApplicationPython): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'keep-alive request') - self.assertIn( - 'success', - self.conf(str(i + 1), 'applications/mirror/processes'), - 'reconfigure 2', - ) + assert resp['body'] == body, 'keep-alive request' + assert 'success' in self.conf( + str(i + 1), 'applications/mirror/processes' + ), 'reconfigure 2' for i in range(conns): resp = self.post( @@ -282,17 +251,15 @@ class TestPythonApplication(TestApplicationPython): body=body, ) - self.assertEqual(resp['body'], body, 'keep-alive close') - self.assertIn( - 'success', - self.conf(str(i + 1), 'applications/mirror/processes'), - 'reconfigure 3', - ) + assert resp['body'] == body, 'keep-alive close' + assert 'success' in self.conf( + str(i + 1), 'applications/mirror/processes' + ), 'reconfigure 3' def test_python_keepalive_reconfigure_2(self): self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' body = '0123456789' @@ -307,11 +274,11 @@ class TestPythonApplication(TestApplicationPython): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'reconfigure 2 keep-alive 1') + assert resp['body'] == body, 'reconfigure 2 keep-alive 1' self.load('empty') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' (resp, sock) = self.post( headers={ @@ -324,23 +291,21 @@ class TestPythonApplication(TestApplicationPython): body=body, ) - self.assertEqual(resp['status'], 200, 'reconfigure 2 keep-alive 2') - self.assertEqual(resp['body'], '', 'reconfigure 2 keep-alive 2 body') + assert resp['status'] == 200, 'reconfigure 2 keep-alive 2' + assert resp['body'] == '', 'reconfigure 2 keep-alive 2 body' - self.assertIn( - 'success', - self.conf({"listeners": {}, "applications": {}}), - 'reconfigure 2 clear configuration', - ) + assert 'success' in self.conf( + {"listeners": {}, "applications": {}} + ), 'reconfigure 2 clear configuration' resp = self.get(sock=sock) - self.assertEqual(resp, {}, 'reconfigure 2 keep-alive 3') + assert resp == {}, 'reconfigure 2 keep-alive 3' def test_python_keepalive_reconfigure_3(self): self.load('empty') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' (_, sock) = self.http( b"""GET / HTTP/1.1 @@ -350,13 +315,11 @@ class TestPythonApplication(TestApplicationPython): no_recv=True, ) - self.assertEqual(self.get()['status'], 200) + assert self.get()['status'] == 200 - self.assertIn( - 'success', - self.conf({"listeners": {}, "applications": {}}), - 'reconfigure 3 clear configuration', - ) + assert 'success' in self.conf( + {"listeners": {}, "applications": {}} + ), 'reconfigure 3 clear configuration' resp = self.http( b"""Host: localhost @@ -367,7 +330,7 @@ Connection: close raw=True, ) - self.assertEqual(resp['status'], 200, 'reconfigure 3') + assert resp['status'] == 200, 'reconfigure 3' def test_python_atexit(self): self.load('atexit') @@ -378,25 +341,24 @@ Connection: close self.stop() - self.assertIsNotNone( - self.wait_for_record(r'At exit called\.'), 'atexit' - ) + assert self.wait_for_record(r'At exit called\.') is not None, 'atexit' def test_python_process_switch(self): self.load('delayed') - self.assertIn( - 'success', - self.conf('2', 'applications/delayed/processes'), - 'configure 2 processes', - ) + assert 'success' in self.conf( + '2', 'applications/delayed/processes' + ), 'configure 2 processes' - self.get(headers={ - 'Host': 'localhost', - 'Content-Length': '0', - 'X-Delay': '5', - 'Connection': 'close', - }, no_recv=True) + self.get( + headers={ + 'Host': 'localhost', + 'Content-Length': '0', + 'X-Delay': '5', + 'Connection': 'close', + }, + no_recv=True, + ) headers_delay_1 = { 'Connection': 'close', @@ -414,11 +376,11 @@ Connection: close self.get(headers=headers_delay_1) - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_python_application_start_response_exit(self): self.load('start_response_exit') - self.assertEqual(self.get()['status'], 500, 'start response exit') + assert self.get()['status'] == 500, 'start response exit' def test_python_application_input_iter(self): self.load('input_iter') @@ -429,10 +391,8 @@ next line last line''' resp = self.post(body=body) - self.assertEqual(resp['body'], body, 'input iter') - self.assertEqual( - resp['headers']['X-Lines-Count'], '4', 'input iter lines' - ) + assert resp['body'] == body, 'input iter' + assert resp['headers']['X-Lines-Count'] == '4', 'input iter lines' def test_python_application_input_readline(self): self.load('input_readline') @@ -443,10 +403,8 @@ next line last line''' resp = self.post(body=body) - self.assertEqual(resp['body'], body, 'input readline') - self.assertEqual( - resp['headers']['X-Lines-Count'], '4', 'input readline lines' - ) + assert resp['body'] == body, 'input readline' + assert resp['headers']['X-Lines-Count'] == '4', 'input readline lines' def test_python_application_input_readline_size(self): self.load('input_readline_size') @@ -456,12 +414,10 @@ next line last line''' - self.assertEqual( - self.post(body=body)['body'], body, 'input readline size' - ) - self.assertEqual( - self.post(body='0123')['body'], '0123', 'input readline size less' - ) + assert self.post(body=body)['body'] == body, 'input readline size' + assert ( + self.post(body='0123')['body'] == '0123' + ), 'input readline size less' def test_python_application_input_readlines(self): self.load('input_readlines') @@ -472,10 +428,8 @@ next line last line''' resp = self.post(body=body) - self.assertEqual(resp['body'], body, 'input readlines') - self.assertEqual( - resp['headers']['X-Lines-Count'], '4', 'input readlines lines' - ) + assert resp['body'] == body, 'input readlines' + assert resp['headers']['X-Lines-Count'] == '4', 'input readlines lines' def test_python_application_input_readlines_huge(self): self.load('input_readlines') @@ -489,11 +443,9 @@ last line: 987654321 * 512 ) - self.assertEqual( - self.post(body=body, read_buffer_size=16384)['body'], - body, - 'input readlines huge', - ) + assert ( + self.post(body=body, read_buffer_size=16384)['body'] == body + ), 'input readlines huge' def test_python_application_input_read_length(self): self.load('input_read_length') @@ -509,7 +461,7 @@ last line: 987654321 body=body, ) - self.assertEqual(resp['body'], body[:5], 'input read length lt body') + assert resp['body'] == body[:5], 'input read length lt body' resp = self.post( headers={ @@ -520,7 +472,7 @@ last line: 987654321 body=body, ) - self.assertEqual(resp['body'], body, 'input read length gt body') + assert resp['body'] == body, 'input read length gt body' resp = self.post( headers={ @@ -531,7 +483,7 @@ last line: 987654321 body=body, ) - self.assertEqual(resp['body'], '', 'input read length zero') + assert resp['body'] == '', 'input read length zero' resp = self.post( headers={ @@ -542,9 +494,9 @@ last line: 987654321 body=body, ) - self.assertEqual(resp['body'], body, 'input read length negative') + assert resp['body'] == body, 'input read length negative' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_python_application_errors_write(self): self.load('errors_write') @@ -552,43 +504,41 @@ last line: 987654321 self.stop() - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+Error in application\.'), - 'errors write', - ) + assert ( + self.wait_for_record(r'\[error\].+Error in application\.') + is not None + ), 'errors write' def test_python_application_body_array(self): self.load('body_array') - self.assertEqual(self.get()['body'], '0123456789', 'body array') + assert self.get()['body'] == '0123456789', 'body array' def test_python_application_body_io(self): self.load('body_io') - self.assertEqual(self.get()['body'], '0123456789', 'body io') + assert self.get()['body'] == '0123456789', 'body io' def test_python_application_body_io_file(self): self.load('body_io_file') - self.assertEqual(self.get()['body'], 'body\n', 'body io file') + assert self.get()['body'] == 'body\n', 'body io file' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_python_application_syntax_error(self): - self.skip_alerts.append(r'Python failed to import module "wsgi"') + skip_alert(r'Python failed to import module "wsgi"') self.load('syntax_error') - self.assertEqual(self.get()['status'], 500, 'syntax error') + assert self.get()['status'] == 500, 'syntax error' def test_python_application_loading_error(self): - self.skip_alerts.append(r'Python failed to import module "blah"') + skip_alert(r'Python failed to import module "blah"') self.load('empty') - self.assertIn( - 'success', self.conf('"blah"', 'applications/empty/module'), - ) + assert 'success' in self.conf('"blah"', 'applications/empty/module') - self.assertEqual(self.get()['status'], 503, 'loading error') + assert self.get()['status'] == 503, 'loading error' def test_python_application_close(self): self.load('close') @@ -597,7 +547,7 @@ last line: 987654321 self.stop() - self.assertIsNotNone(self.wait_for_record(r'Close called\.'), 'close') + assert self.wait_for_record(r'Close called\.') is not None, 'close' def test_python_application_close_error(self): self.load('close_error') @@ -606,9 +556,9 @@ last line: 987654321 self.stop() - self.assertIsNotNone( - self.wait_for_record(r'Close called\.'), 'close error' - ) + assert ( + self.wait_for_record(r'Close called\.') is not None + ), 'close error' def test_python_application_not_iterable(self): self.load('not_iterable') @@ -617,17 +567,17 @@ last line: 987654321 self.stop() - self.assertIsNotNone( + assert ( self.wait_for_record( r'\[error\].+the application returned not an iterable object' - ), - 'not iterable', - ) + ) + is not None + ), 'not iterable' def test_python_application_write(self): self.load('write') - self.assertEqual(self.get()['body'], '0123456789', 'write') + assert self.get()['body'] == '0123456789', 'write' def test_python_application_threading(self): """wait_for_record() timeouts after 5s while every thread works at @@ -639,9 +589,9 @@ last line: 987654321 for _ in range(10): self.get(no_recv=True) - self.assertIsNotNone( - self.wait_for_record(r'\(5\) Thread: 100'), 'last thread finished' - ) + assert ( + self.wait_for_record(r'\(5\) Thread: 100') is not None + ), 'last thread finished' def test_python_application_iter_exception(self): self.load('iter_exception') @@ -656,43 +606,38 @@ last line: 987654321 'Connection': 'close', } ) - self.assertEqual(resp['status'], 200, 'status') - self.assertEqual(resp['body'], 'XXXXXXX', 'body') + assert resp['status'] == 200, 'status' + assert resp['body'] == 'XXXXXXX', 'body' # Exception before start_response(). - self.assertEqual(self.get()['status'], 503, 'error') + assert self.get()['status'] == 503, 'error' - self.assertIsNotNone(self.wait_for_record(r'Traceback'), 'traceback') - self.assertIsNotNone( - self.wait_for_record(r'raise Exception\(\'first exception\'\)'), - 'first exception raise', - ) - self.assertEqual( - len(self.findall(r'Traceback')), 1, 'traceback count 1' - ) + assert self.wait_for_record(r'Traceback') is not None, 'traceback' + assert ( + self.wait_for_record(r'raise Exception\(\'first exception\'\)') + is not None + ), 'first exception raise' + assert len(self.findall(r'Traceback')) == 1, 'traceback count 1' # Exception after start_response(), before first write(). - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Skip': '1', 'Connection': 'close', } - )['status'], - 503, - 'error 2', - ) + )['status'] + == 503 + ), 'error 2' - self.assertIsNotNone( - self.wait_for_record(r'raise Exception\(\'second exception\'\)'), - 'exception raise second', - ) - self.assertEqual( - len(self.findall(r'Traceback')), 2, 'traceback count 2' - ) + assert ( + self.wait_for_record(r'raise Exception\(\'second exception\'\)') + is not None + ), 'exception raise second' + assert len(self.findall(r'Traceback')) == 2, 'traceback count 2' # Exception after first write(), before first __next__(). @@ -705,15 +650,13 @@ last line: 987654321 start=True, ) - self.assertIsNotNone( - self.wait_for_record(r'raise Exception\(\'third exception\'\)'), - 'exception raise third', - ) - self.assertEqual( - len(self.findall(r'Traceback')), 3, 'traceback count 3' - ) + assert ( + self.wait_for_record(r'raise Exception\(\'third exception\'\)') + is not None + ), 'exception raise third' + assert len(self.findall(r'Traceback')) == 3, 'traceback count 3' - self.assertDictEqual(self.get(sock=sock), {}, 'closed connection') + assert self.get(sock=sock) == {}, 'closed connection' # Exception after first write(), before first __next__(), # chunked (incomplete body). @@ -725,13 +668,11 @@ last line: 987654321 'X-Chunked': '1', 'Connection': 'close', }, - raw_resp=True + raw_resp=True, ) if resp: - self.assertNotEqual(resp[-5:], '0\r\n\r\n', 'incomplete body') - self.assertEqual( - len(self.findall(r'Traceback')), 4, 'traceback count 4' - ) + assert resp[-5:] != '0\r\n\r\n', 'incomplete body' + assert len(self.findall(r'Traceback')) == 4, 'traceback count 4' # Exception in __next__(). @@ -744,15 +685,13 @@ last line: 987654321 start=True, ) - self.assertIsNotNone( - self.wait_for_record(r'raise Exception\(\'next exception\'\)'), - 'exception raise next', - ) - self.assertEqual( - len(self.findall(r'Traceback')), 5, 'traceback count 5' - ) + assert ( + self.wait_for_record(r'raise Exception\(\'next exception\'\)') + is not None + ), 'exception raise next' + assert len(self.findall(r'Traceback')) == 5, 'traceback count 5' - self.assertDictEqual(self.get(sock=sock), {}, 'closed connection 2') + assert self.get(sock=sock) == {}, 'closed connection 2' # Exception in __next__(), chunked (incomplete body). @@ -763,40 +702,34 @@ last line: 987654321 'X-Chunked': '1', 'Connection': 'close', }, - raw_resp=True + raw_resp=True, ) if resp: - self.assertNotEqual(resp[-5:], '0\r\n\r\n', 'incomplete body 2') - self.assertEqual( - len(self.findall(r'Traceback')), 6, 'traceback count 6' - ) + assert resp[-5:] != '0\r\n\r\n', 'incomplete body 2' + assert len(self.findall(r'Traceback')) == 6, 'traceback count 6' # Exception before start_response() and in close(). - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Not-Skip-Close': '1', 'Connection': 'close', } - )['status'], - 503, - 'error', - ) + )['status'] + == 503 + ), 'error' - self.assertIsNotNone( - self.wait_for_record(r'raise Exception\(\'close exception\'\)'), - 'exception raise close', - ) - self.assertEqual( - len(self.findall(r'Traceback')), 8, 'traceback count 8' - ) + assert ( + self.wait_for_record(r'raise Exception\(\'close exception\'\)') + is not None + ), 'exception raise close' + assert len(self.findall(r'Traceback')) == 8, 'traceback count 8' - def test_python_user_group(self): - if not self.is_su: - print("requires root") - raise unittest.SkipTest() + def test_python_user_group(self, is_su): + if not is_su: + pytest.skip('requires root') nobody_uid = pwd.getpwnam('nobody').pw_uid @@ -811,40 +744,38 @@ last line: 987654321 self.load('user_group') obj = self.getjson()['body'] - self.assertEqual(obj['UID'], nobody_uid, 'nobody uid') - self.assertEqual(obj['GID'], group_id, 'nobody gid') + assert obj['UID'] == nobody_uid, 'nobody uid' + assert obj['GID'] == group_id, 'nobody gid' self.load('user_group', user='nobody') obj = self.getjson()['body'] - self.assertEqual(obj['UID'], nobody_uid, 'nobody uid user=nobody') - self.assertEqual(obj['GID'], group_id, 'nobody gid user=nobody') + assert obj['UID'] == nobody_uid, 'nobody uid user=nobody' + assert obj['GID'] == group_id, 'nobody gid user=nobody' self.load('user_group', user='nobody', group=group) obj = self.getjson()['body'] - self.assertEqual( - obj['UID'], nobody_uid, 'nobody uid user=nobody group=%s' % group + assert obj['UID'] == nobody_uid, ( + 'nobody uid user=nobody group=%s' % group ) - self.assertEqual( - obj['GID'], group_id, 'nobody gid user=nobody group=%s' % group + assert obj['GID'] == group_id, ( + 'nobody gid user=nobody group=%s' % group ) self.load('user_group', group=group) obj = self.getjson()['body'] - self.assertEqual( - obj['UID'], nobody_uid, 'nobody uid group=%s' % group - ) + assert obj['UID'] == nobody_uid, 'nobody uid group=%s' % group - self.assertEqual(obj['GID'], group_id, 'nobody gid group=%s' % group) + assert obj['GID'] == group_id, 'nobody gid group=%s' % group self.load('user_group', user='root') obj = self.getjson()['body'] - self.assertEqual(obj['UID'], 0, 'root uid user=root') - self.assertEqual(obj['GID'], 0, 'root gid user=root') + assert obj['UID'] == 0, 'root uid user=root' + assert obj['GID'] == 0, 'root gid user=root' group = 'root' @@ -858,14 +789,11 @@ last line: 987654321 self.load('user_group', user='root', group='root') obj = self.getjson()['body'] - self.assertEqual(obj['UID'], 0, 'root uid user=root group=root') - self.assertEqual(obj['GID'], 0, 'root gid user=root group=root') + assert obj['UID'] == 0, 'root uid user=root group=root' + assert obj['GID'] == 0, 'root gid user=root group=root' self.load('user_group', group='root') obj = self.getjson()['body'] - self.assertEqual(obj['UID'], nobody_uid, 'root uid group=root') - self.assertEqual(obj['GID'], 0, 'root gid group=root') - -if __name__ == '__main__': - TestPythonApplication.main() + assert obj['UID'] == nobody_uid, 'root uid group=root' + assert obj['GID'] == 0, 'root gid group=root' diff --git a/test/test_python_basic.py b/test/test_python_basic.py index d6445ac2..0cc70e51 100644 --- a/test/test_python_basic.py +++ b/test/test_python_basic.py @@ -19,142 +19,104 @@ class TestPythonBasic(TestControl): } def test_python_get_empty(self): - self.assertEqual(self.conf_get(), {'listeners': {}, 'applications': {}}) - self.assertEqual(self.conf_get('listeners'), {}) - self.assertEqual(self.conf_get('applications'), {}) + assert self.conf_get() == {'listeners': {}, 'applications': {}} + assert self.conf_get('listeners') == {} + assert self.conf_get('applications') == {} def test_python_get_applications(self): self.conf(self.conf_app, 'applications') conf = self.conf_get() - self.assertEqual(conf['listeners'], {}, 'listeners') - self.assertEqual( - conf['applications'], - { - "app": { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - 'applications', - ) - - self.assertEqual( - self.conf_get('applications'), - { - "app": { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - 'applications prefix', - ) - - self.assertEqual( - self.conf_get('applications/app'), - { + assert conf['listeners'] == {}, 'listeners' + assert conf['applications'] == { + "app": { "type": "python", "processes": {"spare": 0}, "path": "/app", "module": "wsgi", - }, - 'applications prefix 2', - ) + } + }, 'applications' - self.assertEqual( - self.conf_get('applications/app/type'), 'python', 'type' - ) - self.assertEqual( - self.conf_get('applications/app/processes/spare'), 0, 'spare' - ) + assert self.conf_get('applications') == { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, 'applications prefix' + + assert self.conf_get('applications/app') == { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + }, 'applications prefix 2' + + assert self.conf_get('applications/app/type') == 'python', 'type' + assert self.conf_get('applications/app/processes/spare') == 0, 'spare' def test_python_get_listeners(self): self.conf(self.conf_basic) - self.assertEqual( - self.conf_get()['listeners'], - {"*:7080": {"pass": "applications/app"}}, - 'listeners', - ) + assert self.conf_get()['listeners'] == { + "*:7080": {"pass": "applications/app"} + }, 'listeners' - self.assertEqual( - self.conf_get('listeners'), - {"*:7080": {"pass": "applications/app"}}, - 'listeners prefix', - ) + assert self.conf_get('listeners') == { + "*:7080": {"pass": "applications/app"} + }, 'listeners prefix' - self.assertEqual( - self.conf_get('listeners/*:7080'), - {"pass": "applications/app"}, - 'listeners prefix 2', - ) + assert self.conf_get('listeners/*:7080') == { + "pass": "applications/app" + }, 'listeners prefix 2' def test_python_change_listener(self): self.conf(self.conf_basic) self.conf({"*:7081": {"pass": "applications/app"}}, 'listeners') - self.assertEqual( - self.conf_get('listeners'), - {"*:7081": {"pass": "applications/app"}}, - 'change listener', - ) + assert self.conf_get('listeners') == { + "*:7081": {"pass": "applications/app"} + }, 'change listener' def test_python_add_listener(self): self.conf(self.conf_basic) self.conf({"pass": "applications/app"}, 'listeners/*:7082') - self.assertEqual( - self.conf_get('listeners'), - { - "*:7080": {"pass": "applications/app"}, - "*:7082": {"pass": "applications/app"}, - }, - 'add listener', - ) + assert self.conf_get('listeners') == { + "*:7080": {"pass": "applications/app"}, + "*:7082": {"pass": "applications/app"}, + }, 'add listener' def test_python_change_application(self): self.conf(self.conf_basic) self.conf('30', 'applications/app/processes/max') - self.assertEqual( - self.conf_get('applications/app/processes/max'), - 30, - 'change application max', - ) + assert ( + self.conf_get('applications/app/processes/max') == 30 + ), 'change application max' self.conf('"/www"', 'applications/app/path') - self.assertEqual( - self.conf_get('applications/app/path'), - '/www', - 'change application path', - ) + assert ( + self.conf_get('applications/app/path') == '/www' + ), 'change application path' def test_python_delete(self): self.conf(self.conf_basic) - self.assertIn('error', self.conf_delete('applications/app')) - self.assertIn('success', self.conf_delete('listeners/*:7080')) - self.assertIn('success', self.conf_delete('applications/app')) - self.assertIn('error', self.conf_delete('applications/app')) + assert 'error' in self.conf_delete('applications/app') + assert 'success' in self.conf_delete('listeners/*:7080') + assert 'success' in self.conf_delete('applications/app') + assert 'error' in self.conf_delete('applications/app') def test_python_delete_blocks(self): self.conf(self.conf_basic) - self.assertIn('success', self.conf_delete('listeners')) - self.assertIn('success', self.conf_delete('applications')) - - self.assertIn('success', self.conf(self.conf_app, 'applications')) - self.assertIn( - 'success', - self.conf({"*:7081": {"pass": "applications/app"}}, 'listeners'), - 'applications restore', - ) - + assert 'success' in self.conf_delete('listeners') + assert 'success' in self.conf_delete('applications') -if __name__ == '__main__': - TestPythonBasic.main() + assert 'success' in self.conf(self.conf_app, 'applications') + assert 'success' in self.conf( + {"*:7081": {"pass": "applications/app"}}, 'listeners' + ), 'applications restore' diff --git a/test/test_python_environment.py b/test/test_python_environment.py index a03b96e6..2d7d1595 100644 --- a/test/test_python_environment.py +++ b/test/test_python_environment.py @@ -7,97 +7,81 @@ class TestPythonEnvironment(TestApplicationPython): def test_python_environment_name_null(self): self.load('environment') - self.assertIn( - 'error', - self.conf( - {"va\0r": "val1"}, 'applications/environment/environment' - ), - 'name null', - ) + assert 'error' in self.conf( + {"va\0r": "val1"}, 'applications/environment/environment' + ), 'name null' def test_python_environment_name_equals(self): self.load('environment') - self.assertIn( - 'error', - self.conf( - {"var=": "val1"}, 'applications/environment/environment' - ), - 'name equals', - ) + assert 'error' in self.conf( + {"var=": "val1"}, 'applications/environment/environment' + ), 'name equals' def test_python_environment_value_null(self): self.load('environment') - self.assertIn( - 'error', - self.conf( - {"var": "\0val"}, 'applications/environment/environment' - ), - 'value null', - ) + assert 'error' in self.conf( + {"var": "\0val"}, 'applications/environment/environment' + ), 'value null' def test_python_environment_update(self): self.load('environment') self.conf({"var": "val1"}, 'applications/environment/environment') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Variables': 'var', 'Connection': 'close', } - )['body'], - 'val1,', - 'set', - ) + )['body'] + == 'val1,' + ), 'set' self.conf({"var": "val2"}, 'applications/environment/environment') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Variables': 'var', 'Connection': 'close', } - )['body'], - 'val2,', - 'update', - ) + )['body'] + == 'val2,' + ), 'update' def test_python_environment_replace(self): self.load('environment') self.conf({"var1": "val1"}, 'applications/environment/environment') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Variables': 'var1', 'Connection': 'close', } - )['body'], - 'val1,', - 'set', - ) + )['body'] + == 'val1,' + ), 'set' self.conf({"var2": "val2"}, 'applications/environment/environment') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Variables': 'var1,var2', 'Connection': 'close', } - )['body'], - 'val2,', - 'replace', - ) + )['body'] + == 'val2,' + ), 'replace' def test_python_environment_clear(self): self.load('environment') @@ -107,31 +91,29 @@ class TestPythonEnvironment(TestApplicationPython): 'applications/environment/environment', ) - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Variables': 'var1,var2', 'Connection': 'close', } - )['body'], - 'val1,val2,', - 'set', - ) + )['body'] + == 'val1,val2,' + ), 'set' self.conf({}, 'applications/environment/environment') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Variables': 'var1,var2', 'Connection': 'close', } - )['body'], - '', - 'clear', - ) + )['body'] + == '' + ), 'clear' def test_python_environment_replace_default(self): self.load('environment') @@ -144,36 +126,30 @@ class TestPythonEnvironment(TestApplicationPython): } )['body'] - self.assertGreater(len(home_default), 1, 'get default') + assert len(home_default) > 1, 'get default' self.conf({"HOME": "/"}, 'applications/environment/environment') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Variables': 'HOME', 'Connection': 'close', } - )['body'], - '/,', - 'replace default', - ) + )['body'] + == '/,' + ), 'replace default' self.conf({}, 'applications/environment/environment') - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'X-Variables': 'HOME', 'Connection': 'close', } - )['body'], - home_default, - 'restore default', - ) - - -if __name__ == '__main__': - TestPythonEnvironment.main() + )['body'] + == home_default + ), 'restore default' diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index 1bed64ba..564ec79c 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -1,4 +1,4 @@ -import unittest +import pytest from unit.applications.lang.python import TestApplicationPython from unit.feature.isolation import TestFeatureIsolation @@ -10,70 +10,58 @@ class TestPythonIsolation(TestApplicationPython): isolation = TestFeatureIsolation() @classmethod - def setUpClass(cls, complete_check=True): - unit = super().setUpClass(complete_check=False) + def setup_class(cls, complete_check=True): + unit = super().setup_class(complete_check=False) - TestFeatureIsolation().check(cls.available, unit.testdir) + TestFeatureIsolation().check(cls.available, unit.temp_dir) return unit if not complete_check else unit.complete() - def test_python_isolation_rootfs(self): + def test_python_isolation_rootfs(self, is_su): isolation_features = self.available['features']['isolation'].keys() if 'mnt' not in isolation_features: - print('requires mnt ns') - raise unittest.SkipTest() + pytest.skip('requires mnt ns') - if not self.is_su: + if not is_su: if 'user' not in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') if not 'unprivileged_userns_clone' in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') isolation = { - 'namespaces': {'credential': not self.is_su, 'mount': True}, - 'rootfs': self.testdir, + 'namespaces': {'credential': not is_su, 'mount': True}, + 'rootfs': self.temp_dir, } self.load('empty', isolation=isolation) - self.assertEqual(self.get()['status'], 200, 'python rootfs') + assert self.get()['status'] == 200, 'python rootfs' self.load('ns_inspect', isolation=isolation) - self.assertEqual( - self.getjson(url='/?path=' + self.testdir)['body']['FileExists'], - False, - 'testdir does not exists in rootfs', - ) - - self.assertEqual( - self.getjson(url='/?path=/proc/self')['body']['FileExists'], - False, - 'no /proc/self', - ) - - self.assertEqual( - self.getjson(url='/?path=/dev/pts')['body']['FileExists'], - False, - 'no /dev/pts', - ) - - self.assertEqual( - self.getjson(url='/?path=/sys/kernel')['body']['FileExists'], - False, - 'no /sys/kernel', - ) + assert ( + self.getjson(url='/?path=' + self.temp_dir)['body']['FileExists'] + == False + ), 'temp_dir does not exists in rootfs' - ret = self.getjson(url='/?path=/app/python/ns_inspect') + assert ( + self.getjson(url='/?path=/proc/self')['body']['FileExists'] + == False + ), 'no /proc/self' + + assert ( + self.getjson(url='/?path=/dev/pts')['body']['FileExists'] == False + ), 'no /dev/pts' - self.assertEqual( - ret['body']['FileExists'], True, 'application exists in rootfs', - ) + assert ( + self.getjson(url='/?path=/sys/kernel')['body']['FileExists'] + == False + ), 'no /sys/kernel' + ret = self.getjson(url='/?path=/app/python/ns_inspect') -if __name__ == '__main__': - TestPythonIsolation.main() + assert ( + ret['body']['FileExists'] == True + ), 'application exists in rootfs' diff --git a/test/test_python_isolation_chroot.py b/test/test_python_isolation_chroot.py index 7761128e..315fee9f 100644 --- a/test/test_python_isolation_chroot.py +++ b/test/test_python_isolation_chroot.py @@ -1,4 +1,4 @@ -import unittest +import pytest from unit.applications.lang.python import TestApplicationPython from unit.feature.isolation import TestFeatureIsolation @@ -7,51 +7,41 @@ from unit.feature.isolation import TestFeatureIsolation class TestPythonIsolation(TestApplicationPython): prerequisites = {'modules': {'python': 'any'}} - def test_python_isolation_chroot(self): - if not self.is_su: - print('requires root') - raise unittest.SkipTest() + def test_python_isolation_chroot(self, is_su): + if not is_su: + pytest.skip('requires root') isolation = { - 'rootfs': self.testdir, + 'rootfs': self.temp_dir, } self.load('empty', isolation=isolation) - self.assertEqual(self.get()['status'], 200, 'python chroot') + assert self.get()['status'] == 200, 'python chroot' self.load('ns_inspect', isolation=isolation) - self.assertEqual( - self.getjson(url='/?path=' + self.testdir)['body']['FileExists'], - False, - 'testdir does not exists in rootfs', - ) - - self.assertEqual( - self.getjson(url='/?path=/proc/self')['body']['FileExists'], - False, - 'no /proc/self', - ) - - self.assertEqual( - self.getjson(url='/?path=/dev/pts')['body']['FileExists'], - False, - 'no /dev/pts', - ) - - self.assertEqual( - self.getjson(url='/?path=/sys/kernel')['body']['FileExists'], - False, - 'no /sys/kernel', - ) + assert ( + self.getjson(url='/?path=' + self.temp_dir)['body']['FileExists'] + == False + ), 'temp_dir does not exists in rootfs' - ret = self.getjson(url='/?path=/app/python/ns_inspect') + assert ( + self.getjson(url='/?path=/proc/self')['body']['FileExists'] + == False + ), 'no /proc/self' + + assert ( + self.getjson(url='/?path=/dev/pts')['body']['FileExists'] == False + ), 'no /dev/pts' - self.assertEqual( - ret['body']['FileExists'], True, 'application exists in rootfs', - ) + assert ( + self.getjson(url='/?path=/sys/kernel')['body']['FileExists'] + == False + ), 'no /sys/kernel' + ret = self.getjson(url='/?path=/app/python/ns_inspect') -if __name__ == '__main__': - TestPythonIsolation.main() + assert ( + ret['body']['FileExists'] == True + ), 'application exists in rootfs' diff --git a/test/test_python_procman.py b/test/test_python_procman.py index c327ab14..7e727fa8 100644 --- a/test/test_python_procman.py +++ b/test/test_python_procman.py @@ -1,7 +1,7 @@ +import pytest import re import subprocess import time -import unittest from unit.applications.lang.python import TestApplicationPython @@ -9,10 +9,10 @@ from unit.applications.lang.python import TestApplicationPython class TestPythonProcman(TestApplicationPython): prerequisites = {'modules': {'python': 'any'}} - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - self.app_name = "app-" + self.testdir.split('/')[-1] + self.app_name = "app-" + self.temp_dir.split('/')[-1] self.app_proc = 'applications/' + self.app_name + '/processes' self.load('empty', self.app_name) @@ -23,7 +23,7 @@ class TestPythonProcman(TestApplicationPython): pids = set() for m in re.findall('.*' + self.app_name, output.decode()): - pids.add(re.search('^\s*(\d+)', m).group(1)) + pids.add(re.search(r'^\s*(\d+)', m).group(1)) return pids @@ -31,35 +31,35 @@ class TestPythonProcman(TestApplicationPython): if path is None: path = self.app_proc - self.assertIn('success', self.conf(conf, path), 'configure processes') + assert 'success' in self.conf(conf, path), 'configure processes' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_python_processes_idle_timeout_zero(self): self.conf_proc({"spare": 0, "max": 2, "idle_timeout": 0}) self.get() - self.assertEqual(len(self.pids_for_process()), 0, 'idle timeout 0') + assert len(self.pids_for_process()) == 0, 'idle timeout 0' def test_python_prefork(self): self.conf_proc('2') pids = self.pids_for_process() - self.assertEqual(len(pids), 2, 'prefork 2') + assert len(pids) == 2, 'prefork 2' self.get() - self.assertSetEqual(self.pids_for_process(), pids, 'prefork still 2') + assert self.pids_for_process() == pids, 'prefork still 2' self.conf_proc('4') pids = self.pids_for_process() - self.assertEqual(len(pids), 4, 'prefork 4') + assert len(pids) == 4, 'prefork 4' self.get() - self.assertSetEqual(self.pids_for_process(), pids, 'prefork still 4') + assert self.pids_for_process() == pids, 'prefork still 4' self.stop_all() - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_python_prefork_same_processes(self): self.conf_proc('2') pids = self.pids_for_process() @@ -67,25 +67,23 @@ class TestPythonProcman(TestApplicationPython): self.conf_proc('4') pids_new = self.pids_for_process() - self.assertTrue(pids.issubset(pids_new), 'prefork same processes') + assert pids.issubset(pids_new), 'prefork same processes' def test_python_ondemand(self): self.conf_proc({"spare": 0, "max": 8, "idle_timeout": 1}) - self.assertEqual(len(self.pids_for_process()), 0, 'on-demand 0') + assert len(self.pids_for_process()) == 0, 'on-demand 0' self.get() pids = self.pids_for_process() - self.assertEqual(len(pids), 1, 'on-demand 1') + assert len(pids) == 1, 'on-demand 1' self.get() - self.assertSetEqual(self.pids_for_process(), pids, 'on-demand still 1') + assert self.pids_for_process() == pids, 'on-demand still 1' time.sleep(1) - self.assertEqual( - len(self.pids_for_process()), 0, 'on-demand stop idle' - ) + assert len(self.pids_for_process()) == 0, 'on-demand stop idle' self.stop_all() @@ -93,27 +91,25 @@ class TestPythonProcman(TestApplicationPython): self.conf_proc({"spare": 2, "max": 8, "idle_timeout": 1}) pids = self.pids_for_process() - self.assertEqual(len(pids), 2, 'updown 2') + assert len(pids) == 2, 'updown 2' self.get() pids_new = self.pids_for_process() - self.assertEqual(len(pids_new), 3, 'updown 3') - self.assertTrue(pids.issubset(pids_new), 'updown 3 only 1 new') + assert len(pids_new) == 3, 'updown 3' + assert pids.issubset(pids_new), 'updown 3 only 1 new' self.get() - self.assertSetEqual( - self.pids_for_process(), pids_new, 'updown still 3' - ) + assert self.pids_for_process() == pids_new, 'updown still 3' time.sleep(1) pids = self.pids_for_process() - self.assertEqual(len(pids), 2, 'updown stop idle') + assert len(pids) == 2, 'updown stop idle' self.get() pids_new = self.pids_for_process() - self.assertEqual(len(pids_new), 3, 'updown again 3') - self.assertTrue(pids.issubset(pids_new), 'updown again 3 only 1 new') + assert len(pids_new) == 3, 'updown again 3' + assert pids.issubset(pids_new), 'updown again 3 only 1 new' self.stop_all() @@ -121,20 +117,20 @@ class TestPythonProcman(TestApplicationPython): self.conf_proc({"spare": 2, "max": 6, "idle_timeout": 1}) pids = self.pids_for_process() - self.assertEqual(len(pids), 2, 'reconf 2') + assert len(pids) == 2, 'reconf 2' self.get() pids_new = self.pids_for_process() - self.assertEqual(len(pids_new), 3, 'reconf 3') - self.assertTrue(pids.issubset(pids_new), 'reconf 3 only 1 new') + assert len(pids_new) == 3, 'reconf 3' + assert pids.issubset(pids_new), 'reconf 3 only 1 new' self.conf_proc('6', self.app_proc + '/spare') pids = self.pids_for_process() - self.assertEqual(len(pids), 6, 'reconf 6') + assert len(pids) == 6, 'reconf 6' self.get() - self.assertSetEqual(self.pids_for_process(), pids, 'reconf still 6') + assert self.pids_for_process() == pids, 'reconf still 6' self.stop_all() @@ -143,7 +139,7 @@ class TestPythonProcman(TestApplicationPython): self.get() pids = self.pids_for_process() - self.assertEqual(len(pids), 1, 'idle timeout 1') + assert len(pids) == 1, 'idle timeout 1' time.sleep(1) @@ -152,14 +148,12 @@ class TestPythonProcman(TestApplicationPython): time.sleep(1) pids_new = self.pids_for_process() - self.assertEqual(len(pids_new), 1, 'idle timeout still 1') - self.assertSetEqual( - self.pids_for_process(), pids, 'idle timeout still 1 same pid' - ) + assert len(pids_new) == 1, 'idle timeout still 1' + assert self.pids_for_process() == pids, 'idle timeout still 1 same pid' time.sleep(1) - self.assertEqual(len(self.pids_for_process()), 0, 'idle timed out') + assert len(self.pids_for_process()) == 0, 'idle timed out' def test_python_processes_connection_keepalive(self): self.conf_proc({"spare": 0, "max": 6, "idle_timeout": 2}) @@ -169,15 +163,11 @@ class TestPythonProcman(TestApplicationPython): start=True, read_timeout=1, ) - self.assertEqual( - len(self.pids_for_process()), 1, 'keepalive connection 1' - ) + assert len(self.pids_for_process()) == 1, 'keepalive connection 1' time.sleep(2) - self.assertEqual( - len(self.pids_for_process()), 0, 'keepalive connection 0' - ) + assert len(self.pids_for_process()) == 0, 'keepalive connection 0' sock.close() @@ -185,43 +175,29 @@ class TestPythonProcman(TestApplicationPython): self.conf_proc('1') path = '/' + self.app_proc - self.assertIn('error', self.conf_get(path + '/max')) - self.assertIn('error', self.conf_get(path + '/spare')) - self.assertIn('error', self.conf_get(path + '/idle_timeout')) + assert 'error' in self.conf_get(path + '/max') + assert 'error' in self.conf_get(path + '/spare') + assert 'error' in self.conf_get(path + '/idle_timeout') def test_python_processes_invalid(self): - self.assertIn( - 'error', self.conf({"spare": -1}, self.app_proc), 'negative spare', - ) - self.assertIn( - 'error', self.conf({"max": -1}, self.app_proc), 'negative max', - ) - self.assertIn( - 'error', - self.conf({"idle_timeout": -1}, self.app_proc), - 'negative idle_timeout', - ) - self.assertIn( - 'error', - self.conf({"spare": 2}, self.app_proc), - 'spare gt max default', - ) - self.assertIn( - 'error', - self.conf({"spare": 2, "max": 1}, self.app_proc), - 'spare gt max', - ) - self.assertIn( - 'error', - self.conf({"spare": 0, "max": 0}, self.app_proc), - 'max zero', - ) + assert 'error' in self.conf( + {"spare": -1}, self.app_proc + ), 'negative spare' + assert 'error' in self.conf({"max": -1}, self.app_proc), 'negative max' + assert 'error' in self.conf( + {"idle_timeout": -1}, self.app_proc + ), 'negative idle_timeout' + assert 'error' in self.conf( + {"spare": 2}, self.app_proc + ), 'spare gt max default' + assert 'error' in self.conf( + {"spare": 2, "max": 1}, self.app_proc + ), 'spare gt max' + assert 'error' in self.conf( + {"spare": 0, "max": 0}, self.app_proc + ), 'max zero' def stop_all(self): self.conf({"listeners": {}, "applications": {}}) - self.assertEqual(len(self.pids_for_process()), 0, 'stop all') - - -if __name__ == '__main__': - TestPythonProcman.main() + assert len(self.pids_for_process()) == 0, 'stop all' diff --git a/test/test_respawn.py b/test/test_respawn.py index f1c71a20..d40e78a4 100644 --- a/test/test_respawn.py +++ b/test/test_respawn.py @@ -3,6 +3,7 @@ import subprocess import time from unit.applications.lang.python import TestApplicationPython +from conftest import skip_alert class TestRespawn(TestApplicationPython): @@ -11,21 +12,20 @@ class TestRespawn(TestApplicationPython): PATTERN_ROUTER = 'unit: router' PATTERN_CONTROLLER = 'unit: controller' - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - self.app_name = "app-" + self.testdir.split('/')[-1] + self.app_name = "app-" + self.temp_dir.split('/')[-1] self.load('empty', self.app_name) - self.assertIn( - 'success', - self.conf('1', 'applications/' + self.app_name + '/processes') + assert 'success' in self.conf( + '1', 'applications/' + self.app_name + '/processes' ) def pid_by_name(self, name): output = subprocess.check_output(['ps', 'ax']).decode() - m = re.search('\s*(\d+).*' + name, output) + m = re.search(r'\s*(\d+).*' + name, output) return m if m is None else m.group(1) def kill_pids(self, *pids): @@ -44,27 +44,26 @@ class TestRespawn(TestApplicationPython): def smoke_test(self): for _ in range(5): - self.assertIn( - 'success', - self.conf('1', 'applications/' + self.app_name + '/processes') + assert 'success' in self.conf( + '1', 'applications/' + self.app_name + '/processes' ) - self.assertEqual(self.get()['status'], 200) + assert self.get()['status'] == 200 # Check if the only one router, controller, # and application processes running. output = subprocess.check_output(['ps', 'ax']).decode() - self.assertEqual(len(re.findall(self.PATTERN_ROUTER, output)), 1) - self.assertEqual(len(re.findall(self.PATTERN_CONTROLLER, output)), 1) - self.assertEqual(len(re.findall(self.app_name, output)), 1) + assert len(re.findall(self.PATTERN_ROUTER, output)) == 1 + assert len(re.findall(self.PATTERN_CONTROLLER, output)) == 1 + assert len(re.findall(self.app_name, output)) == 1 def test_respawn_router(self): pid = self.pid_by_name(self.PATTERN_ROUTER) self.kill_pids(pid) - self.skip_alerts.append(r'process %s exited on signal 9' % pid) + skip_alert(r'process %s exited on signal 9' % pid) - self.assertIsNotNone(self.wait_for_process(self.PATTERN_ROUTER)) + assert self.wait_for_process(self.PATTERN_ROUTER) is not None self.smoke_test() @@ -72,11 +71,11 @@ class TestRespawn(TestApplicationPython): pid = self.pid_by_name(self.PATTERN_CONTROLLER) self.kill_pids(pid) - self.skip_alerts.append(r'process %s exited on signal 9' % pid) + skip_alert(r'process %s exited on signal 9' % pid) - self.assertIsNotNone(self.wait_for_process(self.PATTERN_CONTROLLER)) + assert self.wait_for_process(self.PATTERN_CONTROLLER) is not None - self.assertEqual(self.get()['status'], 200) + assert self.get()['status'] == 200 self.smoke_test() @@ -84,12 +83,8 @@ class TestRespawn(TestApplicationPython): pid = self.pid_by_name(self.app_name) self.kill_pids(pid) - self.skip_alerts.append(r'process %s exited on signal 9' % pid) + skip_alert(r'process %s exited on signal 9' % pid) - self.assertIsNotNone(self.wait_for_process(self.app_name)) + assert self.wait_for_process(self.app_name) is not None self.smoke_test() - - -if __name__ == '__main__': - TestRespawn.main() diff --git a/test/test_return.py b/test/test_return.py index a89d97e6..64050022 100644 --- a/test/test_return.py +++ b/test/test_return.py @@ -6,8 +6,8 @@ from unit.applications.proto import TestApplicationProto class TestReturn(TestApplicationProto): prerequisites = {} - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() self._load_conf( { @@ -35,59 +35,61 @@ Connection: close def test_return(self): resp = self.get() - self.assertEqual(resp['status'], 200) - self.assertIn('Server', resp['headers']) - self.assertIn('Date', resp['headers']) - self.assertEqual(resp['headers']['Content-Length'], '0') - self.assertEqual(resp['headers']['Connection'], 'close') - self.assertEqual(resp['body'], '', 'body') + assert resp['status'] == 200 + assert 'Server' in resp['headers'] + assert 'Date' in resp['headers'] + assert resp['headers']['Content-Length'] == '0' + assert resp['headers']['Connection'] == 'close' + assert resp['body'] == '', 'body' resp = self.post(body='blah') - self.assertEqual(resp['status'], 200) - self.assertEqual(resp['body'], '', 'body') + assert resp['status'] == 200 + assert resp['body'] == '', 'body' resp = self.get_resps_sc() - self.assertEqual(len(re.findall('200 OK', resp)), 10) - self.assertEqual(len(re.findall('Connection:', resp)), 1) - self.assertEqual(len(re.findall('Connection: close', resp)), 1) + assert len(re.findall('200 OK', resp)) == 10 + assert len(re.findall('Connection:', resp)) == 1 + assert len(re.findall('Connection: close', resp)) == 1 resp = self.get(http_10=True) - self.assertEqual(resp['status'], 200) - self.assertIn('Server', resp['headers']) - self.assertIn('Date', resp['headers']) - self.assertEqual(resp['headers']['Content-Length'], '0') - self.assertNotIn('Connection', resp['headers']) - self.assertEqual(resp['body'], '', 'body') + assert resp['status'] == 200 + assert 'Server' in resp['headers'] + assert 'Date' in resp['headers'] + assert resp['headers']['Content-Length'] == '0' + assert 'Connection' not in resp['headers'] + assert resp['body'] == '', 'body' def test_return_update(self): - self.assertIn('success', self.conf('0', 'routes/0/action/return')) + assert 'success' in self.conf('0', 'routes/0/action/return') resp = self.get() - self.assertEqual(resp['status'], 0) - self.assertEqual(resp['body'], '') + assert resp['status'] == 0 + assert resp['body'] == '' - self.assertIn('success', self.conf('404', 'routes/0/action/return')) + assert 'success' in self.conf('404', 'routes/0/action/return') resp = self.get() - self.assertEqual(resp['status'], 404) - self.assertNotEqual(resp['body'], '') + assert resp['status'] == 404 + assert resp['body'] != '' - self.assertIn('success', self.conf('598', 'routes/0/action/return')) + assert 'success' in self.conf('598', 'routes/0/action/return') resp = self.get() - self.assertEqual(resp['status'], 598) - self.assertNotEqual(resp['body'], '') + assert resp['status'] == 598 + assert resp['body'] != '' - self.assertIn('success', self.conf('999', 'routes/0/action/return')) + assert 'success' in self.conf('999', 'routes/0/action/return') resp = self.get() - self.assertEqual(resp['status'], 999) - self.assertEqual(resp['body'], '') + assert resp['status'] == 999 + assert resp['body'] == '' def test_return_location(self): reserved = ":/?#[]@!$&'()*+,;=" - unreserved = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - "0123456789-._~") + unreserved = ( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789-._~" + ) unsafe = " \"%<>\\^`{|}" unsafe_enc = "%20%22%25%3C%3E%5C%5E%60%7B%7C%7D" @@ -95,15 +97,11 @@ Connection: close if expect is None: expect = location - self.assertIn( - 'success', - self.conf( - {"return": 301, "location": location}, 'routes/0/action' - ), - 'configure location' - ) + assert 'success' in self.conf( + {"return": 301, "location": location}, 'routes/0/action' + ), 'configure location' - self.assertEqual(self.get()['headers']['Location'], expect) + assert self.get()['headers']['Location'] == expect # FAIL: can't specify empty header value. # check_location("") @@ -145,39 +143,29 @@ Connection: close check_location("/%20?%20#%20 ", "/%2520?%2520#%2520%20") def test_return_location_edit(self): - self.assertIn( - 'success', - self.conf( - {"return": 302, "location": "blah"}, 'routes/0/action' - ), - 'configure init location' - ) - self.assertEqual(self.get()['headers']['Location'], 'blah') - - self.assertIn( - 'success', - self.conf_delete('routes/0/action/location'), - 'location delete' - ) - self.assertNotIn('Location', self.get()['headers']) - - self.assertIn( - 'success', - self.conf('"blah"', 'routes/0/action/location'), - 'location restore' - ) - self.assertEqual(self.get()['headers']['Location'], 'blah') - - self.assertIn( - 'error', - self.conf_post('"blah"', 'routes/0/action/location'), - 'location method not allowed' - ) - self.assertEqual(self.get()['headers']['Location'], 'blah') + assert 'success' in self.conf( + {"return": 302, "location": "blah"}, 'routes/0/action' + ), 'configure init location' + assert self.get()['headers']['Location'] == 'blah' + + assert 'success' in self.conf_delete( + 'routes/0/action/location' + ), 'location delete' + assert 'Location' not in self.get()['headers'] + + assert 'success' in self.conf( + '"blah"', 'routes/0/action/location' + ), 'location restore' + assert self.get()['headers']['Location'] == 'blah' + + assert 'error' in self.conf_post( + '"blah"', 'routes/0/action/location' + ), 'location method not allowed' + assert self.get()['headers']['Location'] == 'blah' def test_return_invalid(self): def check_error(conf): - self.assertIn('error', self.conf(conf, 'routes/0/action')) + assert 'error' in self.conf(conf, 'routes/0/action') check_error({"return": "200"}) check_error({"return": []}) @@ -186,13 +174,9 @@ Connection: close check_error({"return": -1}) check_error({"return": 200, "share": "/blah"}) - self.assertIn( - 'error', self.conf('001', 'routes/0/action/return'), 'leading zero' - ) + assert 'error' in self.conf( + '001', 'routes/0/action/return' + ), 'leading zero' check_error({"return": 301, "location": 0}) check_error({"return": 301, "location": []}) - - -if __name__ == '__main__': - TestReturn.main() diff --git a/test/test_routing.py b/test/test_routing.py index 269e8efc..4107f57e 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,117 +1,103 @@ # -*- coding: utf-8 -*- -import unittest +import pytest from unit.applications.proto import TestApplicationProto +from conftest import option, skip_alert class TestRouting(TestApplicationProto): prerequisites = {'modules': {'python': 'any'}} - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "routes"}}, - "routes": [ - { - "match": {"method": "GET"}, - "action": {"return": 200}, - } - ], - "applications": {}, - } - ), - 'routing configure', - ) + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes"}}, + "routes": [ + {"match": {"method": "GET"}, "action": {"return": 200},} + ], + "applications": {}, + } + ), 'routing configure' def route(self, route): return self.conf([route], 'routes') def route_match(self, match): - self.assertIn( - 'success', - self.route({"match": match, "action": {"return": 200}}), - 'route match configure', - ) + assert 'success' in self.route( + {"match": match, "action": {"return": 200}} + ), 'route match configure' def route_match_invalid(self, match): - self.assertIn( - 'error', - self.route({"match": match, "action": {"return": 200}}), - 'route match configure invalid', - ) + assert 'error' in self.route( + {"match": match, "action": {"return": 200}} + ), 'route match configure invalid' def host(self, host, status): - self.assertEqual( - self.get(headers={'Host': host, 'Connection': 'close'})[ - 'status' - ], - status, - 'match host', - ) + assert ( + self.get(headers={'Host': host, 'Connection': 'close'})['status'] + == status + ), 'match host' def cookie(self, cookie, status): - self.assertEqual( + assert ( self.get( headers={ 'Host': 'localhost', 'Cookie': cookie, 'Connection': 'close', }, - )['status'], - status, - 'match cookie', - ) + )['status'] + == status + ), 'match cookie' def test_routes_match_method_positive(self): - self.assertEqual(self.get()['status'], 200, 'GET') - self.assertEqual(self.post()['status'], 404, 'POST') + assert self.get()['status'] == 200, 'GET' + assert self.post()['status'] == 404, 'POST' def test_routes_match_method_positive_many(self): self.route_match({"method": ["GET", "POST"]}) - self.assertEqual(self.get()['status'], 200, 'GET') - self.assertEqual(self.post()['status'], 200, 'POST') - self.assertEqual(self.delete()['status'], 404, 'DELETE') + assert self.get()['status'] == 200, 'GET' + assert self.post()['status'] == 200, 'POST' + assert self.delete()['status'] == 404, 'DELETE' def test_routes_match_method_negative(self): self.route_match({"method": "!GET"}) - self.assertEqual(self.get()['status'], 404, 'GET') - self.assertEqual(self.post()['status'], 200, 'POST') + assert self.get()['status'] == 404, 'GET' + assert self.post()['status'] == 200, 'POST' def test_routes_match_method_negative_many(self): self.route_match({"method": ["!GET", "!POST"]}) - self.assertEqual(self.get()['status'], 404, 'GET') - self.assertEqual(self.post()['status'], 404, 'POST') - self.assertEqual(self.delete()['status'], 200, 'DELETE') + assert self.get()['status'] == 404, 'GET' + assert self.post()['status'] == 404, 'POST' + assert self.delete()['status'] == 200, 'DELETE' def test_routes_match_method_wildcard_left(self): self.route_match({"method": "*ET"}) - self.assertEqual(self.get()['status'], 200, 'GET') - self.assertEqual(self.post()['status'], 404, 'POST') + assert self.get()['status'] == 200, 'GET' + assert self.post()['status'] == 404, 'POST' def test_routes_match_method_wildcard_right(self): self.route_match({"method": "GE*"}) - self.assertEqual(self.get()['status'], 200, 'GET') - self.assertEqual(self.post()['status'], 404, 'POST') + assert self.get()['status'] == 200, 'GET' + assert self.post()['status'] == 404, 'POST' def test_routes_match_method_wildcard_left_right(self): self.route_match({"method": "*GET*"}) - self.assertEqual(self.get()['status'], 200, 'GET') - self.assertEqual(self.post()['status'], 404, 'POST') + assert self.get()['status'] == 200, 'GET' + assert self.post()['status'] == 404, 'POST' def test_routes_match_method_wildcard(self): self.route_match({"method": "*"}) - self.assertEqual(self.get()['status'], 200, 'GET') + assert self.get()['status'] == 200, 'GET' def test_routes_match_invalid(self): self.route_match_invalid({"method": "**"}) @@ -124,32 +110,32 @@ class TestRouting(TestApplicationProto): def test_routes_match_empty_exact(self): self.route_match({"uri": ""}) - self.assertEqual(self.get()['status'], 404) + assert self.get()['status'] == 404 self.route_match({"uri": "/"}) - self.assertEqual(self.get()['status'], 200) - self.assertEqual(self.get(url='/blah')['status'], 404) + assert self.get()['status'] == 200 + assert self.get(url='/blah')['status'] == 404 def test_routes_match_negative(self): self.route_match({"uri": "!"}) - self.assertEqual(self.get()['status'], 404) + assert self.get()['status'] == 404 self.route_match({"uri": "!/"}) - self.assertEqual(self.get()['status'], 404) - self.assertEqual(self.get(url='/blah')['status'], 200) + assert self.get()['status'] == 404 + assert self.get(url='/blah')['status'] == 200 self.route_match({"uri": "!*blah"}) - self.assertEqual(self.get()['status'], 200) - self.assertEqual(self.get(url='/bla')['status'], 200) - self.assertEqual(self.get(url='/blah')['status'], 404) - self.assertEqual(self.get(url='/blah1')['status'], 200) + assert self.get()['status'] == 200 + assert self.get(url='/bla')['status'] == 200 + assert self.get(url='/blah')['status'] == 404 + assert self.get(url='/blah1')['status'] == 200 self.route_match({"uri": "!/blah*1*"}) - self.assertEqual(self.get()['status'], 200) - self.assertEqual(self.get(url='/blah')['status'], 200) - self.assertEqual(self.get(url='/blah1')['status'], 404) - self.assertEqual(self.get(url='/blah12')['status'], 404) - self.assertEqual(self.get(url='/blah2')['status'], 200) + assert self.get()['status'] == 200 + assert self.get(url='/blah')['status'] == 200 + assert self.get(url='/blah1')['status'] == 404 + assert self.get(url='/blah12')['status'] == 404 + assert self.get(url='/blah2')['status'] == 200 def test_routes_match_wildcard_middle(self): self.route_match({"host": "ex*le"}) @@ -162,110 +148,105 @@ class TestRouting(TestApplicationProto): def test_routes_match_method_case_insensitive(self): self.route_match({"method": "get"}) - self.assertEqual(self.get()['status'], 200, 'GET') + assert self.get()['status'] == 200, 'GET' def test_routes_match_wildcard_left_case_insensitive(self): self.route_match({"method": "*get"}) - self.assertEqual(self.get()['status'], 200, 'GET') + assert self.get()['status'] == 200, 'GET' self.route_match({"method": "*et"}) - self.assertEqual(self.get()['status'], 200, 'GET') + assert self.get()['status'] == 200, 'GET' def test_routes_match_wildcard_middle_case_insensitive(self): self.route_match({"method": "g*t"}) - self.assertEqual(self.get()['status'], 200, 'GET') + assert self.get()['status'] == 200, 'GET' def test_routes_match_wildcard_right_case_insensitive(self): self.route_match({"method": "get*"}) - self.assertEqual(self.get()['status'], 200, 'GET') + assert self.get()['status'] == 200, 'GET' self.route_match({"method": "ge*"}) - self.assertEqual(self.get()['status'], 200, 'GET') + assert self.get()['status'] == 200, 'GET' def test_routes_match_wildcard_substring_case_insensitive(self): self.route_match({"method": "*et*"}) - self.assertEqual(self.get()['status'], 200, 'GET') + assert self.get()['status'] == 200, 'GET' def test_routes_match_wildcard_left_case_sensitive(self): self.route_match({"uri": "*blah"}) - self.assertEqual(self.get(url='/blah')['status'], 200, '/blah') - self.assertEqual(self.get(url='/BLAH')['status'], 404, '/BLAH') + assert self.get(url='/blah')['status'] == 200, '/blah' + assert self.get(url='/BLAH')['status'] == 404, '/BLAH' def test_routes_match_wildcard_middle_case_sensitive(self): self.route_match({"uri": "/b*h"}) - self.assertEqual(self.get(url='/blah')['status'], 200, '/blah') - self.assertEqual(self.get(url='/BLAH')['status'], 404, '/BLAH') + assert self.get(url='/blah')['status'] == 200, '/blah' + assert self.get(url='/BLAH')['status'] == 404, '/BLAH' def test_route_match_wildcards_ordered(self): self.route_match({"uri": "/a*x*y*"}) - self.assertEqual(self.get(url='/axy')['status'], 200, '/axy') - self.assertEqual(self.get(url='/ayx')['status'], 404, '/ayx') + assert self.get(url='/axy')['status'] == 200, '/axy' + assert self.get(url='/ayx')['status'] == 404, '/ayx' def test_route_match_wildcards_adjust_start(self): self.route_match({"uri": "/bla*bla*"}) - self.assertEqual(self.get(url='/bla_foo')['status'], 404, '/bla_foo') + assert self.get(url='/bla_foo')['status'] == 404, '/bla_foo' def test_route_match_wildcards_adjust_start_substr(self): self.route_match({"uri": "*bla*bla*"}) - self.assertEqual(self.get(url='/bla_foo')['status'], 404, '/bla_foo') + assert self.get(url='/bla_foo')['status'] == 404, '/bla_foo' def test_route_match_wildcards_adjust_end(self): self.route_match({"uri": "/bla*bla"}) - self.assertEqual(self.get(url='/foo_bla')['status'], 404, '/foo_bla') + assert self.get(url='/foo_bla')['status'] == 404, '/foo_bla' def test_routes_match_wildcard_right_case_sensitive(self): self.route_match({"uri": "/bla*"}) - self.assertEqual(self.get(url='/blah')['status'], 200, '/blah') - self.assertEqual(self.get(url='/BLAH')['status'], 404, '/BLAH') + assert self.get(url='/blah')['status'] == 200, '/blah' + assert self.get(url='/BLAH')['status'] == 404, '/BLAH' def test_routes_match_wildcard_substring_case_sensitive(self): self.route_match({"uri": "*bla*"}) - self.assertEqual(self.get(url='/blah')['status'], 200, '/blah') - self.assertEqual(self.get(url='/BLAH')['status'], 404, '/BLAH') + assert self.get(url='/blah')['status'] == 200, '/blah' + assert self.get(url='/BLAH')['status'] == 404, '/BLAH' def test_routes_match_many_wildcard_substrings_case_sensitive(self): self.route_match({"uri": "*a*B*c*"}) - self.assertEqual(self.get(url='/blah-a-B-c-blah')['status'], 200) - self.assertEqual(self.get(url='/a-B-c')['status'], 200) - self.assertEqual(self.get(url='/aBc')['status'], 200) - self.assertEqual(self.get(url='/aBCaBbc')['status'], 200) - self.assertEqual(self.get(url='/ABc')['status'], 404) + assert self.get(url='/blah-a-B-c-blah')['status'] == 200 + assert self.get(url='/a-B-c')['status'] == 200 + assert self.get(url='/aBc')['status'] == 200 + assert self.get(url='/aBCaBbc')['status'] == 200 + assert self.get(url='/ABc')['status'] == 404 def test_routes_pass_encode(self): def check_pass(path, name): - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "applications/" + path} - }, - "applications": { - name: { - "type": "python", - "processes": {"spare": 0}, - "path": self.current_dir + '/python/empty', - "working_directory": self.current_dir - + '/python/empty', - "module": "wsgi", - } - }, - } - ), + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "applications/" + path}}, + "applications": { + name: { + "type": "python", + "processes": {"spare": 0}, + "path": option.test_dir + '/python/empty', + "working_directory": option.test_dir + + '/python/empty', + "module": "wsgi", + } + }, + } ) - self.assertEqual(self.get()['status'], 200) + assert self.get()['status'] == 200 check_pass("%25", "%") check_pass("blah%2Fblah", "blah/blah") @@ -273,25 +254,20 @@ class TestRouting(TestApplicationProto): check_pass("%20blah%252Fblah%7E", " blah%2Fblah~") def check_pass_error(path, name): - self.assertIn( - 'error', - self.conf( - { - "listeners": { - "*:7080": {"pass": "applications/" + path} - }, - "applications": { - name: { - "type": "python", - "processes": {"spare": 0}, - "path": self.current_dir + '/python/empty', - "working_directory": self.current_dir - + '/python/empty', - "module": "wsgi", - } - }, - } - ), + assert 'error' in self.conf( + { + "listeners": {"*:7080": {"pass": "applications/" + path}}, + "applications": { + name: { + "type": "python", + "processes": {"spare": 0}, + "path": option.test_dir + '/python/empty', + "working_directory": option.test_dir + + '/python/empty', + "module": "wsgi", + } + }, + } ) check_pass_error("%", "%") @@ -305,8 +281,8 @@ class TestRouting(TestApplicationProto): "empty": { "type": "python", "processes": {"spare": 0}, - "path": self.current_dir + '/python/empty', - "working_directory": self.current_dir + "path": option.test_dir + '/python/empty', + "working_directory": option.test_dir + '/python/empty', "module": "wsgi", } @@ -314,179 +290,135 @@ class TestRouting(TestApplicationProto): } ) - self.assertEqual(self.get(port=7081)['status'], 200, 'routes absent') + assert self.get(port=7081)['status'] == 200, 'routes absent' def test_routes_pass_invalid(self): - self.assertIn( - 'error', - self.conf({"pass": "routes/blah"}, 'listeners/*:7080'), - 'routes invalid', - ) + assert 'error' in self.conf( + {"pass": "routes/blah"}, 'listeners/*:7080' + ), 'routes invalid' def test_route_empty(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "routes/main"}}, - "routes": {"main": []}, - "applications": {}, - } - ), - 'route empty configure', - ) + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes/main"}}, + "routes": {"main": []}, + "applications": {}, + } + ), 'route empty configure' - self.assertEqual(self.get()['status'], 404, 'route empty') + assert self.get()['status'] == 404, 'route empty' def test_routes_route_empty(self): - self.assertIn( - 'success', - self.conf({}, 'listeners'), - 'routes empty listeners configure', - ) + assert 'success' in self.conf( + {}, 'listeners' + ), 'routes empty listeners configure' - self.assertIn( - 'success', self.conf({}, 'routes'), 'routes empty configure' - ) + assert 'success' in self.conf({}, 'routes'), 'routes empty configure' def test_routes_route_match_absent(self): - self.assertIn( - 'success', - self.conf([{"action": {"return": 200}}], 'routes'), - 'route match absent configure', - ) + assert 'success' in self.conf( + [{"action": {"return": 200}}], 'routes' + ), 'route match absent configure' - self.assertEqual(self.get()['status'], 200, 'route match absent') + assert self.get()['status'] == 200, 'route match absent' def test_routes_route_action_absent(self): - self.skip_alerts.append(r'failed to apply new conf') + skip_alert(r'failed to apply new conf') - self.assertIn( - 'error', - self.conf([{"match": {"method": "GET"}}], 'routes'), - 'route pass absent configure', - ) + assert 'error' in self.conf( + [{"match": {"method": "GET"}}], 'routes' + ), 'route pass absent configure' def test_routes_route_pass_absent(self): - self.assertIn( - 'error', - self.conf([{"match": {"method": "GET"}, "action": {}}], 'routes'), - 'route pass absent configure', - ) + assert 'error' in self.conf( + [{"match": {"method": "GET"}, "action": {}}], 'routes' + ), 'route pass absent configure' def test_routes_action_unique(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "routes"}, - "*:7081": {"pass": "applications/app"}, - }, - "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], - "applications": { - "app": { - "type": "python", - "processes": {"spare": 0}, - "path": "/app", - "module": "wsgi", - } - }, - } - ), - ) - - self.assertIn( - 'error', - self.conf( - {"proxy": "http://127.0.0.1:7081", "share": self.testdir}, - 'routes/0/action', - ), - 'proxy share', - ) - self.assertIn( - 'error', - self.conf( - { - "proxy": "http://127.0.0.1:7081", - "pass": "applications/app", + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": {"pass": "applications/app"}, }, - 'routes/0/action', - ), - 'proxy pass', - ) - self.assertIn( - 'error', - self.conf( - {"share": self.testdir, "pass": "applications/app"}, - 'routes/0/action', - ), - 'share pass', + "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "applications": { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + } ) + assert 'error' in self.conf( + {"proxy": "http://127.0.0.1:7081", "share": self.temp_dir}, + 'routes/0/action', + ), 'proxy share' + assert 'error' in self.conf( + {"proxy": "http://127.0.0.1:7081", "pass": "applications/app",}, + 'routes/0/action', + ), 'proxy pass' + assert 'error' in self.conf( + {"share": self.temp_dir, "pass": "applications/app"}, + 'routes/0/action', + ), 'share pass' + def test_routes_rules_two(self): - self.assertIn( - 'success', - self.conf( - [ - {"match": {"method": "GET"}, "action": {"return": 200}}, - {"match": {"method": "POST"}, "action": {"return": 201}}, - ], - 'routes', - ), - 'rules two configure', - ) + assert 'success' in self.conf( + [ + {"match": {"method": "GET"}, "action": {"return": 200}}, + {"match": {"method": "POST"}, "action": {"return": 201}}, + ], + 'routes', + ), 'rules two configure' - self.assertEqual(self.get()['status'], 200, 'rules two match first') - self.assertEqual(self.post()['status'], 201, 'rules two match second') + assert self.get()['status'] == 200, 'rules two match first' + assert self.post()['status'] == 201, 'rules two match second' def test_routes_two(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "routes/first"}}, - "routes": { - "first": [ - { - "match": {"method": "GET"}, - "action": {"pass": "routes/second"}, - } - ], - "second": [ - { - "match": {"host": "localhost"}, - "action": {"return": 200}, - } - ], - }, - "applications": {}, - } - ), - 'routes two configure', - ) + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes/first"}}, + "routes": { + "first": [ + { + "match": {"method": "GET"}, + "action": {"pass": "routes/second"}, + } + ], + "second": [ + { + "match": {"host": "localhost"}, + "action": {"return": 200}, + } + ], + }, + "applications": {}, + } + ), 'routes two configure' - self.assertEqual(self.get()['status'], 200, 'routes two') + assert self.get()['status'] == 200, 'routes two' def test_routes_match_host_positive(self): self.route_match({"host": "localhost"}) - self.assertEqual(self.get()['status'], 200, 'localhost') + assert self.get()['status'] == 200, 'localhost' self.host('localhost.', 200) self.host('localhost.', 200) self.host('.localhost', 404) self.host('www.localhost', 404) self.host('localhost1', 404) - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_routes_match_host_absent(self): self.route_match({"host": "localhost"}) - self.assertEqual( - self.get(headers={'Connection': 'close'})['status'], - 400, - 'match host absent', - ) + assert ( + self.get(headers={'Connection': 'close'})['status'] == 400 + ), 'match host absent' def test_routes_match_host_ipv4(self): self.route_match({"host": "127.0.0.1"}) @@ -503,13 +435,13 @@ class TestRouting(TestApplicationProto): def test_routes_match_host_positive_many(self): self.route_match({"host": ["localhost", "example.com"]}) - self.assertEqual(self.get()['status'], 200, 'localhost') + assert self.get()['status'] == 200, 'localhost' self.host('example.com', 200) def test_routes_match_host_positive_and_negative(self): self.route_match({"host": ["*example.com", "!www.example.com"]}) - self.assertEqual(self.get()['status'], 404, 'localhost') + assert self.get()['status'] == 404, 'localhost' self.host('example.com', 200) self.host('www.example.com', 404) self.host('!www.example.com', 200) @@ -535,380 +467,278 @@ class TestRouting(TestApplicationProto): self.route_match({"host": ""}) self.host('', 200) - self.assertEqual( - self.get(http_10=True, headers={})['status'], - 200, - 'match host empty 2', - ) - self.assertEqual(self.get()['status'], 404, 'match host empty 3') + assert ( + self.get(http_10=True, headers={})['status'] == 200 + ), 'match host empty 2' + assert self.get()['status'] == 404, 'match host empty 3' def test_routes_match_uri_positive(self): self.route_match({"uri": ["/blah", "/slash/"]}) - self.assertEqual(self.get()['status'], 404, '/') - self.assertEqual(self.get(url='/blah')['status'], 200, '/blah') - self.assertEqual(self.get(url='/blah#foo')['status'], 200, '/blah#foo') - self.assertEqual(self.get(url='/blah?var')['status'], 200, '/blah?var') - self.assertEqual(self.get(url='//blah')['status'], 200, '//blah') - self.assertEqual( - self.get(url='/slash/foo/../')['status'], 200, 'relative' - ) - self.assertEqual(self.get(url='/slash/./')['status'], 200, '/slash/./') - self.assertEqual( - self.get(url='/slash//.//')['status'], 200, 'adjacent slashes' - ) - self.assertEqual(self.get(url='/%')['status'], 400, 'percent') - self.assertEqual(self.get(url='/%1')['status'], 400, 'percent digit') - self.assertEqual(self.get(url='/%A')['status'], 400, 'percent letter') - self.assertEqual( - self.get(url='/slash/.?args')['status'], 200, 'dot args' - ) - self.assertEqual( - self.get(url='/slash/.#frag')['status'], 200, 'dot frag' - ) - self.assertEqual( - self.get(url='/slash/foo/..?args')['status'], - 200, - 'dot dot args', - ) - self.assertEqual( - self.get(url='/slash/foo/..#frag')['status'], - 200, - 'dot dot frag', - ) - self.assertEqual( - self.get(url='/slash/.')['status'], 200, 'trailing dot' - ) - self.assertEqual( - self.get(url='/slash/foo/..')['status'], - 200, - 'trailing dot dot', - ) + assert self.get()['status'] == 404, '/' + assert self.get(url='/blah')['status'] == 200, '/blah' + assert self.get(url='/blah#foo')['status'] == 200, '/blah#foo' + assert self.get(url='/blah?var')['status'] == 200, '/blah?var' + assert self.get(url='//blah')['status'] == 200, '//blah' + assert self.get(url='/slash/foo/../')['status'] == 200, 'relative' + assert self.get(url='/slash/./')['status'] == 200, '/slash/./' + assert self.get(url='/slash//.//')['status'] == 200, 'adjacent slashes' + assert self.get(url='/%')['status'] == 400, 'percent' + assert self.get(url='/%1')['status'] == 400, 'percent digit' + assert self.get(url='/%A')['status'] == 400, 'percent letter' + assert self.get(url='/slash/.?args')['status'] == 200, 'dot args' + assert self.get(url='/slash/.#frag')['status'] == 200, 'dot frag' + assert ( + self.get(url='/slash/foo/..?args')['status'] == 200 + ), 'dot dot args' + assert ( + self.get(url='/slash/foo/..#frag')['status'] == 200 + ), 'dot dot frag' + assert self.get(url='/slash/.')['status'] == 200, 'trailing dot' + assert ( + self.get(url='/slash/foo/..')['status'] == 200 + ), 'trailing dot dot' def test_routes_match_uri_case_sensitive(self): self.route_match({"uri": "/BLAH"}) - self.assertEqual(self.get(url='/blah')['status'], 404, '/blah') - self.assertEqual(self.get(url='/BlaH')['status'], 404, '/BlaH') - self.assertEqual(self.get(url='/BLAH')['status'], 200, '/BLAH') + assert self.get(url='/blah')['status'] == 404, '/blah' + assert self.get(url='/BlaH')['status'] == 404, '/BlaH' + assert self.get(url='/BLAH')['status'] == 200, '/BLAH' def test_routes_match_uri_normalize(self): self.route_match({"uri": "/blah"}) - self.assertEqual( - self.get(url='/%62%6c%61%68')['status'], 200, 'normalize' - ) + assert self.get(url='/%62%6c%61%68')['status'] == 200, 'normalize' def test_routes_match_empty_array(self): self.route_match({"uri": []}) - self.assertEqual(self.get(url='/blah')['status'], 200, 'empty array') + assert self.get(url='/blah')['status'] == 200, 'empty array' def test_routes_reconfigure(self): - self.assertIn('success', self.conf([], 'routes'), 'redefine') - self.assertEqual(self.get()['status'], 404, 'redefine request') + assert 'success' in self.conf([], 'routes'), 'redefine' + assert self.get()['status'] == 404, 'redefine request' - self.assertIn( - 'success', - self.conf([{"action": {"return": 200}}], 'routes'), - 'redefine 2', - ) - self.assertEqual(self.get()['status'], 200, 'redefine request 2') + assert 'success' in self.conf( + [{"action": {"return": 200}}], 'routes' + ), 'redefine 2' + assert self.get()['status'] == 200, 'redefine request 2' - self.assertIn('success', self.conf([], 'routes'), 'redefine 3') - self.assertEqual(self.get()['status'], 404, 'redefine request 3') + assert 'success' in self.conf([], 'routes'), 'redefine 3' + assert self.get()['status'] == 404, 'redefine request 3' - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "routes/main"}}, - "routes": {"main": [{"action": {"return": 200}}]}, - "applications": {}, - } - ), - 'redefine 4', - ) - self.assertEqual(self.get()['status'], 200, 'redefine request 4') + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes/main"}}, + "routes": {"main": [{"action": {"return": 200}}]}, + "applications": {}, + } + ), 'redefine 4' + assert self.get()['status'] == 200, 'redefine request 4' - self.assertIn( - 'success', self.conf_delete('routes/main/0'), 'redefine 5' - ) - self.assertEqual(self.get()['status'], 404, 'redefine request 5') + assert 'success' in self.conf_delete('routes/main/0'), 'redefine 5' + assert self.get()['status'] == 404, 'redefine request 5' - self.assertIn( - 'success', - self.conf_post({"action": {"return": 200}}, 'routes/main'), - 'redefine 6', - ) - self.assertEqual(self.get()['status'], 200, 'redefine request 6') + assert 'success' in self.conf_post( + {"action": {"return": 200}}, 'routes/main' + ), 'redefine 6' + assert self.get()['status'] == 200, 'redefine request 6' - self.assertIn( - 'error', - self.conf({"action": {"return": 200}}, 'routes/main/2'), - 'redefine 7', - ) - self.assertIn( - 'success', - self.conf({"action": {"return": 201}}, 'routes/main/1'), - 'redefine 8', - ) + assert 'error' in self.conf( + {"action": {"return": 200}}, 'routes/main/2' + ), 'redefine 7' + assert 'success' in self.conf( + {"action": {"return": 201}}, 'routes/main/1' + ), 'redefine 8' - self.assertEqual( - len(self.conf_get('routes/main')), 2, 'redefine conf 8' - ) - self.assertEqual(self.get()['status'], 200, 'redefine request 8') + assert len(self.conf_get('routes/main')) == 2, 'redefine conf 8' + assert self.get()['status'] == 200, 'redefine request 8' def test_routes_edit(self): self.route_match({"method": "GET"}) - self.assertEqual(self.get()['status'], 200, 'routes edit GET') - self.assertEqual(self.post()['status'], 404, 'routes edit POST') - - self.assertIn( - 'success', - self.conf_post( - {"match": {"method": "POST"}, "action": {"return": 200}}, - 'routes', - ), - 'routes edit configure 2', - ) - self.assertEqual( - 'GET', - self.conf_get('routes/0/match/method'), - 'routes edit configure 2 check', - ) - self.assertEqual( - 'POST', - self.conf_get('routes/1/match/method'), - 'routes edit configure 2 check 2', - ) - - self.assertEqual(self.get()['status'], 200, 'routes edit GET 2') - self.assertEqual(self.post()['status'], 200, 'routes edit POST 2') - - self.assertIn( - 'success', self.conf_delete('routes/0'), 'routes edit configure 3', - ) - - self.assertEqual(self.get()['status'], 404, 'routes edit GET 3') - self.assertEqual(self.post()['status'], 200, 'routes edit POST 3') - - self.assertIn( - 'error', - self.conf_delete('routes/1'), - 'routes edit configure invalid', - ) - self.assertIn( - 'error', - self.conf_delete('routes/-1'), - 'routes edit configure invalid 2', - ) - self.assertIn( - 'error', - self.conf_delete('routes/blah'), - 'routes edit configure invalid 3', - ) - - self.assertEqual(self.get()['status'], 404, 'routes edit GET 4') - self.assertEqual(self.post()['status'], 200, 'routes edit POST 4') - - self.assertIn( - 'success', self.conf_delete('routes/0'), 'routes edit configure 5', - ) - - self.assertEqual(self.get()['status'], 404, 'routes edit GET 5') - self.assertEqual(self.post()['status'], 404, 'routes edit POST 5') - - self.assertIn( - 'success', - self.conf_post( - {"match": {"method": "POST"}, "action": {"return": 200}}, - 'routes', - ), - 'routes edit configure 6', - ) - - self.assertEqual(self.get()['status'], 404, 'routes edit GET 6') - self.assertEqual(self.post()['status'], 200, 'routes edit POST 6') - - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "routes/main"}}, - "routes": {"main": [{"action": {"return": 200}}]}, - "applications": {}, - } - ), - 'route edit configure 7', - ) + assert self.get()['status'] == 200, 'routes edit GET' + assert self.post()['status'] == 404, 'routes edit POST' + + assert 'success' in self.conf_post( + {"match": {"method": "POST"}, "action": {"return": 200}}, 'routes', + ), 'routes edit configure 2' + assert 'GET' == self.conf_get( + 'routes/0/match/method' + ), 'routes edit configure 2 check' + assert 'POST' == self.conf_get( + 'routes/1/match/method' + ), 'routes edit configure 2 check 2' + + assert self.get()['status'] == 200, 'routes edit GET 2' + assert self.post()['status'] == 200, 'routes edit POST 2' + + assert 'success' in self.conf_delete( + 'routes/0' + ), 'routes edit configure 3' + + assert self.get()['status'] == 404, 'routes edit GET 3' + assert self.post()['status'] == 200, 'routes edit POST 3' + + assert 'error' in self.conf_delete( + 'routes/1' + ), 'routes edit configure invalid' + assert 'error' in self.conf_delete( + 'routes/-1' + ), 'routes edit configure invalid 2' + assert 'error' in self.conf_delete( + 'routes/blah' + ), 'routes edit configure invalid 3' + + assert self.get()['status'] == 404, 'routes edit GET 4' + assert self.post()['status'] == 200, 'routes edit POST 4' + + assert 'success' in self.conf_delete( + 'routes/0' + ), 'routes edit configure 5' + + assert self.get()['status'] == 404, 'routes edit GET 5' + assert self.post()['status'] == 404, 'routes edit POST 5' + + assert 'success' in self.conf_post( + {"match": {"method": "POST"}, "action": {"return": 200}}, 'routes', + ), 'routes edit configure 6' + + assert self.get()['status'] == 404, 'routes edit GET 6' + assert self.post()['status'] == 200, 'routes edit POST 6' + + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes/main"}}, + "routes": {"main": [{"action": {"return": 200}}]}, + "applications": {}, + } + ), 'route edit configure 7' - self.assertIn( - 'error', - self.conf_delete('routes/0'), - 'routes edit configure invalid 4', - ) - self.assertIn( - 'error', - self.conf_delete('routes/main'), - 'routes edit configure invalid 5', - ) + assert 'error' in self.conf_delete( + 'routes/0' + ), 'routes edit configure invalid 4' + assert 'error' in self.conf_delete( + 'routes/main' + ), 'routes edit configure invalid 5' - self.assertEqual(self.get()['status'], 200, 'routes edit GET 7') + assert self.get()['status'] == 200, 'routes edit GET 7' - self.assertIn( - 'success', - self.conf_delete('listeners/*:7080'), - 'route edit configure 8', - ) - self.assertIn( - 'success', - self.conf_delete('routes/main'), - 'route edit configure 9', - ) + assert 'success' in self.conf_delete( + 'listeners/*:7080' + ), 'route edit configure 8' + assert 'success' in self.conf_delete( + 'routes/main' + ), 'route edit configure 9' def test_match_edit(self): - self.skip_alerts.append(r'failed to apply new conf') + skip_alert(r'failed to apply new conf') self.route_match({"method": ["GET", "POST"]}) - self.assertEqual(self.get()['status'], 200, 'match edit GET') - self.assertEqual(self.post()['status'], 200, 'match edit POST') - self.assertEqual(self.put()['status'], 404, 'match edit PUT') - - self.assertIn( - 'success', - self.conf_post('\"PUT\"', 'routes/0/match/method'), - 'match edit configure 2', - ) - self.assertListEqual( - ['GET', 'POST', 'PUT'], - self.conf_get('routes/0/match/method'), - 'match edit configure 2 check', - ) - - self.assertEqual(self.get()['status'], 200, 'match edit GET 2') - self.assertEqual(self.post()['status'], 200, 'match edit POST 2') - self.assertEqual(self.put()['status'], 200, 'match edit PUT 2') - - self.assertIn( - 'success', - self.conf_delete('routes/0/match/method/1'), - 'match edit configure 3', - ) - self.assertListEqual( - ['GET', 'PUT'], - self.conf_get('routes/0/match/method'), - 'match edit configure 3 check', - ) - - self.assertEqual(self.get()['status'], 200, 'match edit GET 3') - self.assertEqual(self.post()['status'], 404, 'match edit POST 3') - self.assertEqual(self.put()['status'], 200, 'match edit PUT 3') - - self.assertIn( - 'success', - self.conf_delete('routes/0/match/method/1'), - 'match edit configure 4', - ) - self.assertListEqual( - ['GET'], - self.conf_get('routes/0/match/method'), - 'match edit configure 4 check', - ) - - self.assertEqual(self.get()['status'], 200, 'match edit GET 4') - self.assertEqual(self.post()['status'], 404, 'match edit POST 4') - self.assertEqual(self.put()['status'], 404, 'match edit PUT 4') - - self.assertIn( - 'error', - self.conf_delete('routes/0/match/method/1'), - 'match edit configure invalid', - ) - self.assertIn( - 'error', - self.conf_delete('routes/0/match/method/-1'), - 'match edit configure invalid 2', - ) - self.assertIn( - 'error', - self.conf_delete('routes/0/match/method/blah'), - 'match edit configure invalid 3', - ) - self.assertListEqual( - ['GET'], - self.conf_get('routes/0/match/method'), - 'match edit configure 5 check', - ) - - self.assertEqual(self.get()['status'], 200, 'match edit GET 5') - self.assertEqual(self.post()['status'], 404, 'match edit POST 5') - self.assertEqual(self.put()['status'], 404, 'match edit PUT 5') - - self.assertIn( - 'success', - self.conf_delete('routes/0/match/method/0'), - 'match edit configure 6', - ) - self.assertListEqual( - [], - self.conf_get('routes/0/match/method'), - 'match edit configure 6 check', - ) - - self.assertEqual(self.get()['status'], 200, 'match edit GET 6') - self.assertEqual(self.post()['status'], 200, 'match edit POST 6') - self.assertEqual(self.put()['status'], 200, 'match edit PUT 6') - - self.assertIn( - 'success', - self.conf('"GET"', 'routes/0/match/method'), - 'match edit configure 7', - ) - - self.assertEqual(self.get()['status'], 200, 'match edit GET 7') - self.assertEqual(self.post()['status'], 404, 'match edit POST 7') - self.assertEqual(self.put()['status'], 404, 'match edit PUT 7') - - self.assertIn( - 'error', - self.conf_delete('routes/0/match/method/0'), - 'match edit configure invalid 5', - ) - self.assertIn( - 'error', - self.conf({}, 'routes/0/action'), - 'match edit configure invalid 6', - ) - - self.assertIn( - 'success', - self.conf({}, 'routes/0/match'), - 'match edit configure 8', - ) - - self.assertEqual(self.get()['status'], 200, 'match edit GET 8') + assert self.get()['status'] == 200, 'match edit GET' + assert self.post()['status'] == 200, 'match edit POST' + assert self.put()['status'] == 404, 'match edit PUT' + + assert 'success' in self.conf_post( + '\"PUT\"', 'routes/0/match/method' + ), 'match edit configure 2' + assert ['GET', 'POST', 'PUT'] == self.conf_get( + 'routes/0/match/method' + ), 'match edit configure 2 check' + + assert self.get()['status'] == 200, 'match edit GET 2' + assert self.post()['status'] == 200, 'match edit POST 2' + assert self.put()['status'] == 200, 'match edit PUT 2' + + assert 'success' in self.conf_delete( + 'routes/0/match/method/1' + ), 'match edit configure 3' + assert ['GET', 'PUT'] == self.conf_get( + 'routes/0/match/method' + ), 'match edit configure 3 check' + + assert self.get()['status'] == 200, 'match edit GET 3' + assert self.post()['status'] == 404, 'match edit POST 3' + assert self.put()['status'] == 200, 'match edit PUT 3' + + assert 'success' in self.conf_delete( + 'routes/0/match/method/1' + ), 'match edit configure 4' + assert ['GET'] == self.conf_get( + 'routes/0/match/method' + ), 'match edit configure 4 check' + + assert self.get()['status'] == 200, 'match edit GET 4' + assert self.post()['status'] == 404, 'match edit POST 4' + assert self.put()['status'] == 404, 'match edit PUT 4' + + assert 'error' in self.conf_delete( + 'routes/0/match/method/1' + ), 'match edit configure invalid' + assert 'error' in self.conf_delete( + 'routes/0/match/method/-1' + ), 'match edit configure invalid 2' + assert 'error' in self.conf_delete( + 'routes/0/match/method/blah' + ), 'match edit configure invalid 3' + assert ['GET'] == self.conf_get( + 'routes/0/match/method' + ), 'match edit configure 5 check' + + assert self.get()['status'] == 200, 'match edit GET 5' + assert self.post()['status'] == 404, 'match edit POST 5' + assert self.put()['status'] == 404, 'match edit PUT 5' + + assert 'success' in self.conf_delete( + 'routes/0/match/method/0' + ), 'match edit configure 6' + assert [] == self.conf_get( + 'routes/0/match/method' + ), 'match edit configure 6 check' + + assert self.get()['status'] == 200, 'match edit GET 6' + assert self.post()['status'] == 200, 'match edit POST 6' + assert self.put()['status'] == 200, 'match edit PUT 6' + + assert 'success' in self.conf( + '"GET"', 'routes/0/match/method' + ), 'match edit configure 7' + + assert self.get()['status'] == 200, 'match edit GET 7' + assert self.post()['status'] == 404, 'match edit POST 7' + assert self.put()['status'] == 404, 'match edit PUT 7' + + assert 'error' in self.conf_delete( + 'routes/0/match/method/0' + ), 'match edit configure invalid 5' + assert 'error' in self.conf( + {}, 'routes/0/action' + ), 'match edit configure invalid 6' + + assert 'success' in self.conf( + {}, 'routes/0/match' + ), 'match edit configure 8' + + assert self.get()['status'] == 200, 'match edit GET 8' def test_routes_match_rules(self): self.route_match({"method": "GET", "host": "localhost", "uri": "/"}) - self.assertEqual(self.get()['status'], 200, 'routes match rules') + assert self.get()['status'] == 200, 'routes match rules' def test_routes_loop(self): - self.assertIn( - 'success', - self.route({"match": {"uri": "/"}, "action": {"pass": "routes"}}), - 'routes loop configure', - ) + assert 'success' in self.route( + {"match": {"uri": "/"}, "action": {"pass": "routes"}} + ), 'routes loop configure' - self.assertEqual(self.get()['status'], 500, 'routes loop') + assert self.get()['status'] == 500, 'routes loop' def test_routes_match_headers(self): self.route_match({"headers": {"host": "localhost"}}) - self.assertEqual(self.get()['status'], 200, 'match headers') + assert self.get()['status'] == 200, 'match headers' self.host('Localhost', 200) self.host('localhost.com', 404) self.host('llocalhost', 404) @@ -917,134 +747,122 @@ class TestRouting(TestApplicationProto): def test_routes_match_headers_multiple(self): self.route_match({"headers": {"host": "localhost", "x-blah": "test"}}) - self.assertEqual(self.get()['status'], 404, 'match headers multiple') - self.assertEqual( + assert self.get()['status'] == 404, 'match headers multiple' + assert ( self.get( headers={ "Host": "localhost", "X-blah": "test", "Connection": "close", } - )['status'], - 200, - 'match headers multiple 2', - ) + )['status'] + == 200 + ), 'match headers multiple 2' - self.assertEqual( + assert ( self.get( headers={ "Host": "localhost", "X-blah": "", "Connection": "close", } - )['status'], - 404, - 'match headers multiple 3', - ) + )['status'] + == 404 + ), 'match headers multiple 3' def test_routes_match_headers_multiple_values(self): self.route_match({"headers": {"x-blah": "test"}}) - self.assertEqual( + assert ( self.get( headers={ "Host": "localhost", "X-blah": ["test", "test", "test"], "Connection": "close", } - )['status'], - 200, - 'match headers multiple values', - ) - self.assertEqual( + )['status'] + == 200 + ), 'match headers multiple values' + assert ( self.get( headers={ "Host": "localhost", "X-blah": ["test", "blah", "test"], "Connection": "close", } - )['status'], - 404, - 'match headers multiple values 2', - ) - self.assertEqual( + )['status'] + == 404 + ), 'match headers multiple values 2' + assert ( self.get( headers={ "Host": "localhost", "X-blah": ["test", "", "test"], "Connection": "close", } - )['status'], - 404, - 'match headers multiple values 3', - ) + )['status'] + == 404 + ), 'match headers multiple values 3' def test_routes_match_headers_multiple_rules(self): self.route_match({"headers": {"x-blah": ["test", "blah"]}}) - self.assertEqual( - self.get()['status'], 404, 'match headers multiple rules' - ) - self.assertEqual( + assert self.get()['status'] == 404, 'match headers multiple rules' + assert ( self.get( headers={ "Host": "localhost", "X-blah": "test", "Connection": "close", } - )['status'], - 200, - 'match headers multiple rules 2', - ) - self.assertEqual( + )['status'] + == 200 + ), 'match headers multiple rules 2' + assert ( self.get( headers={ "Host": "localhost", "X-blah": "blah", "Connection": "close", } - )['status'], - 200, - 'match headers multiple rules 3', - ) - self.assertEqual( + )['status'] + == 200 + ), 'match headers multiple rules 3' + assert ( self.get( headers={ "Host": "localhost", "X-blah": ["test", "blah", "test"], "Connection": "close", } - )['status'], - 200, - 'match headers multiple rules 4', - ) + )['status'] + == 200 + ), 'match headers multiple rules 4' - self.assertEqual( + assert ( self.get( headers={ "Host": "localhost", "X-blah": ["blah", ""], "Connection": "close", } - )['status'], - 404, - 'match headers multiple rules 5', - ) + )['status'] + == 404 + ), 'match headers multiple rules 5' def test_routes_match_headers_case_insensitive(self): self.route_match({"headers": {"X-BLAH": "TEST"}}) - self.assertEqual( + assert ( self.get( headers={ "Host": "localhost", "x-blah": "test", "Connection": "close", } - )['status'], - 200, - 'match headers case insensitive', - ) + )['status'] + == 200 + ), 'match headers case insensitive' def test_routes_match_headers_invalid(self): self.route_match_invalid({"headers": ["blah"]}) @@ -1054,29 +872,30 @@ class TestRouting(TestApplicationProto): def test_routes_match_headers_empty_rule(self): self.route_match({"headers": {"host": ""}}) - self.assertEqual(self.get()['status'], 404, 'localhost') + assert self.get()['status'] == 404, 'localhost' self.host('', 200) def test_routes_match_headers_empty(self): self.route_match({"headers": {}}) - self.assertEqual(self.get()['status'], 200, 'empty') + assert self.get()['status'] == 200, 'empty' self.route_match({"headers": []}) - self.assertEqual(self.get()['status'], 200, 'empty 2') + assert self.get()['status'] == 200, 'empty 2' def test_routes_match_headers_rule_array_empty(self): self.route_match({"headers": {"blah": []}}) - self.assertEqual(self.get()['status'], 404, 'array empty') - self.assertEqual( + assert self.get()['status'] == 404, 'array empty' + assert ( self.get( headers={ "Host": "localhost", "blah": "foo", "Connection": "close", } - )['status'], 200, 'match headers rule array empty 2' - ) + )['status'] + == 200 + ), 'match headers rule array empty 2' def test_routes_match_headers_array(self): self.route_match( @@ -1090,52 +909,48 @@ class TestRouting(TestApplicationProto): } ) - self.assertEqual(self.get()['status'], 404, 'match headers array') - self.assertEqual( + assert self.get()['status'] == 404, 'match headers array' + assert ( self.get( headers={ "Host": "localhost", "x-header1": "foo123", "Connection": "close", } - )['status'], - 200, - 'match headers array 2', - ) - self.assertEqual( + )['status'] + == 200 + ), 'match headers array 2' + assert ( self.get( headers={ "Host": "localhost", "x-header2": "bar", "Connection": "close", } - )['status'], - 200, - 'match headers array 3', - ) - self.assertEqual( + )['status'] + == 200 + ), 'match headers array 3' + assert ( self.get( headers={ "Host": "localhost", "x-header3": "bar", "Connection": "close", } - )['status'], - 200, - 'match headers array 4', - ) - self.assertEqual( + )['status'] + == 200 + ), 'match headers array 4' + assert ( self.get( headers={ "Host": "localhost", "x-header1": "bar", "Connection": "close", } - )['status'], - 404, - 'match headers array 5', - ) - self.assertEqual( + )['status'] + == 404 + ), 'match headers array 5' + assert ( self.get( headers={ "Host": "localhost", @@ -1143,49 +958,44 @@ class TestRouting(TestApplicationProto): "x-header4": "foo", "Connection": "close", } - )['status'], - 200, - 'match headers array 6', - ) + )['status'] + == 200 + ), 'match headers array 6' - self.assertIn( - 'success', - self.conf_delete('routes/0/match/headers/1'), - 'match headers array configure 2', - ) + assert 'success' in self.conf_delete( + 'routes/0/match/headers/1' + ), 'match headers array configure 2' - self.assertEqual( + assert ( self.get( headers={ "Host": "localhost", "x-header2": "bar", "Connection": "close", } - )['status'], - 404, - 'match headers array 7', - ) - self.assertEqual( + )['status'] + == 404 + ), 'match headers array 7' + assert ( self.get( headers={ "Host": "localhost", "x-header3": "foo", "Connection": "close", } - )['status'], - 200, - 'match headers array 8', - ) + )['status'] + == 200 + ), 'match headers array 8' def test_routes_match_arguments(self): self.route_match({"arguments": {"foo": "bar"}}) - self.assertEqual(self.get()['status'], 404, 'args') - self.assertEqual(self.get(url='/?foo=bar')['status'], 200, 'args 2') - self.assertEqual(self.get(url='/?foo=bar1')['status'], 404, 'args 3') - self.assertEqual(self.get(url='/?1foo=bar')['status'], 404, 'args 4') - self.assertEqual(self.get(url='/?Foo=bar')['status'], 404, 'case') - self.assertEqual(self.get(url='/?foo=Bar')['status'], 404, 'case 2') + assert self.get()['status'] == 404, 'args' + assert self.get(url='/?foo=bar')['status'] == 200, 'args 2' + assert self.get(url='/?foo=bar1')['status'] == 404, 'args 3' + assert self.get(url='/?1foo=bar')['status'] == 404, 'args 4' + assert self.get(url='/?Foo=bar')['status'] == 404, 'case' + assert self.get(url='/?foo=Bar')['status'] == 404, 'case 2' def test_routes_match_arguments_chars(self): chars = ( @@ -1195,15 +1005,30 @@ class TestRouting(TestApplicationProto): chars_enc = "" for h1 in ["2", "3", "4", "5", "6", "7"]: - for h2 in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", - "B", "C", "D", "E", "F", + for h2 in [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "A", + "B", + "C", + "D", + "E", + "F", ]: chars_enc += "%" + h1 + h2 chars_enc = chars_enc[:-3] def check_args(args, query): self.route_match({"arguments": args}) - self.assertEqual(self.get(url='/?' + query)['status'], 200) + assert self.get(url='/?' + query)['status'] == 200 check_args({chars: chars}, chars + '=' + chars) check_args({chars: chars}, chars + '=' + chars_enc) @@ -1216,175 +1041,155 @@ class TestRouting(TestApplicationProto): def test_routes_match_arguments_empty(self): self.route_match({"arguments": {}}) - self.assertEqual(self.get()['status'], 200, 'arguments empty') + assert self.get()['status'] == 200, 'arguments empty' self.route_match({"arguments": []}) - self.assertEqual(self.get()['status'], 200, 'arguments empty 2') + assert self.get()['status'] == 200, 'arguments empty 2' def test_routes_match_arguments_space(self): self.route_match({"arguments": {"+fo o%20": "%20b+a r"}}) - self.assertEqual(self.get(url='/? fo o = b a r&')['status'], 200) - self.assertEqual(self.get(url='/?+fo+o+=+b+a+r&')['status'], 200) - self.assertEqual( - self.get(url='/?%20fo%20o%20=%20b%20a%20r&')['status'], 200 - ) + assert self.get(url='/? fo o = b a r&')['status'] == 200 + assert self.get(url='/?+fo+o+=+b+a+r&')['status'] == 200 + assert self.get(url='/?%20fo%20o%20=%20b%20a%20r&')['status'] == 200 self.route_match({"arguments": {"%20foo": " bar"}}) - self.assertEqual(self.get(url='/? foo= bar')['status'], 200) - self.assertEqual(self.get(url='/?+foo=+bar')['status'], 200) - self.assertEqual(self.get(url='/?%20foo=%20bar')['status'], 200) - self.assertEqual(self.get(url='/?+foo= bar')['status'], 200) - self.assertEqual(self.get(url='/?%20foo=+bar')['status'], 200) + assert self.get(url='/? foo= bar')['status'] == 200 + assert self.get(url='/?+foo=+bar')['status'] == 200 + assert self.get(url='/?%20foo=%20bar')['status'] == 200 + assert self.get(url='/?+foo= bar')['status'] == 200 + assert self.get(url='/?%20foo=+bar')['status'] == 200 def test_routes_match_arguments_equal(self): self.route_match({"arguments": {"=": "="}}) - self.assertEqual(self.get(url='/?%3D=%3D')['status'], 200) - self.assertEqual(self.get(url='/?%3D==')['status'], 200) - self.assertEqual(self.get(url='/?===')['status'], 404) - self.assertEqual(self.get(url='/?%3D%3D%3D')['status'], 404) - self.assertEqual(self.get(url='/?==%3D')['status'], 404) + assert self.get(url='/?%3D=%3D')['status'] == 200 + assert self.get(url='/?%3D==')['status'] == 200 + assert self.get(url='/?===')['status'] == 404 + assert self.get(url='/?%3D%3D%3D')['status'] == 404 + assert self.get(url='/?==%3D')['status'] == 404 def test_routes_match_arguments_enc(self): self.route_match({"arguments": {"Ю": "н"}}) - self.assertEqual(self.get(url='/?%D0%AE=%D0%BD')['status'], 200) - self.assertEqual(self.get(url='/?%d0%ae=%d0%Bd')['status'], 200) + assert self.get(url='/?%D0%AE=%D0%BD')['status'] == 200 + assert self.get(url='/?%d0%ae=%d0%Bd')['status'] == 200 def test_routes_match_arguments_hash(self): self.route_match({"arguments": {"#": "#"}}) - self.assertEqual(self.get(url='/?%23=%23')['status'], 200) - self.assertEqual(self.get(url='/?%23=%23#')['status'], 200) - self.assertEqual(self.get(url='/?#=#')['status'], 404) - self.assertEqual(self.get(url='/?%23=#')['status'], 404) + assert self.get(url='/?%23=%23')['status'] == 200 + assert self.get(url='/?%23=%23#')['status'] == 200 + assert self.get(url='/?#=#')['status'] == 404 + assert self.get(url='/?%23=#')['status'] == 404 def test_routes_match_arguments_wildcard(self): self.route_match({"arguments": {"foo": "*"}}) - self.assertEqual(self.get(url='/?foo')['status'], 200) - self.assertEqual(self.get(url='/?foo=')['status'], 200) - self.assertEqual(self.get(url='/?foo=blah')['status'], 200) - self.assertEqual(self.get(url='/?blah=foo')['status'], 404) + assert self.get(url='/?foo')['status'] == 200 + assert self.get(url='/?foo=')['status'] == 200 + assert self.get(url='/?foo=blah')['status'] == 200 + assert self.get(url='/?blah=foo')['status'] == 404 self.route_match({"arguments": {"foo": "%25*"}}) - self.assertEqual(self.get(url='/?foo=%xx')['status'], 200) + assert self.get(url='/?foo=%xx')['status'] == 200 self.route_match({"arguments": {"foo": "%2A*"}}) - self.assertEqual(self.get(url='/?foo=*xx')['status'], 200) - self.assertEqual(self.get(url='/?foo=xx')['status'], 404) + assert self.get(url='/?foo=*xx')['status'] == 200 + assert self.get(url='/?foo=xx')['status'] == 404 self.route_match({"arguments": {"foo": "*%2A"}}) - self.assertEqual(self.get(url='/?foo=xx*')['status'], 200) - self.assertEqual(self.get(url='/?foo=xx*x')['status'], 404) + assert self.get(url='/?foo=xx*')['status'] == 200 + assert self.get(url='/?foo=xx*x')['status'] == 404 self.route_match({"arguments": {"foo": "1*2"}}) - self.assertEqual(self.get(url='/?foo=12')['status'], 200) - self.assertEqual(self.get(url='/?foo=1blah2')['status'], 200) - self.assertEqual(self.get(url='/?foo=1%2A2')['status'], 200) - self.assertEqual(self.get(url='/?foo=x12')['status'], 404) + assert self.get(url='/?foo=12')['status'] == 200 + assert self.get(url='/?foo=1blah2')['status'] == 200 + assert self.get(url='/?foo=1%2A2')['status'] == 200 + assert self.get(url='/?foo=x12')['status'] == 404 self.route_match({"arguments": {"foo": "bar*", "%25": "%25"}}) - self.assertEqual(self.get(url='/?foo=barxx&%=%')['status'], 200) - self.assertEqual(self.get(url='/?foo=barxx&x%=%')['status'], 404) + assert self.get(url='/?foo=barxx&%=%')['status'] == 200 + assert self.get(url='/?foo=barxx&x%=%')['status'] == 404 def test_routes_match_arguments_negative(self): self.route_match({"arguments": {"foo": "!%25"}}) - self.assertEqual(self.get(url='/?foo=blah')['status'], 200) - self.assertEqual(self.get(url='/?foo=%')['status'], 404) + assert self.get(url='/?foo=blah')['status'] == 200 + assert self.get(url='/?foo=%')['status'] == 404 self.route_match({"arguments": {"foo": "%21blah"}}) - self.assertEqual(self.get(url='/?foo=%21blah')['status'], 200) - self.assertEqual(self.get(url='/?foo=!blah')['status'], 200) - self.assertEqual(self.get(url='/?foo=bar')['status'], 404) + assert self.get(url='/?foo=%21blah')['status'] == 200 + assert self.get(url='/?foo=!blah')['status'] == 200 + assert self.get(url='/?foo=bar')['status'] == 404 self.route_match({"arguments": {"foo": "!!%21*a"}}) - self.assertEqual(self.get(url='/?foo=blah')['status'], 200) - self.assertEqual(self.get(url='/?foo=!blah')['status'], 200) - self.assertEqual(self.get(url='/?foo=!!a')['status'], 404) - self.assertEqual(self.get(url='/?foo=!!bla')['status'], 404) + assert self.get(url='/?foo=blah')['status'] == 200 + assert self.get(url='/?foo=!blah')['status'] == 200 + assert self.get(url='/?foo=!!a')['status'] == 404 + assert self.get(url='/?foo=!!bla')['status'] == 404 def test_routes_match_arguments_percent(self): self.route_match({"arguments": {"%25": "%25"}}) - self.assertEqual(self.get(url='/?%=%')['status'], 200) - self.assertEqual(self.get(url='/?%25=%25')['status'], 200) - self.assertEqual(self.get(url='/?%25=%')['status'], 200) + assert self.get(url='/?%=%')['status'] == 200 + assert self.get(url='/?%25=%25')['status'] == 200 + assert self.get(url='/?%25=%')['status'] == 200 self.route_match({"arguments": {"%251": "%252"}}) - self.assertEqual(self.get(url='/?%1=%2')['status'], 200) - self.assertEqual(self.get(url='/?%251=%252')['status'], 200) - self.assertEqual(self.get(url='/?%251=%2')['status'], 200) + assert self.get(url='/?%1=%2')['status'] == 200 + assert self.get(url='/?%251=%252')['status'] == 200 + assert self.get(url='/?%251=%2')['status'] == 200 self.route_match({"arguments": {"%25%21%251": "%25%24%252"}}) - self.assertEqual(self.get(url='/?%!%1=%$%2')['status'], 200) - self.assertEqual(self.get(url='/?%25!%251=%25$%252')['status'], 200) - self.assertEqual(self.get(url='/?%25!%1=%$%2')['status'], 200) + assert self.get(url='/?%!%1=%$%2')['status'] == 200 + assert self.get(url='/?%25!%251=%25$%252')['status'] == 200 + assert self.get(url='/?%25!%1=%$%2')['status'] == 200 def test_routes_match_arguments_ampersand(self): self.route_match({"arguments": {"foo": "&"}}) - self.assertEqual(self.get(url='/?foo=%26')['status'], 200) - self.assertEqual(self.get(url='/?foo=%26&')['status'], 200) - self.assertEqual(self.get(url='/?foo=%26%26')['status'], 404) - self.assertEqual(self.get(url='/?foo=&')['status'], 404) + assert self.get(url='/?foo=%26')['status'] == 200 + assert self.get(url='/?foo=%26&')['status'] == 200 + assert self.get(url='/?foo=%26%26')['status'] == 404 + assert self.get(url='/?foo=&')['status'] == 404 self.route_match({"arguments": {"&": ""}}) - self.assertEqual(self.get(url='/?%26=')['status'], 200) - self.assertEqual(self.get(url='/?%26=&')['status'], 200) - self.assertEqual(self.get(url='/?%26=%26')['status'], 404) - self.assertEqual(self.get(url='/?&=')['status'], 404) + assert self.get(url='/?%26=')['status'] == 200 + assert self.get(url='/?%26=&')['status'] == 200 + assert self.get(url='/?%26=%26')['status'] == 404 + assert self.get(url='/?&=')['status'] == 404 def test_routes_match_arguments_complex(self): self.route_match({"arguments": {"foo": ""}}) - self.assertEqual(self.get(url='/?foo')['status'], 200, 'complex') - self.assertEqual( - self.get(url='/?blah=blah&foo=')['status'], 200, 'complex 2' - ) - self.assertEqual( - self.get(url='/?&&&foo&&&')['status'], 200, 'complex 3' - ) - self.assertEqual( - self.get(url='/?foo&foo=bar&foo')['status'], 404, 'complex 4' - ) - self.assertEqual( - self.get(url='/?foo=&foo')['status'], 200, 'complex 5' - ) - self.assertEqual( - self.get(url='/?&=&foo&==&')['status'], 200, 'complex 6' - ) - self.assertEqual( - self.get(url='/?&=&bar&==&')['status'], 404, 'complex 7' - ) + assert self.get(url='/?foo')['status'] == 200, 'complex' + assert self.get(url='/?blah=blah&foo=')['status'] == 200, 'complex 2' + assert self.get(url='/?&&&foo&&&')['status'] == 200, 'complex 3' + assert self.get(url='/?foo&foo=bar&foo')['status'] == 404, 'complex 4' + assert self.get(url='/?foo=&foo')['status'] == 200, 'complex 5' + assert self.get(url='/?&=&foo&==&')['status'] == 200, 'complex 6' + assert self.get(url='/?&=&bar&==&')['status'] == 404, 'complex 7' def test_routes_match_arguments_multiple(self): self.route_match({"arguments": {"foo": "bar", "blah": "test"}}) - self.assertEqual(self.get()['status'], 404, 'multiple') - self.assertEqual( - self.get(url='/?foo=bar&blah=test')['status'], 200, 'multiple 2' - ) - self.assertEqual( - self.get(url='/?foo=bar&blah')['status'], 404, 'multiple 3' - ) - self.assertEqual( - self.get(url='/?foo=bar&blah=tes')['status'], 404, 'multiple 4' - ) - self.assertEqual( - self.get(url='/?foo=b%61r&bl%61h=t%65st')['status'], - 200, - 'multiple 5', - ) + assert self.get()['status'] == 404, 'multiple' + assert ( + self.get(url='/?foo=bar&blah=test')['status'] == 200 + ), 'multiple 2' + assert self.get(url='/?foo=bar&blah')['status'] == 404, 'multiple 3' + assert ( + self.get(url='/?foo=bar&blah=tes')['status'] == 404 + ), 'multiple 4' + assert ( + self.get(url='/?foo=b%61r&bl%61h=t%65st')['status'] == 200 + ), 'multiple 5' def test_routes_match_arguments_multiple_rules(self): self.route_match({"arguments": {"foo": ["bar", "blah"]}}) - self.assertEqual(self.get()['status'], 404, 'rules') - self.assertEqual(self.get(url='/?foo=bar')['status'], 200, 'rules 2') - self.assertEqual(self.get(url='/?foo=blah')['status'], 200, 'rules 3') - self.assertEqual( - self.get(url='/?foo=blah&foo=bar&foo=blah')['status'], - 200, - 'rules 4', - ) - self.assertEqual( - self.get(url='/?foo=blah&foo=bar&foo=')['status'], 404, 'rules 5' - ) + assert self.get()['status'] == 404, 'rules' + assert self.get(url='/?foo=bar')['status'] == 200, 'rules 2' + assert self.get(url='/?foo=blah')['status'] == 200, 'rules 3' + assert ( + self.get(url='/?foo=blah&foo=bar&foo=blah')['status'] == 200 + ), 'rules 4' + assert ( + self.get(url='/?foo=blah&foo=bar&foo=')['status'] == 404 + ), 'rules 5' def test_routes_match_arguments_array(self): self.route_match( @@ -1398,27 +1203,23 @@ class TestRouting(TestApplicationProto): } ) - self.assertEqual(self.get()['status'], 404, 'arr') - self.assertEqual(self.get(url='/?var1=val123')['status'], 200, 'arr 2') - self.assertEqual(self.get(url='/?var2=val2')['status'], 200, 'arr 3') - self.assertEqual(self.get(url='/?var3=bar')['status'], 200, 'arr 4') - self.assertEqual(self.get(url='/?var1=bar')['status'], 404, 'arr 5') - self.assertEqual( - self.get(url='/?var1=bar&var4=foo')['status'], 200, 'arr 6' - ) + assert self.get()['status'] == 404, 'arr' + assert self.get(url='/?var1=val123')['status'] == 200, 'arr 2' + assert self.get(url='/?var2=val2')['status'] == 200, 'arr 3' + assert self.get(url='/?var3=bar')['status'] == 200, 'arr 4' + assert self.get(url='/?var1=bar')['status'] == 404, 'arr 5' + assert self.get(url='/?var1=bar&var4=foo')['status'] == 200, 'arr 6' - self.assertIn( - 'success', - self.conf_delete('routes/0/match/arguments/1'), - 'match arguments array configure 2', - ) + assert 'success' in self.conf_delete( + 'routes/0/match/arguments/1' + ), 'match arguments array configure 2' - self.assertEqual(self.get(url='/?var2=val2')['status'], 404, 'arr 7') - self.assertEqual(self.get(url='/?var3=foo')['status'], 200, 'arr 8') + assert self.get(url='/?var2=val2')['status'] == 404, 'arr 7' + assert self.get(url='/?var3=foo')['status'] == 200, 'arr 8' def test_routes_match_arguments_invalid(self): # TODO remove it after controller fixed - self.skip_alerts.append(r'failed to apply new conf') + skip_alert(r'failed to apply new conf') self.route_match_invalid({"arguments": ["var"]}) self.route_match_invalid({"arguments": [{"var1": {}}]}) @@ -1434,7 +1235,7 @@ class TestRouting(TestApplicationProto): def test_routes_match_cookies(self): self.route_match({"cookies": {"foO": "bar"}}) - self.assertEqual(self.get()['status'], 404, 'cookie') + assert self.get()['status'] == 404, 'cookie' self.cookie('foO=bar', 200) self.cookie('foO=bar;1', 200) self.cookie(['foO=bar', 'blah=blah'], 200) @@ -1446,10 +1247,10 @@ class TestRouting(TestApplicationProto): def test_routes_match_cookies_empty(self): self.route_match({"cookies": {}}) - self.assertEqual(self.get()['status'], 200, 'cookies empty') + assert self.get()['status'] == 200, 'cookies empty' self.route_match({"cookies": []}) - self.assertEqual(self.get()['status'], 200, 'cookies empty 2') + assert self.get()['status'] == 200, 'cookies empty 2' def test_routes_match_cookies_invalid(self): self.route_match_invalid({"cookies": ["var"]}) @@ -1458,7 +1259,7 @@ class TestRouting(TestApplicationProto): def test_routes_match_cookies_multiple(self): self.route_match({"cookies": {"foo": "bar", "blah": "blah"}}) - self.assertEqual(self.get()['status'], 404, 'multiple') + assert self.get()['status'] == 404, 'multiple' self.cookie('foo=bar; blah=blah', 200) self.cookie(['foo=bar', 'blah=blah'], 200) self.cookie(['foo=bar; blah', 'blah'], 404) @@ -1474,12 +1275,12 @@ class TestRouting(TestApplicationProto): def test_routes_match_cookies_multiple_rules(self): self.route_match({"cookies": {"blah": ["test", "blah"]}}) - self.assertEqual(self.get()['status'], 404, 'multiple rules') + assert self.get()['status'] == 404, 'multiple rules' self.cookie('blah=test', 200) self.cookie('blah=blah', 200) self.cookie(['blah=blah', 'blah=test', 'blah=blah'], 200) self.cookie(['blah=blah; blah=test', 'blah=blah'], 200) - self.cookie(['blah=blah', 'blah'], 200) # invalid cookie + self.cookie(['blah=blah', 'blah'], 200) # invalid cookie def test_routes_match_cookies_array(self): self.route_match( @@ -1493,7 +1294,7 @@ class TestRouting(TestApplicationProto): } ) - self.assertEqual(self.get()['status'], 404, 'cookies array') + assert self.get()['status'] == 404, 'cookies array' self.cookie('var1=val123', 200) self.cookie('var2=val2', 200) self.cookie(' var2=val2 ', 200) @@ -1503,11 +1304,9 @@ class TestRouting(TestApplicationProto): self.cookie('var1=bar; var4=foo;', 200) self.cookie(['var1=bar', 'var4=foo'], 200) - self.assertIn( - 'success', - self.conf_delete('routes/0/match/cookies/1'), - 'match cookies array configure 2', - ) + assert 'success' in self.conf_delete( + 'routes/0/match/cookies/1' + ), 'match cookies array configure 2' self.cookie('var2=val2', 404) self.cookie('var3=foo', 200) @@ -1535,22 +1334,22 @@ class TestRouting(TestApplicationProto): sock2, port2 = sock_port() self.route_match({"source": "127.0.0.1:" + str(port)}) - self.assertEqual(self.get(sock=sock)['status'], 200, 'exact') - self.assertEqual(self.get(sock=sock2)['status'], 404, 'exact 2') + assert self.get(sock=sock)['status'] == 200, 'exact' + assert self.get(sock=sock2)['status'] == 404, 'exact 2' sock, port = sock_port() sock2, port2 = sock_port() self.route_match({"source": "!127.0.0.1:" + str(port)}) - self.assertEqual(self.get(sock=sock)['status'], 404, 'negative') - self.assertEqual(self.get(sock=sock2)['status'], 200, 'negative 2') + assert self.get(sock=sock)['status'] == 404, 'negative' + assert self.get(sock=sock2)['status'] == 200, 'negative 2' sock, port = sock_port() sock2, port2 = sock_port() self.route_match({"source": ["*:" + str(port), "!127.0.0.1"]}) - self.assertEqual(self.get(sock=sock)['status'], 404, 'negative 3') - self.assertEqual(self.get(sock=sock2)['status'], 404, 'negative 4') + assert self.get(sock=sock)['status'] == 404, 'negative 3' + assert self.get(sock=sock2)['status'] == 404, 'negative 4' sock, port = sock_port() sock2, port2 = sock_port() @@ -1558,8 +1357,8 @@ class TestRouting(TestApplicationProto): self.route_match( {"source": "127.0.0.1:" + str(port) + "-" + str(port)} ) - self.assertEqual(self.get(sock=sock)['status'], 200, 'range single') - self.assertEqual(self.get(sock=sock2)['status'], 404, 'range single 2') + assert self.get(sock=sock)['status'] == 200, 'range single' + assert self.get(sock=sock2)['status'] == 404, 'range single 2' socks = [ sock_port(), @@ -1578,11 +1377,11 @@ class TestRouting(TestApplicationProto): + str(socks[3][1]) # fourth port number } ) - self.assertEqual(self.get(sock=socks[0][0])['status'], 404, 'range') - self.assertEqual(self.get(sock=socks[1][0])['status'], 200, 'range 2') - self.assertEqual(self.get(sock=socks[2][0])['status'], 200, 'range 3') - self.assertEqual(self.get(sock=socks[3][0])['status'], 200, 'range 4') - self.assertEqual(self.get(sock=socks[4][0])['status'], 404, 'range 5') + assert self.get(sock=socks[0][0])['status'] == 404, 'range' + assert self.get(sock=socks[1][0])['status'] == 200, 'range 2' + assert self.get(sock=socks[2][0])['status'] == 200, 'range 3' + assert self.get(sock=socks[3][0])['status'] == 200, 'range 4' + assert self.get(sock=socks[4][0])['status'] == 404, 'range 5' socks = [ sock_port(), @@ -1599,218 +1398,194 @@ class TestRouting(TestApplicationProto): ] } ) - self.assertEqual(self.get(sock=socks[0][0])['status'], 200, 'array') - self.assertEqual(self.get(sock=socks[1][0])['status'], 404, 'array 2') - self.assertEqual(self.get(sock=socks[2][0])['status'], 200, 'array 3') + assert self.get(sock=socks[0][0])['status'] == 200, 'array' + assert self.get(sock=socks[1][0])['status'] == 404, 'array 2' + assert self.get(sock=socks[2][0])['status'] == 200, 'array 3' def test_routes_source_addr(self): - self.assertIn( - 'success', - self.conf( - { - "*:7080": {"pass": "routes"}, - "[::1]:7081": {"pass": "routes"}, - }, - 'listeners', - ), - 'source listeners configure', - ) + assert 'success' in self.conf( + {"*:7080": {"pass": "routes"}, "[::1]:7081": {"pass": "routes"},}, + 'listeners', + ), 'source listeners configure' def get_ipv6(): return self.get(sock_type='ipv6', port=7081) self.route_match({"source": "127.0.0.1"}) - self.assertEqual(self.get()['status'], 200, 'exact') - self.assertEqual(get_ipv6()['status'], 404, 'exact ipv6') + assert self.get()['status'] == 200, 'exact' + assert get_ipv6()['status'] == 404, 'exact ipv6' self.route_match({"source": ["127.0.0.1"]}) - self.assertEqual(self.get()['status'], 200, 'exact 2') - self.assertEqual(get_ipv6()['status'], 404, 'exact 2 ipv6') + assert self.get()['status'] == 200, 'exact 2' + assert get_ipv6()['status'] == 404, 'exact 2 ipv6' self.route_match({"source": "!127.0.0.1"}) - self.assertEqual(self.get()['status'], 404, 'exact neg') - self.assertEqual(get_ipv6()['status'], 200, 'exact neg ipv6') + assert self.get()['status'] == 404, 'exact neg' + assert get_ipv6()['status'] == 200, 'exact neg ipv6' self.route_match({"source": "127.0.0.2"}) - self.assertEqual(self.get()['status'], 404, 'exact 3') - self.assertEqual(get_ipv6()['status'], 404, 'exact 3 ipv6') + assert self.get()['status'] == 404, 'exact 3' + assert get_ipv6()['status'] == 404, 'exact 3 ipv6' self.route_match({"source": "127.0.0.1-127.0.0.1"}) - self.assertEqual(self.get()['status'], 200, 'range single') - self.assertEqual(get_ipv6()['status'], 404, 'range single ipv6') + assert self.get()['status'] == 200, 'range single' + assert get_ipv6()['status'] == 404, 'range single ipv6' self.route_match({"source": "127.0.0.2-127.0.0.2"}) - self.assertEqual(self.get()['status'], 404, 'range single 2') - self.assertEqual(get_ipv6()['status'], 404, 'range single 2 ipv6') + assert self.get()['status'] == 404, 'range single 2' + assert get_ipv6()['status'] == 404, 'range single 2 ipv6' self.route_match({"source": "127.0.0.2-127.0.0.3"}) - self.assertEqual(self.get()['status'], 404, 'range') - self.assertEqual(get_ipv6()['status'], 404, 'range ipv6') + assert self.get()['status'] == 404, 'range' + assert get_ipv6()['status'] == 404, 'range ipv6' self.route_match({"source": "127.0.0.1-127.0.0.2"}) - self.assertEqual(self.get()['status'], 200, 'range 2') - self.assertEqual(get_ipv6()['status'], 404, 'range 2 ipv6') + assert self.get()['status'] == 200, 'range 2' + assert get_ipv6()['status'] == 404, 'range 2 ipv6' self.route_match({"source": "127.0.0.0-127.0.0.2"}) - self.assertEqual(self.get()['status'], 200, 'range 3') - self.assertEqual(get_ipv6()['status'], 404, 'range 3 ipv6') + assert self.get()['status'] == 200, 'range 3' + assert get_ipv6()['status'] == 404, 'range 3 ipv6' self.route_match({"source": "127.0.0.0-127.0.0.1"}) - self.assertEqual(self.get()['status'], 200, 'range 4') - self.assertEqual(get_ipv6()['status'], 404, 'range 4 ipv6') + assert self.get()['status'] == 200, 'range 4' + assert get_ipv6()['status'] == 404, 'range 4 ipv6' self.route_match({"source": "126.0.0.0-127.0.0.0"}) - self.assertEqual(self.get()['status'], 404, 'range 5') - self.assertEqual(get_ipv6()['status'], 404, 'range 5 ipv6') + assert self.get()['status'] == 404, 'range 5' + assert get_ipv6()['status'] == 404, 'range 5 ipv6' self.route_match({"source": "126.126.126.126-127.0.0.2"}) - self.assertEqual(self.get()['status'], 200, 'range 6') - self.assertEqual(get_ipv6()['status'], 404, 'range 6 ipv6') + assert self.get()['status'] == 200, 'range 6' + assert get_ipv6()['status'] == 404, 'range 6 ipv6' def test_routes_source_ipv6(self): - self.assertIn( - 'success', - self.conf( - { - "[::1]:7080": {"pass": "routes"}, - "127.0.0.1:7081": {"pass": "routes"}, - }, - 'listeners', - ), - 'source listeners configure', - ) + assert 'success' in self.conf( + { + "[::1]:7080": {"pass": "routes"}, + "127.0.0.1:7081": {"pass": "routes"}, + }, + 'listeners', + ), 'source listeners configure' self.route_match({"source": "::1"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, 'exact') - self.assertEqual(self.get(port=7081)['status'], 404, 'exact ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, 'exact' + assert self.get(port=7081)['status'] == 404, 'exact ipv4' self.route_match({"source": ["::1"]}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, 'exact 2') - self.assertEqual(self.get(port=7081)['status'], 404, 'exact 2 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, 'exact 2' + assert self.get(port=7081)['status'] == 404, 'exact 2 ipv4' self.route_match({"source": "!::1"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 404, 'exact neg') - self.assertEqual(self.get(port=7081)['status'], 200, 'exact neg ipv4') + assert self.get(sock_type='ipv6')['status'] == 404, 'exact neg' + assert self.get(port=7081)['status'] == 200, 'exact neg ipv4' self.route_match({"source": "::2"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 404, 'exact 3') - self.assertEqual(self.get(port=7081)['status'], 404, 'exact 3 ipv4') + assert self.get(sock_type='ipv6')['status'] == 404, 'exact 3' + assert self.get(port=7081)['status'] == 404, 'exact 3 ipv4' self.route_match({"source": "::1-::1"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, 'range') - self.assertEqual(self.get(port=7081)['status'], 404, 'range ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, 'range' + assert self.get(port=7081)['status'] == 404, 'range ipv4' self.route_match({"source": "::2-::2"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 404, 'range 2') - self.assertEqual(self.get(port=7081)['status'], 404, 'range 2 ipv4') + assert self.get(sock_type='ipv6')['status'] == 404, 'range 2' + assert self.get(port=7081)['status'] == 404, 'range 2 ipv4' self.route_match({"source": "::2-::3"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 404, 'range 3') - self.assertEqual(self.get(port=7081)['status'], 404, 'range 3 ipv4') + assert self.get(sock_type='ipv6')['status'] == 404, 'range 3' + assert self.get(port=7081)['status'] == 404, 'range 3 ipv4' self.route_match({"source": "::1-::2"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, 'range 4') - self.assertEqual(self.get(port=7081)['status'], 404, 'range 4 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, 'range 4' + assert self.get(port=7081)['status'] == 404, 'range 4 ipv4' self.route_match({"source": "::0-::2"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, 'range 5') - self.assertEqual(self.get(port=7081)['status'], 404, 'range 5 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, 'range 5' + assert self.get(port=7081)['status'] == 404, 'range 5 ipv4' self.route_match({"source": "::0-::1"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, 'range 6') - self.assertEqual(self.get(port=7081)['status'], 404, 'range 6 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, 'range 6' + assert self.get(port=7081)['status'] == 404, 'range 6 ipv4' def test_routes_source_cidr(self): - self.assertIn( - 'success', - self.conf( - { - "*:7080": {"pass": "routes"}, - "[::1]:7081": {"pass": "routes"}, - }, - 'listeners', - ), - 'source listeners configure', - ) + assert 'success' in self.conf( + {"*:7080": {"pass": "routes"}, "[::1]:7081": {"pass": "routes"},}, + 'listeners', + ), 'source listeners configure' def get_ipv6(): return self.get(sock_type='ipv6', port=7081) self.route_match({"source": "127.0.0.1/32"}) - self.assertEqual(self.get()['status'], 200, '32') - self.assertEqual(get_ipv6()['status'], 404, '32 ipv6') + assert self.get()['status'] == 200, '32' + assert get_ipv6()['status'] == 404, '32 ipv6' self.route_match({"source": "127.0.0.0/32"}) - self.assertEqual(self.get()['status'], 404, '32 2') - self.assertEqual(get_ipv6()['status'], 404, '32 2 ipv6') + assert self.get()['status'] == 404, '32 2' + assert get_ipv6()['status'] == 404, '32 2 ipv6' self.route_match({"source": "127.0.0.0/31"}) - self.assertEqual(self.get()['status'], 200, '31') - self.assertEqual(get_ipv6()['status'], 404, '31 ipv6') + assert self.get()['status'] == 200, '31' + assert get_ipv6()['status'] == 404, '31 ipv6' self.route_match({"source": "0.0.0.0/1"}) - self.assertEqual(self.get()['status'], 200, '1') - self.assertEqual(get_ipv6()['status'], 404, '1 ipv6') + assert self.get()['status'] == 200, '1' + assert get_ipv6()['status'] == 404, '1 ipv6' self.route_match({"source": "0.0.0.0/0"}) - self.assertEqual(self.get()['status'], 200, '0') - self.assertEqual(get_ipv6()['status'], 404, '0 ipv6') + assert self.get()['status'] == 200, '0' + assert get_ipv6()['status'] == 404, '0 ipv6' def test_routes_source_cidr_ipv6(self): - self.assertIn( - 'success', - self.conf( - { - "[::1]:7080": {"pass": "routes"}, - "127.0.0.1:7081": {"pass": "routes"}, - }, - 'listeners', - ), - 'source listeners configure', - ) + assert 'success' in self.conf( + { + "[::1]:7080": {"pass": "routes"}, + "127.0.0.1:7081": {"pass": "routes"}, + }, + 'listeners', + ), 'source listeners configure' self.route_match({"source": "::1/128"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, '128') - self.assertEqual(self.get(port=7081)['status'], 404, '128 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, '128' + assert self.get(port=7081)['status'] == 404, '128 ipv4' self.route_match({"source": "::0/128"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 404, '128 2') - self.assertEqual(self.get(port=7081)['status'], 404, '128 ipv4') + assert self.get(sock_type='ipv6')['status'] == 404, '128 2' + assert self.get(port=7081)['status'] == 404, '128 ipv4' self.route_match({"source": "::0/127"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, '127') - self.assertEqual(self.get(port=7081)['status'], 404, '127 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, '127' + assert self.get(port=7081)['status'] == 404, '127 ipv4' self.route_match({"source": "::0/32"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, '32') - self.assertEqual(self.get(port=7081)['status'], 404, '32 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, '32' + assert self.get(port=7081)['status'] == 404, '32 ipv4' self.route_match({"source": "::0/1"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, '1') - self.assertEqual(self.get(port=7081)['status'], 404, '1 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, '1' + assert self.get(port=7081)['status'] == 404, '1 ipv4' self.route_match({"source": "::/0"}) - self.assertEqual(self.get(sock_type='ipv6')['status'], 200, '0') - self.assertEqual(self.get(port=7081)['status'], 404, '0 ipv4') + assert self.get(sock_type='ipv6')['status'] == 200, '0' + assert self.get(port=7081)['status'] == 404, '0 ipv4' def test_routes_source_unix(self): - addr = self.testdir + '/sock' + addr = self.temp_dir + '/sock' - self.assertIn( - 'success', - self.conf({"unix:" + addr: {"pass": "routes"}}, 'listeners'), - 'source listeners configure', - ) + assert 'success' in self.conf( + {"unix:" + addr: {"pass": "routes"}}, 'listeners' + ), 'source listeners configure' self.route_match({"source": "!0.0.0.0/0"}) - self.assertEqual( - self.get(sock_type='unix', addr=addr)['status'], 200, 'unix ipv4' - ) + assert ( + self.get(sock_type='unix', addr=addr)['status'] == 200 + ), 'unix ipv4' self.route_match({"source": "!::/0"}) - self.assertEqual( - self.get(sock_type='unix', addr=addr)['status'], 200, 'unix ipv6' - ) + assert ( + self.get(sock_type='unix', addr=addr)['status'] == 200 + ), 'unix ipv6' def test_routes_match_source(self): self.route_match({"source": "::"}) @@ -1863,7 +1638,7 @@ class TestRouting(TestApplicationProto): } ) self.route_match({"source": "*:0-65535"}) - self.assertEqual(self.get()['status'], 200, 'source any') + assert self.get()['status'] == 200, 'source any' def test_routes_match_source_invalid(self): self.route_match_invalid({"source": "127"}) @@ -1888,104 +1663,84 @@ class TestRouting(TestApplicationProto): self.route_match_invalid({"source": "*:65536"}) def test_routes_match_destination(self): - self.assertIn( - 'success', - self.conf( - {"*:7080": {"pass": "routes"}, "*:7081": {"pass": "routes"}}, - 'listeners', - ), - 'listeners configure', - ) + assert 'success' in self.conf( + {"*:7080": {"pass": "routes"}, "*:7081": {"pass": "routes"}}, + 'listeners', + ), 'listeners configure' self.route_match({"destination": "*:7080"}) - self.assertEqual(self.get()['status'], 200, 'dest') - self.assertEqual(self.get(port=7081)['status'], 404, 'dest 2') + assert self.get()['status'] == 200, 'dest' + assert self.get(port=7081)['status'] == 404, 'dest 2' self.route_match({"destination": ["127.0.0.1:7080"]}) - self.assertEqual(self.get()['status'], 200, 'dest 3') - self.assertEqual(self.get(port=7081)['status'], 404, 'dest 4') + assert self.get()['status'] == 200, 'dest 3' + assert self.get(port=7081)['status'] == 404, 'dest 4' self.route_match({"destination": "!*:7080"}) - self.assertEqual(self.get()['status'], 404, 'dest neg') - self.assertEqual(self.get(port=7081)['status'], 200, 'dest neg 2') + assert self.get()['status'] == 404, 'dest neg' + assert self.get(port=7081)['status'] == 200, 'dest neg 2' self.route_match({"destination": ['!*:7080', '!*:7081']}) - self.assertEqual(self.get()['status'], 404, 'dest neg 3') - self.assertEqual(self.get(port=7081)['status'], 404, 'dest neg 4') + assert self.get()['status'] == 404, 'dest neg 3' + assert self.get(port=7081)['status'] == 404, 'dest neg 4' self.route_match({"destination": ['!*:7081', '!*:7082']}) - self.assertEqual(self.get()['status'], 200, 'dest neg 5') + assert self.get()['status'] == 200, 'dest neg 5' self.route_match({"destination": ['*:7080', '!*:7080']}) - self.assertEqual(self.get()['status'], 404, 'dest neg 6') + assert self.get()['status'] == 404, 'dest neg 6' self.route_match( {"destination": ['127.0.0.1:7080', '*:7081', '!*:7080']} ) - self.assertEqual(self.get()['status'], 404, 'dest neg 7') - self.assertEqual(self.get(port=7081)['status'], 200, 'dest neg 8') + assert self.get()['status'] == 404, 'dest neg 7' + assert self.get(port=7081)['status'] == 200, 'dest neg 8' self.route_match({"destination": ['!*:7081', '!*:7082', '*:7083']}) - self.assertEqual(self.get()['status'], 404, 'dest neg 9') + assert self.get()['status'] == 404, 'dest neg 9' self.route_match( {"destination": ['*:7081', '!127.0.0.1:7080', '*:7080']} ) - self.assertEqual(self.get()['status'], 404, 'dest neg 10') - self.assertEqual(self.get(port=7081)['status'], 200, 'dest neg 11') + assert self.get()['status'] == 404, 'dest neg 10' + assert self.get(port=7081)['status'] == 200, 'dest neg 11' - self.assertIn( - 'success', - self.conf_delete('routes/0/match/destination/0'), - 'remove destination rule', - ) - self.assertEqual(self.get()['status'], 404, 'dest neg 12') - self.assertEqual(self.get(port=7081)['status'], 404, 'dest neg 13') + assert 'success' in self.conf_delete( + 'routes/0/match/destination/0' + ), 'remove destination rule' + assert self.get()['status'] == 404, 'dest neg 12' + assert self.get(port=7081)['status'] == 404, 'dest neg 13' - self.assertIn( - 'success', - self.conf_delete('routes/0/match/destination/0'), - 'remove destination rule 2', - ) - self.assertEqual(self.get()['status'], 200, 'dest neg 14') - self.assertEqual(self.get(port=7081)['status'], 404, 'dest neg 15') + assert 'success' in self.conf_delete( + 'routes/0/match/destination/0' + ), 'remove destination rule 2' + assert self.get()['status'] == 200, 'dest neg 14' + assert self.get(port=7081)['status'] == 404, 'dest neg 15' - self.assertIn( - 'success', - self.conf_post("\"!127.0.0.1\"", 'routes/0/match/destination'), - 'add destination rule', - ) - self.assertEqual(self.get()['status'], 404, 'dest neg 16') - self.assertEqual(self.get(port=7081)['status'], 404, 'dest neg 17') + assert 'success' in self.conf_post( + "\"!127.0.0.1\"", 'routes/0/match/destination' + ), 'add destination rule' + assert self.get()['status'] == 404, 'dest neg 16' + assert self.get(port=7081)['status'] == 404, 'dest neg 17' def test_routes_match_destination_proxy(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "routes/first"}, - "*:7081": {"pass": "routes/second"}, - }, - "routes": { - "first": [ - {"action": {"proxy": "http://127.0.0.1:7081"}} - ], - "second": [ - { - "match": {"destination": ["127.0.0.1:7081"]}, - "action": {"return": 200}, - } - ], - }, - "applications": {}, - } - ), - 'proxy configure', - ) - - self.assertEqual(self.get()['status'], 200, 'proxy') - + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "routes/first"}, + "*:7081": {"pass": "routes/second"}, + }, + "routes": { + "first": [{"action": {"proxy": "http://127.0.0.1:7081"}}], + "second": [ + { + "match": {"destination": ["127.0.0.1:7081"]}, + "action": {"return": 200}, + } + ], + }, + "applications": {}, + } + ), 'proxy configure' -if __name__ == '__main__': - TestRouting.main() + assert self.get()['status'] == 200, 'proxy' diff --git a/test/test_routing_tls.py b/test/test_routing_tls.py index a9b8f88d..76cfb485 100644 --- a/test/test_routing_tls.py +++ b/test/test_routing_tls.py @@ -7,36 +7,22 @@ class TestRoutingTLS(TestApplicationTLS): def test_routes_match_scheme_tls(self): self.certificate() - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "routes"}, - "*:7081": { - "pass": "routes", - "tls": {"certificate": 'default'}, - }, + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "routes"}, + "*:7081": { + "pass": "routes", + "tls": {"certificate": 'default'}, }, - "routes": [ - { - "match": {"scheme": "http"}, - "action": {"return": 200}, - }, - { - "match": {"scheme": "https"}, - "action": {"return": 201}, - }, - ], - "applications": {}, - } - ), - 'scheme configure', - ) + }, + "routes": [ + {"match": {"scheme": "http"}, "action": {"return": 200}}, + {"match": {"scheme": "https"}, "action": {"return": 201}}, + ], + "applications": {}, + } + ), 'scheme configure' - self.assertEqual(self.get()['status'], 200, 'http') - self.assertEqual(self.get_ssl(port=7081)['status'], 201, 'https') - - -if __name__ == '__main__': - TestRoutingTLS.main() + assert self.get()['status'] == 200, 'http' + assert self.get_ssl(port=7081)['status'] == 201, 'https' diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index 4709df6c..bdd1afb9 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -1,6 +1,8 @@ -import unittest +import pytest +import re from unit.applications.lang.ruby import TestApplicationRuby +from conftest import skip_alert class TestRubyApplication(TestApplicationRuby): @@ -21,173 +23,151 @@ class TestRubyApplication(TestApplicationRuby): body=body, ) - self.assertEqual(resp['status'], 200, 'status') + assert resp['status'] == 200, 'status' headers = resp['headers'] header_server = headers.pop('Server') - self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header') - self.assertEqual( - headers.pop('Server-Software'), - header_server, - 'server software header', - ) + assert re.search(r'Unit/[\d\.]+', header_server), 'server header' + assert ( + headers.pop('Server-Software') == header_server + ), 'server software header' date = headers.pop('Date') - self.assertEqual(date[-4:], ' GMT', 'date header timezone') - self.assertLess( - abs(self.date_to_sec_epoch(date) - self.sec_epoch()), - 5, - 'date header', - ) - - self.assertDictEqual( - headers, - { - 'Connection': 'close', - 'Content-Length': str(len(body)), - 'Content-Type': 'text/html', - 'Request-Method': 'POST', - 'Request-Uri': '/', - 'Http-Host': 'localhost', - 'Server-Protocol': 'HTTP/1.1', - 'Custom-Header': 'blah', - 'Rack-Version': '13', - 'Rack-Url-Scheme': 'http', - 'Rack-Multithread': 'false', - 'Rack-Multiprocess': 'true', - 'Rack-Run-Once': 'false', - 'Rack-Hijack-Q': 'false', - 'Rack-Hijack': '', - 'Rack-Hijack-IO': '', - }, - 'headers', - ) - self.assertEqual(resp['body'], body, 'body') + assert date[-4:] == ' GMT', 'date header timezone' + assert ( + abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5 + ), 'date header' + + assert headers == { + 'Connection': 'close', + 'Content-Length': str(len(body)), + 'Content-Type': 'text/html', + 'Request-Method': 'POST', + 'Request-Uri': '/', + 'Http-Host': 'localhost', + 'Server-Protocol': 'HTTP/1.1', + 'Custom-Header': 'blah', + 'Rack-Version': '13', + 'Rack-Url-Scheme': 'http', + 'Rack-Multithread': 'false', + 'Rack-Multiprocess': 'true', + 'Rack-Run-Once': 'false', + 'Rack-Hijack-Q': 'false', + 'Rack-Hijack': '', + 'Rack-Hijack-IO': '', + }, 'headers' + assert resp['body'] == body, 'body' def test_ruby_application_query_string(self): self.load('query_string') resp = self.get(url='/?var1=val1&var2=val2') - self.assertEqual( - resp['headers']['Query-String'], - 'var1=val1&var2=val2', - 'Query-String header', - ) + assert ( + resp['headers']['Query-String'] == 'var1=val1&var2=val2' + ), 'Query-String header' def test_ruby_application_query_string_empty(self): self.load('query_string') resp = self.get(url='/?') - self.assertEqual(resp['status'], 200, 'query string empty status') - self.assertEqual( - resp['headers']['Query-String'], '', 'query string empty' - ) + assert resp['status'] == 200, 'query string empty status' + assert resp['headers']['Query-String'] == '', 'query string empty' def test_ruby_application_query_string_absent(self): self.load('query_string') resp = self.get() - self.assertEqual(resp['status'], 200, 'query string absent status') - self.assertEqual( - resp['headers']['Query-String'], '', 'query string absent' - ) + assert resp['status'] == 200, 'query string absent status' + assert resp['headers']['Query-String'] == '', 'query string absent' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_ruby_application_server_port(self): self.load('server_port') - self.assertEqual( - self.get()['headers']['Server-Port'], '7080', 'Server-Port header' - ) + assert ( + self.get()['headers']['Server-Port'] == '7080' + ), 'Server-Port header' def test_ruby_application_status_int(self): self.load('status_int') - self.assertEqual(self.get()['status'], 200, 'status int') + assert self.get()['status'] == 200, 'status int' def test_ruby_application_input_read_empty(self): self.load('input_read_empty') - self.assertEqual(self.get()['body'], '', 'read empty') + assert self.get()['body'] == '', 'read empty' def test_ruby_application_input_read_parts(self): self.load('input_read_parts') - self.assertEqual( - self.post(body='0123456789')['body'], - '012345678', - 'input read parts', - ) + assert ( + self.post(body='0123456789')['body'] == '012345678' + ), 'input read parts' def test_ruby_application_input_read_buffer(self): self.load('input_read_buffer') - self.assertEqual( - self.post(body='0123456789')['body'], - '0123456789', - 'input read buffer', - ) + assert ( + self.post(body='0123456789')['body'] == '0123456789' + ), 'input read buffer' def test_ruby_application_input_read_buffer_not_empty(self): self.load('input_read_buffer_not_empty') - self.assertEqual( - self.post(body='0123456789')['body'], - '0123456789', - 'input read buffer not empty', - ) + assert ( + self.post(body='0123456789')['body'] == '0123456789' + ), 'input read buffer not empty' def test_ruby_application_input_gets(self): self.load('input_gets') body = '0123456789' - self.assertEqual(self.post(body=body)['body'], body, 'input gets') + assert self.post(body=body)['body'] == body, 'input gets' def test_ruby_application_input_gets_2(self): self.load('input_gets') - self.assertEqual( - self.post(body='01234\n56789\n')['body'], '01234\n', 'input gets 2' - ) + assert ( + self.post(body='01234\n56789\n')['body'] == '01234\n' + ), 'input gets 2' def test_ruby_application_input_gets_all(self): self.load('input_gets_all') body = '\n01234\n56789\n\n' - self.assertEqual(self.post(body=body)['body'], body, 'input gets all') + assert self.post(body=body)['body'] == body, 'input gets all' def test_ruby_application_input_each(self): self.load('input_each') body = '\n01234\n56789\n\n' - self.assertEqual(self.post(body=body)['body'], body, 'input each') + assert self.post(body=body)['body'] == body, 'input each' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_ruby_application_input_rewind(self): self.load('input_rewind') body = '0123456789' - self.assertEqual(self.post(body=body)['body'], body, 'input rewind') + assert self.post(body=body)['body'] == body, 'input rewind' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_ruby_application_syntax_error(self): - self.skip_alerts.extend( - [ - r'Failed to parse rack script', - r'syntax error', - r'new_from_string', - r'parse_file', - ] + skip_alert( + r'Failed to parse rack script', + r'syntax error', + r'new_from_string', + r'parse_file', ) self.load('syntax_error') - self.assertEqual(self.get()['status'], 500, 'syntax error') + assert self.get()['status'] == 500, 'syntax error' def test_ruby_application_errors_puts(self): self.load('errors_puts') @@ -196,10 +176,10 @@ class TestRubyApplication(TestApplicationRuby): self.stop() - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+Error in application'), - 'errors puts', - ) + assert ( + self.wait_for_record(r'\[error\].+Error in application') + is not None + ), 'errors puts' def test_ruby_application_errors_puts_int(self): self.load('errors_puts_int') @@ -208,9 +188,9 @@ class TestRubyApplication(TestApplicationRuby): self.stop() - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+1234567890'), 'errors puts int' - ) + assert ( + self.wait_for_record(r'\[error\].+1234567890') is not None + ), 'errors puts int' def test_ruby_application_errors_write(self): self.load('errors_write') @@ -219,15 +199,15 @@ class TestRubyApplication(TestApplicationRuby): self.stop() - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+Error in application'), - 'errors write', - ) + assert ( + self.wait_for_record(r'\[error\].+Error in application') + is not None + ), 'errors write' def test_ruby_application_errors_write_to_s_custom(self): self.load('errors_write_to_s_custom') - self.assertEqual(self.get()['status'], 200, 'errors write to_s custom') + assert self.get()['status'] == 200, 'errors write to_s custom' def test_ruby_application_errors_write_int(self): self.load('errors_write_int') @@ -236,9 +216,9 @@ class TestRubyApplication(TestApplicationRuby): self.stop() - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+1234567890'), 'errors write int' - ) + assert ( + self.wait_for_record(r'\[error\].+1234567890') is not None + ), 'errors write int' def test_ruby_application_at_exit(self): self.load('at_exit') @@ -249,79 +229,81 @@ class TestRubyApplication(TestApplicationRuby): self.stop() - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+At exit called\.'), 'at exit' - ) + assert ( + self.wait_for_record(r'\[error\].+At exit called\.') is not None + ), 'at exit' def test_ruby_application_header_custom(self): self.load('header_custom') resp = self.post(body="\ntc=one,two\ntc=three,four,\n\n") - self.assertEqual( - resp['headers']['Custom-Header'], - ['', 'tc=one,two', 'tc=three,four,', '', ''], - 'header custom', - ) + assert resp['headers']['Custom-Header'] == [ + '', + 'tc=one,two', + 'tc=three,four,', + '', + '', + ], 'header custom' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_ruby_application_header_custom_non_printable(self): self.load('header_custom') - self.assertEqual( - self.post(body='\b')['status'], 500, 'header custom non printable' - ) + assert ( + self.post(body='\b')['status'] == 500 + ), 'header custom non printable' def test_ruby_application_header_status(self): self.load('header_status') - self.assertEqual(self.get()['status'], 200, 'header status') + assert self.get()['status'] == 200, 'header status' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_ruby_application_header_rack(self): self.load('header_rack') - self.assertEqual(self.get()['status'], 500, 'header rack') + assert self.get()['status'] == 500, 'header rack' def test_ruby_application_body_empty(self): self.load('body_empty') - self.assertEqual(self.get()['body'], '', 'body empty') + assert self.get()['body'] == '', 'body empty' def test_ruby_application_body_array(self): self.load('body_array') - self.assertEqual(self.get()['body'], '0123456789', 'body array') + assert self.get()['body'] == '0123456789', 'body array' def test_ruby_application_body_large(self): self.load('mirror') body = '0123456789' * 1000 - self.assertEqual(self.post(body=body)['body'], body, 'body large') + assert self.post(body=body)['body'] == body, 'body large' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_ruby_application_body_each_error(self): self.load('body_each_error') - self.assertEqual(self.get()['status'], 500, 'body each error status') + assert self.get()['status'] == 500, 'body each error status' self.stop() - self.assertIsNotNone( - self.wait_for_record(r'\[error\].+Failed to run ruby script'), - 'body each error', - ) + assert ( + self.wait_for_record(r'\[error\].+Failed to run ruby script') + is not None + ), 'body each error' def test_ruby_application_body_file(self): self.load('body_file') - self.assertEqual(self.get()['body'], 'body\n', 'body file') + assert self.get()['body'] == 'body\n', 'body file' def test_ruby_keepalive_body(self): self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' body = '0123456789' * 500 (resp, sock) = self.post( @@ -335,7 +317,7 @@ class TestRubyApplication(TestApplicationRuby): read_timeout=1, ) - self.assertEqual(resp['body'], body, 'keep-alive 1') + assert resp['body'] == body, 'keep-alive 1' body = '0123456789' resp = self.post( @@ -348,31 +330,22 @@ class TestRubyApplication(TestApplicationRuby): body=body, ) - self.assertEqual(resp['body'], body, 'keep-alive 2') + assert resp['body'] == body, 'keep-alive 2' def test_ruby_application_constants(self): self.load('constants') resp = self.get() - self.assertEqual(resp['status'], 200, 'status') + assert resp['status'] == 200, 'status' headers = resp['headers'] - self.assertGreater(len(headers['X-Copyright']), 0, 'RUBY_COPYRIGHT') - self.assertGreater( - len(headers['X-Description']), 0, 'RUBY_DESCRIPTION' - ) - self.assertGreater(len(headers['X-Engine']), 0, 'RUBY_ENGINE') - self.assertGreater( - len(headers['X-Engine-Version']), 0, 'RUBY_ENGINE_VERSION' - ) - self.assertGreater(len(headers['X-Patchlevel']), 0, 'RUBY_PATCHLEVEL') - self.assertGreater(len(headers['X-Platform']), 0, 'RUBY_PLATFORM') - self.assertGreater( - len(headers['X-Release-Date']), 0, 'RUBY_RELEASE_DATE' - ) - self.assertGreater(len(headers['X-Revision']), 0, 'RUBY_REVISION') - self.assertGreater(len(headers['X-Version']), 0, 'RUBY_VERSION') - -if __name__ == '__main__': - TestRubyApplication.main() + assert len(headers['X-Copyright']) > 0, 'RUBY_COPYRIGHT' + assert len(headers['X-Description']) > 0, 'RUBY_DESCRIPTION' + assert len(headers['X-Engine']) > 0, 'RUBY_ENGINE' + assert len(headers['X-Engine-Version']) > 0, 'RUBY_ENGINE_VERSION' + assert len(headers['X-Patchlevel']) > 0, 'RUBY_PATCHLEVEL' + assert len(headers['X-Platform']) > 0, 'RUBY_PLATFORM' + assert len(headers['X-Release-Date']) > 0, 'RUBY_RELEASE_DATE' + assert len(headers['X-Revision']) > 0, 'RUBY_REVISION' + assert len(headers['X-Version']) > 0, 'RUBY_VERSION' diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py index 9bac162e..be20300e 100644 --- a/test/test_ruby_isolation.py +++ b/test/test_ruby_isolation.py @@ -1,9 +1,10 @@ import os +import pytest import shutil -import unittest from unit.applications.lang.ruby import TestApplicationRuby from unit.feature.isolation import TestFeatureIsolation +from conftest import option class TestRubyIsolation(TestApplicationRuby): @@ -12,60 +13,45 @@ class TestRubyIsolation(TestApplicationRuby): isolation = TestFeatureIsolation() @classmethod - def setUpClass(cls, complete_check=True): - unit = super().setUpClass(complete_check=False) + def setup_class(cls, complete_check=True): + unit = super().setup_class(complete_check=False) - TestFeatureIsolation().check(cls.available, unit.testdir) + TestFeatureIsolation().check(cls.available, unit.temp_dir) return unit if not complete_check else unit.complete() - def test_ruby_isolation_rootfs(self): + def test_ruby_isolation_rootfs(self, is_su): isolation_features = self.available['features']['isolation'].keys() if 'mnt' not in isolation_features: - print('requires mnt ns') - raise unittest.SkipTest() + pytest.skip('requires mnt ns') - if not self.is_su: + if not is_su: if 'user' not in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') if not 'unprivileged_userns_clone' in isolation_features: - print('requires unprivileged userns or root') - raise unittest.SkipTest() + pytest.skip('requires unprivileged userns or root') - os.mkdir(self.testdir + '/ruby') + os.mkdir(self.temp_dir + '/ruby') shutil.copytree( - self.current_dir + '/ruby/status_int', - self.testdir + '/ruby/status_int', + option.test_dir + '/ruby/status_int', + self.temp_dir + '/ruby/status_int', ) isolation = { - 'namespaces': {'credential': not self.is_su, 'mount': True}, - 'rootfs': self.testdir, + 'namespaces': {'credential': not is_su, 'mount': True}, + 'rootfs': self.temp_dir, } self.load('status_int', isolation=isolation) - self.assertIn( - 'success', - self.conf( - '"/ruby/status_int/config.ru"', - 'applications/status_int/script', - ), + assert 'success' in self.conf( + '"/ruby/status_int/config.ru"', 'applications/status_int/script', ) - self.assertIn( - 'success', - self.conf( - '"/ruby/status_int"', - 'applications/status_int/working_directory', - ), + assert 'success' in self.conf( + '"/ruby/status_int"', 'applications/status_int/working_directory', ) - self.assertEqual(self.get()['status'], 200, 'status int') - - -if __name__ == '__main__': - TestRubyIsolation.main() + assert self.get()['status'] == 200, 'status int' diff --git a/test/test_settings.py b/test/test_settings.py index 6600358d..59b4a048 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -1,8 +1,9 @@ +import pytest import socket import time -import unittest from unit.applications.lang.python import TestApplicationPython +import re class TestSettings(TestApplicationPython): @@ -32,7 +33,7 @@ Connection: close raw=True, ) - self.assertEqual(resp['status'], 408, 'status header read timeout') + assert resp['status'] == 408, 'status header read timeout' def test_settings_header_read_timeout_update(self): self.load('empty') @@ -83,9 +84,7 @@ Connection: close raw=True, ) - self.assertEqual( - resp['status'], 408, 'status header read timeout update' - ) + assert resp['status'] == 408, 'status header read timeout update' def test_settings_body_read_timeout(self): self.load('empty') @@ -109,7 +108,7 @@ Connection: close resp = self.http(b"""0123456789""", sock=sock, raw=True) - self.assertEqual(resp['status'], 408, 'status body read timeout') + assert resp['status'] == 408, 'status body read timeout' def test_settings_body_read_timeout_update(self): self.load('empty') @@ -144,9 +143,7 @@ Connection: close resp = self.http(b"""6789""", sock=sock, raw=True) - self.assertEqual( - resp['status'], 200, 'status body read timeout update' - ) + assert resp['status'] == 200, 'status body read timeout update' def test_settings_send_timeout(self): self.load('mirror') @@ -155,7 +152,7 @@ Connection: close self.conf({'http': {'send_timeout': 1}}, 'settings') - addr = self.testdir + '/sock' + addr = self.temp_dir + '/sock' self.conf({"unix:" + addr: {'application': 'mirror'}}, 'listeners') @@ -182,13 +179,13 @@ Connection: close sock.close() - self.assertRegex(data, r'200 OK', 'status send timeout') - self.assertLess(len(data), data_len, 'data send timeout') + assert re.search(r'200 OK', data), 'status send timeout' + assert len(data) < data_len, 'data send timeout' def test_settings_idle_timeout(self): self.load('empty') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' self.conf({'http': {'idle_timeout': 2}}, 'settings') @@ -204,17 +201,15 @@ Connection: close headers={'Host': 'localhost', 'Connection': 'close'}, sock=sock ) - self.assertEqual(resp['status'], 408, 'status idle timeout') + assert resp['status'] == 408, 'status idle timeout' def test_settings_max_body_size(self): self.load('empty') self.conf({'http': {'max_body_size': 5}}, 'settings') - self.assertEqual(self.post(body='01234')['status'], 200, 'status size') - self.assertEqual( - self.post(body='012345')['status'], 413, 'status size max' - ) + assert self.post(body='01234')['status'] == 200, 'status size' + assert self.post(body='012345')['status'] == 413, 'status size max' def test_settings_max_body_size_large(self): self.load('mirror') @@ -223,32 +218,26 @@ Connection: close body = '0123456789abcdef' * 4 * 64 * 1024 resp = self.post(body=body, read_buffer_size=1024 * 1024) - self.assertEqual(resp['status'], 200, 'status size 4') - self.assertEqual(resp['body'], body, 'status body 4') + assert resp['status'] == 200, 'status size 4' + assert resp['body'] == body, 'status body 4' body = '0123456789abcdef' * 8 * 64 * 1024 resp = self.post(body=body, read_buffer_size=1024 * 1024) - self.assertEqual(resp['status'], 200, 'status size 8') - self.assertEqual(resp['body'], body, 'status body 8') + assert resp['status'] == 200, 'status size 8' + assert resp['body'] == body, 'status body 8' body = '0123456789abcdef' * 16 * 64 * 1024 resp = self.post(body=body, read_buffer_size=1024 * 1024) - self.assertEqual(resp['status'], 200, 'status size 16') - self.assertEqual(resp['body'], body, 'status body 16') + assert resp['status'] == 200, 'status size 16' + assert resp['body'] == body, 'status body 16' body = '0123456789abcdef' * 32 * 64 * 1024 resp = self.post(body=body, read_buffer_size=1024 * 1024) - self.assertEqual(resp['status'], 200, 'status size 32') - self.assertEqual(resp['body'], body, 'status body 32') + assert resp['status'] == 200, 'status size 32' + assert resp['body'] == body, 'status body 32' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_settings_negative_value(self): - self.assertIn( - 'error', - self.conf({'http': {'max_body_size': -1}}, 'settings'), - 'settings negative value', - ) - - -if __name__ == '__main__': - TestSettings.main() + assert 'error' in self.conf( + {'http': {'max_body_size': -1}}, 'settings' + ), 'settings negative value' diff --git a/test/test_share_fallback.py b/test/test_share_fallback.py index ca5e2678..391066ec 100644 --- a/test/test_share_fallback.py +++ b/test/test_share_fallback.py @@ -1,20 +1,21 @@ import os from unit.applications.proto import TestApplicationProto +from conftest import skip_alert class TestStatic(TestApplicationProto): prerequisites = {} - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - os.makedirs(self.testdir + '/assets/dir') - with open(self.testdir + '/assets/index.html', 'w') as index: + os.makedirs(self.temp_dir + '/assets/dir') + with open(self.temp_dir + '/assets/index.html', 'w') as index: index.write('0123456789') - os.makedirs(self.testdir + '/assets/403') - os.chmod(self.testdir + '/assets/403', 0o000) + os.makedirs(self.temp_dir + '/assets/403') + os.chmod(self.temp_dir + '/assets/403', 0o000) self._load_conf( { @@ -22,48 +23,46 @@ class TestStatic(TestApplicationProto): "*:7080": {"pass": "routes"}, "*:7081": {"pass": "routes"}, }, - "routes": [{"action": {"share": self.testdir + "/assets"}}], + "routes": [{"action": {"share": self.temp_dir + "/assets"}}], "applications": {}, } ) - def tearDown(self): - os.chmod(self.testdir + '/assets/403', 0o777) + def teardown_method(self): + os.chmod(self.temp_dir + '/assets/403', 0o777) - super().tearDown() + super().teardown_method() def action_update(self, conf): - self.assertIn('success', self.conf(conf, 'routes/0/action')) + assert 'success' in self.conf(conf, 'routes/0/action') def test_fallback(self): self.action_update({"share": "/blah"}) - self.assertEqual(self.get()['status'], 404, 'bad path no fallback') + assert self.get()['status'] == 404, 'bad path no fallback' self.action_update({"share": "/blah", "fallback": {"return": 200}}) resp = self.get() - self.assertEqual(resp['status'], 200, 'bad path fallback status') - self.assertEqual(resp['body'], '', 'bad path fallback') + assert resp['status'] == 200, 'bad path fallback status' + assert resp['body'] == '', 'bad path fallback' def test_fallback_valid_path(self): self.action_update( - {"share": self.testdir + "/assets", "fallback": {"return": 200}} + {"share": self.temp_dir + "/assets", "fallback": {"return": 200}} ) resp = self.get() - self.assertEqual(resp['status'], 200, 'fallback status') - self.assertEqual(resp['body'], '0123456789', 'fallback') + assert resp['status'] == 200, 'fallback status' + assert resp['body'] == '0123456789', 'fallback' resp = self.get(url='/403/') - self.assertEqual(resp['status'], 200, 'fallback status 403') - self.assertEqual(resp['body'], '', 'fallback 403') + assert resp['status'] == 200, 'fallback status 403' + assert resp['body'] == '', 'fallback 403' resp = self.post() - self.assertEqual(resp['status'], 200, 'fallback status 405') - self.assertEqual(resp['body'], '', 'fallback 405') + assert resp['status'] == 200, 'fallback status 405' + assert resp['body'] == '', 'fallback 405' - self.assertEqual( - self.get(url='/dir')['status'], 301, 'fallback status 301' - ) + assert self.get(url='/dir')['status'] == 301, 'fallback status 301' def test_fallback_nested(self): self.action_update( @@ -77,62 +76,56 @@ class TestStatic(TestApplicationProto): ) resp = self.get() - self.assertEqual(resp['status'], 200, 'fallback nested status') - self.assertEqual(resp['body'], '', 'fallback nested') + assert resp['status'] == 200, 'fallback nested status' + assert resp['body'] == '', 'fallback nested' def test_fallback_share(self): self.action_update( { "share": "/blah", - "fallback": {"share": self.testdir + "/assets"}, + "fallback": {"share": self.temp_dir + "/assets"}, } ) resp = self.get() - self.assertEqual(resp['status'], 200, 'fallback share status') - self.assertEqual(resp['body'], '0123456789', 'fallback share') + assert resp['status'] == 200, 'fallback share status' + assert resp['body'] == '0123456789', 'fallback share' resp = self.head() - self.assertEqual(resp['status'], 200, 'fallback share status HEAD') - self.assertEqual(resp['body'], '', 'fallback share HEAD') + assert resp['status'] == 200, 'fallback share status HEAD' + assert resp['body'] == '', 'fallback share HEAD' - self.assertEqual( - self.get(url='/dir')['status'], 301, 'fallback share status 301' - ) + assert ( + self.get(url='/dir')['status'] == 301 + ), 'fallback share status 301' def test_fallback_proxy(self): - self.assertIn( - 'success', - self.conf( - [ - { - "match": {"destination": "*:7081"}, - "action": {"return": 200}, - }, - { - "action": { - "share": "/blah", - "fallback": {"proxy": "http://127.0.0.1:7081"}, - } - }, - ], - 'routes', - ), - 'configure fallback proxy route', - ) + assert 'success' in self.conf( + [ + { + "match": {"destination": "*:7081"}, + "action": {"return": 200}, + }, + { + "action": { + "share": "/blah", + "fallback": {"proxy": "http://127.0.0.1:7081"}, + } + }, + ], + 'routes', + ), 'configure fallback proxy route' resp = self.get() - self.assertEqual(resp['status'], 200, 'fallback proxy status') - self.assertEqual(resp['body'], '', 'fallback proxy') + assert resp['status'] == 200, 'fallback proxy status' + assert resp['body'] == '', 'fallback proxy' def test_fallback_proxy_loop(self): - self.skip_alerts.extend( - [ - r'open.*/blah/index.html.*failed', - r'accept.*failed', - r'socket.*failed', - r'new connections are not accepted', - ] + skip_alert( + r'open.*/blah/index.html.*failed', + r'accept.*failed', + r'socket.*failed', + r'new connections are not accepted', ) self.action_update( @@ -140,12 +133,12 @@ class TestStatic(TestApplicationProto): ) self.get(no_recv=True) - self.assertIn('success', self.conf_delete('listeners/*:7081')) + assert 'success' in self.conf_delete('listeners/*:7081') self.get(read_timeout=1) def test_fallback_invalid(self): def check_error(conf): - self.assertIn('error', self.conf(conf, 'routes/0/action')) + assert 'error' in self.conf(conf, 'routes/0/action') check_error({"share": "/blah", "fallback": {}}) check_error({"share": "/blah", "fallback": ""}) @@ -154,7 +147,3 @@ class TestStatic(TestApplicationProto): {"proxy": "http://127.0.0.1:7081", "fallback": {"share": "/blah"}} ) check_error({"fallback": {"share": "/blah"}}) - - -if __name__ == '__main__': - TestStatic.main() diff --git a/test/test_static.py b/test/test_static.py index bee5db28..fc8bb0a9 100644 --- a/test/test_static.py +++ b/test/test_static.py @@ -1,21 +1,23 @@ import os +import pytest import socket -import unittest from unit.applications.proto import TestApplicationProto +from conftest import waitforfiles class TestStatic(TestApplicationProto): prerequisites = {} - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - os.makedirs(self.testdir + '/assets/dir') - with open(self.testdir + '/assets/index.html', 'w') as index, \ - open(self.testdir + '/assets/README', 'w') as readme, \ - open(self.testdir + '/assets/log.log', 'w') as log, \ - open(self.testdir + '/assets/dir/file', 'w') as file: + os.makedirs(self.temp_dir + '/assets/dir') + with open(self.temp_dir + '/assets/index.html', 'w') as index, open( + self.temp_dir + '/assets/README', 'w' + ) as readme, open(self.temp_dir + '/assets/log.log', 'w') as log, open( + self.temp_dir + '/assets/dir/file', 'w' + ) as file: index.write('0123456789') readme.write('readme') log.write('[debug]') @@ -24,7 +26,7 @@ class TestStatic(TestApplicationProto): self._load_conf( { "listeners": {"*:7080": {"pass": "routes"}}, - "routes": [{"action": {"share": self.testdir + "/assets"}}], + "routes": [{"action": {"share": self.temp_dir + "/assets"}}], "settings": { "http": { "static": { @@ -36,123 +38,95 @@ class TestStatic(TestApplicationProto): ) def test_static_index(self): - self.assertEqual( - self.get(url='/index.html')['body'], '0123456789', 'index' - ) - self.assertEqual(self.get(url='/')['body'], '0123456789', 'index 2') - self.assertEqual(self.get(url='//')['body'], '0123456789', 'index 3') - self.assertEqual(self.get(url='/.')['body'], '0123456789', 'index 4') - self.assertEqual(self.get(url='/./')['body'], '0123456789', 'index 5') - self.assertEqual( - self.get(url='/?blah')['body'], '0123456789', 'index vars' - ) - self.assertEqual( - self.get(url='/#blah')['body'], '0123456789', 'index anchor' - ) - self.assertEqual( - self.get(url='/dir/')['status'], 404, 'index not found' - ) + assert self.get(url='/index.html')['body'] == '0123456789', 'index' + assert self.get(url='/')['body'] == '0123456789', 'index 2' + assert self.get(url='//')['body'] == '0123456789', 'index 3' + assert self.get(url='/.')['body'] == '0123456789', 'index 4' + assert self.get(url='/./')['body'] == '0123456789', 'index 5' + assert self.get(url='/?blah')['body'] == '0123456789', 'index vars' + assert self.get(url='/#blah')['body'] == '0123456789', 'index anchor' + assert self.get(url='/dir/')['status'] == 404, 'index not found' resp = self.get(url='/index.html/') - self.assertEqual(resp['status'], 404, 'index not found 2 status') - self.assertEqual( - resp['headers']['Content-Type'], - 'text/html', - 'index not found 2 Content-Type', - ) + assert resp['status'] == 404, 'index not found 2 status' + assert ( + resp['headers']['Content-Type'] == 'text/html' + ), 'index not found 2 Content-Type' def test_static_large_file(self): file_size = 32 * 1024 * 1024 - with open(self.testdir + '/assets/large', 'wb') as f: + with open(self.temp_dir + '/assets/large', 'wb') as f: f.seek(file_size - 1) f.write(b'\0') - self.assertEqual( - len( - self.get(url='/large', read_buffer_size=1024 * 1024)['body'] - ), - file_size, - 'large file', - ) + assert ( + len(self.get(url='/large', read_buffer_size=1024 * 1024)['body']) + == file_size + ), 'large file' def test_static_etag(self): etag = self.get(url='/')['headers']['ETag'] etag_2 = self.get(url='/README')['headers']['ETag'] - self.assertNotEqual(etag, etag_2, 'different ETag') - self.assertEqual( - etag, self.get(url='/')['headers']['ETag'], 'same ETag' - ) + assert etag != etag_2, 'different ETag' + assert etag == self.get(url='/')['headers']['ETag'], 'same ETag' - with open(self.testdir + '/assets/index.html', 'w') as f: + with open(self.temp_dir + '/assets/index.html', 'w') as f: f.write('blah') - self.assertNotEqual( - etag, self.get(url='/')['headers']['ETag'], 'new ETag' - ) + assert etag != self.get(url='/')['headers']['ETag'], 'new ETag' def test_static_redirect(self): resp = self.get(url='/dir') - self.assertEqual(resp['status'], 301, 'redirect status') - self.assertEqual( - resp['headers']['Location'], '/dir/', 'redirect Location' - ) - self.assertNotIn( - 'Content-Type', resp['headers'], 'redirect Content-Type' - ) + assert resp['status'] == 301, 'redirect status' + assert resp['headers']['Location'] == '/dir/', 'redirect Location' + assert 'Content-Type' not in resp['headers'], 'redirect Content-Type' def test_static_space_in_name(self): os.rename( - self.testdir + '/assets/dir/file', - self.testdir + '/assets/dir/fi le', - ) - self.waitforfiles(self.testdir + '/assets/dir/fi le') - self.assertEqual( - self.get(url='/dir/fi le')['body'], 'blah', 'file name' + self.temp_dir + '/assets/dir/file', + self.temp_dir + '/assets/dir/fi le', ) + assert waitforfiles(self.temp_dir + '/assets/dir/fi le') + assert self.get(url='/dir/fi le')['body'] == 'blah', 'file name' - os.rename(self.testdir + '/assets/dir', self.testdir + '/assets/di r') - self.waitforfiles(self.testdir + '/assets/di r/fi le') - self.assertEqual( - self.get(url='/di r/fi le')['body'], 'blah', 'dir name' - ) + os.rename(self.temp_dir + '/assets/dir', self.temp_dir + '/assets/di r') + assert waitforfiles(self.temp_dir + '/assets/di r/fi le') + assert self.get(url='/di r/fi le')['body'] == 'blah', 'dir name' os.rename( - self.testdir + '/assets/di r', self.testdir + '/assets/ di r ' - ) - self.waitforfiles(self.testdir + '/assets/ di r /fi le') - self.assertEqual( - self.get(url='/ di r /fi le')['body'], 'blah', 'dir name enclosing' - ) - - self.assertEqual( - self.get(url='/%20di%20r%20/fi le')['body'], 'blah', 'dir encoded' - ) - self.assertEqual( - self.get(url='/ di r %2Ffi le')['body'], 'blah', 'slash encoded' - ) - self.assertEqual( - self.get(url='/ di r /fi%20le')['body'], 'blah', 'file encoded' - ) - self.assertEqual( - self.get(url='/%20di%20r%20%2Ffi%20le')['body'], 'blah', 'encoded' - ) - self.assertEqual( - self.get(url='/%20%64%69%20%72%20%2F%66%69%20%6C%65')['body'], - 'blah', - 'encoded 2', - ) + self.temp_dir + '/assets/di r', self.temp_dir + '/assets/ di r ' + ) + assert waitforfiles(self.temp_dir + '/assets/ di r /fi le') + assert ( + self.get(url='/ di r /fi le')['body'] == 'blah' + ), 'dir name enclosing' + + assert ( + self.get(url='/%20di%20r%20/fi le')['body'] == 'blah' + ), 'dir encoded' + assert ( + self.get(url='/ di r %2Ffi le')['body'] == 'blah' + ), 'slash encoded' + assert ( + self.get(url='/ di r /fi%20le')['body'] == 'blah' + ), 'file encoded' + assert ( + self.get(url='/%20di%20r%20%2Ffi%20le')['body'] == 'blah' + ), 'encoded' + assert ( + self.get(url='/%20%64%69%20%72%20%2F%66%69%20%6C%65')['body'] + == 'blah' + ), 'encoded 2' os.rename( - self.testdir + '/assets/ di r /fi le', - self.testdir + '/assets/ di r / fi le ', - ) - self.waitforfiles(self.testdir + '/assets/ di r / fi le ') - self.assertEqual( - self.get(url='/%20di%20r%20/%20fi%20le%20')['body'], - 'blah', - 'file name enclosing', + self.temp_dir + '/assets/ di r /fi le', + self.temp_dir + '/assets/ di r / fi le ', ) + assert waitforfiles(self.temp_dir + '/assets/ di r / fi le ') + assert ( + self.get(url='/%20di%20r%20/%20fi%20le%20')['body'] == 'blah' + ), 'file name enclosing' try: print('файл') @@ -163,267 +137,190 @@ class TestStatic(TestApplicationProto): if utf8: os.rename( - self.testdir + '/assets/ di r / fi le ', - self.testdir + '/assets/ di r /фа йл', - ) - self.waitforfiles(self.testdir + '/assets/ di r /фа йл') - self.assertEqual( - self.get(url='/ di r /фа йл')['body'], 'blah', 'file name 2' + self.temp_dir + '/assets/ di r / fi le ', + self.temp_dir + '/assets/ di r /фа йл', ) + assert waitforfiles(self.temp_dir + '/assets/ di r /фа йл') + assert ( + self.get(url='/ di r /фа йл')['body'] == 'blah' + ), 'file name 2' os.rename( - self.testdir + '/assets/ di r ', - self.testdir + '/assets/ди ректория', - ) - self.waitforfiles(self.testdir + '/assets/ди ректория/фа йл') - self.assertEqual( - self.get(url='/ди ректория/фа йл')['body'], 'blah', 'dir name 2' + self.temp_dir + '/assets/ di r ', + self.temp_dir + '/assets/ди ректория', ) + assert waitforfiles(self.temp_dir + '/assets/ди ректория/фа йл') + assert ( + self.get(url='/ди ректория/фа йл')['body'] == 'blah' + ), 'dir name 2' def test_static_unix_socket(self): sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sock.bind(self.testdir + '/assets/unix_socket') + sock.bind(self.temp_dir + '/assets/unix_socket') - self.assertEqual(self.get(url='/unix_socket')['status'], 404, 'socket') + assert self.get(url='/unix_socket')['status'] == 404, 'socket' sock.close() def test_static_unix_fifo(self): - os.mkfifo(self.testdir + '/assets/fifo') + os.mkfifo(self.temp_dir + '/assets/fifo') - self.assertEqual(self.get(url='/fifo')['status'], 404, 'fifo') + assert self.get(url='/fifo')['status'] == 404, 'fifo' def test_static_symlink(self): - os.symlink(self.testdir + '/assets/dir', self.testdir + '/assets/link') + os.symlink(self.temp_dir + '/assets/dir', self.temp_dir + '/assets/link') - self.assertEqual(self.get(url='/dir')['status'], 301, 'dir') - self.assertEqual(self.get(url='/dir/file')['status'], 200, 'file') - self.assertEqual(self.get(url='/link')['status'], 301, 'symlink dir') - self.assertEqual( - self.get(url='/link/file')['status'], 200, 'symlink file' - ) + assert self.get(url='/dir')['status'] == 301, 'dir' + assert self.get(url='/dir/file')['status'] == 200, 'file' + assert self.get(url='/link')['status'] == 301, 'symlink dir' + assert self.get(url='/link/file')['status'] == 200, 'symlink file' def test_static_method(self): resp = self.head() - self.assertEqual(resp['status'], 200, 'HEAD status') - self.assertEqual(resp['body'], '', 'HEAD empty body') + assert resp['status'] == 200, 'HEAD status' + assert resp['body'] == '', 'HEAD empty body' - self.assertEqual(self.delete()['status'], 405, 'DELETE') - self.assertEqual(self.post()['status'], 405, 'POST') - self.assertEqual(self.put()['status'], 405, 'PUT') + assert self.delete()['status'] == 405, 'DELETE' + assert self.post()['status'] == 405, 'POST' + assert self.put()['status'] == 405, 'PUT' def test_static_path(self): - self.assertEqual( - self.get(url='/dir/../dir/file')['status'], 200, 'relative' - ) + assert self.get(url='/dir/../dir/file')['status'] == 200, 'relative' - self.assertEqual(self.get(url='./')['status'], 400, 'path invalid') - self.assertEqual(self.get(url='../')['status'], 400, 'path invalid 2') - self.assertEqual(self.get(url='/..')['status'], 400, 'path invalid 3') - self.assertEqual( - self.get(url='../assets/')['status'], 400, 'path invalid 4' - ) - self.assertEqual( - self.get(url='/../assets/')['status'], 400, 'path invalid 5' - ) + assert self.get(url='./')['status'] == 400, 'path invalid' + assert self.get(url='../')['status'] == 400, 'path invalid 2' + assert self.get(url='/..')['status'] == 400, 'path invalid 3' + assert self.get(url='../assets/')['status'] == 400, 'path invalid 4' + assert self.get(url='/../assets/')['status'] == 400, 'path invalid 5' def test_static_two_clients(self): _, sock = self.get(url='/', start=True, no_recv=True) _, sock2 = self.get(url='/', start=True, no_recv=True) - self.assertEqual(sock.recv(1), b'H', 'client 1') - self.assertEqual(sock2.recv(1), b'H', 'client 2') - self.assertEqual(sock.recv(1), b'T', 'client 1 again') - self.assertEqual(sock2.recv(1), b'T', 'client 2 again') + assert sock.recv(1) == b'H', 'client 1' + assert sock2.recv(1) == b'H', 'client 2' + assert sock.recv(1) == b'T', 'client 1 again' + assert sock2.recv(1) == b'T', 'client 2 again' sock.close() sock2.close() def test_static_mime_types(self): - self.assertIn( - 'success', - self.conf( - { - "text/x-code/x-blah/x-blah": "readme", - "text/plain": [".html", ".log", "file"], - }, - 'settings/http/static/mime_types', - ), - 'configure mime_types', - ) - - self.assertEqual( - self.get(url='/README')['headers']['Content-Type'], - 'text/x-code/x-blah/x-blah', - 'mime_types string case insensitive', - ) - self.assertEqual( - self.get(url='/index.html')['headers']['Content-Type'], - 'text/plain', - 'mime_types html', - ) - self.assertEqual( - self.get(url='/')['headers']['Content-Type'], - 'text/plain', - 'mime_types index default', - ) - self.assertEqual( - self.get(url='/dir/file')['headers']['Content-Type'], - 'text/plain', - 'mime_types file in dir', - ) + assert 'success' in self.conf( + { + "text/x-code/x-blah/x-blah": "readme", + "text/plain": [".html", ".log", "file"], + }, + 'settings/http/static/mime_types', + ), 'configure mime_types' + + assert ( + self.get(url='/README')['headers']['Content-Type'] + == 'text/x-code/x-blah/x-blah' + ), 'mime_types string case insensitive' + assert ( + self.get(url='/index.html')['headers']['Content-Type'] + == 'text/plain' + ), 'mime_types html' + assert ( + self.get(url='/')['headers']['Content-Type'] == 'text/plain' + ), 'mime_types index default' + assert ( + self.get(url='/dir/file')['headers']['Content-Type'] + == 'text/plain' + ), 'mime_types file in dir' def test_static_mime_types_partial_match(self): - self.assertIn( - 'success', - self.conf( - { - "text/x-blah": ["ile", "fil", "f", "e", ".file"], - }, - 'settings/http/static/mime_types', - ), - 'configure mime_types', - ) - self.assertNotIn( - 'Content-Type', self.get(url='/dir/file'), 'partial match' - ) + assert 'success' in self.conf( + {"text/x-blah": ["ile", "fil", "f", "e", ".file"],}, + 'settings/http/static/mime_types', + ), 'configure mime_types' + assert 'Content-Type' not in self.get(url='/dir/file'), 'partial match' def test_static_mime_types_reconfigure(self): - self.assertIn( - 'success', - self.conf( - { - "text/x-code": "readme", - "text/plain": [".html", ".log", "file"], - }, - 'settings/http/static/mime_types', - ), - 'configure mime_types', - ) - - self.assertEqual( - self.conf_get('settings/http/static/mime_types'), - {'text/x-code': 'readme', 'text/plain': ['.html', '.log', 'file']}, - 'mime_types get', - ) - self.assertEqual( - self.conf_get('settings/http/static/mime_types/text%2Fx-code'), - 'readme', - 'mime_types get string', - ) - self.assertEqual( - self.conf_get('settings/http/static/mime_types/text%2Fplain'), - ['.html', '.log', 'file'], - 'mime_types get array', - ) - self.assertEqual( - self.conf_get('settings/http/static/mime_types/text%2Fplain/1'), - '.log', - 'mime_types get array element', - ) - - self.assertIn( - 'success', - self.conf_delete('settings/http/static/mime_types/text%2Fplain/2'), - 'mime_types remove array element', - ) - self.assertNotIn( - 'Content-Type', - self.get(url='/dir/file')['headers'], - 'mime_types removed', - ) - - self.assertIn( - 'success', - self.conf_post( - '"file"', 'settings/http/static/mime_types/text%2Fplain' - ), - 'mime_types add array element', - ) - self.assertEqual( - self.get(url='/dir/file')['headers']['Content-Type'], - 'text/plain', - 'mime_types reverted', - ) - - self.assertIn( - 'success', - self.conf( - '"file"', 'settings/http/static/mime_types/text%2Fplain' - ), - 'configure mime_types update', - ) - self.assertEqual( - self.get(url='/dir/file')['headers']['Content-Type'], - 'text/plain', - 'mime_types updated', - ) - self.assertNotIn( - 'Content-Type', - self.get(url='/log.log')['headers'], - 'mime_types updated 2', - ) - - self.assertIn( - 'success', - self.conf( - '".log"', 'settings/http/static/mime_types/text%2Fblahblahblah' - ), - 'configure mime_types create', - ) - self.assertEqual( - self.get(url='/log.log')['headers']['Content-Type'], - 'text/blahblahblah', - 'mime_types create', - ) + assert 'success' in self.conf( + { + "text/x-code": "readme", + "text/plain": [".html", ".log", "file"], + }, + 'settings/http/static/mime_types', + ), 'configure mime_types' + + assert self.conf_get('settings/http/static/mime_types') == { + 'text/x-code': 'readme', + 'text/plain': ['.html', '.log', 'file'], + }, 'mime_types get' + assert ( + self.conf_get('settings/http/static/mime_types/text%2Fx-code') + == 'readme' + ), 'mime_types get string' + assert self.conf_get( + 'settings/http/static/mime_types/text%2Fplain' + ) == ['.html', '.log', 'file'], 'mime_types get array' + assert ( + self.conf_get('settings/http/static/mime_types/text%2Fplain/1') + == '.log' + ), 'mime_types get array element' + + assert 'success' in self.conf_delete( + 'settings/http/static/mime_types/text%2Fplain/2' + ), 'mime_types remove array element' + assert ( + 'Content-Type' not in self.get(url='/dir/file')['headers'] + ), 'mime_types removed' + + assert 'success' in self.conf_post( + '"file"', 'settings/http/static/mime_types/text%2Fplain' + ), 'mime_types add array element' + assert ( + self.get(url='/dir/file')['headers']['Content-Type'] + == 'text/plain' + ), 'mime_types reverted' + + assert 'success' in self.conf( + '"file"', 'settings/http/static/mime_types/text%2Fplain' + ), 'configure mime_types update' + assert ( + self.get(url='/dir/file')['headers']['Content-Type'] + == 'text/plain' + ), 'mime_types updated' + assert ( + 'Content-Type' not in self.get(url='/log.log')['headers'] + ), 'mime_types updated 2' + + assert 'success' in self.conf( + '".log"', 'settings/http/static/mime_types/text%2Fblahblahblah' + ), 'configure mime_types create' + assert ( + self.get(url='/log.log')['headers']['Content-Type'] + == 'text/blahblahblah' + ), 'mime_types create' def test_static_mime_types_correct(self): - self.assertIn( - 'error', - self.conf( - {"text/x-code": "readme", "text/plain": "readme"}, - 'settings/http/static/mime_types', - ), - 'mime_types same extensions', - ) - self.assertIn( - 'error', - self.conf( - {"text/x-code": [".h", ".c"], "text/plain": ".c"}, - 'settings/http/static/mime_types', - ), - 'mime_types same extensions array', - ) - self.assertIn( - 'error', - self.conf( - { - "text/x-code": [".h", ".c", "readme"], - "text/plain": "README", - }, - 'settings/http/static/mime_types', - ), - 'mime_types same extensions case insensitive', - ) - - @unittest.skip('not yet') + assert 'error' in self.conf( + {"text/x-code": "readme", "text/plain": "readme"}, + 'settings/http/static/mime_types', + ), 'mime_types same extensions' + assert 'error' in self.conf( + {"text/x-code": [".h", ".c"], "text/plain": ".c"}, + 'settings/http/static/mime_types', + ), 'mime_types same extensions array' + assert 'error' in self.conf( + {"text/x-code": [".h", ".c", "readme"], "text/plain": "README",}, + 'settings/http/static/mime_types', + ), 'mime_types same extensions case insensitive' + + @pytest.mark.skip('not yet') def test_static_mime_types_invalid(self): - self.assertIn( - 'error', - self.http( - b"""PUT /config/settings/http/static/mime_types/%0%00% HTTP/1.1\r + assert 'error' in self.http( + b"""PUT /config/settings/http/static/mime_types/%0%00% HTTP/1.1\r Host: localhost\r Connection: close\r Content-Length: 6\r \r \"blah\"""", - raw_resp=True, - raw=True, - sock_type='unix', - addr=self.testdir + '/control.unit.sock', - ), - 'mime_types invalid', - ) - -if __name__ == '__main__': - TestStatic.main() + raw_resp=True, + raw=True, + sock_type='unix', + addr=self.temp_dir + '/control.unit.sock', + ), 'mime_types invalid' diff --git a/test/test_tls.py b/test/test_tls.py index a0434174..9881e973 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -1,17 +1,18 @@ import io +import pytest import re import ssl import subprocess -import unittest from unit.applications.tls import TestApplicationTLS +from conftest import skip_alert class TestTLS(TestApplicationTLS): prerequisites = {'modules': {'python': 'any', 'openssl': 'any'}} def findall(self, pattern): - with open(self.testdir + '/unit.log', 'r', errors='ignore') as f: + with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f: return re.findall(pattern, f.read()) def openssl_date_to_sec_epoch(self, date): @@ -38,7 +39,7 @@ class TestTLS(TestApplicationTLS): self.add_tls() - self.assertEqual(self.get_ssl()['status'], 200, 'add listener option') + assert self.get_ssl()['status'] == 200, 'add listener option' def test_tls_listener_option_remove(self): self.load('empty') @@ -51,18 +52,16 @@ class TestTLS(TestApplicationTLS): self.remove_tls() - self.assertEqual(self.get()['status'], 200, 'remove listener option') + assert self.get()['status'] == 200, 'remove listener option' def test_tls_certificate_remove(self): self.load('empty') self.certificate() - self.assertIn( - 'success', - self.conf_delete('/certificates/default'), - 'remove certificate', - ) + assert 'success' in self.conf_delete( + '/certificates/default' + ), 'remove certificate' def test_tls_certificate_remove_used(self): self.load('empty') @@ -71,11 +70,9 @@ class TestTLS(TestApplicationTLS): self.add_tls() - self.assertIn( - 'error', - self.conf_delete('/certificates/default'), - 'remove certificate', - ) + assert 'error' in self.conf_delete( + '/certificates/default' + ), 'remove certificate' def test_tls_certificate_remove_nonexisting(self): self.load('empty') @@ -84,13 +81,11 @@ class TestTLS(TestApplicationTLS): self.add_tls() - self.assertIn( - 'error', - self.conf_delete('/certificates/blah'), - 'remove nonexistings certificate', - ) + assert 'error' in self.conf_delete( + '/certificates/blah' + ), 'remove nonexistings certificate' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_tls_certificate_update(self): self.load('empty') @@ -102,20 +97,18 @@ class TestTLS(TestApplicationTLS): self.certificate() - self.assertNotEqual( - cert_old, self.get_server_certificate(), 'update certificate' - ) + assert cert_old != self.get_server_certificate(), 'update certificate' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_tls_certificate_key_incorrect(self): self.load('empty') self.certificate('first', False) self.certificate('second', False) - self.assertIn( - 'error', self.certificate_load('first', 'second'), 'key incorrect' - ) + assert 'error' in self.certificate_load( + 'first', 'second' + ), 'key incorrect' def test_tls_certificate_change(self): self.load('empty') @@ -129,20 +122,16 @@ class TestTLS(TestApplicationTLS): self.add_tls(cert='new') - self.assertNotEqual( - cert_old, self.get_server_certificate(), 'change certificate' - ) + assert cert_old != self.get_server_certificate(), 'change certificate' def test_tls_certificate_key_rsa(self): self.load('empty') self.certificate() - self.assertEqual( - self.conf_get('/certificates/default/key'), - 'RSA (2048 bits)', - 'certificate key rsa', - ) + assert ( + self.conf_get('/certificates/default/key') == 'RSA (2048 bits)' + ), 'certificate key rsa' def test_tls_certificate_key_ec(self): self.load('empty') @@ -155,8 +144,10 @@ class TestTLS(TestApplicationTLS): 'ecparam', '-noout', '-genkey', - '-out', self.testdir + '/ec.key', - '-name', 'prime256v1', + '-out', + self.temp_dir + '/ec.key', + '-name', + 'prime256v1', ], stderr=subprocess.STDOUT, ) @@ -167,19 +158,23 @@ class TestTLS(TestApplicationTLS): 'req', '-x509', '-new', - '-subj', '/CN=ec/', - '-config', self.testdir + '/openssl.conf', - '-key', self.testdir + '/ec.key', - '-out', self.testdir + '/ec.crt', + '-subj', + '/CN=ec/', + '-config', + self.temp_dir + '/openssl.conf', + '-key', + self.temp_dir + '/ec.key', + '-out', + self.temp_dir + '/ec.crt', ], stderr=subprocess.STDOUT, ) self.certificate_load('ec') - self.assertEqual( - self.conf_get('/certificates/ec/key'), 'ECDH', 'certificate key ec' - ) + assert ( + self.conf_get('/certificates/ec/key') == 'ECDH' + ), 'certificate key ec' def test_tls_certificate_chain_options(self): self.load('empty') @@ -188,35 +183,29 @@ class TestTLS(TestApplicationTLS): chain = self.conf_get('/certificates/default/chain') - self.assertEqual(len(chain), 1, 'certificate chain length') + assert len(chain) == 1, 'certificate chain length' cert = chain[0] - self.assertEqual( - cert['subject']['common_name'], - 'default', - 'certificate subject common name', - ) - self.assertEqual( - cert['issuer']['common_name'], - 'default', - 'certificate issuer common name', - ) + assert ( + cert['subject']['common_name'] == 'default' + ), 'certificate subject common name' + assert ( + cert['issuer']['common_name'] == 'default' + ), 'certificate issuer common name' - self.assertLess( + assert ( abs( self.sec_epoch() - self.openssl_date_to_sec_epoch(cert['validity']['since']) - ), - 5, - 'certificate validity since', - ) - self.assertEqual( + ) + < 5 + ), 'certificate validity since' + assert ( self.openssl_date_to_sec_epoch(cert['validity']['until']) - - self.openssl_date_to_sec_epoch(cert['validity']['since']), - 2592000, - 'certificate validity until', - ) + - self.openssl_date_to_sec_epoch(cert['validity']['since']) + == 2592000 + ), 'certificate validity until' def test_tls_certificate_chain(self): self.load('empty') @@ -228,10 +217,14 @@ class TestTLS(TestApplicationTLS): 'openssl', 'req', '-new', - '-subj', '/CN=int/', - '-config', self.testdir + '/openssl.conf', - '-out', self.testdir + '/int.csr', - '-keyout', self.testdir + '/int.key', + '-subj', + '/CN=int/', + '-config', + self.temp_dir + '/openssl.conf', + '-out', + self.temp_dir + '/int.csr', + '-keyout', + self.temp_dir + '/int.key', ], stderr=subprocess.STDOUT, ) @@ -241,15 +234,19 @@ class TestTLS(TestApplicationTLS): 'openssl', 'req', '-new', - '-subj', '/CN=end/', - '-config', self.testdir + '/openssl.conf', - '-out', self.testdir + '/end.csr', - '-keyout', self.testdir + '/end.key', + '-subj', + '/CN=end/', + '-config', + self.temp_dir + '/openssl.conf', + '-out', + self.temp_dir + '/end.csr', + '-keyout', + self.temp_dir + '/end.key', ], stderr=subprocess.STDOUT, ) - with open(self.testdir + '/ca.conf', 'w') as f: + with open(self.temp_dir + '/ca.conf', 'w') as f: f.write( """[ ca ] default_ca = myca @@ -269,16 +266,16 @@ commonName = supplied [ myca_extensions ] basicConstraints = critical,CA:TRUE""" % { - 'dir': self.testdir, - 'database': self.testdir + '/certindex', - 'certserial': self.testdir + '/certserial', + 'dir': self.temp_dir, + 'database': self.temp_dir + '/certindex', + 'certserial': self.temp_dir + '/certserial', } ) - with open(self.testdir + '/certserial', 'w') as f: + with open(self.temp_dir + '/certserial', 'w') as f: f.write('1000') - with open(self.testdir + '/certindex', 'w') as f: + with open(self.temp_dir + '/certindex', 'w') as f: f.write('') subprocess.call( @@ -286,12 +283,18 @@ basicConstraints = critical,CA:TRUE""" 'openssl', 'ca', '-batch', - '-subj', '/CN=int/', - '-config', self.testdir + '/ca.conf', - '-keyfile', self.testdir + '/root.key', - '-cert', self.testdir + '/root.crt', - '-in', self.testdir + '/int.csr', - '-out', self.testdir + '/int.crt', + '-subj', + '/CN=int/', + '-config', + self.temp_dir + '/ca.conf', + '-keyfile', + self.temp_dir + '/root.key', + '-cert', + self.temp_dir + '/root.crt', + '-in', + self.temp_dir + '/int.csr', + '-out', + self.temp_dir + '/int.crt', ], stderr=subprocess.STDOUT, ) @@ -301,50 +304,50 @@ basicConstraints = critical,CA:TRUE""" 'openssl', 'ca', '-batch', - '-subj', '/CN=end/', - '-config', self.testdir + '/ca.conf', - '-keyfile', self.testdir + '/int.key', - '-cert', self.testdir + '/int.crt', - '-in', self.testdir + '/end.csr', - '-out', self.testdir + '/end.crt', + '-subj', + '/CN=end/', + '-config', + self.temp_dir + '/ca.conf', + '-keyfile', + self.temp_dir + '/int.key', + '-cert', + self.temp_dir + '/int.crt', + '-in', + self.temp_dir + '/end.csr', + '-out', + self.temp_dir + '/end.crt', ], stderr=subprocess.STDOUT, ) - crt_path = self.testdir + '/end-int.crt' - end_path = self.testdir + '/end.crt' - int_path = self.testdir + '/int.crt' + crt_path = self.temp_dir + '/end-int.crt' + end_path = self.temp_dir + '/end.crt' + int_path = self.temp_dir + '/int.crt' - with open(crt_path, 'wb') as crt, \ - open(end_path, 'rb') as end, \ - open(int_path, 'rb') as int: + with open(crt_path, 'wb') as crt, open(end_path, 'rb') as end, open( + int_path, 'rb' + ) as int: crt.write(end.read() + int.read()) self.context = ssl.create_default_context() self.context.check_hostname = False self.context.verify_mode = ssl.CERT_REQUIRED - self.context.load_verify_locations(self.testdir + '/root.crt') + self.context.load_verify_locations(self.temp_dir + '/root.crt') # incomplete chain - self.assertIn( - 'success', - self.certificate_load('end', 'end'), - 'certificate chain end upload', - ) + assert 'success' in self.certificate_load( + 'end', 'end' + ), 'certificate chain end upload' chain = self.conf_get('/certificates/end/chain') - self.assertEqual(len(chain), 1, 'certificate chain end length') - self.assertEqual( - chain[0]['subject']['common_name'], - 'end', - 'certificate chain end subject common name', - ) - self.assertEqual( - chain[0]['issuer']['common_name'], - 'int', - 'certificate chain end issuer common name', - ) + assert len(chain) == 1, 'certificate chain end length' + assert ( + chain[0]['subject']['common_name'] == 'end' + ), 'certificate chain end subject common name' + assert ( + chain[0]['issuer']['common_name'] == 'int' + ), 'certificate chain end issuer common name' self.add_tls(cert='end') @@ -353,79 +356,61 @@ basicConstraints = critical,CA:TRUE""" except ssl.SSLError: resp = None - self.assertEqual(resp, None, 'certificate chain incomplete chain') + assert resp == None, 'certificate chain incomplete chain' # intermediate - self.assertIn( - 'success', - self.certificate_load('int', 'int'), - 'certificate chain int upload', - ) + assert 'success' in self.certificate_load( + 'int', 'int' + ), 'certificate chain int upload' chain = self.conf_get('/certificates/int/chain') - self.assertEqual(len(chain), 1, 'certificate chain int length') - self.assertEqual( - chain[0]['subject']['common_name'], - 'int', - 'certificate chain int subject common name', - ) - self.assertEqual( - chain[0]['issuer']['common_name'], - 'root', - 'certificate chain int issuer common name', - ) + assert len(chain) == 1, 'certificate chain int length' + assert ( + chain[0]['subject']['common_name'] == 'int' + ), 'certificate chain int subject common name' + assert ( + chain[0]['issuer']['common_name'] == 'root' + ), 'certificate chain int issuer common name' self.add_tls(cert='int') - self.assertEqual( - self.get_ssl()['status'], 200, 'certificate chain intermediate' - ) + assert ( + self.get_ssl()['status'] == 200 + ), 'certificate chain intermediate' # intermediate server - self.assertIn( - 'success', - self.certificate_load('end-int', 'end'), - 'certificate chain end-int upload', - ) + assert 'success' in self.certificate_load( + 'end-int', 'end' + ), 'certificate chain end-int upload' chain = self.conf_get('/certificates/end-int/chain') - self.assertEqual(len(chain), 2, 'certificate chain end-int length') - self.assertEqual( - chain[0]['subject']['common_name'], - 'end', - 'certificate chain end-int int subject common name', - ) - self.assertEqual( - chain[0]['issuer']['common_name'], - 'int', - 'certificate chain end-int int issuer common name', - ) - self.assertEqual( - chain[1]['subject']['common_name'], - 'int', - 'certificate chain end-int end subject common name', - ) - self.assertEqual( - chain[1]['issuer']['common_name'], - 'root', - 'certificate chain end-int end issuer common name', - ) + assert len(chain) == 2, 'certificate chain end-int length' + assert ( + chain[0]['subject']['common_name'] == 'end' + ), 'certificate chain end-int int subject common name' + assert ( + chain[0]['issuer']['common_name'] == 'int' + ), 'certificate chain end-int int issuer common name' + assert ( + chain[1]['subject']['common_name'] == 'int' + ), 'certificate chain end-int end subject common name' + assert ( + chain[1]['issuer']['common_name'] == 'root' + ), 'certificate chain end-int end issuer common name' self.add_tls(cert='end-int') - self.assertEqual( - self.get_ssl()['status'], - 200, - 'certificate chain intermediate server', - ) + assert ( + self.get_ssl()['status'] == 200 + ), 'certificate chain intermediate server' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_tls_reconfigure(self): self.load('empty') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' self.certificate() @@ -435,21 +420,17 @@ basicConstraints = critical,CA:TRUE""" read_timeout=1, ) - self.assertEqual(resp['status'], 200, 'initial status') + assert resp['status'] == 200, 'initial status' self.add_tls() - self.assertEqual( - self.get(sock=sock)['status'], 200, 'reconfigure status' - ) - self.assertEqual( - self.get_ssl()['status'], 200, 'reconfigure tls status' - ) + assert self.get(sock=sock)['status'] == 200, 'reconfigure status' + assert self.get_ssl()['status'] == 200, 'reconfigure tls status' def test_tls_keepalive(self): self.load('mirror') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' self.certificate() @@ -466,7 +447,7 @@ basicConstraints = critical,CA:TRUE""" read_timeout=1, ) - self.assertEqual(resp['body'], '0123456789', 'keepalive 1') + assert resp['body'] == '0123456789', 'keepalive 1' resp = self.post_ssl( headers={ @@ -478,13 +459,13 @@ basicConstraints = critical,CA:TRUE""" body='0123456789', ) - self.assertEqual(resp['body'], '0123456789', 'keepalive 2') + assert resp['body'] == '0123456789', 'keepalive 2' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_tls_keepalive_certificate_remove(self): self.load('empty') - self.assertEqual(self.get()['status'], 200, 'init') + assert self.get()['status'] == 200, 'init' self.certificate() @@ -506,19 +487,17 @@ basicConstraints = critical,CA:TRUE""" except: resp = None - self.assertEqual(resp, None, 'keepalive remove certificate') + assert resp == None, 'keepalive remove certificate' - @unittest.skip('not yet') + @pytest.mark.skip('not yet') def test_tls_certificates_remove_all(self): self.load('empty') self.certificate() - self.assertIn( - 'success', - self.conf_delete('/certificates'), - 'remove all certificates', - ) + assert 'success' in self.conf_delete( + '/certificates' + ), 'remove all certificates' def test_tls_application_respawn(self): self.load('mirror') @@ -544,7 +523,7 @@ basicConstraints = critical,CA:TRUE""" subprocess.call(['kill', '-9', app_id]) - self.skip_alerts.append(r'process %s exited on signal 9' % app_id) + skip_alert(r'process %s exited on signal 9' % app_id) self.wait_for_record( re.compile( @@ -562,15 +541,13 @@ basicConstraints = critical,CA:TRUE""" body='0123456789', ) - self.assertEqual(resp['status'], 200, 'application respawn status') - self.assertEqual( - resp['body'], '0123456789', 'application respawn body' - ) + assert resp['status'] == 200, 'application respawn status' + assert resp['body'] == '0123456789', 'application respawn body' def test_tls_url_scheme(self): self.load('variables') - self.assertEqual( + assert ( self.post( headers={ 'Host': 'localhost', @@ -578,16 +555,15 @@ basicConstraints = critical,CA:TRUE""" 'Custom-Header': '', 'Connection': 'close', } - )['headers']['Wsgi-Url-Scheme'], - 'http', - 'url scheme http', - ) + )['headers']['Wsgi-Url-Scheme'] + == 'http' + ), 'url scheme http' self.certificate() self.add_tls(application='variables') - self.assertEqual( + assert ( self.post_ssl( headers={ 'Host': 'localhost', @@ -595,10 +571,9 @@ basicConstraints = critical,CA:TRUE""" 'Custom-Header': '', 'Connection': 'close', } - )['headers']['Wsgi-Url-Scheme'], - 'https', - 'url scheme https', - ) + )['headers']['Wsgi-Url-Scheme'] + == 'https' + ), 'url scheme https' def test_tls_big_upload(self): self.load('upload') @@ -610,15 +585,14 @@ basicConstraints = critical,CA:TRUE""" filename = 'test.txt' data = '0123456789' * 9000 - res = self.post_ssl(body={ - 'file': { - 'filename': filename, - 'type': 'text/plain', - 'data': io.StringIO(data), + res = self.post_ssl( + body={ + 'file': { + 'filename': filename, + 'type': 'text/plain', + 'data': io.StringIO(data), + } } - }) - self.assertEqual(res['status'], 200, 'status ok') - self.assertEqual(res['body'], filename + data) - -if __name__ == '__main__': - TestTLS.main() + ) + assert res['status'] == 200, 'status ok' + assert res['body'] == filename + data diff --git a/test/test_upstreams_rr.py b/test/test_upstreams_rr.py index 2f74fbde..ceab11c3 100644 --- a/test/test_upstreams_rr.py +++ b/test/test_upstreams_rr.py @@ -2,49 +2,46 @@ import os import re from unit.applications.lang.python import TestApplicationPython +from conftest import option class TestUpstreamsRR(TestApplicationPython): prerequisites = {'modules': {'python': 'any'}} - def setUp(self): - super().setUp() + def setup_method(self): + super().setup_method() - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "upstreams/one"}, - "*:7090": {"pass": "upstreams/two"}, - "*:7081": {"pass": "routes/one"}, - "*:7082": {"pass": "routes/two"}, - "*:7083": {"pass": "routes/three"}, - }, - "upstreams": { - "one": { - "servers": { - "127.0.0.1:7081": {}, - "127.0.0.1:7082": {}, - }, - }, - "two": { - "servers": { - "127.0.0.1:7081": {}, - "127.0.0.1:7082": {}, - }, + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "upstreams/one"}, + "*:7090": {"pass": "upstreams/two"}, + "*:7081": {"pass": "routes/one"}, + "*:7082": {"pass": "routes/two"}, + "*:7083": {"pass": "routes/three"}, + }, + "upstreams": { + "one": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, }, }, - "routes": { - "one": [{"action": {"return": 200}}], - "two": [{"action": {"return": 201}}], - "three": [{"action": {"return": 202}}], + "two": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, }, - "applications": {}, }, - ), - 'upstreams initial configuration', - ) + "routes": { + "one": [{"action": {"return": 200}}], + "two": [{"action": {"return": 201}}], + "three": [{"action": {"return": 202}}], + }, + "applications": {}, + }, + ), 'upstreams initial configuration' self.cpu_count = os.cpu_count() @@ -91,113 +88,87 @@ Connection: close def test_upstreams_rr_no_weight(self): resps = self.get_resps() - self.assertEqual(sum(resps), 100, 'no weight sum') - self.assertLessEqual( - abs(resps[0] - resps[1]), self.cpu_count, 'no weight' - ) + assert sum(resps) == 100, 'no weight sum' + assert abs(resps[0] - resps[1]) <= self.cpu_count, 'no weight' - self.assertIn( - 'success', - self.conf_delete('upstreams/one/servers/127.0.0.1:7081'), - 'no weight server remove', - ) + assert 'success' in self.conf_delete( + 'upstreams/one/servers/127.0.0.1:7081' + ), 'no weight server remove' resps = self.get_resps(req=50) - self.assertEqual(resps[1], 50, 'no weight 2') + assert resps[1] == 50, 'no weight 2' - self.assertIn( - 'success', - self.conf({}, 'upstreams/one/servers/127.0.0.1:7081'), - 'no weight server revert', - ) + assert 'success' in self.conf( + {}, 'upstreams/one/servers/127.0.0.1:7081' + ), 'no weight server revert' resps = self.get_resps() - self.assertEqual(sum(resps), 100, 'no weight 3 sum') - self.assertLessEqual( - abs(resps[0] - resps[1]), self.cpu_count, 'no weight 3' - ) + assert sum(resps) == 100, 'no weight 3 sum' + assert abs(resps[0] - resps[1]) <= self.cpu_count, 'no weight 3' - self.assertIn( - 'success', - self.conf({}, 'upstreams/one/servers/127.0.0.1:7083'), - 'no weight server new', - ) + assert 'success' in self.conf( + {}, 'upstreams/one/servers/127.0.0.1:7083' + ), 'no weight server new' resps = self.get_resps() - self.assertEqual(sum(resps), 100, 'no weight 4 sum') - self.assertLessEqual( - max(resps) - min(resps), self.cpu_count, 'no weight 4' - ) + assert sum(resps) == 100, 'no weight 4 sum' + assert max(resps) - min(resps) <= self.cpu_count, 'no weight 4' resps = self.get_resps_sc(req=30) - self.assertEqual(resps[0], 10, 'no weight 4 0') - self.assertEqual(resps[1], 10, 'no weight 4 1') - self.assertEqual(resps[2], 10, 'no weight 4 2') + assert resps[0] == 10, 'no weight 4 0' + assert resps[1] == 10, 'no weight 4 1' + assert resps[2] == 10, 'no weight 4 2' def test_upstreams_rr_weight(self): - self.assertIn( - 'success', - self.conf({"weight": 3}, 'upstreams/one/servers/127.0.0.1:7081'), - 'configure weight', - ) + assert 'success' in self.conf( + {"weight": 3}, 'upstreams/one/servers/127.0.0.1:7081' + ), 'configure weight' resps = self.get_resps_sc() - self.assertEqual(resps[0], 75, 'weight 3 0') - self.assertEqual(resps[1], 25, 'weight 3 1') + assert resps[0] == 75, 'weight 3 0' + assert resps[1] == 25, 'weight 3 1' - self.assertIn( - 'success', - self.conf_delete('upstreams/one/servers/127.0.0.1:7081/weight'), - 'configure weight remove', - ) + assert 'success' in self.conf_delete( + 'upstreams/one/servers/127.0.0.1:7081/weight' + ), 'configure weight remove' resps = self.get_resps_sc(req=10) - self.assertEqual(resps[0], 5, 'weight 0 0') - self.assertEqual(resps[1], 5, 'weight 0 1') + assert resps[0] == 5, 'weight 0 0' + assert resps[1] == 5, 'weight 0 1' - self.assertIn( - 'success', - self.conf('1', 'upstreams/one/servers/127.0.0.1:7081/weight'), - 'configure weight 1', - ) + assert 'success' in self.conf( + '1', 'upstreams/one/servers/127.0.0.1:7081/weight' + ), 'configure weight 1' resps = self.get_resps_sc() - self.assertEqual(resps[0], 50, 'weight 1 0') - self.assertEqual(resps[1], 50, 'weight 1 1') + assert resps[0] == 50, 'weight 1 0' + assert resps[1] == 50, 'weight 1 1' - self.assertIn( - 'success', - self.conf( - { - "127.0.0.1:7081": {"weight": 3}, - "127.0.0.1:7083": {"weight": 2}, - }, - 'upstreams/one/servers', - ), - 'configure weight 2', - ) + assert 'success' in self.conf( + { + "127.0.0.1:7081": {"weight": 3}, + "127.0.0.1:7083": {"weight": 2}, + }, + 'upstreams/one/servers', + ), 'configure weight 2' resps = self.get_resps_sc() - self.assertEqual(resps[0], 60, 'weight 2 0') - self.assertEqual(resps[2], 40, 'weight 2 1') + assert resps[0] == 60, 'weight 2 0' + assert resps[2] == 40, 'weight 2 1' def test_upstreams_rr_weight_rational(self): def set_weights(w1, w2): - self.assertIn( - 'success', - self.conf( - { - "127.0.0.1:7081": {"weight": w1}, - "127.0.0.1:7082": {"weight": w2}, - }, - 'upstreams/one/servers', - ), - 'configure weights', - ) + assert 'success' in self.conf( + { + "127.0.0.1:7081": {"weight": w1}, + "127.0.0.1:7082": {"weight": w2}, + }, + 'upstreams/one/servers', + ), 'configure weights' def check_reqs(w1, w2, reqs=10): resps = self.get_resps_sc(req=reqs) - self.assertEqual(resps[0], reqs * w1 / (w1 + w2), 'weight 1') - self.assertEqual(resps[1], reqs * w2 / (w1 + w2), 'weight 2') + assert resps[0] == reqs * w1 / (w1 + w2), 'weight 1' + assert resps[1] == reqs * w2 / (w1 + w2), 'weight 2' def check_weights(w1, w2): set_weights(w1, w2) @@ -207,39 +178,33 @@ Connection: close check_weights(0, 999999.0123456) check_weights(1, 9) check_weights(100000, 900000) - check_weights(1, .25) check_weights(1, 0.25) - check_weights(0.2, .8) + check_weights(1, 0.25) + check_weights(0.2, 0.8) check_weights(1, 1.5) - check_weights(1e-3, 1E-3) + check_weights(1e-3, 1e-3) check_weights(1e-20, 1e-20) check_weights(1e4, 1e4) check_weights(1000000, 1000000) set_weights(0.25, 0.25) - self.assertIn( - 'success', - self.conf_delete('upstreams/one/servers/127.0.0.1:7081/weight'), - 'delete weight', - ) + assert 'success' in self.conf_delete( + 'upstreams/one/servers/127.0.0.1:7081/weight' + ), 'delete weight' check_reqs(1, 0.25) - self.assertIn( - 'success', - self.conf( - { - "127.0.0.1:7081": {"weight": 0.1}, - "127.0.0.1:7082": {"weight": 1}, - "127.0.0.1:7083": {"weight": 0.9}, - }, - 'upstreams/one/servers', - ), - 'configure weights', - ) + assert 'success' in self.conf( + { + "127.0.0.1:7081": {"weight": 0.1}, + "127.0.0.1:7082": {"weight": 1}, + "127.0.0.1:7083": {"weight": 0.9}, + }, + 'upstreams/one/servers', + ), 'configure weights' resps = self.get_resps_sc(req=20) - self.assertEqual(resps[0], 1, 'weight 3 1') - self.assertEqual(resps[1], 10, 'weight 3 2') - self.assertEqual(resps[2], 9, 'weight 3 3') + assert resps[0] == 1, 'weight 3 1' + assert resps[1] == 10, 'weight 3 2' + assert resps[2] == 9, 'weight 3 3' def test_upstreams_rr_independent(self): def sum_resps(*args): @@ -250,90 +215,77 @@ Connection: close return sum resps = self.get_resps_sc(req=30, port=7090) - self.assertEqual(resps[0], 15, 'dep two before 0') - self.assertEqual(resps[1], 15, 'dep two before 1') + assert resps[0] == 15, 'dep two before 0' + assert resps[1] == 15, 'dep two before 1' resps = self.get_resps_sc(req=30) - self.assertEqual(resps[0], 15, 'dep one before 0') - self.assertEqual(resps[1], 15, 'dep one before 1') + assert resps[0] == 15, 'dep one before 0' + assert resps[1] == 15, 'dep one before 1' - self.assertIn( - 'success', - self.conf('2', 'upstreams/two/servers/127.0.0.1:7081/weight'), - 'configure dep weight', - ) + assert 'success' in self.conf( + '2', 'upstreams/two/servers/127.0.0.1:7081/weight' + ), 'configure dep weight' resps = self.get_resps_sc(req=30, port=7090) - self.assertEqual(resps[0], 20, 'dep two 0') - self.assertEqual(resps[1], 10, 'dep two 1') + assert resps[0] == 20, 'dep two 0' + assert resps[1] == 10, 'dep two 1' resps = self.get_resps_sc(req=30) - self.assertEqual(resps[0], 15, 'dep one 0') - self.assertEqual(resps[1], 15, 'dep one 1') + assert resps[0] == 15, 'dep one 0' + assert resps[1] == 15, 'dep one 1' - self.assertIn( - 'success', - self.conf('1', 'upstreams/two/servers/127.0.0.1:7081/weight'), - 'configure dep weight 1', - ) + assert 'success' in self.conf( + '1', 'upstreams/two/servers/127.0.0.1:7081/weight' + ), 'configure dep weight 1' r_one, r_two = [0, 0], [0, 0] for _ in range(10): r_one = sum_resps(r_one, self.get_resps(req=10)) r_two = sum_resps(r_two, self.get_resps(req=10, port=7090)) - - self.assertEqual(sum(r_one), 100, 'dep one mix sum') - self.assertLessEqual( - abs(r_one[0] - r_one[1]), self.cpu_count, 'dep one mix' - ) - self.assertEqual(sum(r_two), 100, 'dep two mix sum') - self.assertLessEqual( - abs(r_two[0] - r_two[1]), self.cpu_count, 'dep two mix' - ) + assert sum(r_one) == 100, 'dep one mix sum' + assert abs(r_one[0] - r_one[1]) <= self.cpu_count, 'dep one mix' + assert sum(r_two) == 100, 'dep two mix sum' + assert abs(r_two[0] - r_two[1]) <= self.cpu_count, 'dep two mix' def test_upstreams_rr_delay(self): - self.assertIn( - 'success', - self.conf( - { - "listeners": { - "*:7080": {"pass": "upstreams/one"}, - "*:7081": {"pass": "routes"}, - "*:7082": {"pass": "routes"}, - }, - "upstreams": { - "one": { - "servers": { - "127.0.0.1:7081": {}, - "127.0.0.1:7082": {}, - }, + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "upstreams/one"}, + "*:7081": {"pass": "routes"}, + "*:7082": {"pass": "routes"}, + }, + "upstreams": { + "one": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, }, }, - "routes": [ - { - "match": {"destination": "*:7081"}, - "action": {"pass": "applications/delayed"}, - }, - { - "match": {"destination": "*:7082"}, - "action": {"return": 201}, - }, - ], - "applications": { - "delayed": { - "type": "python", - "processes": {"spare": 0}, - "path": self.current_dir + "/python/delayed", - "working_directory": self.current_dir - + "/python/delayed", - "module": "wsgi", - } + }, + "routes": [ + { + "match": {"destination": "*:7081"}, + "action": {"pass": "applications/delayed"}, }, + { + "match": {"destination": "*:7082"}, + "action": {"return": 201}, + }, + ], + "applications": { + "delayed": { + "type": "python", + "processes": {"spare": 0}, + "path": option.test_dir + "/python/delayed", + "working_directory": option.test_dir + + "/python/delayed", + "module": "wsgi", + } }, - ), - 'upstreams initial configuration', - ) + }, + ), 'upstreams initial configuration' req = 50 @@ -357,12 +309,12 @@ Connection: close resp = self.recvall(socks[i]).decode() socks[i].close() - m = re.search('HTTP/1.1 20(\d)', resp) - self.assertIsNotNone(m, 'status') + m = re.search(r'HTTP/1.1 20(\d)', resp) + assert m is not None, 'status' resps[int(m.group(1))] += 1 - self.assertEqual(sum(resps), req, 'delay sum') - self.assertLessEqual(abs(resps[0] - resps[1]), self.cpu_count, 'delay') + assert sum(resps) == req, 'delay sum' + assert abs(resps[0] - resps[1]) <= self.cpu_count, 'delay' def test_upstreams_rr_active_req(self): conns = 5 @@ -389,59 +341,46 @@ Connection: close # Send one more request and read response to make sure that previous # requests had enough time to reach server. - self.assertEqual(self.get()['body'], '') - - self.assertIn( - 'success', - self.conf( - {"127.0.0.1:7083": {"weight": 2}}, 'upstreams/one/servers', - ), - 'active req new server', - ) - self.assertIn( - 'success', - self.conf_delete('upstreams/one/servers/127.0.0.1:7083'), - 'active req server remove', - ) - self.assertIn( - 'success', self.conf_delete('listeners/*:7080'), 'delete listener' - ) - self.assertIn( - 'success', - self.conf_delete('upstreams/one'), - 'active req upstream remove', - ) + assert self.get()['body'] == '' + + assert 'success' in self.conf( + {"127.0.0.1:7083": {"weight": 2}}, 'upstreams/one/servers', + ), 'active req new server' + assert 'success' in self.conf_delete( + 'upstreams/one/servers/127.0.0.1:7083' + ), 'active req server remove' + assert 'success' in self.conf_delete( + 'listeners/*:7080' + ), 'delete listener' + assert 'success' in self.conf_delete( + 'upstreams/one' + ), 'active req upstream remove' for i in range(conns): - self.assertEqual( - self.http(b'', sock=socks[i], raw=True)['body'], - '', - 'active req GET', - ) + assert ( + self.http(b'', sock=socks[i], raw=True)['body'] == '' + ), 'active req GET' - self.assertEqual( - self.http(b"""0123456789""", sock=socks2[i], raw=True)['body'], - '', - 'active req POST', - ) + assert ( + self.http(b"""0123456789""", sock=socks2[i], raw=True)['body'] + == '' + ), 'active req POST' def test_upstreams_rr_bad_server(self): - self.assertIn( - 'success', - self.conf({"weight": 1}, 'upstreams/one/servers/127.0.0.1:7084'), - 'configure bad server', - ) + assert 'success' in self.conf( + {"weight": 1}, 'upstreams/one/servers/127.0.0.1:7084' + ), 'configure bad server' resps = self.get_resps_sc(req=30) - self.assertEqual(resps[0], 10, 'bad server 0') - self.assertEqual(resps[1], 10, 'bad server 1') - self.assertEqual(sum(resps), 20, 'bad server sum') + assert resps[0] == 10, 'bad server 0' + assert resps[1] == 10, 'bad server 1' + assert sum(resps) == 20, 'bad server sum' def test_upstreams_rr_pipeline(self): resps = self.get_resps_sc() - self.assertEqual(resps[0], 50, 'pipeline 0') - self.assertEqual(resps[1], 50, 'pipeline 1') + assert resps[0] == 50, 'pipeline 0' + assert resps[1] == 50, 'pipeline 1' def test_upstreams_rr_post(self): resps = [0, 0] @@ -449,120 +388,87 @@ Connection: close resps[self.get()['status'] % 10] += 1 resps[self.post(body='0123456789')['status'] % 10] += 1 - self.assertEqual(sum(resps), 100, 'post sum') - self.assertLessEqual(abs(resps[0] - resps[1]), self.cpu_count, 'post') + assert sum(resps) == 100, 'post sum' + assert abs(resps[0] - resps[1]) <= self.cpu_count, 'post' def test_upstreams_rr_unix(self): - addr_0 = self.testdir + '/sock_0' - addr_1 = self.testdir + '/sock_1' - - self.assertIn( - 'success', - self.conf( - { - "*:7080": {"pass": "upstreams/one"}, - "unix:" + addr_0: {"pass": "routes/one"}, - "unix:" + addr_1: {"pass": "routes/two"}, - }, - 'listeners', - ), - 'configure listeners unix', - ) - - self.assertIn( - 'success', - self.conf( - {"unix:" + addr_0: {}, "unix:" + addr_1: {}}, - 'upstreams/one/servers', - ), - 'configure servers unix', - ) + addr_0 = self.temp_dir + '/sock_0' + addr_1 = self.temp_dir + '/sock_1' + + assert 'success' in self.conf( + { + "*:7080": {"pass": "upstreams/one"}, + "unix:" + addr_0: {"pass": "routes/one"}, + "unix:" + addr_1: {"pass": "routes/two"}, + }, + 'listeners', + ), 'configure listeners unix' + + assert 'success' in self.conf( + {"unix:" + addr_0: {}, "unix:" + addr_1: {}}, + 'upstreams/one/servers', + ), 'configure servers unix' resps = self.get_resps_sc() - self.assertEqual(resps[0], 50, 'unix 0') - self.assertEqual(resps[1], 50, 'unix 1') + assert resps[0] == 50, 'unix 0' + assert resps[1] == 50, 'unix 1' def test_upstreams_rr_ipv6(self): - self.assertIn( - 'success', - self.conf( - { - "*:7080": {"pass": "upstreams/one"}, - "[::1]:7081": {"pass": "routes/one"}, - "[::1]:7082": {"pass": "routes/two"}, - }, - 'listeners', - ), - 'configure listeners ipv6', - ) - - self.assertIn( - 'success', - self.conf( - {"[::1]:7081": {}, "[::1]:7082": {}}, 'upstreams/one/servers' - ), - 'configure servers ipv6', - ) + assert 'success' in self.conf( + { + "*:7080": {"pass": "upstreams/one"}, + "[::1]:7081": {"pass": "routes/one"}, + "[::1]:7082": {"pass": "routes/two"}, + }, + 'listeners', + ), 'configure listeners ipv6' + + assert 'success' in self.conf( + {"[::1]:7081": {}, "[::1]:7082": {}}, 'upstreams/one/servers' + ), 'configure servers ipv6' resps = self.get_resps_sc() - self.assertEqual(resps[0], 50, 'ipv6 0') - self.assertEqual(resps[1], 50, 'ipv6 1') + assert resps[0] == 50, 'ipv6 0' + assert resps[1] == 50, 'ipv6 1' def test_upstreams_rr_servers_empty(self): - self.assertIn( - 'success', - self.conf({}, 'upstreams/one/servers'), - 'configure servers empty', - ) - self.assertEqual(self.get()['status'], 502, 'servers empty') - - self.assertIn( - 'success', - self.conf( - {"127.0.0.1:7081": {"weight": 0}}, 'upstreams/one/servers' - ), - 'configure servers empty one', - ) - self.assertEqual(self.get()['status'], 502, 'servers empty one') - self.assertIn( - 'success', - self.conf( - { - "127.0.0.1:7081": {"weight": 0}, - "127.0.0.1:7082": {"weight": 0}, - }, - 'upstreams/one/servers', - ), - 'configure servers empty two', - ) - self.assertEqual(self.get()['status'], 502, 'servers empty two') + assert 'success' in self.conf( + {}, 'upstreams/one/servers' + ), 'configure servers empty' + assert self.get()['status'] == 502, 'servers empty' + + assert 'success' in self.conf( + {"127.0.0.1:7081": {"weight": 0}}, 'upstreams/one/servers' + ), 'configure servers empty one' + assert self.get()['status'] == 502, 'servers empty one' + assert 'success' in self.conf( + { + "127.0.0.1:7081": {"weight": 0}, + "127.0.0.1:7082": {"weight": 0}, + }, + 'upstreams/one/servers', + ), 'configure servers empty two' + assert self.get()['status'] == 502, 'servers empty two' def test_upstreams_rr_invalid(self): - self.assertIn( - 'error', self.conf({}, 'upstreams'), 'upstreams empty', - ) - self.assertIn( - 'error', self.conf({}, 'upstreams/one'), 'named upstreams empty', - ) - self.assertIn( - 'error', - self.conf({}, 'upstreams/one/servers/127.0.0.1'), - 'invalid address', - ) - self.assertIn( - 'error', - self.conf({}, 'upstreams/one/servers/127.0.0.1:7081/blah'), - 'invalid server option', - ) + assert 'error' in self.conf({}, 'upstreams'), 'upstreams empty' + assert 'error' in self.conf( + {}, 'upstreams/one' + ), 'named upstreams empty' + assert 'error' in self.conf( + {}, 'upstreams/one/servers/127.0.0.1' + ), 'invalid address' + assert 'error' in self.conf( + {}, 'upstreams/one/servers/127.0.0.1:7081/blah' + ), 'invalid server option' def check_weight(w): - self.assertIn( - 'error', - self.conf(w, 'upstreams/one/servers/127.0.0.1:7081/weight'), - 'invalid weight option', - ) + assert 'error' in self.conf( + w, 'upstreams/one/servers/127.0.0.1:7081/weight' + ), 'invalid weight option' + check_weight({}) check_weight('-1') check_weight('1.') @@ -571,7 +477,3 @@ Connection: close check_weight('.01234567890123') check_weight('1000001') check_weight('2e6') - - -if __name__ == '__main__': - TestUpstreamsRR.main() diff --git a/test/test_usr1.py b/test/test_usr1.py index d1db652f..19081223 100644 --- a/test/test_usr1.py +++ b/test/test_usr1.py @@ -2,6 +2,7 @@ import os from subprocess import call from unit.applications.lang.python import TestApplicationPython +from conftest import waitforfiles class TestUSR1(TestApplicationPython): @@ -12,83 +13,74 @@ class TestUSR1(TestApplicationPython): log = 'access.log' log_new = 'new.log' - log_path = self.testdir + '/' + log + log_path = self.temp_dir + '/' + log - self.assertIn( - 'success', - self.conf('"' + log_path + '"', 'access_log'), - 'access log configure', - ) + assert 'success' in self.conf( + '"' + log_path + '"', 'access_log' + ), 'access log configure' - self.assertTrue(self.waitforfiles(log_path), 'open') + assert waitforfiles(log_path), 'open' - os.rename(log_path, self.testdir + '/' + log_new) + os.rename(log_path, self.temp_dir + '/' + log_new) - self.assertEqual(self.get()['status'], 200) + assert self.get()['status'] == 200 - self.assertIsNotNone( - self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', log_new), - 'rename new', - ) - self.assertFalse(os.path.isfile(log_path), 'rename old') + assert ( + self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', log_new) + is not None + ), 'rename new' + assert not os.path.isfile(log_path), 'rename old' - with open(self.testdir + '/unit.pid', 'r') as f: + with open(self.temp_dir + '/unit.pid', 'r') as f: pid = f.read().rstrip() call(['kill', '-s', 'USR1', pid]) - self.assertTrue(self.waitforfiles(log_path), 'reopen') + assert waitforfiles(log_path), 'reopen' - self.assertEqual(self.get(url='/usr1')['status'], 200) + assert self.get(url='/usr1')['status'] == 200 self.stop() - self.assertIsNotNone( - self.wait_for_record(r'"GET /usr1 HTTP/1.1" 200 0 "-" "-"', log), - 'reopen 2', - ) - self.assertIsNone( - self.search_in_log(r'/usr1', log_new), 'rename new 2' - ) + assert ( + self.wait_for_record(r'"GET /usr1 HTTP/1.1" 200 0 "-" "-"', log) + is not None + ), 'reopen 2' + assert self.search_in_log(r'/usr1', log_new) is None, 'rename new 2' def test_usr1_unit_log(self): self.load('log_body') log_new = 'new.log' - log_path = self.testdir + '/unit.log' - log_path_new = self.testdir + '/' + log_new + log_path = self.temp_dir + '/unit.log' + log_path_new = self.temp_dir + '/' + log_new os.rename(log_path, log_path_new) body = 'body_for_a_log_new' - self.assertEqual(self.post(body=body)['status'], 200) + assert self.post(body=body)['status'] == 200 - self.assertIsNotNone( - self.wait_for_record(body, log_new), 'rename new' - ) - self.assertFalse(os.path.isfile(log_path), 'rename old') + assert self.wait_for_record(body, log_new) is not None, 'rename new' + assert not os.path.isfile(log_path), 'rename old' - with open(self.testdir + '/unit.pid', 'r') as f: + with open(self.temp_dir + '/unit.pid', 'r') as f: pid = f.read().rstrip() call(['kill', '-s', 'USR1', pid]) - self.assertTrue(self.waitforfiles(log_path), 'reopen') + assert waitforfiles(log_path), 'reopen' body = 'body_for_a_log_unit' - self.assertEqual(self.post(body=body)['status'], 200) + assert self.post(body=body)['status'] == 200 self.stop() - self.assertIsNotNone(self.wait_for_record(body), 'rename new') - self.assertIsNone(self.search_in_log(body, log_new), 'rename new 2') + assert self.wait_for_record(body) is not None, 'rename new' + assert self.search_in_log(body, log_new) is None, 'rename new 2' # merge two log files into unit.log to check alerts - with open(log_path, 'w') as unit_log, \ - open(log_path_new, 'r') as unit_log_new: + with open(log_path, 'w') as unit_log, open( + log_path_new, 'r' + ) as unit_log_new: unit_log.write(unit_log_new.read()) - - -if __name__ == '__main__': - TestUSR1.main() diff --git a/test/test_variables.py b/test/test_variables.py index fb481be5..0fa4296c 100644 --- a/test/test_variables.py +++ b/test/test_variables.py @@ -4,52 +4,48 @@ from unit.applications.proto import TestApplicationProto class TestVariables(TestApplicationProto): prerequisites = {} - def setUp(self): - super().setUp() - - self.assertIn( - 'success', - self.conf( - { - "listeners": {"*:7080": {"pass": "routes/$method"}}, - "routes": { - "GET": [{"action": {"return": 201}}], - "POST": [{"action": {"return": 202}}], - "3": [{"action": {"return": 203}}], - "4*": [{"action": {"return": 204}}], - "blahGET}": [{"action": {"return": 205}}], - "5GET": [{"action": {"return": 206}}], - "GETGET": [{"action": {"return": 207}}], - "localhost": [{"action": {"return": 208}}], - }, + def setup_method(self): + super().setup_method() + + assert 'success' in self.conf( + { + "listeners": {"*:7080": {"pass": "routes/$method"}}, + "routes": { + "GET": [{"action": {"return": 201}}], + "POST": [{"action": {"return": 202}}], + "3": [{"action": {"return": 203}}], + "4*": [{"action": {"return": 204}}], + "blahGET}": [{"action": {"return": 205}}], + "5GET": [{"action": {"return": 206}}], + "GETGET": [{"action": {"return": 207}}], + "localhost": [{"action": {"return": 208}}], }, - ), - 'configure routes', - ) + }, + ), 'configure routes' def conf_routes(self, routes): - self.assertIn('success', self.conf(routes, 'listeners/*:7080/pass')) + assert 'success' in self.conf(routes, 'listeners/*:7080/pass') def test_variables_method(self): - self.assertEqual(self.get()['status'], 201, 'method GET') - self.assertEqual(self.post()['status'], 202, 'method POST') + assert self.get()['status'] == 201, 'method GET' + assert self.post()['status'] == 202, 'method POST' def test_variables_uri(self): self.conf_routes("\"routes$uri\"") - self.assertEqual(self.get(url='/3')['status'], 203, 'uri') - self.assertEqual(self.get(url='/4*')['status'], 204, 'uri 2') - self.assertEqual(self.get(url='/4%2A')['status'], 204, 'uri 3') + assert self.get(url='/3')['status'] == 203, 'uri' + assert self.get(url='/4*')['status'] == 204, 'uri 2' + assert self.get(url='/4%2A')['status'] == 204, 'uri 3' def test_variables_host(self): self.conf_routes("\"routes/$host\"") def check_host(host, status=208): - self.assertEqual( + assert ( self.get(headers={'Host': host, 'Connection': 'close'})[ 'status' - ], - status, + ] + == status ) check_host('localhost') @@ -61,43 +57,41 @@ class TestVariables(TestApplicationProto): def test_variables_many(self): self.conf_routes("\"routes$uri$method\"") - self.assertEqual(self.get(url='/5')['status'], 206, 'many') + assert self.get(url='/5')['status'] == 206, 'many' self.conf_routes("\"routes${uri}${method}\"") - self.assertEqual(self.get(url='/5')['status'], 206, 'many 2') + assert self.get(url='/5')['status'] == 206, 'many 2' self.conf_routes("\"routes${uri}$method\"") - self.assertEqual(self.get(url='/5')['status'], 206, 'many 3') + assert self.get(url='/5')['status'] == 206, 'many 3' self.conf_routes("\"routes/$method$method\"") - self.assertEqual(self.get()['status'], 207, 'many 4') + assert self.get()['status'] == 207, 'many 4' self.conf_routes("\"routes/$method$uri\"") - self.assertEqual(self.get()['status'], 404, 'no route') - self.assertEqual(self.get(url='/blah')['status'], 404, 'no route 2') + assert self.get()['status'] == 404, 'no route' + assert self.get(url='/blah')['status'] == 404, 'no route 2' def test_variables_replace(self): - self.assertEqual(self.get()['status'], 201) + assert self.get()['status'] == 201 self.conf_routes("\"routes$uri\"") - self.assertEqual(self.get(url='/3')['status'], 203) + assert self.get(url='/3')['status'] == 203 self.conf_routes("\"routes/${method}\"") - self.assertEqual(self.post()['status'], 202) + assert self.post()['status'] == 202 self.conf_routes("\"routes${uri}\"") - self.assertEqual(self.get(url='/4*')['status'], 204) + assert self.get(url='/4*')['status'] == 204 self.conf_routes("\"routes/blah$method}\"") - self.assertEqual(self.get()['status'], 205) + assert self.get()['status'] == 205 def test_variables_invalid(self): def check_variables(routes): - self.assertIn( - 'error', - self.conf(routes, 'listeners/*:7080/pass'), - 'invalid variables', - ) + assert 'error' in self.conf( + routes, 'listeners/*:7080/pass' + ), 'invalid variables' check_variables("\"routes$\"") check_variables("\"routes${\"") @@ -106,6 +100,3 @@ class TestVariables(TestApplicationProto): check_variables("\"routes$uriblah\"") check_variables("\"routes${uri\"") check_variables("\"routes${{uri}\"") - -if __name__ == '__main__': - TestVariables.main() diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 83bde4d8..069bdecb 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -2,17 +2,18 @@ import os import subprocess from unit.applications.proto import TestApplicationProto +from conftest import option class TestApplicationGo(TestApplicationProto): @classmethod - def setUpClass(cls, complete_check=True): - unit = super().setUpClass(complete_check=False) + def setup_class(cls, complete_check=True): + unit = super().setup_class(complete_check=False) # check go module go_app = TestApplicationGo() - go_app.testdir = unit.testdir + go_app.temp_dir = unit.temp_dir proc = go_app.prepare_env('empty', 'app') if proc and proc.returncode == 0: cls.available['modules']['go'] = [] @@ -20,8 +21,8 @@ class TestApplicationGo(TestApplicationProto): return unit if not complete_check else unit.complete() def prepare_env(self, script, name, static=False): - if not os.path.exists(self.testdir + '/go'): - os.mkdir(self.testdir + '/go') + if not os.path.exists(self.temp_dir + '/go'): + os.mkdir(self.temp_dir + '/go') env = os.environ.copy() env['GOPATH'] = self.pardir + '/build/go' @@ -35,16 +36,16 @@ class TestApplicationGo(TestApplicationProto): '-ldflags', '-extldflags "-static"', '-o', - self.testdir + '/go/' + name, - self.current_dir + '/go/' + script + '/' + name + '.go', + self.temp_dir + '/go/' + name, + option.test_dir + '/go/' + script + '/' + name + '.go', ] else: args = [ 'go', 'build', '-o', - self.testdir + '/go/' + name, - self.current_dir + '/go/' + script + '/' + name + '.go', + self.temp_dir + '/go/' + name, + option.test_dir + '/go/' + script + '/' + name + '.go', ] try: @@ -59,8 +60,8 @@ class TestApplicationGo(TestApplicationProto): def load(self, script, name='app', **kwargs): static_build = False - wdir = self.current_dir + "/go/" + script - executable = self.testdir + "/go/" + name + wdir = option.test_dir + "/go/" + script + executable = self.temp_dir + "/go/" + name if 'isolation' in kwargs and 'rootfs' in kwargs['isolation']: wdir = "/go/" diff --git a/test/unit/applications/lang/java.py b/test/unit/applications/lang/java.py index c2c6dc51..b5511883 100644 --- a/test/unit/applications/lang/java.py +++ b/test/unit/applications/lang/java.py @@ -1,17 +1,19 @@ import glob import os +import pytest import shutil import subprocess from unit.applications.proto import TestApplicationProto +from conftest import option class TestApplicationJava(TestApplicationProto): def load(self, script, name='app', **kwargs): - app_path = self.testdir + '/java' + app_path = self.temp_dir + '/java' web_inf_path = app_path + '/WEB-INF/' classes_path = web_inf_path + 'classes/' - script_path = self.current_dir + '/java/' + script + '/' + script_path = option.test_dir + '/java/' + script + '/' if not os.path.isdir(app_path): os.makedirs(app_path) @@ -54,7 +56,7 @@ class TestApplicationJava(TestApplicationProto): ) if not ws_jars: - self.fail('websocket api jar not found.') + pytest.fail('websocket api jar not found.') javac = [ 'javac', @@ -69,7 +71,7 @@ class TestApplicationJava(TestApplicationProto): process.communicate() except: - self.fail('Cann\'t run javac process.') + pytest.fail('Cann\'t run javac process.') self._load_conf( { diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index cf2a99f6..f510acce 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -3,12 +3,13 @@ import shutil from urllib.parse import quote from unit.applications.proto import TestApplicationProto +from conftest import option, public_dir class TestApplicationNode(TestApplicationProto): @classmethod - def setUpClass(cls, complete_check=True): - unit = super().setUpClass(complete_check=False) + def setup_class(cls, complete_check=True): + unit = super().setup_class(complete_check=False) # check node module @@ -21,17 +22,17 @@ class TestApplicationNode(TestApplicationProto): # copy application shutil.copytree( - self.current_dir + '/node/' + script, self.testdir + '/node' + option.test_dir + '/node/' + script, self.temp_dir + '/node' ) # copy modules shutil.copytree( self.pardir + '/node/node_modules', - self.testdir + '/node/node_modules', + self.temp_dir + '/node/node_modules', ) - self.public_dir(self.testdir + '/node') + public_dir(self.temp_dir + '/node') self._load_conf( { @@ -42,7 +43,7 @@ class TestApplicationNode(TestApplicationProto): script: { "type": "external", "processes": {"spare": 0}, - "working_directory": self.testdir + '/node', + "working_directory": self.temp_dir + '/node', "executable": name, } }, diff --git a/test/unit/applications/lang/perl.py b/test/unit/applications/lang/perl.py index d32aca33..92939d88 100644 --- a/test/unit/applications/lang/perl.py +++ b/test/unit/applications/lang/perl.py @@ -1,11 +1,12 @@ from unit.applications.proto import TestApplicationProto +from conftest import option class TestApplicationPerl(TestApplicationProto): application_type = "perl" def load(self, script, name='psgi.pl', **kwargs): - script_path = self.current_dir + '/perl/' + script + script_path = option.test_dir + '/perl/' + script self._load_conf( { diff --git a/test/unit/applications/lang/php.py b/test/unit/applications/lang/php.py index e8c70c62..350eb29b 100644 --- a/test/unit/applications/lang/php.py +++ b/test/unit/applications/lang/php.py @@ -1,11 +1,12 @@ from unit.applications.proto import TestApplicationProto +from conftest import option class TestApplicationPHP(TestApplicationProto): application_type = "php" def load(self, script, index='index.php', **kwargs): - script_path = self.current_dir + '/php/' + script + script_path = option.test_dir + '/php/' + script self._load_conf( { diff --git a/test/unit/applications/lang/python.py b/test/unit/applications/lang/python.py index 91559f4b..dcdd2ffe 100644 --- a/test/unit/applications/lang/python.py +++ b/test/unit/applications/lang/python.py @@ -1,20 +1,23 @@ import os import shutil +import pytest from unit.applications.proto import TestApplicationProto +from conftest import option class TestApplicationPython(TestApplicationProto): application_type = "python" def load(self, script, name=None, **kwargs): + print() if name is None: name = script if script[0] == '/': script_path = script else: - script_path = self.current_dir + '/python/' + script + script_path = option.test_dir + '/python/' + script if kwargs.get('isolation') and kwargs['isolation'].get('rootfs'): rootfs = kwargs['isolation']['rootfs'] @@ -27,12 +30,17 @@ class TestApplicationPython(TestApplicationProto): script_path = '/app/python/' + name + appication_type = self.get_appication_type() + + if appication_type is None: + appication_type = self.application_type + self._load_conf( { "listeners": {"*:7080": {"pass": "applications/" + name}}, "applications": { name: { - "type": self.application_type, + "type": appication_type, "processes": {"spare": 0}, "path": script_path, "working_directory": script_path, diff --git a/test/unit/applications/lang/ruby.py b/test/unit/applications/lang/ruby.py index 8c8acecc..534227bd 100644 --- a/test/unit/applications/lang/ruby.py +++ b/test/unit/applications/lang/ruby.py @@ -1,11 +1,12 @@ from unit.applications.proto import TestApplicationProto +from conftest import option class TestApplicationRuby(TestApplicationProto): application_type = "ruby" def load(self, script, name='config.ru', **kwargs): - script_path = self.current_dir + '/ruby/' + script + script_path = option.test_dir + '/ruby/' + script self._load_conf( { diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index 244cb5be..7bf7e244 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -1,7 +1,9 @@ +import os import re import time from unit.control import TestControl +from conftest import option class TestApplicationProto(TestControl): @@ -12,7 +14,7 @@ class TestApplicationProto(TestControl): return time.mktime(time.strptime(date, template)) def search_in_log(self, pattern, name='unit.log'): - with open(self.testdir + '/' + name, 'r', errors='ignore') as f: + with open(self.temp_dir + '/' + name, 'r', errors='ignore') as f: return re.search(pattern, f.read()) def wait_for_record(self, pattern, name='unit.log'): @@ -26,6 +28,16 @@ class TestApplicationProto(TestControl): return found + def get_appication_type(self): + current_test = ( + os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0] + ) + + if current_test in option.generated_tests: + return option.generated_tests[current_test] + + return None + def _load_conf(self, conf, **kwargs): if 'applications' in conf: for app in conf['applications'].keys(): @@ -39,6 +51,4 @@ class TestApplicationProto(TestControl): if 'isolation' in kwargs: app_conf['isolation'] = kwargs['isolation'] - self.assertIn( - 'success', self.conf(conf), 'load application configuration' - ) + assert 'success' in self.conf(conf), 'load application configuration' diff --git a/test/unit/applications/tls.py b/test/unit/applications/tls.py index e6a846b2..5453eef0 100644 --- a/test/unit/applications/tls.py +++ b/test/unit/applications/tls.py @@ -4,19 +4,20 @@ import ssl import subprocess from unit.applications.proto import TestApplicationProto +from conftest import option class TestApplicationTLS(TestApplicationProto): - def __init__(self, test): - super().__init__(test) + def setup_method(self): + super().setup_method() self.context = ssl.create_default_context() self.context.check_hostname = False self.context.verify_mode = ssl.CERT_NONE @classmethod - def setUpClass(cls, complete_check=True): - unit = super().setUpClass(complete_check=False) + def setup_class(cls, complete_check=True): + unit = super().setup_class(complete_check=False) # check tls module @@ -45,9 +46,9 @@ class TestApplicationTLS(TestApplicationProto): '-x509', '-new', '-subj', '/CN=' + name + '/', - '-config', self.testdir + '/openssl.conf', - '-out', self.testdir + '/' + name + '.crt', - '-keyout', self.testdir + '/' + name + '.key', + '-config', self.temp_dir + '/openssl.conf', + '-out', self.temp_dir + '/' + name + '.crt', + '-keyout', self.temp_dir + '/' + name + '.key', ], stderr=subprocess.STDOUT, ) @@ -59,8 +60,8 @@ class TestApplicationTLS(TestApplicationProto): if key is None: key = crt - key_path = self.testdir + '/' + key + '.key' - crt_path = self.testdir + '/' + crt + '.crt' + key_path = self.temp_dir + '/' + key + '.key' + crt_path = self.temp_dir + '/' + crt + '.crt' with open(key_path, 'rb') as k, open(crt_path, 'rb') as c: return self.conf(k.read() + c.read(), '/certificates/' + crt) @@ -87,7 +88,7 @@ class TestApplicationTLS(TestApplicationProto): return ssl.get_server_certificate(addr, ssl_version=ssl_version) def openssl_conf(self): - conf_path = self.testdir + '/openssl.conf' + conf_path = self.temp_dir + '/openssl.conf' if os.path.exists(conf_path): return @@ -105,7 +106,7 @@ distinguished_name = req_distinguished_name if name is None: name = script - script_path = self.current_dir + '/python/' + script + script_path = option.test_dir + '/python/' + script self._load_conf( { diff --git a/test/unit/applications/websockets.py b/test/unit/applications/websockets.py index e0dd2c0d..f1ddf630 100644 --- a/test/unit/applications/websockets.py +++ b/test/unit/applications/websockets.py @@ -1,6 +1,7 @@ import base64 import hashlib import itertools +import pytest import random import re import select @@ -21,9 +22,6 @@ class TestApplicationWebsocket(TestApplicationProto): OP_PONG = 0x0A CLOSE_CODES = [1000, 1001, 1002, 1003, 1007, 1008, 1009, 1010, 1011] - def __init__(self, preinit=False): - self.preinit = preinit - def key(self): raw_key = bytes(random.getrandbits(8) for _ in range(16)) return base64.b64encode(raw_key).decode() @@ -56,7 +54,7 @@ class TestApplicationWebsocket(TestApplicationProto): while True: rlist = select.select([sock], [], [], 60)[0] if not rlist: - self.fail('Can\'t read response from server.') + pytest.fail('Can\'t read response from server.') resp += sock.recv(4096).decode() @@ -84,7 +82,7 @@ class TestApplicationWebsocket(TestApplicationProto): # For all current cases if the "read_timeout" was changed # than test do not expect to get a response from server. if read_timeout == 60: - self.fail('Can\'t read response from server.') + pytest.fail('Can\'t read response from server.') break data += sock.recv(bytes - len(data)) @@ -130,19 +128,19 @@ class TestApplicationWebsocket(TestApplicationProto): code, = struct.unpack('!H', data[:2]) reason = data[2:].decode('utf-8') if not (code in self.CLOSE_CODES or 3000 <= code < 5000): - self.fail('Invalid status code') + pytest.fail('Invalid status code') frame['code'] = code frame['reason'] = reason elif length == 0: frame['code'] = 1005 frame['reason'] = '' else: - self.fail('Close frame too short') + pytest.fail('Close frame too short') frame['data'] = data if frame['mask']: - self.fail('Received frame with mask') + pytest.fail('Received frame with mask') return frame diff --git a/test/unit/control.py b/test/unit/control.py index 029072b5..6fd350f4 100644 --- a/test/unit/control.py +++ b/test/unit/control.py @@ -53,7 +53,7 @@ class TestControl(TestHTTP): args = { 'url': url, 'sock_type': 'unix', - 'addr': self.testdir + '/control.unit.sock', + 'addr': self.temp_dir + '/control.unit.sock', } if conf is not None: diff --git a/test/unit/feature/isolation.py b/test/unit/feature/isolation.py index 4f33d04a..c6f6f3c0 100644 --- a/test/unit/feature/isolation.py +++ b/test/unit/feature/isolation.py @@ -13,7 +13,7 @@ from unit.applications.proto import TestApplicationProto class TestFeatureIsolation(TestApplicationProto): allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net'] - def check(self, available, testdir): + def check(self, available, temp_dir): test_conf = {"namespaces": {"credential": True}} module = '' @@ -45,7 +45,7 @@ class TestFeatureIsolation(TestApplicationProto): if not module: return - module.testdir = testdir + module.temp_dir = temp_dir module.load(app) resp = module.conf(test_conf, 'applications/' + app + '/isolation') diff --git a/test/unit/http.py b/test/unit/http.py index de3bb2a4..54d32c06 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -2,12 +2,14 @@ import binascii import io import json import os +import pytest import re import select import socket import time from unit.main import TestUnit +from conftest import option class TestHTTP(TestUnit): @@ -56,7 +58,7 @@ class TestHTTP(TestUnit): sock.connect(connect_args) except ConnectionRefusedError: sock.close() - self.fail('Client can\'t connect to the server.') + pytest.fail('Client can\'t connect to the server.') else: sock = kwargs['sock'] @@ -128,7 +130,7 @@ class TestHTTP(TestUnit): return (resp, sock) def log_out(self, log, encoding): - if TestUnit.detailed: + if option.detailed: print('>>>') log = self.log_truncate(log) try: @@ -137,7 +139,7 @@ class TestHTTP(TestUnit): print(log) def log_in(self, log): - if TestUnit.detailed: + if option.detailed: print('<<<') log = self.log_truncate(log) try: @@ -190,7 +192,7 @@ class TestHTTP(TestUnit): # For all current cases if the "read_timeout" was changed # than test do not expect to get a response from server. if timeout == timeout_default: - self.fail('Can\'t read response from server.') + pytest.fail('Can\'t read response from server.') break try: @@ -243,28 +245,28 @@ class TestHTTP(TestUnit): chunks = raw_body.split(crlf) if len(chunks) < 3: - self.fail('Invalid chunked body') + pytest.fail('Invalid chunked body') if chunks.pop() != b'': - self.fail('No CRLF at the end of the body') + pytest.fail('No CRLF at the end of the body') try: last_size = int(chunks[-2], 16) except: - self.fail('Invalid zero size chunk') + pytest.fail('Invalid zero size chunk') if last_size != 0 or chunks[-1] != b'': - self.fail('Incomplete body') + pytest.fail('Incomplete body') body = b'' while len(chunks) >= 2: try: size = int(chunks.pop(0), 16) except: - self.fail('Invalid chunk size %s' % str(size)) + pytest.fail('Invalid chunk size %s' % str(size)) if size == 0: - self.assertEqual(len(chunks), 1, 'last zero size') + assert len(chunks) == 1, 'last zero size' break temp_body = crlf.join(chunks) @@ -280,8 +282,8 @@ class TestHTTP(TestUnit): def _parse_json(self, resp): headers = resp['headers'] - self.assertIn('Content-Type', headers) - self.assertEqual(headers['Content-Type'], 'application/json') + assert 'Content-Type' in headers + assert headers['Content-Type'] == 'application/json' resp['body'] = json.loads(resp['body']) @@ -305,7 +307,7 @@ class TestHTTP(TestUnit): sock.close() - self.assertTrue(ret, 'socket connected') + assert ret, 'socket connected' def form_encode(self, fields): is_multipart = False @@ -345,7 +347,7 @@ class TestHTTP(TestUnit): datatype = value['type'] if not isinstance(value['data'], io.IOBase): - self.fail('multipart encoding of file requires a stream.') + pytest.fail('multipart encoding of file requires a stream.') data = value['data'].read() @@ -353,7 +355,7 @@ class TestHTTP(TestUnit): data = value else: - self.fail('multipart requires a string or stream data') + pytest.fail('multipart requires a string or stream data') body += ( "--%s\r\nContent-Disposition: form-data; name=\"%s\"" diff --git a/test/unit/main.py b/test/unit/main.py index 83aa9139..18ea326e 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -1,8 +1,8 @@ import argparse import atexit -import fcntl import os import platform +import pytest import re import shutil import signal @@ -11,80 +11,19 @@ import subprocess import sys import tempfile import time -import unittest +from conftest import option, public_dir, waitforfiles, _check_alerts, _print_log from multiprocessing import Process -class TestUnit(unittest.TestCase): +class TestUnit(): - current_dir = os.path.abspath( - os.path.join(os.path.dirname(__file__), os.pardir) - ) pardir = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir, os.pardir) ) - is_su = os.geteuid() == 0 - uid = os.geteuid() - gid = os.getegid() - architecture = platform.architecture()[0] - system = platform.system() - maxDiff = None - - detailed = False - save_log = False - print_log = False - unsafe = False - - def __init__(self, methodName='runTest'): - super().__init__(methodName) - - if re.match(r'.*\/run\.py$', sys.argv[0]): - args, rest = TestUnit._parse_args() - - TestUnit._set_args(args) - - def run(self, result=None): - if not hasattr(self, 'application_type'): - return super().run(result) - - # rerun test for each available module version - - type = self.application_type - for module in self.prerequisites['modules']: - if module in self.available['modules']: - prereq_version = self.prerequisites['modules'][module] - available_versions = self.available['modules'][module] - - if prereq_version == 'all': - for version in available_versions: - self.application_type = type + ' ' + version - super().run(result) - elif prereq_version == 'any': - self.application_type = type + ' ' + available_versions[0] - super().run(result) - else: - for version in available_versions: - if version.startswith(prereq_version): - self.application_type = type + ' ' + version - super().run(result) - - @classmethod - def main(cls): - args, rest = TestUnit._parse_args() - - for i, arg in enumerate(rest): - if arg[:5] == 'test_': - rest[i] = cls.__name__ + '.' + arg - - sys.argv = sys.argv[:1] + rest - - TestUnit._set_args(args) - - unittest.main() @classmethod - def setUpClass(cls, complete_check=True): - cls.available = {'modules': {}, 'features': {}} + def setup_class(cls, complete_check=True): + cls.available = option.available unit = TestUnit() unit._run() @@ -92,7 +31,7 @@ class TestUnit(unittest.TestCase): # read unit.log for i in range(50): - with open(unit.testdir + '/unit.log', 'r') as f: + with open(unit.temp_dir + '/unit.log', 'r') as f: log = f.read() m = re.search('controller started', log) @@ -102,7 +41,7 @@ class TestUnit(unittest.TestCase): break if m is None: - unit._print_log() + _print_log() exit("Unit is writing log too long") # discover available modules from unit.log @@ -128,8 +67,7 @@ class TestUnit(unittest.TestCase): missed.append(module) if missed: - print('Unit has no ' + ', '.join(missed) + ' module(s)') - raise unittest.SkipTest() + pytest.skip('Unit has no ' + ', '.join(missed) + ' module(s)') # check features @@ -143,13 +81,12 @@ class TestUnit(unittest.TestCase): missed.append(feature) if missed: - print(', '.join(missed) + ' feature(s) not supported') - raise unittest.SkipTest() + pytest.skip(', '.join(missed) + ' feature(s) not supported') def destroy(): unit.stop() - unit._check_alerts(log) - shutil.rmtree(unit.testdir) + _check_alerts(log) + shutil.rmtree(unit.temp_dir) def complete(): destroy() @@ -161,7 +98,7 @@ class TestUnit(unittest.TestCase): unit.complete = complete return unit - def setUp(self): + def setup_method(self): self._run() def _run(self): @@ -171,82 +108,56 @@ class TestUnit(unittest.TestCase): if not os.path.isfile(self.unitd): exit("Could not find unit") - self.testdir = tempfile.mkdtemp(prefix='unit-test-') + self.temp_dir = tempfile.mkdtemp(prefix='unit-test-') - self.public_dir(self.testdir) + public_dir(self.temp_dir) if oct(stat.S_IMODE(os.stat(build_dir).st_mode)) != '0o777': - self.public_dir(build_dir) + public_dir(build_dir) - os.mkdir(self.testdir + '/state') + os.mkdir(self.temp_dir + '/state') - with open(self.testdir + '/unit.log', 'w') as log: + with open(self.temp_dir + '/unit.log', 'w') as log: self._p = subprocess.Popen( [ self.unitd, '--no-daemon', '--modules', self.pardir + '/build', - '--state', self.testdir + '/state', - '--pid', self.testdir + '/unit.pid', - '--log', self.testdir + '/unit.log', - '--control', 'unix:' + self.testdir + '/control.unit.sock', - '--tmp', self.testdir, + '--state', self.temp_dir + '/state', + '--pid', self.temp_dir + '/unit.pid', + '--log', self.temp_dir + '/unit.log', + '--control', 'unix:' + self.temp_dir + '/control.unit.sock', + '--tmp', self.temp_dir, ], stderr=log, ) atexit.register(self.stop) - if not self.waitforfiles(self.testdir + '/control.unit.sock'): - self._print_log() + if not waitforfiles(self.temp_dir + '/control.unit.sock'): + _print_log() exit("Could not start unit") self._started = True - self.skip_alerts = [ - r'read signalfd\(4\) failed', - r'sendmsg.+failed', - r'recvmsg.+failed', - ] - self.skip_sanitizer = False - - def tearDown(self): + def teardown_method(self): self.stop() - # detect errors and failures for current test - - def list2reason(exc_list): - if exc_list and exc_list[-1][0] is self: - return exc_list[-1][1] - - if hasattr(self, '_outcome'): - result = self.defaultTestResult() - self._feedErrorsToResult(result, self._outcome.errors) - else: - result = getattr( - self, '_outcomeForDoCleanups', self._resultForDoCleanups - ) - - success = not list2reason(result.errors) and not list2reason( - result.failures - ) - # check unit.log for alerts - unit_log = self.testdir + '/unit.log' + unit_log = self.temp_dir + '/unit.log' with open(unit_log, 'r', encoding='utf-8', errors='ignore') as f: - self._check_alerts(f.read()) + _check_alerts(f.read()) # remove unit.log - if not TestUnit.save_log and success: - shutil.rmtree(self.testdir) - + if not option.save_log: + shutil.rmtree(self.temp_dir) else: - self._print_log() + _print_log() - self.assertListEqual(self.stop_errors, [None, None], 'stop errors') + assert self.stop_errors == [None, None], 'stop errors' def stop(self): if not self._started: @@ -301,121 +212,3 @@ class TestUnit(unittest.TestCase): if fail: return 'Fail to stop process' - - def waitforfiles(self, *files): - for i in range(50): - wait = False - ret = False - - for f in files: - if not os.path.exists(f): - wait = True - break - - if wait: - time.sleep(0.1) - - else: - ret = True - break - - return ret - - def public_dir(self, path): - os.chmod(path, 0o777) - - for root, dirs, files in os.walk(path): - for d in dirs: - os.chmod(os.path.join(root, d), 0o777) - for f in files: - os.chmod(os.path.join(root, f), 0o777) - - def _check_alerts(self, log): - found = False - - alerts = re.findall('.+\[alert\].+', log) - - if alerts: - print('All alerts/sanitizer errors found in log:') - [print(alert) for alert in alerts] - found = True - - if self.skip_alerts: - for skip in self.skip_alerts: - alerts = [al for al in alerts if re.search(skip, al) is None] - - if alerts: - self._print_log(log) - self.assertFalse(alerts, 'alert(s)') - - if not self.skip_sanitizer: - sanitizer_errors = re.findall('.+Sanitizer.+', log) - - if sanitizer_errors: - self._print_log(log) - self.assertFalse(sanitizer_errors, 'sanitizer error(s)') - - if found: - print('skipped.') - - @staticmethod - def _parse_args(): - parser = argparse.ArgumentParser(add_help=False) - - parser.add_argument( - '-d', - '--detailed', - dest='detailed', - action='store_true', - help='Detailed output for tests', - ) - parser.add_argument( - '-l', - '--log', - dest='save_log', - action='store_true', - help='Save unit.log after the test execution', - ) - parser.add_argument( - '-r', - '--reprint_log', - dest='print_log', - action='store_true', - help='Print unit.log to stdout in case of errors', - ) - parser.add_argument( - '-u', - '--unsafe', - dest='unsafe', - action='store_true', - help='Run unsafe tests', - ) - - return parser.parse_known_args() - - @staticmethod - def _set_args(args): - TestUnit.detailed = args.detailed - TestUnit.save_log = args.save_log - TestUnit.print_log = args.print_log - TestUnit.unsafe = args.unsafe - - # set stdout to non-blocking - - if TestUnit.detailed or TestUnit.print_log: - fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, 0) - - def _print_log(self, data=None): - path = self.testdir + '/unit.log' - - print('Path to unit.log:\n' + path + '\n') - - if TestUnit.print_log: - os.set_blocking(sys.stdout.fileno(), True) - sys.stdout.flush() - - if data is None: - with open(path, 'r', encoding='utf-8', errors='ignore') as f: - shutil.copyfileobj(f, sys.stdout) - else: - sys.stdout.write(data) -- cgit From 806135f1c93c09bb513efc1341d084951b080278 Mon Sep 17 00:00:00 2001 From: hongzhidao Date: Fri, 28 Aug 2020 00:53:36 -0400 Subject: Router: fixed "pass" to upstreams. Messed up return values in nxt_upstream_find() caused error in applying any configuration with a valid "pass" value in router configuration pointing to upstream. That wasn't the case in "listeners" objects, where the return value wasn't checked. Also, it caused segfault in cases where the "pass" option was configured with variables and resulting value was pointing to a non-existent upstream. Added missing return checks as well to catch possible memory allocation errors. The bug was introduced in d32bc428f46b. This closes #472 issue on GitHub. --- test/test_routing.py | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'test') diff --git a/test/test_routing.py b/test/test_routing.py index 4107f57e..734825ef 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -329,11 +329,90 @@ class TestRouting(TestApplicationProto): [{"match": {"method": "GET"}}], 'routes' ), 'route pass absent configure' + def test_routes_route_pass(self): + assert 'success' in self.conf( + { + "applications": { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + "upstreams": { + "one": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, + }, + "two": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, + }, + }, + } + ) + + assert 'success' in self.conf( + [{"action": {"pass": "routes"}}], 'routes' + ) + assert 'success' in self.conf( + [{"action": {"pass": "applications/app"}}], 'routes' + ) + assert 'success' in self.conf( + [{"action": {"pass": "upstreams/one"}}], 'routes' + ) + def test_routes_route_pass_absent(self): assert 'error' in self.conf( [{"match": {"method": "GET"}, "action": {}}], 'routes' ), 'route pass absent configure' + def test_routes_route_pass_invalid(self): + assert 'success' in self.conf( + { + "applications": { + "app": { + "type": "python", + "processes": {"spare": 0}, + "path": "/app", + "module": "wsgi", + } + }, + "upstreams": { + "one": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, + }, + "two": { + "servers": { + "127.0.0.1:7081": {}, + "127.0.0.1:7082": {}, + }, + }, + }, + } + ) + + assert 'error' in self.conf( + [{"action": {"pass": "blah"}}], 'routes' + ), 'route pass invalid' + assert 'error' in self.conf( + [{"action": {"pass": "routes/blah"}}], 'routes' + ), 'route pass routes invalid' + assert 'error' in self.conf( + [{"action": {"pass": "applications/blah"}}], 'routes' + ), 'route pass applications invalid' + assert 'error' in self.conf( + [{"action": {"pass": "upstreams/blah"}}], 'routes' + ), 'route pass upstreams invalid' + def test_routes_action_unique(self): assert 'success' in self.conf( { -- cgit From af964488bad7fe00855749520d929ea1cb0de9d4 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Mon, 21 Sep 2020 10:32:14 +0300 Subject: Tests: changing Python application callable name. --- test/python/callable/wsgi.py | 7 +++++++ test/test_python_application.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 test/python/callable/wsgi.py (limited to 'test') diff --git a/test/python/callable/wsgi.py b/test/python/callable/wsgi.py new file mode 100644 index 00000000..365f82fa --- /dev/null +++ b/test/python/callable/wsgi.py @@ -0,0 +1,7 @@ +def application(env, start_response): + start_response('204', [('Content-Length', '0')]) + return [] + +def app(env, start_response): + start_response('200', [('Content-Length', '0')]) + return [] diff --git a/test/test_python_application.py b/test/test_python_application.py index d1079116..e6ad6a01 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -797,3 +797,31 @@ last line: 987654321 obj = self.getjson()['body'] assert obj['UID'] == nobody_uid, 'root uid group=root' assert obj['GID'] == 0, 'root gid group=root' + + def test_python_application_callable(self): + skip_alert(r'Python failed to get "blah" from module') + self.load('callable') + + assert self.get()['status'] == 204, 'default application response' + + assert 'success' in self.conf( + '"app"', 'applications/callable/callable' + ) + + assert self.get()['status'] == 200, 'callable response' + + assert 'success' in self.conf( + '"blah"', 'applications/callable/callable' + ) + + assert self.get()['status'] not in [200, 204], 'callable response inv' + + assert 'success' in self.conf( + '"app"', 'applications/callable/callable' + ) + + assert self.get()['status'] == 200, 'callable response 2' + + assert 'success' in self.conf_delete('applications/callable/callable') + + assert self.get()['status'] == 204, 'default response 2' -- cgit From 449652afa16160aaf2e36c81b64b0220e6ba96b1 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Mon, 21 Sep 2020 21:18:13 +0300 Subject: Tests: added multiple headers concatenation test. --- test/test_python_application.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/test_python_application.py b/test/test_python_application.py index e6ad6a01..434ceb19 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -20,14 +20,18 @@ class TestPythonApplication(TestApplicationPython): body = 'Test body string.' - resp = self.post( - headers={ - 'Host': 'localhost', - 'Content-Type': 'text/html', - 'Custom-Header': 'blah', - 'Connection': 'close', - }, - body=body, + resp = self.http( + b"""POST / HTTP/1.1 +Host: localhost +Content-Length: %d +Custom-Header: blah +Custom-hEader: Blah +Content-Type: text/html +Connection: close +custom-header: BLAH + +%s""" % (len(body), body.encode()), + raw=True, ) assert resp['status'] == 200, 'status' @@ -52,7 +56,7 @@ class TestPythonApplication(TestApplicationPython): 'Request-Uri': '/', 'Http-Host': 'localhost', 'Server-Protocol': 'HTTP/1.1', - 'Custom-Header': 'blah', + 'Custom-Header': 'blah, Blah, BLAH', 'Wsgi-Version': '(1, 0)', 'Wsgi-Url-Scheme': 'http', 'Wsgi-Multithread': 'False', -- cgit From 39008c1f05b30e9ac51cf7c46743c9d2dc34f505 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 21 Sep 2020 21:24:42 +0100 Subject: Tests: added test for "idle_timeout" with empty payload. --- test/test_settings.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'test') diff --git a/test/test_settings.py b/test/test_settings.py index 59b4a048..797af5ed 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -203,6 +203,24 @@ Connection: close assert resp['status'] == 408, 'status idle timeout' + def test_settings_idle_timeout_2(self): + self.load('empty') + + assert self.get()['status'] == 200, 'init' + + self.conf({'http': {'idle_timeout': 1}}, 'settings') + + _, sock = self.http(b'', start=True, raw=True, no_recv=True) + + time.sleep(2) + + assert ( + self.get( + headers={'Host': 'localhost', 'Connection': 'close'}, sock=sock + )['status'] + == 408 + ), 'status idle timeout' + def test_settings_max_body_size(self): self.load('empty') -- cgit From 98c86c415caa5d40744f26f72c0d20a0bde058ee Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 21 Sep 2020 21:29:34 +0100 Subject: Tests: added variable test with nonexistent upstream. --- test/test_variables.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'test') diff --git a/test/test_variables.py b/test/test_variables.py index 0fa4296c..c458b636 100644 --- a/test/test_variables.py +++ b/test/test_variables.py @@ -87,6 +87,29 @@ class TestVariables(TestApplicationProto): self.conf_routes("\"routes/blah$method}\"") assert self.get()['status'] == 205 + def test_variables_upstream(self): + assert 'success' in self.conf( + { + "listeners": { + "*:7080": {"pass": "upstreams$uri"}, + "*:7081": {"pass": "routes/one"}, + }, + "upstreams": { + "1": { + "servers": { + "127.0.0.1:7081": {}, + }, + }, + }, + "routes": { + "one": [{"action": {"return": 200}}], + }, + }, + ), 'upstreams initial configuration' + + assert self.get(url='/1')['status'] == 200 + assert self.get(url='/2')['status'] == 404 + def test_variables_invalid(self): def check_variables(routes): assert 'error' in self.conf( -- cgit From 767c4cb50899d6086430ff4ed86d06352ffa974d Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 22 Sep 2020 12:40:18 +0300 Subject: Tests: using dict.get() method with default value. No functional changes. Only code readability improved. --- test/unit/http.py | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) (limited to 'test') diff --git a/test/unit/http.py b/test/unit/http.py index 54d32c06..e5231b3d 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -14,20 +14,15 @@ from conftest import option class TestHTTP(TestUnit): def http(self, start_str, **kwargs): - sock_type = ( - 'ipv4' if 'sock_type' not in kwargs else kwargs['sock_type'] - ) - port = 7080 if 'port' not in kwargs else kwargs['port'] - url = '/' if 'url' not in kwargs else kwargs['url'] + sock_type = kwargs.get('sock_type', 'ipv4') + port = kwargs.get('port', 7080) + url = kwargs.get('url', '/') http = 'HTTP/1.0' if 'http_10' in kwargs else 'HTTP/1.1' - headers = ( - {'Host': 'localhost', 'Connection': 'close'} - if 'headers' not in kwargs - else kwargs['headers'] - ) + headers = kwargs.get('headers', + {'Host': 'localhost', 'Connection': 'close'}) - body = b'' if 'body' not in kwargs else kwargs['body'] + body = kwargs.get('body', b'') crlf = '\r\n' if 'addr' not in kwargs: @@ -92,7 +87,7 @@ class TestHTTP(TestUnit): sock.sendall(req) - encoding = 'utf-8' if 'encoding' not in kwargs else kwargs['encoding'] + encoding = kwargs.get('encoding', 'utf-8') self.log_out(req, encoding) @@ -178,12 +173,8 @@ class TestHTTP(TestUnit): def recvall(self, sock, **kwargs): timeout_default = 60 - timeout = ( - timeout_default - if 'read_timeout' not in kwargs - else kwargs['read_timeout'] - ) - buff_size = 4096 if 'buff_size' not in kwargs else kwargs['buff_size'] + timeout = kwargs.get('read_timeout', timeout_default) + buff_size = kwargs.get('buff_size', 4096) data = b'' while True: -- cgit From dc49c561e204fd70008aa6af8c6171ef7d227db1 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 22 Sep 2020 12:40:35 +0300 Subject: Tests: improved response receiving while upgrade. The patch required to process non-101 response. --- test/unit/applications/websockets.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'test') diff --git a/test/unit/applications/websockets.py b/test/unit/applications/websockets.py index f1ddf630..cb9f40aa 100644 --- a/test/unit/applications/websockets.py +++ b/test/unit/applications/websockets.py @@ -58,10 +58,7 @@ class TestApplicationWebsocket(TestApplicationProto): resp += sock.recv(4096).decode() - if ( - re.search('101 Switching Protocols', resp) - and resp[-4:] == '\r\n\r\n' - ): + if (resp.startswith('HTTP/') and '\r\n\r\n' in resp): resp = self._resp_to_dict(resp) break -- cgit From 1fc51cf140d22958d6dcf7e7729826b0f9671fd7 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 22 Sep 2020 19:53:19 +0300 Subject: Tests: introduced module name configuration. Also fixed problem with "/" in application name. --- test/unit/applications/lang/python.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/unit/applications/lang/python.py b/test/unit/applications/lang/python.py index dcdd2ffe..75d34722 100644 --- a/test/unit/applications/lang/python.py +++ b/test/unit/applications/lang/python.py @@ -3,17 +3,22 @@ import shutil import pytest from unit.applications.proto import TestApplicationProto +from urllib.parse import quote from conftest import option class TestApplicationPython(TestApplicationProto): application_type = "python" + load_module = "wsgi" - def load(self, script, name=None, **kwargs): + def load(self, script, name=None, module=None, **kwargs): print() if name is None: name = script + if module is None: + module = self.load_module + if script[0] == '/': script_path = script else: @@ -37,14 +42,16 @@ class TestApplicationPython(TestApplicationProto): self._load_conf( { - "listeners": {"*:7080": {"pass": "applications/" + name}}, + "listeners": { + "*:7080": {"pass": "applications/" + quote(name, '')} + }, "applications": { name: { "type": appication_type, "processes": {"spare": 0}, "path": script_path, "working_directory": script_path, - "module": "wsgi", + "module": module, } }, }, -- cgit From efe65dee4de9d429a3cd0d7e88e4999a8c89081a Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Thu, 24 Sep 2020 09:47:27 +0300 Subject: Tests: prerequisites check improved by using callable. This is required for more flexible Python version check since ASGI works for Python 3.5+. Version check via 'startswith()' function removed as not consistent. --- test/conftest.py | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 8683a023..6bc871e2 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -67,32 +67,40 @@ def pytest_generate_tests(metafunc): type = cls.application_type + def generate_tests(versions): + metafunc.fixturenames.append('tmp_ct') + metafunc.parametrize('tmp_ct', range(len(versions))) + + for i, version in enumerate(versions): + option.generated_tests[ + metafunc.function.__name__ + '[{}]'.format(i) + ] = (type + ' ' + version) + # take available module from option and generate tests for each version - for module in cls.prerequisites['modules']: + for module, prereq_version in cls.prerequisites['modules'].items(): if module in option.available['modules']: - prereq_version = cls.prerequisites['modules'][module] available_versions = option.available['modules'][module] if prereq_version == 'all': - metafunc.fixturenames.append('tmp_ct') - metafunc.parametrize('tmp_ct', range(len(available_versions))) - - for i in range(len(available_versions)): - version = available_versions[i] - option.generated_tests[ - metafunc.function.__name__ + '[{}]'.format(i) - ] = (type + ' ' + version) + generate_tests(available_versions) + elif prereq_version == 'any': option.generated_tests[metafunc.function.__name__] = ( type + ' ' + available_versions[0] ) + elif callable(prereq_version): + generate_tests( + list(filter(prereq_version, available_versions)) + ) + else: - for version in available_versions: - if version.startswith(prereq_version): - option.generated_tests[metafunc.function.__name__] = ( - type + ' ' + version - ) + raise ValueError( + """ +Unexpected prerequisite version "%s" for module "%s" in %s. +'all', 'any' or callable expected.""" + % (str(prereq_version), module, str(cls)) + ) def pytest_sessionstart(session): -- cgit From 409545494627690a644d1a9024b0d4bdb8f49acb Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Sun, 27 Sep 2020 23:27:19 +0100 Subject: Tests: added pytest.ini. --- test/pytest.ini | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 test/pytest.ini (limited to 'test') diff --git a/test/pytest.ini b/test/pytest.ini new file mode 100644 index 00000000..c672788a --- /dev/null +++ b/test/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +addopts = -rs -vvv +python_functions = test_* -- cgit From 4de6ffa63fb11bc37d47dcddc305bbf6f5768a84 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Sun, 27 Sep 2020 23:46:31 +0100 Subject: Tests: tuned delay in test_settings_idle_timeout_2. --- test/test_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/test_settings.py b/test/test_settings.py index 797af5ed..89f55703 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -212,7 +212,7 @@ Connection: close _, sock = self.http(b'', start=True, raw=True, no_recv=True) - time.sleep(2) + time.sleep(3) assert ( self.get( -- cgit From 1fe1518ab1b9ad5dac6f2f8a1e41571cbc4d96e9 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 30 Sep 2020 22:45:58 +0100 Subject: Tests: fixed test_static_space_in_name. --- test/test_static.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/test_static.py b/test/test_static.py index fc8bb0a9..2290bc38 100644 --- a/test/test_static.py +++ b/test/test_static.py @@ -129,7 +129,7 @@ class TestStatic(TestApplicationProto): ), 'file name enclosing' try: - print('файл') + open(self.temp_dir + '/ф а', 'a').close() utf8 = True except: -- cgit From d491527555c076695a4202577198e12bf0b919ec Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 1 Oct 2020 10:17:00 +0100 Subject: Tests: minor fixes. Fixed temporary dir removing. Fixed printing path to log. Module checks moved to the separate file. --- test/conftest.py | 33 +++++++++++++++++++++++++++------ test/test_java_isolation_rootfs.py | 3 ++- test/unit/applications/lang/go.py | 16 +--------------- test/unit/applications/lang/java.py | 8 +++++--- test/unit/applications/lang/node.py | 13 +------------ test/unit/applications/tls.py | 21 --------------------- test/unit/check/go.py | 29 +++++++++++++++++++++++++++++ test/unit/check/node.py | 6 ++++++ test/unit/check/tls.py | 13 +++++++++++++ test/unit/main.py | 23 +++++------------------ 10 files changed, 89 insertions(+), 76 deletions(-) create mode 100644 test/unit/check/go.py create mode 100644 test/unit/check/node.py create mode 100644 test/unit/check/tls.py (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 6bc871e2..8e9009b6 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -2,6 +2,7 @@ import fcntl import os import platform import pytest +import shutil import signal import stat import subprocess @@ -10,6 +11,10 @@ import re import tempfile import time +from unit.check.go import check_go +from unit.check.node import check_node +from unit.check.tls import check_openssl + def pytest_addoption(parser): parser.addoption( @@ -132,6 +137,20 @@ def pytest_sessionstart(session): else: option.available['modules'][module[0]].append(module[1]) + # discover modules from check + + option.available['modules']['openssl'] = check_openssl(unit['unitd']) + option.available['modules']['go'] = check_go( + option.current_dir, unit['temp_dir'], option.test_dir + ) + option.available['modules']['node'] = check_node(option.current_dir) + + # remove None values + + option.available['modules'] = { + k: v for k, v in option.available['modules'].items() if v is not None + } + unit_stop() @@ -216,6 +235,7 @@ def unit_stop(): p.kill() return 'Could not terminate unit' + shutil.rmtree(unit_instance['temp_dir']) def public_dir(path): os.chmod(path, 0o777) @@ -265,31 +285,32 @@ def _check_alerts(log): alerts = [al for al in alerts if re.search(skip, al) is None] if alerts: - _print_log(log) + _print_log(data=log) assert not alerts, 'alert(s)' if not option.skip_sanitizer: sanitizer_errors = re.findall('.+Sanitizer.+', log) if sanitizer_errors: - _print_log(log) + _print_log(data=log) assert not sanitizer_errors, 'sanitizer error(s)' if found: print('skipped.') -def _print_log(data=None): - unit_log = unit_instance['log'] +def _print_log(path=None, data=None): + if path is None: + path = unit_instance['log'] - print('Path to unit.log:\n' + unit_log + '\n') + print('Path to unit.log:\n' + path + '\n') if option.print_log: os.set_blocking(sys.stdout.fileno(), True) sys.stdout.flush() if data is None: - with open(unit_log, 'r', encoding='utf-8', errors='ignore') as f: + with open(path, 'r', encoding='utf-8', errors='ignore') as f: shutil.copyfileobj(f, sys.stdout) else: sys.stdout.write(data) diff --git a/test/test_java_isolation_rootfs.py b/test/test_java_isolation_rootfs.py index fa227469..df3ccdfa 100644 --- a/test/test_java_isolation_rootfs.py +++ b/test/test_java_isolation_rootfs.py @@ -3,6 +3,7 @@ import subprocess import pytest from unit.applications.lang.java import TestApplicationJava +from conftest import option class TestJavaIsolationRootfs(TestApplicationJava): @@ -23,7 +24,7 @@ class TestJavaIsolationRootfs(TestApplicationJava): [ "mount", "--bind", - self.pardir + "/build", + option.current_dir + "/build", self.temp_dir + "/jars", ], stderr=subprocess.STDOUT, diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 069bdecb..946b5421 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -6,26 +6,12 @@ from conftest import option class TestApplicationGo(TestApplicationProto): - @classmethod - def setup_class(cls, complete_check=True): - unit = super().setup_class(complete_check=False) - - # check go module - - go_app = TestApplicationGo() - go_app.temp_dir = unit.temp_dir - proc = go_app.prepare_env('empty', 'app') - if proc and proc.returncode == 0: - cls.available['modules']['go'] = [] - - return unit if not complete_check else unit.complete() - def prepare_env(self, script, name, static=False): if not os.path.exists(self.temp_dir + '/go'): os.mkdir(self.temp_dir + '/go') env = os.environ.copy() - env['GOPATH'] = self.pardir + '/build/go' + env['GOPATH'] = option.current_dir + '/build/go' if static: args = [ diff --git a/test/unit/applications/lang/java.py b/test/unit/applications/lang/java.py index b5511883..93427709 100644 --- a/test/unit/applications/lang/java.py +++ b/test/unit/applications/lang/java.py @@ -49,10 +49,12 @@ class TestApplicationJava(TestApplicationProto): if not os.path.isdir(classes_path): os.makedirs(classes_path) - classpath = self.pardir + '/build/tomcat-servlet-api-9.0.13.jar' + classpath = ( + option.current_dir + '/build/tomcat-servlet-api-9.0.13.jar' + ) ws_jars = glob.glob( - self.pardir + '/build/websocket-api-java-*.jar' + option.current_dir + '/build/websocket-api-java-*.jar' ) if not ws_jars: @@ -78,7 +80,7 @@ class TestApplicationJava(TestApplicationProto): "listeners": {"*:7080": {"pass": "applications/" + script}}, "applications": { script: { - "unit_jars": self.pardir + '/build', + "unit_jars": option.current_dir + '/build', "type": 'java', "processes": {"spare": 0}, "working_directory": script_path, diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index f510acce..dbb7036b 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -7,17 +7,6 @@ from conftest import option, public_dir class TestApplicationNode(TestApplicationProto): - @classmethod - def setup_class(cls, complete_check=True): - unit = super().setup_class(complete_check=False) - - # check node module - - if os.path.exists(unit.pardir + '/node/node_modules'): - cls.available['modules']['node'] = [] - - return unit if not complete_check else unit.complete() - def load(self, script, name='app.js', **kwargs): # copy application @@ -28,7 +17,7 @@ class TestApplicationNode(TestApplicationProto): # copy modules shutil.copytree( - self.pardir + '/node/node_modules', + option.current_dir + '/node/node_modules', self.temp_dir + '/node/node_modules', ) diff --git a/test/unit/applications/tls.py b/test/unit/applications/tls.py index 5453eef0..7c95f27b 100644 --- a/test/unit/applications/tls.py +++ b/test/unit/applications/tls.py @@ -15,27 +15,6 @@ class TestApplicationTLS(TestApplicationProto): self.context.check_hostname = False self.context.verify_mode = ssl.CERT_NONE - @classmethod - def setup_class(cls, complete_check=True): - unit = super().setup_class(complete_check=False) - - # check tls module - - try: - subprocess.check_output(['which', 'openssl']) - - output = subprocess.check_output( - [unit.unitd, '--version'], stderr=subprocess.STDOUT - ) - - if re.search('--openssl', output.decode()): - cls.available['modules']['openssl'] = [] - - except: - pass - - return unit if not complete_check else unit.complete() - def certificate(self, name='default', load=True): self.openssl_conf() diff --git a/test/unit/check/go.py b/test/unit/check/go.py new file mode 100644 index 00000000..dd2150eb --- /dev/null +++ b/test/unit/check/go.py @@ -0,0 +1,29 @@ +import os +import subprocess + + +def check_go(current_dir, temp_dir, test_dir): + if not os.path.exists(temp_dir + '/go'): + os.mkdir(temp_dir + '/go') + + env = os.environ.copy() + env['GOPATH'] = current_dir + '/build/go' + + try: + process = subprocess.Popen( + [ + 'go', + 'build', + '-o', + temp_dir + '/go/app', + test_dir + '/go/empty/app.go', + ], + env=env, + ) + process.communicate() + + if process.returncode == 0: + return True + + except: + return None diff --git a/test/unit/check/node.py b/test/unit/check/node.py new file mode 100644 index 00000000..236ba7b5 --- /dev/null +++ b/test/unit/check/node.py @@ -0,0 +1,6 @@ +import os + + +def check_node(current_dir): + if os.path.exists(current_dir + '/node/node_modules'): + return True diff --git a/test/unit/check/tls.py b/test/unit/check/tls.py new file mode 100644 index 00000000..b878ff7d --- /dev/null +++ b/test/unit/check/tls.py @@ -0,0 +1,13 @@ +import re +import subprocess + + +def check_openssl(unitd): + subprocess.check_output(['which', 'openssl']) + + output = subprocess.check_output( + [unitd, '--version'], stderr=subprocess.STDOUT + ) + + if re.search('--openssl', output.decode()): + return True diff --git a/test/unit/main.py b/test/unit/main.py index 18ea326e..053ce145 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -16,11 +16,6 @@ from multiprocessing import Process class TestUnit(): - - pardir = os.path.abspath( - os.path.join(os.path.dirname(__file__), os.pardir, os.pardir) - ) - @classmethod def setup_class(cls, complete_check=True): cls.available = option.available @@ -41,17 +36,9 @@ class TestUnit(): break if m is None: - _print_log() + _print_log(path=unit.temp_dir + '/unit.log') exit("Unit is writing log too long") - # discover available modules from unit.log - - for module in re.findall(r'module: ([a-zA-Z]+) (.*) ".*"$', log, re.M): - if module[0] not in cls.available['modules']: - cls.available['modules'][module[0]] = [module[1]] - else: - cls.available['modules'][module[0]].append(module[1]) - def check(available, prerequisites): missed = [] @@ -102,7 +89,7 @@ class TestUnit(): self._run() def _run(self): - build_dir = self.pardir + '/build' + build_dir = option.current_dir + '/build' self.unitd = build_dir + '/unitd' if not os.path.isfile(self.unitd): @@ -122,7 +109,7 @@ class TestUnit(): [ self.unitd, '--no-daemon', - '--modules', self.pardir + '/build', + '--modules', build_dir, '--state', self.temp_dir + '/state', '--pid', self.temp_dir + '/unit.pid', '--log', self.temp_dir + '/unit.log', @@ -135,7 +122,7 @@ class TestUnit(): atexit.register(self.stop) if not waitforfiles(self.temp_dir + '/control.unit.sock'): - _print_log() + _print_log(path=self.temp_dir + '/unit.log') exit("Could not start unit") self._started = True @@ -155,7 +142,7 @@ class TestUnit(): if not option.save_log: shutil.rmtree(self.temp_dir) else: - _print_log() + _print_log(path=self.temp_dir) assert self.stop_errors == [None, None], 'stop errors' -- cgit From c2eb245b32870b6360079ff9a4b063a7cd84d585 Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Wed, 9 Sep 2020 19:28:44 +0100 Subject: PHP: fixed "rootfs" isolation dependency on system mounts. --- test/test_php_isolation.py | 51 ------------------------------------------- test/test_python_isolation.py | 30 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 51 deletions(-) (limited to 'test') diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index f4170f1b..556bd387 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -85,54 +85,3 @@ class TestPHPIsolation(TestApplicationPHP): assert 'json' in extensions, 'json in extensions list' assert 'unit' in extensions, 'unit in extensions list' - - def test_php_isolation_rootfs_no_language_libs(self, is_su): - isolation_features = self.available['features']['isolation'].keys() - - if not is_su: - if 'user' not in isolation_features: - pytest.skip('requires unprivileged userns or root') - - if not 'unprivileged_userns_clone' in isolation_features: - pytest.skip('requires unprivileged userns or root') - - if 'mnt' not in isolation_features: - pytest.skip('requires mnt ns') - - isolation = { - 'rootfs': option.test_dir, - 'automount': {'language_deps': False}, - 'namespaces': {'credential': not is_su, 'mount': not is_su}, - } - - self.load('list-extensions', isolation=isolation) - - assert 'success' in self.conf( - '"/php/list-extensions"', 'applications/list-extensions/root' - ) - - assert 'success' in self.conf( - {'file': '/php/list-extensions/php.ini'}, - 'applications/list-extensions/options', - ) - - assert 'success' in self.conf( - '"/php/list-extensions"', - 'applications/list-extensions/working_directory', - ) - - extensions = self.getjson()['body'] - - assert 'unit' in extensions, 'unit in extensions list' - assert 'json' not in extensions, 'json not in extensions list' - - assert 'success' in self.conf( - {'language_deps': True}, - 'applications/list-extensions/isolation/automount', - ) - - extensions = self.getjson()['body'] - - assert 'unit' in extensions, 'unit in extensions list 2' - assert 'json' in extensions, 'json in extensions list 2' - diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index 564ec79c..59ac670a 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -65,3 +65,33 @@ class TestPythonIsolation(TestApplicationPython): assert ( ret['body']['FileExists'] == True ), 'application exists in rootfs' + + def test_python_isolation_rootfs_no_language_deps(self, is_su): + isolation_features = self.available['features']['isolation'].keys() + + if 'mnt' not in isolation_features: + pytest.skip('requires mnt ns') + + if not is_su: + if 'user' not in isolation_features: + pytest.skip('requires unprivileged userns or root') + + if not 'unprivileged_userns_clone' in isolation_features: + pytest.skip('requires unprivileged userns or root') + + isolation = { + 'namespaces': {'credential': not is_su, 'mount': True}, + 'rootfs': self.temp_dir, + 'automount': {'language_deps': False} + } + + self.load('empty', isolation=isolation) + + assert (self.get()['status'] != 200), 'disabled language_deps' + + isolation['automount']['language_deps'] = True + + self.load('empty', isolation=isolation) + + assert (self.get()['status'] == 200), 'enabled language_deps' + -- cgit From d97e3a3296db77f6a33ce010a66d2a0b2d4bac49 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Thu, 1 Oct 2020 23:55:35 +0300 Subject: Tests: added ASGI WebSocket. --- test/python/websockets/mirror/asgi.py | 18 + test/python/websockets/subprotocol/asgi.py | 25 + test/test_asgi_websockets.py | 1432 ++++++++++++++++++++++++++++ test/unit/applications/websockets.py | 2 +- 4 files changed, 1476 insertions(+), 1 deletion(-) create mode 100644 test/python/websockets/mirror/asgi.py create mode 100644 test/python/websockets/subprotocol/asgi.py create mode 100644 test/test_asgi_websockets.py (limited to 'test') diff --git a/test/python/websockets/mirror/asgi.py b/test/python/websockets/mirror/asgi.py new file mode 100644 index 00000000..0f1d9953 --- /dev/null +++ b/test/python/websockets/mirror/asgi.py @@ -0,0 +1,18 @@ +async def application(scope, receive, send): + if scope['type'] == 'websocket': + while True: + m = await receive() + if m['type'] == 'websocket.connect': + await send({ + 'type': 'websocket.accept', + }) + + if m['type'] == 'websocket.receive': + await send({ + 'type': 'websocket.send', + 'bytes': m.get('bytes', None), + 'text': m.get('text', None), + }) + + if m['type'] == 'websocket.disconnect': + break; diff --git a/test/python/websockets/subprotocol/asgi.py b/test/python/websockets/subprotocol/asgi.py new file mode 100644 index 00000000..92263dd7 --- /dev/null +++ b/test/python/websockets/subprotocol/asgi.py @@ -0,0 +1,25 @@ +async def application(scope, receive, send): + assert scope['type'] == 'websocket' + + while True: + m = await receive() + if m['type'] == 'websocket.connect': + subprotocols = scope['subprotocols'] + + await send({ + 'type': 'websocket.accept', + 'headers': [ + (b'x-subprotocols', str(subprotocols).encode()), + ], + 'subprotocol': subprotocols[0], + }) + + if m['type'] == 'websocket.receive': + await send({ + 'type': 'websocket.send', + 'bytes': m.get('bytes', None), + 'text': m.get('text', None), + }) + + if m['type'] == 'websocket.disconnect': + break; diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py new file mode 100644 index 00000000..249f630f --- /dev/null +++ b/test/test_asgi_websockets.py @@ -0,0 +1,1432 @@ +import pytest +import struct +import time +from distutils.version import LooseVersion + +from unit.applications.lang.python import TestApplicationPython +from unit.applications.websockets import TestApplicationWebsocket +from conftest import option, skip_alert + + +class TestASGIWebsockets(TestApplicationPython): + prerequisites = {'modules': {'python': + lambda v: LooseVersion(v) >= LooseVersion('3.5')}} + load_module = 'asgi' + + ws = TestApplicationWebsocket() + + def setup_method(self): + super().setup_method() + + assert 'success' in self.conf( + {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' + ), 'clear keepalive_interval' + + skip_alert(r'socket close\(\d+\) failed') + + def close_connection(self, sock): + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' + + self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) + + self.check_close(sock) + + def check_close(self, sock, code=1000, no_close=False): + frame = self.ws.frame_read(sock) + + assert frame['fin'] == True, 'close fin' + assert frame['opcode'] == self.ws.OP_CLOSE, 'close opcode' + assert frame['code'] == code, 'close code' + + if not no_close: + sock.close() + + def check_frame(self, frame, fin, opcode, payload, decode=True): + if opcode == self.ws.OP_BINARY or not decode: + data = frame['data'] + else: + data = frame['data'].decode('utf-8') + + assert frame['fin'] == fin, 'fin' + assert frame['opcode'] == opcode, 'opcode' + assert data == payload, 'payload' + + def test_asgi_websockets_handshake(self): + self.load('websockets/mirror') + + resp, sock, key = self.ws.upgrade() + sock.close() + + assert resp['status'] == 101, 'status' + assert resp['headers']['Upgrade'] == 'websocket', 'upgrade' + assert resp['headers']['Connection'] == 'Upgrade', 'connection' + assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept( + key + ), 'key' + + def test_asgi_websockets_subprotocol(self): + self.load('websockets/subprotocol') + + resp, sock, key = self.ws.upgrade() + sock.close() + + assert resp['status'] == 101, 'status' + assert resp['headers']['x-subprotocols'] == "('chat', 'phone', 'video')", 'subprotocols' + assert resp['headers']['sec-websocket-protocol'] == 'chat', 'key' + + def test_asgi_websockets_mirror(self): + self.load('websockets/mirror') + + message = 'blah' + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, message) + frame = self.ws.frame_read(sock) + + assert message == frame['data'].decode('utf-8'), 'mirror' + + self.ws.frame_write(sock, self.ws.OP_TEXT, message) + frame = self.ws.frame_read(sock) + + assert message == frame['data'].decode('utf-8'), 'mirror 2' + + sock.close() + + def test_asgi_websockets_no_mask(self): + self.load('websockets/mirror') + + message = 'blah' + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, message, mask=False) + + frame = self.ws.frame_read(sock) + + assert frame['opcode'] == self.ws.OP_CLOSE, 'no mask opcode' + assert frame['code'] == 1002, 'no mask close code' + + sock.close() + + def test_asgi_websockets_fragmentation(self): + self.load('websockets/mirror') + + message = 'blah' + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, message, fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, ' ', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, message) + + frame = self.ws.frame_read(sock) + + assert message + ' ' + message == frame['data'].decode( + 'utf-8' + ), 'mirror framing' + + sock.close() + + def test_asgi_websockets_frame_fragmentation_invalid(self): + self.load('websockets/mirror') + + message = 'blah' + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_PING, message, fin=False) + + frame = self.ws.frame_read(sock) + + frame.pop('data') + assert frame == { + 'fin': True, + 'rsv1': False, + 'rsv2': False, + 'rsv3': False, + 'opcode': self.ws.OP_CLOSE, + 'mask': 0, + 'code': 1002, + 'reason': 'Fragmented control frame', + }, 'close frame' + + sock.close() + + def test_asgi_websockets_large(self): + self.load('websockets/mirror') + + message = '0123456789' * 300 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, message) + + frame = self.ws.frame_read(sock) + data = frame['data'].decode('utf-8') + + frame = self.ws.frame_read(sock) + data += frame['data'].decode('utf-8') + + assert message == data, 'large' + + sock.close() + + def test_asgi_websockets_two_clients(self): + self.load('websockets/mirror') + + message1 = 'blah1' + message2 = 'blah2' + + _, sock1, _ = self.ws.upgrade() + _, sock2, _ = self.ws.upgrade() + + self.ws.frame_write(sock1, self.ws.OP_TEXT, message1) + self.ws.frame_write(sock2, self.ws.OP_TEXT, message2) + + frame1 = self.ws.frame_read(sock1) + frame2 = self.ws.frame_read(sock2) + + assert message1 == frame1['data'].decode('utf-8'), 'client 1' + assert message2 == frame2['data'].decode('utf-8'), 'client 2' + + sock1.close() + sock2.close() + + @pytest.mark.skip('not yet') + def test_asgi_websockets_handshake_upgrade_absent( + self + ): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1 + self.load('websockets/mirror') + + resp = self.get( + headers={ + 'Host': 'localhost', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Key': self.ws.key(), + 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Version': 13, + }, + ) + + assert resp['status'] == 400, 'upgrade absent' + + def test_asgi_websockets_handshake_case_insensitive(self): + self.load('websockets/mirror') + + resp, sock, _ = self.ws.upgrade( + headers={ + 'Host': 'localhost', + 'Upgrade': 'WEBSOCKET', + 'Connection': 'UPGRADE', + 'Sec-WebSocket-Key': self.ws.key(), + 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Version': 13, + } + ) + sock.close() + + assert resp['status'] == 101, 'status' + + @pytest.mark.skip('not yet') + def test_asgi_websockets_handshake_connection_absent(self): # FAIL + self.load('websockets/mirror') + + resp = self.get( + headers={ + 'Host': 'localhost', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Key': self.ws.key(), + 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Version': 13, + }, + ) + + assert resp['status'] == 400, 'status' + + def test_asgi_websockets_handshake_version_absent(self): + self.load('websockets/mirror') + + resp = self.get( + headers={ + 'Host': 'localhost', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Key': self.ws.key(), + 'Sec-WebSocket-Protocol': 'chat', + }, + ) + + assert resp['status'] == 426, 'status' + + @pytest.mark.skip('not yet') + def test_asgi_websockets_handshake_key_invalid(self): + self.load('websockets/mirror') + + resp = self.get( + headers={ + 'Host': 'localhost', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Key': '!', + 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Version': 13, + }, + ) + + assert resp['status'] == 400, 'key length' + + key = self.ws.key() + resp = self.get( + headers={ + 'Host': 'localhost', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Key': [key, key], + 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Version': 13, + }, + ) + + assert resp['status'] == 400, 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1 + + def test_asgi_websockets_handshake_method_invalid(self): + self.load('websockets/mirror') + + resp = self.post( + headers={ + 'Host': 'localhost', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Key': self.ws.key(), + 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Version': 13, + }, + ) + + assert resp['status'] == 400, 'status' + + def test_asgi_websockets_handshake_http_10(self): + self.load('websockets/mirror') + + resp = self.get( + headers={ + 'Host': 'localhost', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Key': self.ws.key(), + 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Version': 13, + }, + http_10=True, + ) + + assert resp['status'] == 400, 'status' + + def test_asgi_websockets_handshake_uri_invalid(self): + self.load('websockets/mirror') + + resp = self.get( + headers={ + 'Host': 'localhost', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Key': self.ws.key(), + 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Version': 13, + }, + url='!', + ) + + assert resp['status'] == 400, 'status' + + def test_asgi_websockets_protocol_absent(self): + self.load('websockets/mirror') + + key = self.ws.key() + resp, sock, _ = self.ws.upgrade( + headers={ + 'Host': 'localhost', + 'Upgrade': 'websocket', + 'Connection': 'Upgrade', + 'Sec-WebSocket-Key': key, + 'Sec-WebSocket-Version': 13, + } + ) + sock.close() + + assert resp['status'] == 101, 'status' + assert resp['headers']['Upgrade'] == 'websocket', 'upgrade' + assert resp['headers']['Connection'] == 'Upgrade', 'connection' + assert resp['headers']['Sec-WebSocket-Accept'] == self.ws.accept( + key + ), 'key' + + # autobahn-testsuite + # + # Some following tests fail because of Unit does not support UTF-8 + # validation for websocket frames. It should be implemented + # by application, if necessary. + + def test_asgi_websockets_1_1_1__1_1_8(self): + self.load('websockets/mirror') + + opcode = self.ws.OP_TEXT + + _, sock, _ = self.ws.upgrade() + + def check_length(length, chopsize=None): + payload = '*' * length + + self.ws.frame_write(sock, opcode, payload, chopsize=chopsize) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, opcode, payload) + + check_length(0) # 1_1_1 + check_length(125) # 1_1_2 + check_length(126) # 1_1_3 + check_length(127) # 1_1_4 + check_length(128) # 1_1_5 + check_length(65535) # 1_1_6 + check_length(65536) # 1_1_7 + check_length(65536, chopsize = 997) # 1_1_8 + + self.close_connection(sock) + + def test_asgi_websockets_1_2_1__1_2_8(self): + self.load('websockets/mirror') + + opcode = self.ws.OP_BINARY + + _, sock, _ = self.ws.upgrade() + + def check_length(length, chopsize=None): + payload = b'\xfe' * length + + self.ws.frame_write(sock, opcode, payload, chopsize=chopsize) + frame = self.ws.frame_read(sock) + + self.check_frame(frame, True, opcode, payload) + + check_length(0) # 1_2_1 + check_length(125) # 1_2_2 + check_length(126) # 1_2_3 + check_length(127) # 1_2_4 + check_length(128) # 1_2_5 + check_length(65535) # 1_2_6 + check_length(65536) # 1_2_7 + check_length(65536, chopsize = 997) # 1_2_8 + + self.close_connection(sock) + + def test_asgi_websockets_2_1__2_6(self): + self.load('websockets/mirror') + + op_ping = self.ws.OP_PING + op_pong = self.ws.OP_PONG + + _, sock, _ = self.ws.upgrade() + + def check_ping(payload, chopsize=None, decode=True): + self.ws.frame_write(sock, op_ping, payload, chopsize=chopsize) + frame = self.ws.frame_read(sock) + + self.check_frame(frame, True, op_pong, payload, decode=decode) + + check_ping('') # 2_1 + check_ping('Hello, world!') # 2_2 + check_ping(b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', decode=False) # 2_3 + check_ping(b'\xfe' * 125, decode=False) # 2_4 + check_ping(b'\xfe' * 125, chopsize=1, decode=False) # 2_6 + + self.close_connection(sock) + + # 2_5 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_PING, b'\xfe' * 126) + self.check_close(sock, 1002) + + def test_asgi_websockets_2_7__2_9(self): + self.load('websockets/mirror') + + # 2_7 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_PONG, '') + assert self.recvall(sock, read_timeout=0.1) == b'', '2_7' + + # 2_8 + + self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload') + assert self.recvall(sock, read_timeout=0.1) == b'', '2_8' + + # 2_9 + + payload = 'ping payload' + + self.ws.frame_write(sock, self.ws.OP_PONG, 'unsolicited pong payload') + self.ws.frame_write(sock, self.ws.OP_PING, payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, payload) + + self.close_connection(sock) + + def test_asgi_websockets_2_10__2_11(self): + self.load('websockets/mirror') + + # 2_10 + + _, sock, _ = self.ws.upgrade() + + for i in range(0, 10): + self.ws.frame_write(sock, self.ws.OP_PING, 'payload-%d' % i) + + for i in range(0, 10): + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i) + + # 2_11 + + for i in range(0, 10): + opcode = self.ws.OP_PING + self.ws.frame_write(sock, opcode, 'payload-%d' % i, chopsize=1) + + for i in range(0, 10): + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, 'payload-%d' % i) + + self.close_connection(sock) + + @pytest.mark.skip('not yet') + def test_asgi_websockets_3_1__3_7(self): + self.load('websockets/mirror') + + payload = 'Hello, world!' + + # 3_1 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv1=True) + self.check_close(sock, 1002) + + # 3_2 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + self.ws.frame_write(sock, self.ws.OP_TEXT, payload, rsv2=True) + self.ws.frame_write(sock, self.ws.OP_PING, '') + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.check_close(sock, 1002, no_close=True) + + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_2' + sock.close() + + # 3_3 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.ws.frame_write( + sock, self.ws.OP_TEXT, payload, rsv1=True, rsv2=True + ) + + self.check_close(sock, 1002, no_close=True) + + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_3' + sock.close() + + # 3_4 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1) + self.ws.frame_write( + sock, self.ws.OP_TEXT, payload, rsv3=True, chopsize=1 + ) + self.ws.frame_write(sock, self.ws.OP_PING, '') + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.check_close(sock, 1002, no_close=True) + + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty 3_4' + sock.close() + + # 3_5 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write( + sock, + self.ws.OP_BINARY, + b'\x00\xff\xfe\xfd\xfc\xfb\x00\xff', + rsv1=True, + rsv3=True, + ) + + self.check_close(sock, 1002) + + # 3_6 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write( + sock, self.ws.OP_PING, payload, rsv2=True, rsv3=True + ) + + self.check_close(sock, 1002) + + # 3_7 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write( + sock, self.ws.OP_CLOSE, payload, rsv1=True, rsv2=True, rsv3=True + ) + + self.check_close(sock, 1002) + + def test_asgi_websockets_4_1_1__4_2_5(self): + self.load('websockets/mirror') + + payload = 'Hello, world!' + + # 4_1_1 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, 0x03, '') + self.check_close(sock, 1002) + + # 4_1_2 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, 0x04, 'reserved opcode payload') + self.check_close(sock, 1002) + + # 4_1_3 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.ws.frame_write(sock, 0x05, '') + self.ws.frame_write(sock, self.ws.OP_PING, '') + + self.check_close(sock, 1002) + + # 4_1_4 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.ws.frame_write(sock, 0x06, payload) + self.ws.frame_write(sock, self.ws.OP_PING, '') + + self.check_close(sock, 1002) + + # 4_1_5 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.ws.frame_write(sock, 0x07, payload, chopsize=1) + self.ws.frame_write(sock, self.ws.OP_PING, '') + + self.check_close(sock, 1002) + + # 4_2_1 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, 0x0B, '') + self.check_close(sock, 1002) + + # 4_2_2 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, 0x0C, 'reserved opcode payload') + self.check_close(sock, 1002) + + # 4_2_3 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.ws.frame_write(sock, 0x0D, '') + self.ws.frame_write(sock, self.ws.OP_PING, '') + + self.check_close(sock, 1002) + + # 4_2_4 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.ws.frame_write(sock, 0x0E, payload) + self.ws.frame_write(sock, self.ws.OP_PING, '') + + self.check_close(sock, 1002) + + # 4_2_5 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload, chopsize=1) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.ws.frame_write(sock, 0x0F, payload, chopsize=1) + self.ws.frame_write(sock, self.ws.OP_PING, '') + + self.check_close(sock, 1002) + + def test_asgi_websockets_5_1__5_20(self): + self.load('websockets/mirror') + + # 5_1 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_PING, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) + self.check_close(sock, 1002) + + # 5_2 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_PONG, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) + self.check_close(sock, 1002) + + # 5_3 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + + # 5_4 + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + assert self.recvall(sock, read_timeout=0.1) == b'', '5_4' + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + + # 5_5 + + self.ws.frame_write( + sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1 + ) + self.ws.frame_write( + sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1 + ) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + + # 5_6 + + ping_payload = 'ping payload' + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_PING, ping_payload) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, ping_payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + + # 5_7 + + ping_payload = 'ping payload' + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + assert self.recvall(sock, read_timeout=0.1) == b'', '5_7' + + self.ws.frame_write(sock, self.ws.OP_PING, ping_payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, ping_payload) + + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + + # 5_8 + + ping_payload = 'ping payload' + + self.ws.frame_write( + sock, self.ws.OP_TEXT, 'fragment1', fin=False, chopsize=1 + ) + self.ws.frame_write(sock, self.ws.OP_PING, ping_payload, chopsize=1) + self.ws.frame_write( + sock, self.ws.OP_CONT, 'fragment2', fin=True, chopsize=1 + ) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, ping_payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2') + + # 5_9 + + self.ws.frame_write( + sock, self.ws.OP_CONT, 'non-continuation payload', fin=True + ) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True) + self.check_close(sock, 1002) + + # 5_10 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write( + sock, self.ws.OP_CONT, 'non-continuation payload', fin=True + ) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True) + self.check_close(sock, 1002) + + # 5_11 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write( + sock, + self.ws.OP_CONT, + 'non-continuation payload', + fin=True, + chopsize=1, + ) + self.ws.frame_write( + sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1 + ) + self.check_close(sock, 1002) + + # 5_12 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write( + sock, self.ws.OP_CONT, 'non-continuation payload', fin=False + ) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True) + self.check_close(sock, 1002) + + # 5_13 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write( + sock, self.ws.OP_CONT, 'non-continuation payload', fin=False + ) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'Hello, world!', fin=True) + self.check_close(sock, 1002) + + # 5_14 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write( + sock, + self.ws.OP_CONT, + 'non-continuation payload', + fin=False, + chopsize=1, + ) + self.ws.frame_write( + sock, self.ws.OP_TEXT, 'Hello, world!', fin=True, chopsize=1 + ) + self.check_close(sock, 1002) + + # 5_15 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=True) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment4', fin=True) + self.check_close(sock, 1002) + + # 5_16 + + _, sock, _ = self.ws.upgrade() + + for i in range(0, 2): + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True) + self.check_close(sock, 1002) + + # 5_17 + + _, sock, _ = self.ws.upgrade() + + for i in range(0, 2): + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment1', fin=True) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=True) + self.check_close(sock, 1002) + + # 5_18 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment2') + self.check_close(sock, 1002) + + # 5_19 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False) + self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!') + + time.sleep(1) + + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False) + self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!') + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5') + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!') + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!') + + self.check_frame( + self.ws.frame_read(sock), + True, + self.ws.OP_TEXT, + 'fragment1fragment2fragment3fragment4fragment5', + ) + + # 5_20 + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2', fin=False) + self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 1!') + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 1!') + + time.sleep(1) + + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment3', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment4', fin=False) + self.ws.frame_write(sock, self.ws.OP_PING, 'pongme 2!') + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PONG, 'pongme 2!') + + assert self.recvall(sock, read_timeout=0.1) == b'', '5_20' + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment5') + + self.check_frame( + self.ws.frame_read(sock), + True, + self.ws.OP_TEXT, + 'fragment1fragment2fragment3fragment4fragment5', + ) + + self.close_connection(sock) + + def test_asgi_websockets_6_1_1__6_4_4(self): + self.load('websockets/mirror') + + # 6_1_1 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, '') + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, '') + + # 6_1_2 + + self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, '', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, '') + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, '') + + # 6_1_3 + + payload = 'middle frame payload' + + self.ws.frame_write(sock, self.ws.OP_TEXT, '', fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, payload, fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, '') + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + # 6_2_1 + + payload = 'Hello-µ@ßöäüàá-UTF-8!!' + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + # 6_2_2 + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload[:12], fin=False) + self.ws.frame_write(sock, self.ws.OP_CONT, payload[12:]) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + # 6_2_3 + + self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + # 6_2_4 + + payload = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5' + + self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.close_connection(sock) + +# Unit does not support UTF-8 validation +# +# # 6_3_1 FAIL +# +# payload_1 = '\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5' +# payload_2 = '\xed\xa0\x80' +# payload_3 = '\x65\x64\x69\x74\x65\x64' +# +# payload = payload_1 + payload_2 + payload_3 +# +# self.ws.message(sock, self.ws.OP_TEXT, payload) +# self.check_close(sock, 1007) +# +# # 6_3_2 FAIL +# +# _, sock, _ = self.ws.upgrade() +# +# self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1) +# self.check_close(sock, 1007) +# +# # 6_4_1 ... 6_4_4 FAIL + + def test_asgi_websockets_7_1_1__7_5_1(self): + self.load('websockets/mirror') + + # 7_1_1 + + _, sock, _ = self.ws.upgrade() + + payload = "Hello World!" + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.close_connection(sock) + + # 7_1_2 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) + self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) + + self.check_close(sock) + + # 7_1_3 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) + self.check_close(sock, no_close=True) + + self.ws.frame_write(sock, self.ws.OP_PING, '') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' + + sock.close() + + # 7_1_4 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) + self.check_close(sock, no_close=True) + + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' + + sock.close() + + # 7_1_5 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) + self.check_close(sock, no_close=True) + + self.ws.frame_write(sock, self.ws.OP_CONT, 'fragment2') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' + + sock.close() + + # 7_1_6 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'BAsd7&jh23' * 26 * 2 ** 10) + self.ws.frame_write(sock, self.ws.OP_TEXT, payload) + self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) + + self.recvall(sock, read_timeout=1) + + self.ws.frame_write(sock, self.ws.OP_PING, '') + assert self.recvall(sock, read_timeout=0.1) == b'', 'empty soc' + + sock.close() + + # 7_3_1 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_CLOSE, '') + self.check_close(sock) + + # 7_3_2 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_CLOSE, 'a') + self.check_close(sock, 1002) + + # 7_3_3 + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_CLOSE, self.ws.serialize_close()) + self.check_close(sock) + + # 7_3_4 + + _, sock, _ = self.ws.upgrade() + + payload = self.ws.serialize_close(reason='Hello World!') + + self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) + self.check_close(sock) + + # 7_3_5 + + _, sock, _ = self.ws.upgrade() + + payload = self.ws.serialize_close(reason='*' * 123) + + self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) + self.check_close(sock) + + # 7_3_6 + + _, sock, _ = self.ws.upgrade() + + payload = self.ws.serialize_close(reason='*' * 124) + + self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) + self.check_close(sock, 1002) + +# # 7_5_1 FAIL Unit does not support UTF-8 validation +# +# _, sock, _ = self.ws.upgrade() +# +# payload = self.ws.serialize_close(reason = '\xce\xba\xe1\xbd\xb9\xcf' \ +# '\x83\xce\xbc\xce\xb5\xed\xa0\x80\x65\x64\x69\x74\x65\x64') +# +# self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) +# self.check_close(sock, 1007) + + def test_asgi_websockets_7_7_X__7_9_X(self): + self.load('websockets/mirror') + + valid_codes = [ + 1000, + 1001, + 1002, + 1003, + 1007, + 1008, + 1009, + 1010, + 1011, + 3000, + 3999, + 4000, + 4999, + ] + + invalid_codes = [0, 999, 1004, 1005, 1006, 1016, 1100, 2000, 2999] + + for code in valid_codes: + _, sock, _ = self.ws.upgrade() + + payload = self.ws.serialize_close(code=code) + + self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) + self.check_close(sock) + + for code in invalid_codes: + _, sock, _ = self.ws.upgrade() + + payload = self.ws.serialize_close(code=code) + + self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) + self.check_close(sock, 1002) + + def test_asgi_websockets_7_13_1__7_13_2(self): + self.load('websockets/mirror') + + # 7_13_1 + + _, sock, _ = self.ws.upgrade() + + payload = self.ws.serialize_close(code=5000) + + self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) + self.check_close(sock, 1002) + + # 7_13_2 + + _, sock, _ = self.ws.upgrade() + + payload = struct.pack('!I', 65536) + ''.encode('utf-8') + + self.ws.frame_write(sock, self.ws.OP_CLOSE, payload) + self.check_close(sock, 1002) + + def test_asgi_websockets_9_1_1__9_6_6(self, is_unsafe): + if not is_unsafe: + pytest.skip('unsafe, long run') + + self.load('websockets/mirror') + + assert 'success' in self.conf( + { + 'http': { + 'websocket': { + 'max_frame_size': 33554432, + 'keepalive_interval': 0, + } + } + }, + 'settings', + ), 'increase max_frame_size and keepalive_interval' + + _, sock, _ = self.ws.upgrade() + + op_text = self.ws.OP_TEXT + op_binary = self.ws.OP_BINARY + + def check_payload(opcode, length, chopsize=None): + if opcode == self.ws.OP_TEXT: + payload = '*' * length + else: + payload = b'*' * length + + self.ws.frame_write(sock, opcode, payload, chopsize=chopsize) + frame = self.ws.frame_read(sock, read_timeout=5) + self.check_frame(frame, True, opcode, payload) + + def check_message(opcode, f_size): + if opcode == self.ws.OP_TEXT: + payload = '*' * 4 * 2 ** 20 + else: + payload = b'*' * 4 * 2 ** 20 + + self.ws.message(sock, opcode, payload, fragmention_size=f_size) + frame = self.ws.frame_read(sock, read_timeout=5) + self.check_frame(frame, True, opcode, payload) + + check_payload(op_text, 64 * 2 ** 10) # 9_1_1 + check_payload(op_text, 256 * 2 ** 10) # 9_1_2 + check_payload(op_text, 2 ** 20) # 9_1_3 + check_payload(op_text, 4 * 2 ** 20) # 9_1_4 + check_payload(op_text, 8 * 2 ** 20) # 9_1_5 + check_payload(op_text, 16 * 2 ** 20) # 9_1_6 + + check_payload(op_binary, 64 * 2 ** 10) # 9_2_1 + check_payload(op_binary, 256 * 2 ** 10) # 9_2_2 + check_payload(op_binary, 2 ** 20) # 9_2_3 + check_payload(op_binary, 4 * 2 ** 20) # 9_2_4 + check_payload(op_binary, 8 * 2 ** 20) # 9_2_5 + check_payload(op_binary, 16 * 2 ** 20) # 9_2_6 + + if option.system != 'Darwin' and option.system != 'FreeBSD': + check_message(op_text, 64) # 9_3_1 + check_message(op_text, 256) # 9_3_2 + check_message(op_text, 2 ** 10) # 9_3_3 + check_message(op_text, 4 * 2 ** 10) # 9_3_4 + check_message(op_text, 16 * 2 ** 10) # 9_3_5 + check_message(op_text, 64 * 2 ** 10) # 9_3_6 + check_message(op_text, 256 * 2 ** 10) # 9_3_7 + check_message(op_text, 2 ** 20) # 9_3_8 + check_message(op_text, 4 * 2 ** 20) # 9_3_9 + + check_message(op_binary, 64) # 9_4_1 + check_message(op_binary, 256) # 9_4_2 + check_message(op_binary, 2 ** 10) # 9_4_3 + check_message(op_binary, 4 * 2 ** 10) # 9_4_4 + check_message(op_binary, 16 * 2 ** 10) # 9_4_5 + check_message(op_binary, 64 * 2 ** 10) # 9_4_6 + check_message(op_binary, 256 * 2 ** 10) # 9_4_7 + check_message(op_binary, 2 ** 20) # 9_4_8 + check_message(op_binary, 4 * 2 ** 20) # 9_4_9 + + check_payload(op_text, 2 ** 20, chopsize=64) # 9_5_1 + check_payload(op_text, 2 ** 20, chopsize=128) # 9_5_2 + check_payload(op_text, 2 ** 20, chopsize=256) # 9_5_3 + check_payload(op_text, 2 ** 20, chopsize=512) # 9_5_4 + check_payload(op_text, 2 ** 20, chopsize=1024) # 9_5_5 + check_payload(op_text, 2 ** 20, chopsize=2048) # 9_5_6 + + check_payload(op_binary, 2 ** 20, chopsize=64) # 9_6_1 + check_payload(op_binary, 2 ** 20, chopsize=128) # 9_6_2 + check_payload(op_binary, 2 ** 20, chopsize=256) # 9_6_3 + check_payload(op_binary, 2 ** 20, chopsize=512) # 9_6_4 + check_payload(op_binary, 2 ** 20, chopsize=1024) # 9_6_5 + check_payload(op_binary, 2 ** 20, chopsize=2048) # 9_6_6 + + self.close_connection(sock) + + def test_asgi_websockets_10_1_1(self): + self.load('websockets/mirror') + + _, sock, _ = self.ws.upgrade() + + payload = '*' * 65536 + + self.ws.message(sock, self.ws.OP_TEXT, payload, fragmention_size=1300) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_TEXT, payload) + + self.close_connection(sock) + + # settings + + def test_asgi_websockets_max_frame_size(self): + self.load('websockets/mirror') + + assert 'success' in self.conf( + {'http': {'websocket': {'max_frame_size': 100}}}, 'settings' + ), 'configure max_frame_size' + + _, sock, _ = self.ws.upgrade() + + payload = '*' * 94 + opcode = self.ws.OP_TEXT + + self.ws.frame_write(sock, opcode, payload) # frame length is 100 + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, opcode, payload) + + payload = '*' * 95 + + self.ws.frame_write(sock, opcode, payload) # frame length is 101 + self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE + + def test_asgi_websockets_read_timeout(self): + self.load('websockets/mirror') + + assert 'success' in self.conf( + {'http': {'websocket': {'read_timeout': 5}}}, 'settings' + ), 'configure read_timeout' + + _, sock, _ = self.ws.upgrade() + + frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah') + sock.sendall(frame[:2]) + + time.sleep(2) + + self.check_close(sock, 1001) # 1001 - CLOSE_GOING_AWAY + + def test_asgi_websockets_keepalive_interval(self): + self.load('websockets/mirror') + + assert 'success' in self.conf( + {'http': {'websocket': {'keepalive_interval': 5}}}, 'settings' + ), 'configure keepalive_interval' + + _, sock, _ = self.ws.upgrade() + + frame = self.ws.frame_to_send(self.ws.OP_TEXT, 'blah') + sock.sendall(frame[:2]) + + time.sleep(2) + + frame = self.ws.frame_read(sock) + self.check_frame(frame, True, self.ws.OP_PING, '') # PING frame + + sock.close() diff --git a/test/unit/applications/websockets.py b/test/unit/applications/websockets.py index cb9f40aa..bae40620 100644 --- a/test/unit/applications/websockets.py +++ b/test/unit/applications/websockets.py @@ -40,7 +40,7 @@ class TestApplicationWebsocket(TestApplicationProto): 'Upgrade': 'websocket', 'Connection': 'Upgrade', 'Sec-WebSocket-Key': key, - 'Sec-WebSocket-Protocol': 'chat', + 'Sec-WebSocket-Protocol': 'chat, phone, video', 'Sec-WebSocket-Version': 13, } -- cgit From 12f225a43acc6b5086b08c3d7df6f6ac2322efa1 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Thu, 1 Oct 2020 23:55:43 +0300 Subject: Tests: added ASGI HTTP applications. --- test/python/204_no_content/asgi.py | 8 + test/python/delayed/asgi.py | 51 +++++ test/python/empty/asgi.py | 10 + test/python/mirror/asgi.py | 22 ++ test/python/query_string/asgi.py | 11 + test/python/server_port/asgi.py | 11 + test/python/threading/asgi.py | 42 ++++ test/python/variables/asgi.py | 40 ++++ test/test_asgi_application.py | 403 +++++++++++++++++++++++++++++++++++++ 9 files changed, 598 insertions(+) create mode 100644 test/python/204_no_content/asgi.py create mode 100644 test/python/delayed/asgi.py create mode 100644 test/python/empty/asgi.py create mode 100644 test/python/mirror/asgi.py create mode 100644 test/python/query_string/asgi.py create mode 100644 test/python/server_port/asgi.py create mode 100644 test/python/threading/asgi.py create mode 100644 test/python/variables/asgi.py create mode 100644 test/test_asgi_application.py (limited to 'test') diff --git a/test/python/204_no_content/asgi.py b/test/python/204_no_content/asgi.py new file mode 100644 index 00000000..634facc2 --- /dev/null +++ b/test/python/204_no_content/asgi.py @@ -0,0 +1,8 @@ +async def application(scope, receive, send): + assert scope['type'] == 'http' + + await send({ + 'type': 'http.response.start', + 'status': 204, + 'headers': [], + }) diff --git a/test/python/delayed/asgi.py b/test/python/delayed/asgi.py new file mode 100644 index 00000000..d5cad929 --- /dev/null +++ b/test/python/delayed/asgi.py @@ -0,0 +1,51 @@ +import asyncio + +async def application(scope, receive, send): + assert scope['type'] == 'http' + + body = b'' + while True: + m = await receive() + body += m.get('body', b'') + if not m.get('more_body', False): + break + + headers = scope.get('headers', []) + + def get_header(n, v=None): + for h in headers: + if h[0] == n: + return h[1] + return v + + parts = int(get_header(b'x-parts', 1)) + delay = int(get_header(b'x-delay', 0)) + + loop = asyncio.get_event_loop() + + async def sleep(n): + future = loop.create_future() + loop.call_later(n, future.set_result, None) + await future + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + (b'content-length', str(len(body)).encode()), + ] + }) + + if not body: + await sleep(delay) + return + + step = int(len(body) / parts) + for i in range(0, len(body), step): + await send({ + 'type': 'http.response.body', + 'body': body[i : i + step], + 'more_body': True, + }) + + await sleep(delay) diff --git a/test/python/empty/asgi.py b/test/python/empty/asgi.py new file mode 100644 index 00000000..58b7c1f2 --- /dev/null +++ b/test/python/empty/asgi.py @@ -0,0 +1,10 @@ +async def application(scope, receive, send): + assert scope['type'] == 'http' + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + (b'content-length', b'0'), + ] + }) diff --git a/test/python/mirror/asgi.py b/test/python/mirror/asgi.py new file mode 100644 index 00000000..7088e893 --- /dev/null +++ b/test/python/mirror/asgi.py @@ -0,0 +1,22 @@ +async def application(scope, receive, send): + assert scope['type'] == 'http' + + body = b'' + while True: + m = await receive() + body += m.get('body', b'') + if not m.get('more_body', False): + break + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + (b'content-length', str(len(body)).encode()), + ] + }) + + await send({ + 'type': 'http.response.body', + 'body': body, + }) diff --git a/test/python/query_string/asgi.py b/test/python/query_string/asgi.py new file mode 100644 index 00000000..28f4d107 --- /dev/null +++ b/test/python/query_string/asgi.py @@ -0,0 +1,11 @@ +async def application(scope, receive, send): + assert scope['type'] == 'http' + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + (b'content-length', b'0'), + (b'query-string', scope['query_string']), + ] + }) diff --git a/test/python/server_port/asgi.py b/test/python/server_port/asgi.py new file mode 100644 index 00000000..e79ced00 --- /dev/null +++ b/test/python/server_port/asgi.py @@ -0,0 +1,11 @@ +async def application(scope, receive, send): + assert scope['type'] == 'http' + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + (b'content-length', b'0'), + (b'server-port', str(scope['server'][1]).encode()), + ] + }) diff --git a/test/python/threading/asgi.py b/test/python/threading/asgi.py new file mode 100644 index 00000000..3c978e50 --- /dev/null +++ b/test/python/threading/asgi.py @@ -0,0 +1,42 @@ +import asyncio +import sys +import time +import threading + + +class Foo(threading.Thread): + num = 10 + + def __init__(self, x): + self.__x = x + threading.Thread.__init__(self) + + def log_index(self, index): + sys.stderr.write( + "(" + str(index) + ") Thread: " + str(self.__x) + "\n" + ) + sys.stderr.flush() + + def run(self): + i = 0 + for _ in range(3): + self.log_index(i) + i += 1 + time.sleep(1) + self.log_index(i) + i += 1 + + +async def application(scope, receive, send): + assert scope['type'] == 'http' + + Foo(Foo.num).start() + Foo.num += 10 + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + (b'content-length', b'0'), + ] + }) diff --git a/test/python/variables/asgi.py b/test/python/variables/asgi.py new file mode 100644 index 00000000..dd1cca72 --- /dev/null +++ b/test/python/variables/asgi.py @@ -0,0 +1,40 @@ +async def application(scope, receive, send): + assert scope['type'] == 'http' + + body = b'' + while True: + m = await receive() + body += m.get('body', b'') + if not m.get('more_body', False): + break + + headers = scope.get('headers', []) + + def get_header(n): + res = [] + for h in headers: + if h[0] == n: + res.append(h[1]) + return b', '.join(res) + + await send({ + 'type': 'http.response.start', + 'status': 200, + 'headers': [ + (b'content-type', get_header(b'content-type')), + (b'content-length', str(len(body)).encode()), + (b'request-method', scope['method'].encode()), + (b'request-uri', scope['path'].encode()), + (b'http-host', get_header(b'host')), + (b'http-version', scope['http_version'].encode()), + (b'asgi-version', scope['asgi']['version'].encode()), + (b'asgi-spec-version', scope['asgi']['spec_version'].encode()), + (b'scheme', scope['scheme'].encode()), + (b'custom-header', get_header(b'custom-header')), + ] + }) + + await send({ + 'type': 'http.response.body', + 'body': body, + }) diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py new file mode 100644 index 00000000..7816caec --- /dev/null +++ b/test/test_asgi_application.py @@ -0,0 +1,403 @@ +import grp +import pytest +import pwd +import re +import time +from distutils.version import LooseVersion + +from unit.applications.lang.python import TestApplicationPython +from conftest import skip_alert + + +class TestASGIApplication(TestApplicationPython): + prerequisites = {'modules': {'python': + lambda v: LooseVersion(v) >= LooseVersion('3.5')}} + load_module = 'asgi' + + def findall(self, pattern): + with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f: + return re.findall(pattern, f.read()) + + def test_asgi_application__variables(self): + self.load('variables') + + body = 'Test body string.' + + resp = self.http( + b"""POST / HTTP/1.1 +Host: localhost +Content-Length: %d +Custom-Header: blah +Custom-hEader: Blah +Content-Type: text/html +Connection: close +custom-header: BLAH + +%s""" % (len(body), body.encode()), + raw=True, + ) + + assert resp['status'] == 200, 'status' + headers = resp['headers'] + header_server = headers.pop('Server') + assert re.search(r'Unit/[\d\.]+', header_server), 'server header' + + date = headers.pop('Date') + assert date[-4:] == ' GMT', 'date header timezone' + assert ( + abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5 + ), 'date header' + + assert headers == { + 'Connection': 'close', + 'content-length': str(len(body)), + 'content-type': 'text/html', + 'request-method': 'POST', + 'request-uri': '/', + 'http-host': 'localhost', + 'http-version': '1.1', + 'custom-header': 'blah, Blah, BLAH', + 'asgi-version': '3.0', + 'asgi-spec-version': '2.1', + 'scheme': 'http', + }, 'headers' + assert resp['body'] == body, 'body' + + def test_asgi_application__query_string(self): + self.load('query_string') + + resp = self.get(url='/?var1=val1&var2=val2') + + assert ( + resp['headers']['query-string'] == 'var1=val1&var2=val2' + ), 'query-string header' + + def test_asgi_application__query_string_space(self): + self.load('query_string') + + resp = self.get(url='/ ?var1=val1&var2=val2') + assert ( + resp['headers']['query-string'] == 'var1=val1&var2=val2' + ), 'query-string space' + + resp = self.get(url='/ %20?var1=val1&var2=val2') + assert ( + resp['headers']['query-string'] == 'var1=val1&var2=val2' + ), 'query-string space 2' + + resp = self.get(url='/ %20 ?var1=val1&var2=val2') + assert ( + resp['headers']['query-string'] == 'var1=val1&var2=val2' + ), 'query-string space 3' + + resp = self.get(url='/blah %20 blah? var1= val1 & var2=val2') + assert ( + resp['headers']['query-string'] == ' var1= val1 & var2=val2' + ), 'query-string space 4' + + def test_asgi_application__query_string_empty(self): + self.load('query_string') + + resp = self.get(url='/?') + + assert resp['status'] == 200, 'query string empty status' + assert resp['headers']['query-string'] == '', 'query string empty' + + def test_asgi_application__query_string_absent(self): + self.load('query_string') + + resp = self.get() + + assert resp['status'] == 200, 'query string absent status' + assert resp['headers']['query-string'] == '', 'query string absent' + + @pytest.mark.skip('not yet') + def test_asgi_application__server_port(self): + self.load('server_port') + + assert ( + self.get()['headers']['Server-Port'] == '7080' + ), 'Server-Port header' + + @pytest.mark.skip('not yet') + def test_asgi_application__working_directory_invalid(self): + self.load('empty') + + assert 'success' in self.conf( + '"/blah"', 'applications/empty/working_directory' + ), 'configure invalid working_directory' + + assert self.get()['status'] == 500, 'status' + + def test_asgi_application__204_transfer_encoding(self): + self.load('204_no_content') + + assert ( + 'Transfer-Encoding' not in self.get()['headers'] + ), '204 header transfer encoding' + + def test_asgi_application__shm_ack_handle(self): + self.load('mirror') + + # Minimum possible limit + shm_limit = 10 * 1024 * 1024 + + assert ( + 'success' in self.conf('{"shm": ' + str(shm_limit) + '}', + 'applications/mirror/limits') + ) + + # Should exceed shm_limit + max_body_size = 12 * 1024 * 1024 + + assert ( + 'success' in self.conf('{"http":{"max_body_size": ' + + str(max_body_size) + ' }}', + 'settings') + ) + + assert self.get()['status'] == 200, 'init' + + body = '0123456789AB' * 1024 * 1024 # 12 Mb + resp = self.post( + headers={ + 'Host': 'localhost', + 'Connection': 'close', + 'Content-Type': 'text/html', + }, + body=body, + read_buffer_size=1024 * 1024, + ) + + assert resp['body'] == body, 'keep-alive 1' + + def test_asgi_keepalive_body(self): + self.load('mirror') + + assert self.get()['status'] == 200, 'init' + + body = '0123456789' * 500 + (resp, sock) = self.post( + headers={ + 'Host': 'localhost', + 'Connection': 'keep-alive', + 'Content-Type': 'text/html', + }, + start=True, + body=body, + read_timeout=1, + ) + + assert resp['body'] == body, 'keep-alive 1' + + body = '0123456789' + resp = self.post( + headers={ + 'Host': 'localhost', + 'Connection': 'close', + 'Content-Type': 'text/html', + }, + sock=sock, + body=body, + ) + + assert resp['body'] == body, 'keep-alive 2' + + def test_asgi_keepalive_reconfigure(self): + skip_alert( + r'pthread_mutex.+failed', + r'failed to apply', + r'process \d+ exited on signal', + ) + self.load('mirror') + + assert self.get()['status'] == 200, 'init' + + body = '0123456789' + conns = 3 + socks = [] + + for i in range(conns): + (resp, sock) = self.post( + headers={ + 'Host': 'localhost', + 'Connection': 'keep-alive', + 'Content-Type': 'text/html', + }, + start=True, + body=body, + read_timeout=1, + ) + + assert resp['body'] == body, 'keep-alive open' + assert 'success' in self.conf( + str(i + 1), 'applications/mirror/processes' + ), 'reconfigure' + + socks.append(sock) + + for i in range(conns): + (resp, sock) = self.post( + headers={ + 'Host': 'localhost', + 'Connection': 'keep-alive', + 'Content-Type': 'text/html', + }, + start=True, + sock=socks[i], + body=body, + read_timeout=1, + ) + + assert resp['body'] == body, 'keep-alive request' + assert 'success' in self.conf( + str(i + 1), 'applications/mirror/processes' + ), 'reconfigure 2' + + for i in range(conns): + resp = self.post( + headers={ + 'Host': 'localhost', + 'Connection': 'close', + 'Content-Type': 'text/html', + }, + sock=socks[i], + body=body, + ) + + assert resp['body'] == body, 'keep-alive close' + assert 'success' in self.conf( + str(i + 1), 'applications/mirror/processes' + ), 'reconfigure 3' + + def test_asgi_keepalive_reconfigure_2(self): + self.load('mirror') + + assert self.get()['status'] == 200, 'init' + + body = '0123456789' + + (resp, sock) = self.post( + headers={ + 'Host': 'localhost', + 'Connection': 'keep-alive', + 'Content-Type': 'text/html', + }, + start=True, + body=body, + read_timeout=1, + ) + + assert resp['body'] == body, 'reconfigure 2 keep-alive 1' + + self.load('empty') + + assert self.get()['status'] == 200, 'init' + + (resp, sock) = self.post( + headers={ + 'Host': 'localhost', + 'Connection': 'close', + 'Content-Type': 'text/html', + }, + start=True, + sock=sock, + body=body, + ) + + assert resp['status'] == 200, 'reconfigure 2 keep-alive 2' + assert resp['body'] == '', 'reconfigure 2 keep-alive 2 body' + + assert 'success' in self.conf( + {"listeners": {}, "applications": {}} + ), 'reconfigure 2 clear configuration' + + resp = self.get(sock=sock) + + assert resp == {}, 'reconfigure 2 keep-alive 3' + + def test_asgi_keepalive_reconfigure_3(self): + self.load('empty') + + assert self.get()['status'] == 200, 'init' + + (_, sock) = self.http( + b"""GET / HTTP/1.1 +""", + start=True, + raw=True, + no_recv=True, + ) + + assert self.get()['status'] == 200 + + assert 'success' in self.conf( + {"listeners": {}, "applications": {}} + ), 'reconfigure 3 clear configuration' + + resp = self.http( + b"""Host: localhost +Connection: close + +""", + sock=sock, + raw=True, + ) + + assert resp['status'] == 200, 'reconfigure 3' + + def test_asgi_process_switch(self): + self.load('delayed') + + assert 'success' in self.conf( + '2', 'applications/delayed/processes' + ), 'configure 2 processes' + + self.get( + headers={ + 'Host': 'localhost', + 'Content-Length': '0', + 'X-Delay': '5', + 'Connection': 'close', + }, + no_recv=True, + ) + + headers_delay_1 = { + 'Connection': 'close', + 'Host': 'localhost', + 'Content-Length': '0', + 'X-Delay': '1', + } + + self.get(headers=headers_delay_1, no_recv=True) + + time.sleep(0.5) + + for _ in range(10): + self.get(headers=headers_delay_1, no_recv=True) + + self.get(headers=headers_delay_1) + + def test_asgi_application__loading_error(self): + skip_alert(r'Python failed to import module "blah"') + + self.load('empty') + + assert 'success' in self.conf('"blah"', 'applications/empty/module') + + assert self.get()['status'] == 503, 'loading error' + + def test_asgi_application__threading(self): + """wait_for_record() timeouts after 5s while every thread works at + least 3s. So without releasing GIL test should fail. + """ + + self.load('threading') + + for _ in range(10): + self.get(no_recv=True) + + assert ( + self.wait_for_record(r'\(5\) Thread: 100') is not None + ), 'last thread finished' -- cgit From 152ad526f491e70905e2fec3b7d33a89cf23813b Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 5 Oct 2020 11:05:00 +0100 Subject: Tests: added ASGI Lifespan. --- test/python/lifespan/empty/asgi.py | 27 +++++++++++++ test/python/lifespan/error/asgi.py | 3 ++ test/python/lifespan/error_auto/asgi.py | 2 + test/python/lifespan/failed/asgi.py | 11 +++++ test/test_asgi_lifespan.py | 71 +++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+) create mode 100644 test/python/lifespan/empty/asgi.py create mode 100644 test/python/lifespan/error/asgi.py create mode 100644 test/python/lifespan/error_auto/asgi.py create mode 100644 test/python/lifespan/failed/asgi.py create mode 100644 test/test_asgi_lifespan.py (limited to 'test') diff --git a/test/python/lifespan/empty/asgi.py b/test/python/lifespan/empty/asgi.py new file mode 100644 index 00000000..ea43af13 --- /dev/null +++ b/test/python/lifespan/empty/asgi.py @@ -0,0 +1,27 @@ +import os + + +async def application(scope, receive, send): + if scope['type'] == 'lifespan': + with open('version', 'w+') as f: + f.write( + scope['asgi']['version'] + ' ' + scope['asgi']['spec_version'] + ) + while True: + message = await receive() + if message['type'] == 'lifespan.startup': + os.remove('startup') + await send({'type': 'lifespan.startup.complete'}) + elif message['type'] == 'lifespan.shutdown': + os.remove('shutdown') + await send({'type': 'lifespan.shutdown.complete'}) + return + + if scope['type'] == 'http': + await send( + { + 'type': 'http.response.start', + 'status': 204, + 'headers': [(b'content-length', b'0'),], + } + ) diff --git a/test/python/lifespan/error/asgi.py b/test/python/lifespan/error/asgi.py new file mode 100644 index 00000000..509cb3ee --- /dev/null +++ b/test/python/lifespan/error/asgi.py @@ -0,0 +1,3 @@ +async def application(scope, receive, send): + if scope['type'] != 'http': + raise Exception('Exception blah') diff --git a/test/python/lifespan/error_auto/asgi.py b/test/python/lifespan/error_auto/asgi.py new file mode 100644 index 00000000..90d506a1 --- /dev/null +++ b/test/python/lifespan/error_auto/asgi.py @@ -0,0 +1,2 @@ +async def application(scope, receive, send): + assert scope['type'] == 'http' diff --git a/test/python/lifespan/failed/asgi.py b/test/python/lifespan/failed/asgi.py new file mode 100644 index 00000000..8f315f70 --- /dev/null +++ b/test/python/lifespan/failed/asgi.py @@ -0,0 +1,11 @@ +async def application(scope, receive, send): + if scope['type'] == 'lifespan': + while True: + message = await receive() + if message['type'] == 'lifespan.startup': + await send({"type": "lifespan.startup.failed"}) + raise Exception('Exception blah') + + elif message['type'] == 'lifespan.shutdown': + await send({'type': 'lifespan.shutdown.complete'}) + return diff --git a/test/test_asgi_lifespan.py b/test/test_asgi_lifespan.py new file mode 100644 index 00000000..2fbc68f8 --- /dev/null +++ b/test/test_asgi_lifespan.py @@ -0,0 +1,71 @@ +import os +import pytest +from distutils.version import LooseVersion + +from unit.applications.lang.python import TestApplicationPython +from conftest import option + + +class TestASGILifespan(TestApplicationPython): + prerequisites = { + 'modules': {'python': lambda v: LooseVersion(v) >= LooseVersion('3.5')} + } + load_module = 'asgi' + + def test_asgi_lifespan(self): + self.load('lifespan/empty') + + startup_path = option.test_dir + '/python/lifespan/empty/startup' + shutdown_path = option.test_dir + '/python/lifespan/empty/shutdown' + version_path = option.test_dir + '/python/lifespan/empty/version' + + open(startup_path, 'a').close() + open(shutdown_path, 'a').close() + open(version_path, 'a').close() + + assert self.get()['status'] == 204 + + self.stop() + + is_startup = os.path.isfile(startup_path) + is_shutdown = os.path.isfile(shutdown_path) + + if is_startup: + os.remove(startup_path) + + if is_shutdown: + os.remove(shutdown_path) + + with open(version_path, 'r') as f: + version = f.read() + + os.remove(version_path) + + assert not is_startup, 'startup' + assert not is_shutdown, 'shutdown' + assert version == '3.0 2.0', 'version' + + def test_asgi_lifespan_failed(self): + self.load('lifespan/failed') + + assert self.get()['status'] == 503 + + assert ( + self.wait_for_record(r'\[error\].*Application startup failed') + is not None + ), 'error message' + assert self.wait_for_record(r'Exception blah') is not None, 'exception' + + def test_asgi_lifespan_error(self): + self.load('lifespan/error') + + self.get() + + assert self.wait_for_record(r'Exception blah') is not None, 'exception' + + def test_asgi_lifespan_error_auto(self): + self.load('lifespan/error_auto') + + self.get() + + assert self.wait_for_record(r'AssertionError') is not None, 'assertion' -- cgit From 58cc73994f071fc5db3347a3956f8089cb8e4dd0 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 5 Oct 2020 11:05:19 +0100 Subject: Tests: added websocket test with long length. --- test/test_asgi_websockets.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'test') diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py index 249f630f..cbd77109 100644 --- a/test/test_asgi_websockets.py +++ b/test/test_asgi_websockets.py @@ -128,6 +128,18 @@ class TestASGIWebsockets(TestApplicationPython): sock.close() + def test_asgi_websockets_length_long(self): + self.load('websockets/mirror') + + _, sock, _ = self.ws.upgrade() + + self.ws.frame_write(sock, self.ws.OP_TEXT, 'fragment1', fin=False) + self.ws.frame_write( + sock, self.ws.OP_CONT, 'fragment2', length=2**64 - 1 + ) + + self.check_close(sock, 1009) # 1009 - CLOSE_TOO_LARGE + def test_asgi_websockets_frame_fragmentation_invalid(self): self.load('websockets/mirror') -- cgit From 481e950b8696740397eeda0d3c01a2dda2239143 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Mon, 5 Oct 2020 13:26:35 +0300 Subject: Tests: pretty versions output for multi-version tests. --- test/conftest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 8e9009b6..0bc5cdf9 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -74,11 +74,11 @@ def pytest_generate_tests(metafunc): def generate_tests(versions): metafunc.fixturenames.append('tmp_ct') - metafunc.parametrize('tmp_ct', range(len(versions))) + metafunc.parametrize('tmp_ct', versions) - for i, version in enumerate(versions): + for version in versions: option.generated_tests[ - metafunc.function.__name__ + '[{}]'.format(i) + metafunc.function.__name__ + '[{}]'.format(version) ] = (type + ' ' + version) # take available module from option and generate tests for each version -- cgit From 37390d2a3be3646ad5a4c52d46ce93fc8f8a416b Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 6 Oct 2020 20:30:51 +0100 Subject: Tests: fixed tests to run as root. --- test/test_asgi_lifespan.py | 4 +++- test/test_ruby_isolation.py | 8 +------- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/test/test_asgi_lifespan.py b/test/test_asgi_lifespan.py index 2fbc68f8..3d6fdcce 100644 --- a/test/test_asgi_lifespan.py +++ b/test/test_asgi_lifespan.py @@ -3,7 +3,7 @@ import pytest from distutils.version import LooseVersion from unit.applications.lang.python import TestApplicationPython -from conftest import option +from conftest import option, public_dir class TestASGILifespan(TestApplicationPython): @@ -23,6 +23,8 @@ class TestASGILifespan(TestApplicationPython): open(shutdown_path, 'a').close() open(version_path, 'a').close() + public_dir(option.test_dir + '/python/lifespan/empty') + assert self.get()['status'] == 204 self.stop() diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py index be20300e..e88c60b2 100644 --- a/test/test_ruby_isolation.py +++ b/test/test_ruby_isolation.py @@ -33,15 +33,9 @@ class TestRubyIsolation(TestApplicationRuby): if not 'unprivileged_userns_clone' in isolation_features: pytest.skip('requires unprivileged userns or root') - os.mkdir(self.temp_dir + '/ruby') - - shutil.copytree( - option.test_dir + '/ruby/status_int', - self.temp_dir + '/ruby/status_int', - ) isolation = { 'namespaces': {'credential': not is_su, 'mount': True}, - 'rootfs': self.temp_dir, + 'rootfs': option.test_dir, } self.load('status_int', isolation=isolation) -- cgit From 3f513f434fbe44810ea2352d4ffc7d4d702b3e12 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Wed, 7 Oct 2020 20:06:30 +0300 Subject: Router: fixed "not empty" pattern matching. The "!" pattern should be opposite to "", i.e. match only non-empty values. But after 3c00af54b937 it was equal to "!*", which is wrong. --- test/test_routing.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'test') diff --git a/test/test_routing.py b/test/test_routing.py index 734825ef..32a7fbc8 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -118,6 +118,9 @@ class TestRouting(TestApplicationProto): def test_routes_match_negative(self): self.route_match({"uri": "!"}) + assert self.get()['status'] == 200 + + self.route_match({"uri": "!*"}) assert self.get()['status'] == 404 self.route_match({"uri": "!/"}) @@ -1187,6 +1190,18 @@ class TestRouting(TestApplicationProto): assert self.get(url='/?foo=barxx&x%=%')['status'] == 404 def test_routes_match_arguments_negative(self): + self.route_match({"arguments": {"foo": "!"}}) + assert self.get(url='/?bar')['status'] == 404 + assert self.get(url='/?foo')['status'] == 404 + assert self.get(url='/?foo=')['status'] == 404 + assert self.get(url='/?foo=%25')['status'] == 200 + + self.route_match({"arguments": {"foo": "!*"}}) + assert self.get(url='/?bar')['status'] == 404 + assert self.get(url='/?foo')['status'] == 404 + assert self.get(url='/?foo=')['status'] == 404 + assert self.get(url='/?foo=blah')['status'] == 404 + self.route_match({"arguments": {"foo": "!%25"}}) assert self.get(url='/?foo=blah')['status'] == 200 assert self.get(url='/?foo=%')['status'] == 404 -- cgit From 645683f432d742f42f2769f589fe769585fb7aa0 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Wed, 7 Oct 2020 22:04:54 +0300 Subject: Tests: fixed loading selected module version. Previously, for PHP, Ruby, and Perl the latest version was always loaded in multi-version tests. --- test/unit/applications/lang/perl.py | 6 +++++- test/unit/applications/lang/php.py | 6 +++++- test/unit/applications/lang/ruby.py | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/unit/applications/lang/perl.py b/test/unit/applications/lang/perl.py index 92939d88..d686cc8a 100644 --- a/test/unit/applications/lang/perl.py +++ b/test/unit/applications/lang/perl.py @@ -7,13 +7,17 @@ class TestApplicationPerl(TestApplicationProto): def load(self, script, name='psgi.pl', **kwargs): script_path = option.test_dir + '/perl/' + script + appication_type = self.get_appication_type() + + if appication_type is None: + appication_type = self.application_type self._load_conf( { "listeners": {"*:7080": {"pass": "applications/" + script}}, "applications": { script: { - "type": self.application_type, + "type": appication_type, "processes": {"spare": 0}, "working_directory": script_path, "script": script_path + '/' + name, diff --git a/test/unit/applications/lang/php.py b/test/unit/applications/lang/php.py index 350eb29b..6ac3d710 100644 --- a/test/unit/applications/lang/php.py +++ b/test/unit/applications/lang/php.py @@ -7,13 +7,17 @@ class TestApplicationPHP(TestApplicationProto): def load(self, script, index='index.php', **kwargs): script_path = option.test_dir + '/php/' + script + appication_type = self.get_appication_type() + + if appication_type is None: + appication_type = self.application_type self._load_conf( { "listeners": {"*:7080": {"pass": "applications/" + script}}, "applications": { script: { - "type": self.application_type, + "type": appication_type, "processes": {"spare": 0}, "root": script_path, "working_directory": script_path, diff --git a/test/unit/applications/lang/ruby.py b/test/unit/applications/lang/ruby.py index 534227bd..a6c39b2a 100644 --- a/test/unit/applications/lang/ruby.py +++ b/test/unit/applications/lang/ruby.py @@ -7,13 +7,17 @@ class TestApplicationRuby(TestApplicationProto): def load(self, script, name='config.ru', **kwargs): script_path = option.test_dir + '/ruby/' + script + appication_type = self.get_appication_type() + + if appication_type is None: + appication_type = self.application_type self._load_conf( { "listeners": {"*:7080": {"pass": "applications/" + script}}, "applications": { script: { - "type": self.application_type, + "type": appication_type, "processes": {"spare": 0}, "working_directory": script_path, "script": script_path + '/' + name, -- cgit From 6ec0ff35964c7805712d978625949f72ff5a63bc Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 7 Oct 2020 23:18:43 +0100 Subject: Tests: minor fixes. --- test/conftest.py | 5 +++-- test/test_access_log.py | 3 ++- test/test_asgi_application.py | 29 ++++++++++++++--------------- test/test_asgi_lifespan.py | 15 +++++++++++---- test/test_asgi_websockets.py | 6 ++++-- test/test_configuration.py | 8 ++++---- test/test_go_application.py | 3 ++- test/test_go_isolation.py | 1 + test/test_go_isolation_rootfs.py | 1 + test/test_http_header.py | 4 ++-- test/test_java_application.py | 4 +++- test/test_java_isolation_rootfs.py | 3 ++- test/test_java_websockets.py | 6 ++++-- test/test_node_application.py | 9 +++++---- test/test_node_websockets.py | 6 ++++-- test/test_perl_application.py | 5 +++-- test/test_php_application.py | 5 +++-- test/test_php_isolation.py | 2 +- test/test_php_targets.py | 2 +- test/test_proxy.py | 8 +++++--- test/test_proxy_chunked.py | 2 +- test/test_python_application.py | 5 +++-- test/test_python_isolation.py | 1 - test/test_python_procman.py | 3 ++- test/test_respawn.py | 2 +- test/test_routing.py | 3 ++- test/test_ruby_application.py | 5 +++-- test/test_ruby_isolation.py | 5 ++--- test/test_settings.py | 5 +++-- test/test_share_fallback.py | 2 +- test/test_static.py | 5 +++-- test/test_tls.py | 7 ++++--- test/test_upstreams_rr.py | 2 +- test/test_usr1.py | 2 +- test/unit/applications/lang/go.py | 2 +- test/unit/applications/lang/java.py | 4 ++-- test/unit/applications/lang/node.py | 4 ++-- test/unit/applications/lang/perl.py | 2 +- test/unit/applications/lang/php.py | 2 +- test/unit/applications/lang/python.py | 6 +++--- test/unit/applications/lang/ruby.py | 2 +- test/unit/applications/proto.py | 2 +- test/unit/applications/tls.py | 3 +-- test/unit/applications/websockets.py | 3 +-- test/unit/http.py | 4 ++-- test/unit/main.py | 12 +++++++----- 46 files changed, 125 insertions(+), 95 deletions(-) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 0bc5cdf9..b62264ca 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,16 +1,17 @@ import fcntl import os import platform -import pytest +import re import shutil import signal import stat import subprocess import sys -import re import tempfile import time +import pytest + from unit.check.go import check_go from unit.check.node import check_node from unit.check.tls import check_openssl diff --git a/test/test_access_log.py b/test/test_access_log.py index 010c56c2..eaba82ab 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -1,6 +1,7 @@ -import pytest import time +import pytest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index 7816caec..948d9823 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -1,12 +1,11 @@ -import grp -import pytest -import pwd import re import time from distutils.version import LooseVersion -from unit.applications.lang.python import TestApplicationPython +import pytest + from conftest import skip_alert +from unit.applications.lang.python import TestApplicationPython class TestASGIApplication(TestApplicationPython): @@ -18,7 +17,7 @@ class TestASGIApplication(TestApplicationPython): with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f: return re.findall(pattern, f.read()) - def test_asgi_application__variables(self): + def test_asgi_application_variables(self): self.load('variables') body = 'Test body string.' @@ -63,7 +62,7 @@ custom-header: BLAH }, 'headers' assert resp['body'] == body, 'body' - def test_asgi_application__query_string(self): + def test_asgi_application_query_string(self): self.load('query_string') resp = self.get(url='/?var1=val1&var2=val2') @@ -72,7 +71,7 @@ custom-header: BLAH resp['headers']['query-string'] == 'var1=val1&var2=val2' ), 'query-string header' - def test_asgi_application__query_string_space(self): + def test_asgi_application_query_string_space(self): self.load('query_string') resp = self.get(url='/ ?var1=val1&var2=val2') @@ -95,7 +94,7 @@ custom-header: BLAH resp['headers']['query-string'] == ' var1= val1 & var2=val2' ), 'query-string space 4' - def test_asgi_application__query_string_empty(self): + def test_asgi_application_query_string_empty(self): self.load('query_string') resp = self.get(url='/?') @@ -103,7 +102,7 @@ custom-header: BLAH assert resp['status'] == 200, 'query string empty status' assert resp['headers']['query-string'] == '', 'query string empty' - def test_asgi_application__query_string_absent(self): + def test_asgi_application_query_string_absent(self): self.load('query_string') resp = self.get() @@ -112,7 +111,7 @@ custom-header: BLAH assert resp['headers']['query-string'] == '', 'query string absent' @pytest.mark.skip('not yet') - def test_asgi_application__server_port(self): + def test_asgi_application_server_port(self): self.load('server_port') assert ( @@ -120,7 +119,7 @@ custom-header: BLAH ), 'Server-Port header' @pytest.mark.skip('not yet') - def test_asgi_application__working_directory_invalid(self): + def test_asgi_application_working_directory_invalid(self): self.load('empty') assert 'success' in self.conf( @@ -129,14 +128,14 @@ custom-header: BLAH assert self.get()['status'] == 500, 'status' - def test_asgi_application__204_transfer_encoding(self): + def test_asgi_application_204_transfer_encoding(self): self.load('204_no_content') assert ( 'Transfer-Encoding' not in self.get()['headers'] ), '204 header transfer encoding' - def test_asgi_application__shm_ack_handle(self): + def test_asgi_application_shm_ack_handle(self): self.load('mirror') # Minimum possible limit @@ -379,7 +378,7 @@ Connection: close self.get(headers=headers_delay_1) - def test_asgi_application__loading_error(self): + def test_asgi_application_loading_error(self): skip_alert(r'Python failed to import module "blah"') self.load('empty') @@ -388,7 +387,7 @@ Connection: close assert self.get()['status'] == 503, 'loading error' - def test_asgi_application__threading(self): + def test_asgi_application_threading(self): """wait_for_record() timeouts after 5s while every thread works at least 3s. So without releasing GIL test should fail. """ diff --git a/test/test_asgi_lifespan.py b/test/test_asgi_lifespan.py index 3d6fdcce..c37a1aae 100644 --- a/test/test_asgi_lifespan.py +++ b/test/test_asgi_lifespan.py @@ -1,9 +1,11 @@ import os -import pytest from distutils.version import LooseVersion +import pytest + +from conftest import option +from conftest import public_dir from unit.applications.lang.python import TestApplicationPython -from conftest import option, public_dir class TestASGILifespan(TestApplicationPython): @@ -19,11 +21,16 @@ class TestASGILifespan(TestApplicationPython): shutdown_path = option.test_dir + '/python/lifespan/empty/shutdown' version_path = option.test_dir + '/python/lifespan/empty/version' + os.chmod(option.test_dir + '/python/lifespan/empty', 0o777) + open(startup_path, 'a').close() + os.chmod(startup_path, 0o777) + open(shutdown_path, 'a').close() - open(version_path, 'a').close() + os.chmod(shutdown_path, 0o777) - public_dir(option.test_dir + '/python/lifespan/empty') + open(version_path, 'a').close() + os.chmod(version_path, 0o777) assert self.get()['status'] == 204 diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py index cbd77109..ab49b130 100644 --- a/test/test_asgi_websockets.py +++ b/test/test_asgi_websockets.py @@ -1,11 +1,13 @@ -import pytest import struct import time from distutils.version import LooseVersion +import pytest + +from conftest import option +from conftest import skip_alert from unit.applications.lang.python import TestApplicationPython from unit.applications.websockets import TestApplicationWebsocket -from conftest import option, skip_alert class TestASGIWebsockets(TestApplicationPython): diff --git a/test/test_configuration.py b/test/test_configuration.py index 07b8d522..d1e6f000 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -1,7 +1,7 @@ import pytest -from unit.control import TestControl from conftest import skip_alert +from unit.control import TestControl class TestConfiguration(TestControl): @@ -15,7 +15,7 @@ class TestConfiguration(TestControl): def test_json_unicode(self): assert 'success' in self.conf( - b""" + u""" { "ap\u0070": { "type": "\u0070ython", @@ -53,8 +53,8 @@ class TestConfiguration(TestControl): assert 'приложение' in self.conf_get('applications'), 'unicode 2 get' def test_json_unicode_number(self): - assert 'error' in self.conf( - b""" + assert 'success' in self.conf( + u""" { "app": { "type": "python", diff --git a/test/test_go_application.py b/test/test_go_application.py index 828a8e6e..8c77dfc5 100644 --- a/test/test_go_application.py +++ b/test/test_go_application.py @@ -1,6 +1,7 @@ -from unit.applications.lang.go import TestApplicationGo import re +from unit.applications.lang.go import TestApplicationGo + class TestGoApplication(TestApplicationGo): prerequisites = {'modules': {'go': 'all'}} diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index bcfdd015..1e7243f6 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -1,6 +1,7 @@ import grp import os import pwd + import pytest from unit.applications.lang.go import TestApplicationGo diff --git a/test/test_go_isolation_rootfs.py b/test/test_go_isolation_rootfs.py index 68891cd6..d8e177b1 100644 --- a/test/test_go_isolation_rootfs.py +++ b/test/test_go_isolation_rootfs.py @@ -1,4 +1,5 @@ import os + import pytest from unit.applications.lang.go import TestApplicationGo diff --git a/test/test_http_header.py b/test/test_http_header.py index 8c1e211b..8381a0d9 100644 --- a/test/test_http_header.py +++ b/test/test_http_header.py @@ -108,7 +108,7 @@ class TestHTTPHeader(TestApplicationPython): resp = self.get( headers={ 'Host': 'localhost', - 'Custom-Header': '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~', + 'Custom-Header': r'(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~', 'Connection': 'close', } ) @@ -116,7 +116,7 @@ class TestHTTPHeader(TestApplicationPython): assert resp['status'] == 200, 'value chars status' assert ( resp['headers']['Custom-Header'] - == '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~' + == r'(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~' ), 'value chars custom header' def test_http_header_value_chars_edge(self): diff --git a/test/test_java_application.py b/test/test_java_application.py index a2bd3d44..afcdf651 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -3,8 +3,10 @@ import os import re import time +from conftest import option +from conftest import public_dir +from conftest import skip_alert from unit.applications.lang.java import TestApplicationJava -from conftest import option, public_dir, skip_alert class TestJavaApplication(TestApplicationJava): prerequisites = {'modules': {'java': 'all'}} diff --git a/test/test_java_isolation_rootfs.py b/test/test_java_isolation_rootfs.py index df3ccdfa..f0f04df1 100644 --- a/test/test_java_isolation_rootfs.py +++ b/test/test_java_isolation_rootfs.py @@ -1,9 +1,10 @@ import os import subprocess + import pytest -from unit.applications.lang.java import TestApplicationJava from conftest import option +from unit.applications.lang.java import TestApplicationJava class TestJavaIsolationRootfs(TestApplicationJava): diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index 1bbefa1e..7e6d82e8 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -1,10 +1,12 @@ -import pytest import struct import time +import pytest + +from conftest import option +from conftest import skip_alert from unit.applications.lang.java import TestApplicationJava from unit.applications.websockets import TestApplicationWebsocket -from conftest import option, skip_alert class TestJavaWebsockets(TestApplicationJava): diff --git a/test/test_node_application.py b/test/test_node_application.py index c2b0ed69..a0b882f3 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -1,8 +1,9 @@ -import pytest import re -from unit.applications.lang.node import TestApplicationNode +import pytest + from conftest import waitforfiles +from unit.applications.lang.node import TestApplicationNode class TestNodeApplication(TestApplicationNode): @@ -50,8 +51,8 @@ class TestNodeApplication(TestApplicationNode): raw_headers = headers.pop('Request-Raw-Headers') assert re.search( r'^(?:Host|localhost|Content-Type|' - 'text\/html|Custom-Header|blah|Content-Length|17|Connection|' - 'close|,)+$', + r'text\/html|Custom-Header|blah|Content-Length|17|Connection|' + r'close|,)+$', raw_headers, ), 'raw headers' diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index 5af2f6f3..6a6b7f2d 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -1,10 +1,12 @@ -import pytest import struct import time +import pytest + +from conftest import option +from conftest import skip_alert from unit.applications.lang.node import TestApplicationNode from unit.applications.websockets import TestApplicationWebsocket -from conftest import option, skip_alert class TestNodeWebsockets(TestApplicationNode): diff --git a/test/test_perl_application.py b/test/test_perl_application.py index bb63eceb..78e32a43 100644 --- a/test/test_perl_application.py +++ b/test/test_perl_application.py @@ -1,8 +1,9 @@ -import pytest import re -from unit.applications.lang.perl import TestApplicationPerl +import pytest + from conftest import skip_alert +from unit.applications.lang.perl import TestApplicationPerl class TestPerlApplication(TestApplicationPerl): diff --git a/test/test_php_application.py b/test/test_php_application.py index 18a5c085..48fab5ee 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -1,11 +1,12 @@ import os -import pytest import re import shutil import time -from unit.applications.lang.php import TestApplicationPHP +import pytest + from conftest import option +from unit.applications.lang.php import TestApplicationPHP class TestPHPApplication(TestApplicationPHP): prerequisites = {'modules': {'php': 'all'}} diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index 556bd387..8ab3419a 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -1,8 +1,8 @@ import pytest +from conftest import option from unit.applications.lang.php import TestApplicationPHP from unit.feature.isolation import TestFeatureIsolation -from conftest import option class TestPHPIsolation(TestApplicationPHP): diff --git a/test/test_php_targets.py b/test/test_php_targets.py index 2eadf071..e64cd6b6 100644 --- a/test/test_php_targets.py +++ b/test/test_php_targets.py @@ -1,5 +1,5 @@ -from unit.applications.lang.php import TestApplicationPHP from conftest import option +from unit.applications.lang.php import TestApplicationPHP class TestPHPTargets(TestApplicationPHP): diff --git a/test/test_proxy.py b/test/test_proxy.py index 1476670c..d02c96a7 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -1,10 +1,12 @@ -import pytest import re import socket import time +import pytest + +from conftest import option +from conftest import skip_alert from unit.applications.lang.python import TestApplicationPython -from conftest import option, skip_alert class TestProxy(TestApplicationPython): @@ -215,7 +217,7 @@ Content-Length: 10 == header_value ), 'custom header' - header_value = '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~' + header_value = r'(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~' assert ( self.get_http10( headers={'Host': 'localhost', 'Custom-Header': header_value} diff --git a/test/test_proxy_chunked.py b/test/test_proxy_chunked.py index 93746703..26023617 100644 --- a/test/test_proxy_chunked.py +++ b/test/test_proxy_chunked.py @@ -51,7 +51,7 @@ class TestProxyChunked(TestApplicationPython): for line in re.split('\r\n', body): add = '' - m1 = re.search('(.*)\sX\s(\d+)', line) + m1 = re.search(r'(.*)\sX\s(\d+)', line) if m1 is not None: add = m1.group(1) * int(m1.group(2)) diff --git a/test/test_python_application.py b/test/test_python_application.py index 434ceb19..3e27a24c 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -1,11 +1,12 @@ import grp -import pytest import pwd import re import time -from unit.applications.lang.python import TestApplicationPython +import pytest + from conftest import skip_alert +from unit.applications.lang.python import TestApplicationPython class TestPythonApplication(TestApplicationPython): diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index 59ac670a..ac678103 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -94,4 +94,3 @@ class TestPythonIsolation(TestApplicationPython): self.load('empty', isolation=isolation) assert (self.get()['status'] == 200), 'enabled language_deps' - diff --git a/test/test_python_procman.py b/test/test_python_procman.py index 7e727fa8..8eccae3e 100644 --- a/test/test_python_procman.py +++ b/test/test_python_procman.py @@ -1,8 +1,9 @@ -import pytest import re import subprocess import time +import pytest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_respawn.py b/test/test_respawn.py index d40e78a4..18b9d535 100644 --- a/test/test_respawn.py +++ b/test/test_respawn.py @@ -2,8 +2,8 @@ import re import subprocess import time -from unit.applications.lang.python import TestApplicationPython from conftest import skip_alert +from unit.applications.lang.python import TestApplicationPython class TestRespawn(TestApplicationPython): diff --git a/test/test_routing.py b/test/test_routing.py index 32a7fbc8..2b528435 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- import pytest +from conftest import option +from conftest import skip_alert from unit.applications.proto import TestApplicationProto -from conftest import option, skip_alert class TestRouting(TestApplicationProto): diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index bdd1afb9..f84935f8 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -1,8 +1,9 @@ -import pytest import re -from unit.applications.lang.ruby import TestApplicationRuby +import pytest + from conftest import skip_alert +from unit.applications.lang.ruby import TestApplicationRuby class TestRubyApplication(TestApplicationRuby): diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py index e88c60b2..13ca0e16 100644 --- a/test/test_ruby_isolation.py +++ b/test/test_ruby_isolation.py @@ -1,10 +1,9 @@ -import os + import pytest -import shutil +from conftest import option from unit.applications.lang.ruby import TestApplicationRuby from unit.feature.isolation import TestFeatureIsolation -from conftest import option class TestRubyIsolation(TestApplicationRuby): diff --git a/test/test_settings.py b/test/test_settings.py index 89f55703..b0af6b04 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -1,9 +1,10 @@ -import pytest +import re import socket import time +import pytest + from unit.applications.lang.python import TestApplicationPython -import re class TestSettings(TestApplicationPython): diff --git a/test/test_share_fallback.py b/test/test_share_fallback.py index 391066ec..391d0836 100644 --- a/test/test_share_fallback.py +++ b/test/test_share_fallback.py @@ -1,7 +1,7 @@ import os -from unit.applications.proto import TestApplicationProto from conftest import skip_alert +from unit.applications.proto import TestApplicationProto class TestStatic(TestApplicationProto): diff --git a/test/test_static.py b/test/test_static.py index 2290bc38..0b82b4e8 100644 --- a/test/test_static.py +++ b/test/test_static.py @@ -1,9 +1,10 @@ import os -import pytest import socket -from unit.applications.proto import TestApplicationProto +import pytest + from conftest import waitforfiles +from unit.applications.proto import TestApplicationProto class TestStatic(TestApplicationProto): diff --git a/test/test_tls.py b/test/test_tls.py index 9881e973..518a834c 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -1,11 +1,12 @@ import io -import pytest import re import ssl import subprocess -from unit.applications.tls import TestApplicationTLS +import pytest + from conftest import skip_alert +from unit.applications.tls import TestApplicationTLS class TestTLS(TestApplicationTLS): @@ -527,7 +528,7 @@ basicConstraints = critical,CA:TRUE""" self.wait_for_record( re.compile( - ' (?!' + app_id + '#)(\d+)#\d+ "mirror" application started' + r' (?!' + app_id + r'#)(\d+)#\d+ "mirror" application started' ) ) diff --git a/test/test_upstreams_rr.py b/test/test_upstreams_rr.py index ceab11c3..2ecf1d9a 100644 --- a/test/test_upstreams_rr.py +++ b/test/test_upstreams_rr.py @@ -1,8 +1,8 @@ import os import re -from unit.applications.lang.python import TestApplicationPython from conftest import option +from unit.applications.lang.python import TestApplicationPython class TestUpstreamsRR(TestApplicationPython): diff --git a/test/test_usr1.py b/test/test_usr1.py index 19081223..2e48c18f 100644 --- a/test/test_usr1.py +++ b/test/test_usr1.py @@ -1,8 +1,8 @@ import os from subprocess import call -from unit.applications.lang.python import TestApplicationPython from conftest import waitforfiles +from unit.applications.lang.python import TestApplicationPython class TestUSR1(TestApplicationPython): diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 946b5421..7715bd6c 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -1,8 +1,8 @@ import os import subprocess -from unit.applications.proto import TestApplicationProto from conftest import option +from unit.applications.proto import TestApplicationProto class TestApplicationGo(TestApplicationProto): diff --git a/test/unit/applications/lang/java.py b/test/unit/applications/lang/java.py index 93427709..01cbfa0b 100644 --- a/test/unit/applications/lang/java.py +++ b/test/unit/applications/lang/java.py @@ -1,11 +1,11 @@ import glob import os -import pytest import shutil import subprocess -from unit.applications.proto import TestApplicationProto +import pytest from conftest import option +from unit.applications.proto import TestApplicationProto class TestApplicationJava(TestApplicationProto): diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index dbb7036b..877fc461 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -1,9 +1,9 @@ -import os import shutil from urllib.parse import quote +from conftest import option +from conftest import public_dir from unit.applications.proto import TestApplicationProto -from conftest import option, public_dir class TestApplicationNode(TestApplicationProto): diff --git a/test/unit/applications/lang/perl.py b/test/unit/applications/lang/perl.py index d686cc8a..a27c7649 100644 --- a/test/unit/applications/lang/perl.py +++ b/test/unit/applications/lang/perl.py @@ -1,5 +1,5 @@ -from unit.applications.proto import TestApplicationProto from conftest import option +from unit.applications.proto import TestApplicationProto class TestApplicationPerl(TestApplicationProto): diff --git a/test/unit/applications/lang/php.py b/test/unit/applications/lang/php.py index 6ac3d710..2d50df2e 100644 --- a/test/unit/applications/lang/php.py +++ b/test/unit/applications/lang/php.py @@ -1,5 +1,5 @@ -from unit.applications.proto import TestApplicationProto from conftest import option +from unit.applications.proto import TestApplicationProto class TestApplicationPHP(TestApplicationProto): diff --git a/test/unit/applications/lang/python.py b/test/unit/applications/lang/python.py index 75d34722..47b95dac 100644 --- a/test/unit/applications/lang/python.py +++ b/test/unit/applications/lang/python.py @@ -1,10 +1,10 @@ import os import shutil -import pytest - -from unit.applications.proto import TestApplicationProto from urllib.parse import quote + +import pytest from conftest import option +from unit.applications.proto import TestApplicationProto class TestApplicationPython(TestApplicationProto): diff --git a/test/unit/applications/lang/ruby.py b/test/unit/applications/lang/ruby.py index a6c39b2a..bc3cefc6 100644 --- a/test/unit/applications/lang/ruby.py +++ b/test/unit/applications/lang/ruby.py @@ -1,5 +1,5 @@ -from unit.applications.proto import TestApplicationProto from conftest import option +from unit.applications.proto import TestApplicationProto class TestApplicationRuby(TestApplicationProto): diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index 7bf7e244..2f748c21 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -2,8 +2,8 @@ import os import re import time -from unit.control import TestControl from conftest import option +from unit.control import TestControl class TestApplicationProto(TestControl): diff --git a/test/unit/applications/tls.py b/test/unit/applications/tls.py index 7c95f27b..fdf681ae 100644 --- a/test/unit/applications/tls.py +++ b/test/unit/applications/tls.py @@ -1,10 +1,9 @@ import os -import re import ssl import subprocess -from unit.applications.proto import TestApplicationProto from conftest import option +from unit.applications.proto import TestApplicationProto class TestApplicationTLS(TestApplicationProto): diff --git a/test/unit/applications/websockets.py b/test/unit/applications/websockets.py index bae40620..cc720a98 100644 --- a/test/unit/applications/websockets.py +++ b/test/unit/applications/websockets.py @@ -1,12 +1,11 @@ import base64 import hashlib import itertools -import pytest import random -import re import select import struct +import pytest from unit.applications.proto import TestApplicationProto GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" diff --git a/test/unit/http.py b/test/unit/http.py index e5231b3d..7845f9a8 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -2,14 +2,14 @@ import binascii import io import json import os -import pytest import re import select import socket import time -from unit.main import TestUnit +import pytest from conftest import option +from unit.main import TestUnit class TestHTTP(TestUnit): diff --git a/test/unit/main.py b/test/unit/main.py index 053ce145..d5940995 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -1,19 +1,21 @@ -import argparse import atexit import os -import platform -import pytest import re import shutil import signal import stat import subprocess -import sys import tempfile import time -from conftest import option, public_dir, waitforfiles, _check_alerts, _print_log from multiprocessing import Process +import pytest +from conftest import _check_alerts +from conftest import _print_log +from conftest import option +from conftest import public_dir +from conftest import waitforfiles + class TestUnit(): @classmethod -- cgit From 2821b3347c026ae171228146c5ccd0bd7408358f Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Tue, 6 Oct 2020 18:12:05 +0300 Subject: PHP: compatibility with 8.0.0 RC1. This closes #474 PR on GitHub. --- test/php/get_variables/index.php | 6 +++--- test/php/post_variables/index.php | 4 ++-- test/test_php_application.py | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'test') diff --git a/test/php/get_variables/index.php b/test/php/get_variables/index.php index dd7ef985..d6eb7d6b 100644 --- a/test/php/get_variables/index.php +++ b/test/php/get_variables/index.php @@ -1,7 +1,7 @@ diff --git a/test/php/post_variables/index.php b/test/php/post_variables/index.php index 5ea17324..8981d54d 100644 --- a/test/php/post_variables/index.php +++ b/test/php/post_variables/index.php @@ -1,6 +1,6 @@ diff --git a/test/test_php_application.py b/test/test_php_application.py index 48fab5ee..063d3e0c 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -198,9 +198,9 @@ class TestPHPApplication(TestApplicationPHP): resp = self.get(url='/?var1=val1&var2=&var3') assert resp['headers']['X-Var-1'] == 'val1', 'GET variables' - assert resp['headers']['X-Var-2'] == '1', 'GET variables 2' - assert resp['headers']['X-Var-3'] == '1', 'GET variables 3' - assert resp['headers']['X-Var-4'] == '', 'GET variables 4' + assert resp['headers']['X-Var-2'] == '', 'GET variables 2' + assert resp['headers']['X-Var-3'] == '', 'GET variables 3' + assert resp['headers']['X-Var-4'] == 'not set', 'GET variables 4' def test_php_application_post_variables(self): self.load('post_variables') @@ -214,8 +214,8 @@ class TestPHPApplication(TestApplicationPHP): body='var1=val1&var2=', ) assert resp['headers']['X-Var-1'] == 'val1', 'POST variables' - assert resp['headers']['X-Var-2'] == '1', 'POST variables 2' - assert resp['headers']['X-Var-3'] == '', 'POST variables 3' + assert resp['headers']['X-Var-2'] == '', 'POST variables 2' + assert resp['headers']['X-Var-3'] == 'not set', 'POST variables 3' def test_php_application_cookies(self): self.load('cookies') -- cgit