From 8f6e6086cb7bceeff6eec7cf0a2e3ff94f8d7705 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Mon, 20 Apr 2020 14:04:55 +0100 Subject: Tests: skips adjusted. --- test/test_proxy.py | 9 ++++++++- test/test_share_fallback.py | 21 +++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/test_proxy.py b/test/test_proxy.py index 74bd0873..b539d5f6 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -601,8 +601,14 @@ Content-Length: 10 'proxy ipv6 invalid 4', ) - @unittest.skip('not yet') def test_proxy_loop(self): + self.skip_alerts.extend( + [ + r'socket.*failed', + r'accept.*failed', + r'new connections are not accepted', + ] + ) self.conf( { "listeners": { @@ -625,6 +631,7 @@ 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_share_fallback.py b/test/test_share_fallback.py index c51e43ee..3f288d89 100644 --- a/test/test_share_fallback.py +++ b/test/test_share_fallback.py @@ -125,18 +125,23 @@ class TestStatic(TestApplicationProto): self.assertEqual(resp['status'], 200, 'fallback proxy status') self.assertEqual(resp['body'], '', 'fallback proxy') - @unittest.skip('not yet') - def test_fallback_proxy_cycle(self): + 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', + ] + ) + self.action_update( - { - "share": "/blah", - "fallback": {"proxy": "http://127.0.0.1:7080"}, - } + {"share": "/blah", "fallback": {"proxy": "http://127.0.0.1:7080"}} ) - self.assertNotEqual(self.get()['status'], 200, 'fallback cycle') + self.get(no_recv=True) self.assertIn('success', self.conf_delete('listeners/*:7081')) - self.assertNotEqual(self.get()['status'], 200, 'fallback cycle 2') + self.get(read_timeout=1) def test_fallback_invalid(self): def check_error(conf): -- cgit From 6a9a4fe0d46263d4d158803d4a82851e240e0e63 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Fri, 24 Apr 2020 05:08:56 +0100 Subject: Tests: introduced module version specification in prerequisites. --- test/test_access_log.py | 2 +- test/test_configuration.py | 2 +- test/test_go_application.py | 2 +- test/test_go_isolation.py | 2 +- test/test_http_header.py | 2 +- test/test_java_application.py | 2 +- test/test_java_websockets.py | 2 +- test/test_node_application.py | 2 +- test/test_node_websockets.py | 2 +- test/test_perl_application.py | 2 +- test/test_php_application.py | 2 +- test/test_php_basic.py | 2 +- test/test_proxy.py | 2 +- test/test_python_application.py | 2 +- test/test_python_basic.py | 2 +- test/test_python_environment.py | 2 +- test/test_python_procman.py | 2 +- test/test_routing.py | 2 +- test/test_routing_tls.py | 2 +- test/test_ruby_application.py | 2 +- test/test_settings.py | 2 +- test/test_tls.py | 2 +- test/test_upstreams_rr.py | 2 +- test/test_usr1.py | 2 +- test/unit/main.py | 16 ++++++++++++++-- 25 files changed, 38 insertions(+), 26 deletions(-) (limited to 'test') diff --git a/test/test_access_log.py b/test/test_access_log.py index 898d8b24..9287097f 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -6,7 +6,7 @@ from unit.applications.lang.python import TestApplicationPython class TestAccessLog(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def load(self, script): super().load(script) diff --git a/test/test_configuration.py b/test/test_configuration.py index daba874b..24efc914 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -3,7 +3,7 @@ from unit.control import TestControl class TestConfiguration(TestControl): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def test_json_empty(self): self.assertIn('error', self.conf(''), 'empty') diff --git a/test/test_go_application.py b/test/test_go_application.py index c9d4ba77..b9b78e2b 100644 --- a/test/test_go_application.py +++ b/test/test_go_application.py @@ -2,7 +2,7 @@ from unit.applications.lang.go import TestApplicationGo class TestGoApplication(TestApplicationGo): - prerequisites = {'modules': ['go']} + prerequisites = {'modules': {'go': 'all'}} def test_go_application_variables(self): self.load('variables') diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index 7884274d..cf78959a 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -7,7 +7,7 @@ from unit.feature.isolation import TestFeatureIsolation class TestGoIsolation(TestApplicationGo): - prerequisites = {'modules': ['go'], 'features': ['isolation']} + prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']} isolation = TestFeatureIsolation() diff --git a/test/test_http_header.py b/test/test_http_header.py index b773bd68..00d83f94 100644 --- a/test/test_http_header.py +++ b/test/test_http_header.py @@ -3,7 +3,7 @@ from unit.applications.lang.python import TestApplicationPython class TestHTTPHeader(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def test_http_header_value_leading_sp(self): self.load('custom_header') diff --git a/test/test_java_application.py b/test/test_java_application.py index 7bd351a4..0b4828c7 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -6,7 +6,7 @@ from unit.applications.lang.java import TestApplicationJava class TestJavaApplication(TestApplicationJava): - prerequisites = {'modules': ['java']} + prerequisites = {'modules': {'java': 'all'}} def test_java_conf_error(self): self.skip_alerts.extend( diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index 7ea04620..0f8f62a5 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -6,7 +6,7 @@ from unit.applications.websockets import TestApplicationWebsocket class TestJavaWebsockets(TestApplicationJava): - prerequisites = {'modules': ['java']} + prerequisites = {'modules': {'java': 'any'}} ws = TestApplicationWebsocket() diff --git a/test/test_node_application.py b/test/test_node_application.py index 174af15d..ed32357d 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -3,7 +3,7 @@ from unit.applications.lang.node import TestApplicationNode class TestNodeApplication(TestApplicationNode): - prerequisites = {'modules': ['node']} + prerequisites = {'modules': {'node': 'all'}} def test_node_application_basic(self): self.load('basic') diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index 4ce727db..14921991 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -6,7 +6,7 @@ from unit.applications.websockets import TestApplicationWebsocket class TestNodeWebsockets(TestApplicationNode): - prerequisites = {'modules': ['node']} + prerequisites = {'modules': {'node': 'any'}} ws = TestApplicationWebsocket() diff --git a/test/test_perl_application.py b/test/test_perl_application.py index cc4eb915..612c0792 100644 --- a/test/test_perl_application.py +++ b/test/test_perl_application.py @@ -3,7 +3,7 @@ from unit.applications.lang.perl import TestApplicationPerl class TestPerlApplication(TestApplicationPerl): - prerequisites = {'modules': ['perl']} + prerequisites = {'modules': {'perl': 'all'}} def test_perl_application(self): self.load('variables') diff --git a/test/test_php_application.py b/test/test_php_application.py index 48e1e815..746d61d5 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -5,7 +5,7 @@ import unittest from unit.applications.lang.php import TestApplicationPHP class TestPHPApplication(TestApplicationPHP): - prerequisites = {'modules': ['php']} + prerequisites = {'modules': {'php': 'all'}} def before_disable_functions(self): body = self.get()['body'] diff --git a/test/test_php_basic.py b/test/test_php_basic.py index 5fde3e00..16483c4a 100644 --- a/test/test_php_basic.py +++ b/test/test_php_basic.py @@ -2,7 +2,7 @@ from unit.control import TestControl class TestPHPBasic(TestControl): - prerequisites = {'modules': ['php']} + prerequisites = {'modules': {'php': 'any'}} conf_app = { "app": { diff --git a/test/test_proxy.py b/test/test_proxy.py index b539d5f6..852e970f 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -6,7 +6,7 @@ from unit.applications.lang.python import TestApplicationPython class TestProxy(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} SERVER_PORT = 7999 diff --git a/test/test_python_application.py b/test/test_python_application.py index 8d435b48..d7d39be2 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -8,7 +8,7 @@ from unit.applications.lang.python import TestApplicationPython class TestPythonApplication(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'all'}} def findall(self, pattern): with open(self.testdir + '/unit.log', 'r', errors='ignore') as f: diff --git a/test/test_python_basic.py b/test/test_python_basic.py index 3233fca2..d6445ac2 100644 --- a/test/test_python_basic.py +++ b/test/test_python_basic.py @@ -2,7 +2,7 @@ from unit.control import TestControl class TestPythonBasic(TestControl): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} conf_app = { "app": { diff --git a/test/test_python_environment.py b/test/test_python_environment.py index f808f795..a03b96e6 100644 --- a/test/test_python_environment.py +++ b/test/test_python_environment.py @@ -2,7 +2,7 @@ from unit.applications.lang.python import TestApplicationPython class TestPythonEnvironment(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def test_python_environment_name_null(self): self.load('environment') diff --git a/test/test_python_procman.py b/test/test_python_procman.py index a2e6126c..daa2c53d 100644 --- a/test/test_python_procman.py +++ b/test/test_python_procman.py @@ -6,7 +6,7 @@ from unit.applications.lang.python import TestApplicationPython class TestPythonProcman(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def setUp(self): super().setUp() diff --git a/test/test_routing.py b/test/test_routing.py index ad793662..e4f13e29 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -3,7 +3,7 @@ from unit.applications.proto import TestApplicationProto class TestRouting(TestApplicationProto): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def setUp(self): super().setUp() diff --git a/test/test_routing_tls.py b/test/test_routing_tls.py index 36bd9057..a9b8f88d 100644 --- a/test/test_routing_tls.py +++ b/test/test_routing_tls.py @@ -2,7 +2,7 @@ from unit.applications.tls import TestApplicationTLS class TestRoutingTLS(TestApplicationTLS): - prerequisites = {'modules': ['openssl']} + prerequisites = {'modules': {'openssl': 'any'}} def test_routes_match_scheme_tls(self): self.certificate() diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index bdaabe51..90ebd6a8 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -3,7 +3,7 @@ from unit.applications.lang.ruby import TestApplicationRuby class TestRubyApplication(TestApplicationRuby): - prerequisites = {'modules': ['ruby']} + prerequisites = {'modules': {'ruby': 'all'}} def test_ruby_application(self): self.load('variables') diff --git a/test/test_settings.py b/test/test_settings.py index 9de3a928..0b471d4e 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -5,7 +5,7 @@ from unit.applications.lang.python import TestApplicationPython class TestSettings(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def test_settings_header_read_timeout(self): self.load('empty') diff --git a/test/test_tls.py b/test/test_tls.py index d9dcf237..c482bf5a 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -8,7 +8,7 @@ from unit.applications.tls import TestApplicationTLS class TestTLS(TestApplicationTLS): - prerequisites = {'modules': ['python', 'openssl']} + prerequisites = {'modules': {'python': 'any', 'openssl': 'any'}} def findall(self, pattern): with open(self.testdir + '/unit.log', 'r', errors='ignore') as f: diff --git a/test/test_upstreams_rr.py b/test/test_upstreams_rr.py index 7045318a..56d4cbbb 100644 --- a/test/test_upstreams_rr.py +++ b/test/test_upstreams_rr.py @@ -5,7 +5,7 @@ from unit.applications.lang.python import TestApplicationPython class TestUpstreamsRR(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def setUp(self): super().setUp() diff --git a/test/test_usr1.py b/test/test_usr1.py index 155303ea..0627ca1d 100644 --- a/test/test_usr1.py +++ b/test/test_usr1.py @@ -5,7 +5,7 @@ from unit.applications.lang.python import TestApplicationPython class TestUSR1(TestApplicationPython): - prerequisites = {'modules': ['python']} + prerequisites = {'modules': {'python': 'any'}} def test_usr1_access_log(self): self.load('empty') diff --git a/test/unit/main.py b/test/unit/main.py index 4507f71a..074d053e 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -52,9 +52,21 @@ class TestUnit(unittest.TestCase): type = self.application_type for module in self.prerequisites['modules']: if module in self.available['modules']: - for version in self.available['modules'][module]: - self.application_type = type + ' ' + version + 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): -- cgit From d803ec39bc75622194802d249edc11fedc8e2441 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 12 May 2020 17:59:47 +0100 Subject: Tests: added respawn tests. --- test/test_respawn.py | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 test/test_respawn.py (limited to 'test') diff --git a/test/test_respawn.py b/test/test_respawn.py new file mode 100644 index 00000000..e7eef004 --- /dev/null +++ b/test/test_respawn.py @@ -0,0 +1,95 @@ +import re +import time +import subprocess +import unittest +from unit.applications.lang.python import TestApplicationPython + + +class TestRespawn(TestApplicationPython): + prerequisites = {'modules': {'python': 'any'}} + + PATTERN_ROUTER = 'unit: router' + PATTERN_CONTROLLER = 'unit: controller' + + def setUp(self): + super().setUp() + + self.app_name = "app-" + self.testdir.split('/')[-1] + + self.load('empty', self.app_name) + + self.assertIn( + 'success', + 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) + return m if m is None else m.group(1) + + def kill_pids(self, *pids): + subprocess.call(['kill', '-9'] + list(pids)) + + def wait_for_process(self, process): + for i in range(50): + found = self.pid_by_name(process) + + if found is not None: + break + + time.sleep(0.1) + + return found + + def smoke_test(self): + for _ in range(5): + self.assertIn( + 'success', + self.conf('1', 'applications/' + self.app_name + '/processes') + ) + self.assertEqual(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) + + 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) + + self.assertIsNotNone(self.wait_for_process(self.PATTERN_ROUTER)) + + self.smoke_test() + + def test_respawn_controller(self): + pid = self.pid_by_name(self.PATTERN_CONTROLLER) + + self.kill_pids(pid) + self.skip_alerts.append(r'process %s exited on signal 9' % pid) + + self.assertIsNotNone(self.wait_for_process(self.PATTERN_CONTROLLER)) + + self.assertEqual(self.get()['status'], 200) + + self.smoke_test() + + def test_respawn_application(self): + pid = self.pid_by_name(self.app_name) + + self.kill_pids(pid) + self.skip_alerts.append(r'process %s exited on signal 9' % pid) + + self.assertIsNotNone(self.wait_for_process(self.app_name)) + + self.smoke_test() + + +if __name__ == '__main__': + TestRespawn.main() -- cgit From 0174c971b5ec0d604e4e9becfa41e0bc31179e57 Mon Sep 17 00:00:00 2001 From: Valentin Bartenev Date: Thu, 14 May 2020 13:15:00 +0300 Subject: Configuration: URI encoding in the "pass" option. This is useful to escape "/" in path fragments. For example, in order to reference the application named "foo/bar": { "pass": "applications/foo%2Fbar" } --- test/unit/applications/lang/node.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index d818298f..1f5d5027 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -1,5 +1,6 @@ import os import shutil +from urllib.parse import quote from unit.applications.proto import TestApplicationProto @@ -33,7 +34,9 @@ class TestApplicationNode(TestApplicationProto): self._load_conf( { - "listeners": {"*:7080": {"pass": "applications/" + script}}, + "listeners": { + "*:7080": {"pass": "applications/" + quote(script, '')} + }, "applications": { script: { "type": "external", -- cgit From 26f407e24ad301e50b3abeea3a7c390577928c00 Mon Sep 17 00:00:00 2001 From: Axel Duch Date: Thu, 14 May 2020 12:29:22 +0200 Subject: Tests: decode uri and args. --- test/test_routing.py | 193 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 158 insertions(+), 35 deletions(-) (limited to 'test') diff --git a/test/test_routing.py b/test/test_routing.py index e4f13e29..9e45707e 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import unittest from unit.applications.proto import TestApplicationProto @@ -1069,6 +1071,33 @@ class TestRouting(TestApplicationProto): self.assertEqual(self.get(url='/?Foo=bar')['status'], 404, 'case') self.assertEqual(self.get(url='/?foo=Bar')['status'], 404, 'case 2') + def test_routes_match_arguments_chars(self): + chars = ( + " !\"%23$%25%26'()*%2B,-./0123456789:;<%3D>?@" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + ) + + 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", + ]: + 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) + + check_args({chars: chars}, chars + '=' + chars) + check_args({chars: chars}, chars + '=' + chars_enc) + check_args({chars: chars}, chars_enc + '=' + chars) + check_args({chars: chars}, chars_enc + '=' + chars_enc) + check_args({chars_enc: chars_enc}, chars + '=' + chars) + check_args({chars_enc: chars_enc}, chars + '=' + chars_enc) + check_args({chars_enc: chars_enc}, chars_enc + '=' + chars) + check_args({chars_enc: chars_enc}, chars_enc + '=' + chars_enc) + def test_routes_match_arguments_empty(self): self.route_match({"arguments": {}}) self.assertEqual(self.get()['status'], 200, 'arguments empty') @@ -1076,43 +1105,113 @@ class TestRouting(TestApplicationProto): self.route_match({"arguments": []}) self.assertEqual(self.get()['status'], 200, 'arguments empty 2') - def test_routes_match_arguments_invalid(self): - self.route_match_invalid({"arguments": ["var"]}) - self.route_match_invalid({"arguments": [{"var1": {}}]}) - self.route_match_invalid({"arguments": {"": "bar"}}) - - @unittest.skip('not yet') def test_routes_match_arguments_space(self): - self.route_match({"arguments": {"foo": "bar "}}) - - self.assertEqual(self.get(url='/?foo=bar &')['status'], 200, 'sp') - # FAIL - self.assertEqual(self.get(url='/?foo=bar+&')['status'], 200, 'sp 2') - # FAIL - self.assertEqual(self.get(url='/?foo=bar%20&')['status'], 200, 'sp 3') - - @unittest.skip('not yet') - def test_routes_match_arguments_plus(self): - self.route_match({"arguments": [{"foo": "bar+"}]}) - - self.assertEqual(self.get(url='/?foo=bar+&')['status'], 200, 'plus') - # FAIL - self.assertEqual( - self.get(url='/?foo=bar%2B&')['status'], 200, 'plus 2' - ) - - @unittest.skip('not yet') - def test_routes_match_arguments_hex(self): - self.route_match({"arguments": [{"foo": "bar"}]}) - + 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='/?%66%6F%6f=%62%61%72&')['status'], 200, 'hex' - ) - - def test_routes_match_arguments_chars(self): - self.route_match({"arguments": {"foo": "-._()[],;"}}) - - self.assertEqual(self.get(url='/?foo=-._()[],;')['status'], 200, 'chs') + 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) + + 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) + + 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) + + 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) + + 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) + + self.route_match({"arguments": {"foo": "%25*"}}) + self.assertEqual(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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) def test_routes_match_arguments_complex(self): self.route_match({"arguments": {"foo": ""}}) @@ -1147,6 +1246,14 @@ class TestRouting(TestApplicationProto): 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', + ) def test_routes_match_arguments_multiple_rules(self): self.route_match({"arguments": {"foo": ["bar", "blah"]}}) @@ -1193,6 +1300,22 @@ class TestRouting(TestApplicationProto): self.assertEqual(self.get(url='/?var2=val2')['status'], 404, 'arr 7') self.assertEqual(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') + + self.route_match_invalid({"arguments": ["var"]}) + self.route_match_invalid({"arguments": [{"var1": {}}]}) + self.route_match_invalid({"arguments": {"": "bar"}}) + self.route_match_invalid({"arguments": {"foo": "*ba*r"}}) + self.route_match_invalid({"arguments": {"foo": "%"}}) + self.route_match_invalid({"arguments": {"foo": "%1G"}}) + self.route_match_invalid({"arguments": {"%": "bar"}}) + self.route_match_invalid({"arguments": {"foo": "%0"}}) + self.route_match_invalid({"arguments": {"foo": "%%1F"}}) + self.route_match_invalid({"arguments": {"%%1F": ""}}) + self.route_match_invalid({"arguments": {"%7%F": ""}}) + def test_routes_match_cookies(self): self.route_match({"cookies": {"foO": "bar"}}) -- cgit From cf73fb809395da2a97e4a11a1185647e1d2b1d3d Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Fri, 15 May 2020 04:20:45 +0100 Subject: Tests: test_proxy_invalid simplified. --- test/test_proxy.py | 99 +++++++++++------------------------------------------- 1 file changed, 20 insertions(+), 79 deletions(-) (limited to 'test') diff --git a/test/test_proxy.py b/test/test_proxy.py index 852e970f..c163b14d 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -521,85 +521,26 @@ Content-Length: 10 self.assertEqual(len(resp['body']), 10, 'body gt Content-Length 15') def test_proxy_invalid(self): - self.assertIn( - 'error', - self.conf([{"action": {"proxy": 'blah'}}], 'routes'), - 'proxy invalid', - ) - self.assertIn( - 'error', - self.conf([{"action": {"proxy": '/blah'}}], 'routes'), - 'proxy invalid 2', - ) - self.assertIn( - 'error', - self.conf([{"action": {"proxy": 'unix:/blah'}}], 'routes'), - 'proxy unix invalid 2', - ) - self.assertIn( - 'error', - self.conf([{"action": {"proxy": 'http://blah'}}], 'routes'), - 'proxy unix invalid 3', - ) - self.assertIn( - 'error', - self.conf([{"action": {"proxy": 'http://127.0.0.1'}}], 'routes'), - 'proxy ipv4 invalid', - ) - self.assertIn( - 'error', - self.conf([{"action": {"proxy": 'http://127.0.0.1:'}}], 'routes'), - 'proxy ipv4 invalid 2', - ) - self.assertIn( - 'error', - self.conf( - [{"action": {"proxy": 'http://127.0.0.1:blah'}}], 'routes' - ), - 'proxy ipv4 invalid 3', - ) - self.assertIn( - 'error', - self.conf( - [{"action": {"proxy": 'http://127.0.0.1:-1'}}], 'routes' - ), - 'proxy ipv4 invalid 4', - ) - self.assertIn( - 'error', - self.conf( - [{"action": {"proxy": 'http://127.0.0.1:7080b'}}], 'routes' - ), - 'proxy ipv4 invalid 5', - ) - self.assertIn( - 'error', - self.conf( - [{"action": {"proxy": 'http://[]'}}], 'routes' - ), - 'proxy ipv6 invalid', - ) - self.assertIn( - 'error', - self.conf( - [{"action": {"proxy": 'http://[]:7080'}}], 'routes' - ), - 'proxy ipv6 invalid 2', - ) - self.assertIn( - 'error', - self.conf( - [{"action": {"proxy": 'http://[:]:7080'}}], 'routes' - ), - 'proxy ipv6 invalid 3', - ) - self.assertIn( - 'error', - self.conf( - [{"action": {"proxy": 'http://[::7080'}}], 'routes' - ), - 'proxy ipv6 invalid 4', - ) + def check_proxy(proxy): + self.assertIn( + 'error', + self.conf([{"action": {"proxy": proxy}}], 'routes'), + 'proxy invalid', + ) + + check_proxy('blah') + check_proxy('/blah') + check_proxy('unix:/blah') + check_proxy('http://blah') + check_proxy('http://127.0.0.1') + check_proxy('http://127.0.0.1:') + check_proxy('http://127.0.0.1:blah') + check_proxy('http://127.0.0.1:-1') + check_proxy('http://127.0.0.1:7080b') + check_proxy('http://[]') + check_proxy('http://[]:7080') + check_proxy('http://[:]:7080') + check_proxy('http://[::7080') def test_proxy_loop(self): self.skip_alerts.extend( -- cgit From ce4a2bbd05f42d258f9bf7880060a604ac1a866e Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Fri, 15 May 2020 04:20:56 +0100 Subject: Tests: style. --- test/run.py | 5 ++--- test/test_access_log.py | 3 +-- test/test_configuration.py | 1 + test/test_go_isolation.py | 4 ++-- test/test_http_header.py | 1 + test/test_java_application.py | 2 +- test/test_java_websockets.py | 3 ++- test/test_node_application.py | 1 + test/test_node_websockets.py | 3 ++- test/test_perl_application.py | 1 + test/test_php_application.py | 2 +- test/test_proxy.py | 3 ++- test/test_python_application.py | 4 ++-- test/test_python_procman.py | 3 ++- test/test_respawn.py | 4 ++-- test/test_return.py | 2 +- test/test_routing.py | 3 ++- test/test_ruby_application.py | 1 + test/test_settings.py | 3 ++- test/test_share_fallback.py | 2 +- test/test_static.py | 1 + test/test_tls.py | 2 +- test/test_upstreams_rr.py | 2 +- test/test_usr1.py | 2 +- test/unit/applications/lang/go.py | 1 + test/unit/applications/lang/java.py | 3 ++- test/unit/applications/lang/node.py | 1 + test/unit/applications/proto.py | 1 + test/unit/applications/tls.py | 1 + test/unit/applications/websockets.py | 9 +++++---- test/unit/control.py | 1 + test/unit/feature/isolation.py | 4 ++-- test/unit/http.py | 7 ++++--- test/unit/main.py | 17 ++++++++--------- 34 files changed, 60 insertions(+), 43 deletions(-) (limited to 'test') diff --git a/test/run.py b/test/run.py index 59e06bcb..384663f9 100755 --- a/test/run.py +++ b/test/run.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 - -import unittest -import sys import os +import sys +import unittest if __name__ == '__main__': loader = unittest.TestLoader() diff --git a/test/test_access_log.py b/test/test_access_log.py index 9287097f..3ef8f7a0 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -1,7 +1,6 @@ -import os -import re import time import unittest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_configuration.py b/test/test_configuration.py index 24efc914..0329ef5e 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -1,4 +1,5 @@ import unittest + from unit.control import TestControl diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index cf78959a..e6aade9b 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -1,7 +1,7 @@ -import pwd import grp -import json +import pwd import unittest + from unit.applications.lang.go import TestApplicationGo from unit.feature.isolation import TestFeatureIsolation diff --git a/test/test_http_header.py b/test/test_http_header.py index 00d83f94..ea4520c1 100644 --- a/test/test_http_header.py +++ b/test/test_http_header.py @@ -1,4 +1,5 @@ import unittest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_java_application.py b/test/test_java_application.py index 0b4828c7..3051ddea 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -1,7 +1,7 @@ import io import os import time -import unittest + from unit.applications.lang.java import TestApplicationJava diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index 0f8f62a5..d78f7263 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -1,6 +1,7 @@ -import time import struct +import time import unittest + from unit.applications.lang.java import TestApplicationJava from unit.applications.websockets import TestApplicationWebsocket diff --git a/test/test_node_application.py b/test/test_node_application.py index ed32357d..e46cc6a1 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -1,4 +1,5 @@ import unittest + from unit.applications.lang.node import TestApplicationNode diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index 14921991..1928d8c9 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -1,6 +1,7 @@ -import time import struct +import time import unittest + from unit.applications.lang.node import TestApplicationNode from unit.applications.websockets import TestApplicationWebsocket diff --git a/test/test_perl_application.py b/test/test_perl_application.py index 612c0792..dbf6abf7 100644 --- a/test/test_perl_application.py +++ b/test/test_perl_application.py @@ -1,4 +1,5 @@ import unittest + from unit.applications.lang.perl import TestApplicationPerl diff --git a/test/test_php_application.py b/test/test_php_application.py index 746d61d5..1259d22d 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -1,7 +1,7 @@ import os -import re import shutil import unittest + from unit.applications.lang.php import TestApplicationPHP class TestPHPApplication(TestApplicationPHP): diff --git a/test/test_proxy.py b/test/test_proxy.py index c163b14d..feec1ac4 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -1,7 +1,8 @@ import re -import time import socket +import time import unittest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_python_application.py b/test/test_python_application.py index d7d39be2..8bd3f750 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -1,9 +1,9 @@ -import re -import os import grp import pwd +import re import time import unittest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_python_procman.py b/test/test_python_procman.py index daa2c53d..8613f58e 100644 --- a/test/test_python_procman.py +++ b/test/test_python_procman.py @@ -1,7 +1,8 @@ import re -import time import subprocess +import time import unittest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_respawn.py b/test/test_respawn.py index e7eef004..f1c71a20 100644 --- a/test/test_respawn.py +++ b/test/test_respawn.py @@ -1,7 +1,7 @@ import re -import time import subprocess -import unittest +import time + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_return.py b/test/test_return.py index fcb51745..a89d97e6 100644 --- a/test/test_return.py +++ b/test/test_return.py @@ -1,5 +1,5 @@ import re -import unittest + from unit.applications.proto import TestApplicationProto diff --git a/test/test_routing.py b/test/test_routing.py index 9e45707e..5c4de519 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- - import unittest + from unit.applications.proto import TestApplicationProto @@ -1871,5 +1871,6 @@ class TestRouting(TestApplicationProto): self.assertEqual(self.get()['status'], 200, 'proxy') + if __name__ == '__main__': TestRouting.main() diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index 90ebd6a8..4709df6c 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -1,4 +1,5 @@ import unittest + from unit.applications.lang.ruby import TestApplicationRuby diff --git a/test/test_settings.py b/test/test_settings.py index 0b471d4e..6600358d 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -1,6 +1,7 @@ -import time import socket +import time import unittest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_share_fallback.py b/test/test_share_fallback.py index 3f288d89..ca5e2678 100644 --- a/test/test_share_fallback.py +++ b/test/test_share_fallback.py @@ -1,5 +1,5 @@ import os -import unittest + from unit.applications.proto import TestApplicationProto diff --git a/test/test_static.py b/test/test_static.py index b2489aa0..bee5db28 100644 --- a/test/test_static.py +++ b/test/test_static.py @@ -1,6 +1,7 @@ import os import socket import unittest + from unit.applications.proto import TestApplicationProto diff --git a/test/test_tls.py b/test/test_tls.py index c482bf5a..a0434174 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -1,9 +1,9 @@ import io -import os import re import ssl import subprocess import unittest + from unit.applications.tls import TestApplicationTLS diff --git a/test/test_upstreams_rr.py b/test/test_upstreams_rr.py index 56d4cbbb..2f74fbde 100644 --- a/test/test_upstreams_rr.py +++ b/test/test_upstreams_rr.py @@ -1,6 +1,6 @@ import os import re -import unittest + from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_usr1.py b/test/test_usr1.py index 0627ca1d..d1db652f 100644 --- a/test/test_usr1.py +++ b/test/test_usr1.py @@ -1,6 +1,6 @@ import os -import unittest from subprocess import call + from unit.applications.lang.python import TestApplicationPython diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index e0f83c0a..9070beb6 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -1,5 +1,6 @@ import os import subprocess + from unit.applications.proto import TestApplicationProto diff --git a/test/unit/applications/lang/java.py b/test/unit/applications/lang/java.py index a8a09ce5..c2c6dc51 100644 --- a/test/unit/applications/lang/java.py +++ b/test/unit/applications/lang/java.py @@ -1,7 +1,8 @@ -import os import glob +import os import shutil import subprocess + from unit.applications.proto import TestApplicationProto diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index 1f5d5027..cf2a99f6 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -1,6 +1,7 @@ import os import shutil from urllib.parse import quote + from unit.applications.proto import TestApplicationProto diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index ae1af354..244cb5be 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -1,5 +1,6 @@ import re import time + from unit.control import TestControl diff --git a/test/unit/applications/tls.py b/test/unit/applications/tls.py index 9213974a..e6a846b2 100644 --- a/test/unit/applications/tls.py +++ b/test/unit/applications/tls.py @@ -2,6 +2,7 @@ import os import re import ssl import subprocess + from unit.applications.proto import TestApplicationProto diff --git a/test/unit/applications/websockets.py b/test/unit/applications/websockets.py index fc15e8e4..e0dd2c0d 100644 --- a/test/unit/applications/websockets.py +++ b/test/unit/applications/websockets.py @@ -1,10 +1,11 @@ -import re -import random import base64 -import struct -import select import hashlib import itertools +import random +import re +import select +import struct + from unit.applications.proto import TestApplicationProto GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" diff --git a/test/unit/control.py b/test/unit/control.py index 0b344ed5..029072b5 100644 --- a/test/unit/control.py +++ b/test/unit/control.py @@ -1,4 +1,5 @@ import json + from unit.http import TestHTTP diff --git a/test/unit/feature/isolation.py b/test/unit/feature/isolation.py index 3f474993..4f33d04a 100644 --- a/test/unit/feature/isolation.py +++ b/test/unit/feature/isolation.py @@ -1,6 +1,5 @@ import os -import json -from unit.applications.proto import TestApplicationProto + from unit.applications.lang.go import TestApplicationGo from unit.applications.lang.java import TestApplicationJava from unit.applications.lang.node import TestApplicationNode @@ -8,6 +7,7 @@ from unit.applications.lang.perl import TestApplicationPerl from unit.applications.lang.php import TestApplicationPHP from unit.applications.lang.python import TestApplicationPython from unit.applications.lang.ruby import TestApplicationRuby +from unit.applications.proto import TestApplicationProto class TestFeatureIsolation(TestApplicationProto): diff --git a/test/unit/http.py b/test/unit/http.py index 13384dc8..de3bb2a4 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -1,11 +1,12 @@ import binascii import io +import json import os import re -import time -import json -import socket import select +import socket +import time + from unit.main import TestUnit diff --git a/test/unit/main.py b/test/unit/main.py index 074d053e..42918c9d 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -1,17 +1,17 @@ +import argparse +import atexit +import fcntl import os +import platform import re -import sys -import stat -import time -import fcntl -import atexit import shutil import signal -import argparse -import platform +import stat +import subprocess +import sys import tempfile +import time import unittest -import subprocess from multiprocessing import Process @@ -410,4 +410,3 @@ class TestUnit(unittest.TestCase): data = f.read() print(data) - -- cgit From ea841400f543fa4139adca926fefdd8565c227d2 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Fri, 15 May 2020 04:21:10 +0100 Subject: Tests: added test for encoding in the "pass" option. --- test/test_routing.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'test') diff --git a/test/test_routing.py b/test/test_routing.py index 5c4de519..3cf4009c 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -181,6 +181,61 @@ class TestRouting(TestApplicationProto): self.assertEqual(self.get(url='/blah')['status'], 200, '/blah') self.assertEqual(self.get(url='/BLAH')['status'], 404, '/BLAH') + 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", + } + }, + } + ), + ) + + self.assertEqual(self.get()['status'], 200) + + check_pass("%25", "%") + check_pass("blah%2Fblah", "blah/blah") + check_pass("%2Fblah%2F%2Fblah%2F", "/blah//blah/") + 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", + } + }, + } + ), + ) + + check_pass_error("%", "%") + check_pass_error("%1", "%1") + def test_routes_absent(self): self.conf( { -- cgit From 82471c1dd33fc13a18a334113b2c220cc06f3d5b Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Fri, 15 May 2020 04:21:25 +0100 Subject: Tests: added tests for "targets" option. --- test/php/targets/1.php | 4 ++ test/php/targets/2/2.php | 4 ++ test/php/targets/index.php | 4 ++ test/test_php_targets.py | 129 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 test/php/targets/1.php create mode 100644 test/php/targets/2/2.php create mode 100644 test/php/targets/index.php create mode 100644 test/test_php_targets.py (limited to 'test') diff --git a/test/php/targets/1.php b/test/php/targets/1.php new file mode 100644 index 00000000..09f7ae2c --- /dev/null +++ b/test/php/targets/1.php @@ -0,0 +1,4 @@ + diff --git a/test/php/targets/2/2.php b/test/php/targets/2/2.php new file mode 100644 index 00000000..0c5d27c6 --- /dev/null +++ b/test/php/targets/2/2.php @@ -0,0 +1,4 @@ + diff --git a/test/php/targets/index.php b/test/php/targets/index.php new file mode 100644 index 00000000..88239d5f --- /dev/null +++ b/test/php/targets/index.php @@ -0,0 +1,4 @@ + diff --git a/test/test_php_targets.py b/test/test_php_targets.py new file mode 100644 index 00000000..9c1ba2a6 --- /dev/null +++ b/test/test_php_targets.py @@ -0,0 +1,129 @@ +import unittest +from unit.applications.lang.php import TestApplicationPHP + +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": { + "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", + }, + }, + } + }, + } + ), + ) + + 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') + + self.assertIn( + 'success', + self.conf( + "\"1.php\"", 'applications/targets/targets/default/index' + ), + 'change targets index', + ) + self.assertEqual(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') + + def test_php_application_targets_error(self): + self.assertIn( + 'success', + self.conf( + { + "listeners": { + "*:7080": {"pass": "applications/targets/default"} + }, + "applications": { + "targets": { + "type": "php", + "processes": {"spare": 0}, + "targets": { + "default": { + "index": "index.php", + "root": self.current_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', + ) + + +if __name__ == '__main__': + TestPHPTargets.main() -- cgit From fa4d4b61200b6f465edbe24ebcdce1a7a8675d39 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 20 May 2020 23:06:56 +0100 Subject: Tests: print unit.log in case of errors. Thanks to hongzhidao. --- test/unit/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/unit/main.py b/test/unit/main.py index 42918c9d..d415f58f 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -102,7 +102,7 @@ class TestUnit(unittest.TestCase): break if m is None: - unit.stop() + unit._print_log() exit("Unit is writing log too long") # discover available modules from unit.log @@ -198,6 +198,7 @@ class TestUnit(unittest.TestCase): atexit.register(self.stop) if not self.waitforfiles(self.testdir + '/control.unit.sock'): + self._print_log() exit("Could not start unit") self.skip_alerts = [ -- cgit From e9e5ddd5a5d9ce99768833137eac2551a710becf Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Mon, 9 Mar 2020 16:28:25 +0000 Subject: Refactor of process management. The process abstraction has changed to: setup(task, process) start(task, process_data) prefork(task, process, mp) The prefork() occurs in the main process right before fork. The file src/nxt_main_process.c is completely free of process specific logic. The creation of a process now supports a PROCESS_CREATED state. The The setup() function of each process can set its state to either created or ready. If created, a MSG_PROCESS_CREATED is sent to main process, where external setup can be done (required for rootfs under container). The core processes (discovery, controller and router) doesn't need external setup, then they all proceeds to their start() function straight away. In the case of applications, the load of the module happens at the process setup() time and The module's init() function has changed to be the start() of the process. The module API has changed to: setup(task, process, conf) start(task, data) As a direct benefit of the PROCESS_CREATED message, the clone(2) of processes using pid namespaces now doesn't need to create a pipe to make the child block until parent setup uid/gid mappings nor it needs to receive the child pid. --- test/test_java_application.py | 1 + 1 file changed, 1 insertion(+) (limited to 'test') diff --git a/test/test_java_application.py b/test/test_java_application.py index 3051ddea..0cb18c25 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -13,6 +13,7 @@ class TestJavaApplication(TestApplicationJava): [ r'realpath.*failed', r'failed to apply new conf', + r'application setup failed', ] ) self.assertIn( -- cgit From 08b765ae4289f399bb3642d327ccf402efca3537 Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Thu, 28 May 2020 14:59:52 +0100 Subject: Tests: Added rootfs tests. --- test/go/ns_inspect/app.go | 21 +++++++-- test/python/ns_inspect/wsgi.py | 31 +++++++++++++ test/test_go_isolation.py | 46 +++++++++++++++++++ test/test_go_isolation_rootfs.py | 34 ++++++++++++++ test/test_java_isolation_rootfs.py | 85 +++++++++++++++++++++++++++++++++++ test/test_php_isolation.py | 57 +++++++++++++++++++++++ test/test_python_isolation.py | 79 ++++++++++++++++++++++++++++++++ test/test_python_isolation_chroot.py | 57 +++++++++++++++++++++++ test/test_ruby_isolation.py | 71 +++++++++++++++++++++++++++++ test/unit/applications/lang/go.py | 75 +++++++++++++++++++------------ test/unit/applications/lang/python.py | 19 +++++++- test/unit/main.py | 3 +- 12 files changed, 543 insertions(+), 35 deletions(-) create mode 100644 test/python/ns_inspect/wsgi.py create mode 100644 test/test_go_isolation_rootfs.py create mode 100644 test/test_java_isolation_rootfs.py create mode 100644 test/test_php_isolation.py create mode 100644 test/test_python_isolation.py create mode 100644 test/test_python_isolation_chroot.py create mode 100644 test/test_ruby_isolation.py (limited to 'test') diff --git a/test/go/ns_inspect/app.go b/test/go/ns_inspect/app.go index d9b561c9..4d19a796 100644 --- a/test/go/ns_inspect/app.go +++ b/test/go/ns_inspect/app.go @@ -21,10 +21,11 @@ type ( } Output struct { - PID int - UID int - GID int - NS NS + PID int + UID int + GID int + NS NS + FileExists bool } ) @@ -64,6 +65,18 @@ func handler(w http.ResponseWriter, r *http.Request) { CGROUP: getns("cgroup"), }, } + + err := r.ParseForm() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + if fname := r.Form.Get("file"); fname != "" { + _, err = os.Stat(fname); + out.FileExists = err == nil + } + data, err := json.Marshal(out) if err != nil { w.WriteHeader(http.StatusInternalServerError) diff --git a/test/python/ns_inspect/wsgi.py b/test/python/ns_inspect/wsgi.py new file mode 100644 index 00000000..fa1222e4 --- /dev/null +++ b/test/python/ns_inspect/wsgi.py @@ -0,0 +1,31 @@ +import json +import os + +try: + # Python 3 + from urllib.parse import parse_qs +except ImportError: + # Python 2 + from urlparse import parse_qs + + +def application(environ, start_response): + ret = { + 'FileExists': False, + } + + d = parse_qs(environ['QUERY_STRING']) + + ret['FileExists'] = os.path.exists(d.get('path')[0]) + + out = json.dumps(ret) + + start_response( + '200', + [ + ('Content-Type', 'application/json'), + ('Content-Length', str(len(out))), + ], + ) + + return out.encode('utf-8') diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index e6aade9b..61d39617 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -281,6 +281,52 @@ class TestGoIsolation(TestApplicationGo): '%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() + + 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=/go/app')['body'] + + self.assertEqual(obj['FileExists'], True, 'app relative to rootfs') + + obj = self.getjson(url='/?file=/bin/sh')['body'] + self.assertEqual(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() + + if not self.isolation_key('mnt'): + print('mnt namespace is not supported') + raise unittest.SkipTest() + + isolation = { + 'namespaces': {'mount': True}, + 'rootfs': self.testdir, + } + + self.load('ns_inspect', isolation=isolation) + + obj = self.getjson(url='/?file=/go/app')['body'] + + self.assertEqual(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__': TestGoIsolation.main() diff --git a/test/test_go_isolation_rootfs.py b/test/test_go_isolation_rootfs.py new file mode 100644 index 00000000..0039ff87 --- /dev/null +++ b/test/test_go_isolation_rootfs.py @@ -0,0 +1,34 @@ +import os +import unittest + +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() + + if os.uname().sysname == 'Darwin': + print('chroot tests not supported on OSX') + raise unittest.SkipTest() + + isolation = { + 'rootfs': self.testdir, + } + + self.load('ns_inspect', isolation=isolation) + + obj = self.getjson(url='/?file=/go/app')['body'] + + self.assertEqual(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() diff --git a/test/test_java_isolation_rootfs.py b/test/test_java_isolation_rootfs.py new file mode 100644 index 00000000..4d39bdc3 --- /dev/null +++ b/test/test_java_isolation_rootfs.py @@ -0,0 +1,85 @@ +import os +import subprocess +import unittest + +from unit.applications.lang.java import TestApplicationJava + + +class TestJavaIsolationRootfs(TestApplicationJava): + prerequisites = {'modules': {'java': 'all'}} + + def setUp(self): + if not self.is_su: + return + + super().setUp() + + os.makedirs(self.testdir + '/jars') + os.makedirs(self.testdir + '/tmp') + os.chmod(self.testdir + '/tmp', 0o777) + + try: + process = subprocess.Popen( + [ + "mount", + "--bind", + self.pardir + "/build", + self.testdir + "/jars", + ], + stderr=subprocess.STDOUT, + ) + + process.communicate() + + except: + self.fail('Cann\'t run mount process.') + + def tearDown(self): + if not self.is_su: + return + + try: + process = subprocess.Popen( + ["umount", "--lazy", self.testdir + "/jars"], + stderr=subprocess.STDOUT, + ) + + process.communicate() + + except: + self.fail('Cann\'t run mount process.') + + # super teardown must happen after unmount to avoid deletion of /build + super().tearDown() + + def test_java_isolation_rootfs_chroot_war(self): + if not self.is_su: + print('require root') + raise unittest.SkipTest() + + isolation = { + 'rootfs': self.testdir, + } + + self.load('empty_war', isolation=isolation) + + self.assertIn( + 'success', + self.conf( + '"/"', '/config/applications/empty_war/working_directory', + ), + ) + + self.assertIn( + 'success', self.conf('"/jars"', 'applications/empty_war/unit_jars') + ) + self.assertIn( + 'success', + self.conf('"/java/empty.war"', 'applications/empty_war/webapp'), + ) + + self.assertEqual(self.get()['status'], 200, 'war') + + +if __name__ == '__main__': + TestJavaIsolationRootfs.main() diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py new file mode 100644 index 00000000..1b70ef02 --- /dev/null +++ b/test/test_php_isolation.py @@ -0,0 +1,57 @@ +import unittest + +from unit.applications.lang.php import TestApplicationPHP +from unit.feature.isolation import TestFeatureIsolation + + +class TestPHPIsolation(TestApplicationPHP): + prerequisites = {'modules': {'php': 'any'}, 'features': ['isolation']} + + isolation = TestFeatureIsolation() + + @classmethod + def setUpClass(cls, complete_check=True): + unit = super().setUpClass(complete_check=False) + + TestFeatureIsolation().check(cls.available, unit.testdir) + + return unit if not complete_check else unit.complete() + + def test_php_isolation_rootfs(self): + isolation_features = self.available['features']['isolation'].keys() + + if 'mnt' not in isolation_features: + print('requires mnt ns') + raise unittest.SkipTest() + + 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() + + isolation = { + 'namespaces': {'credential': not self.is_su, 'mount': True}, + 'rootfs': self.current_dir, + } + + self.load('phpinfo', isolation=isolation) + + self.assertIn( + 'success', self.conf('"/php/phpinfo"', 'applications/phpinfo/root') + ) + self.assertIn( + 'success', + self.conf( + '"/php/phpinfo"', 'applications/phpinfo/working_directory' + ), + ) + + self.assertEqual(self.get()['status'], 200, 'empty rootfs') + + +if __name__ == '__main__': + TestPHPIsolation.main() diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py new file mode 100644 index 00000000..1bed64ba --- /dev/null +++ b/test/test_python_isolation.py @@ -0,0 +1,79 @@ +import unittest + +from unit.applications.lang.python import TestApplicationPython +from unit.feature.isolation import TestFeatureIsolation + + +class TestPythonIsolation(TestApplicationPython): + prerequisites = {'modules': {'python': 'any'}, 'features': ['isolation']} + + isolation = TestFeatureIsolation() + + @classmethod + def setUpClass(cls, complete_check=True): + unit = super().setUpClass(complete_check=False) + + TestFeatureIsolation().check(cls.available, unit.testdir) + + return unit if not complete_check else unit.complete() + + def test_python_isolation_rootfs(self): + isolation_features = self.available['features']['isolation'].keys() + + if 'mnt' not in isolation_features: + print('requires mnt ns') + raise unittest.SkipTest() + + 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() + + isolation = { + 'namespaces': {'credential': not self.is_su, 'mount': True}, + 'rootfs': self.testdir, + } + + self.load('empty', isolation=isolation) + + self.assertEqual(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', + ) + + ret = self.getjson(url='/?path=/app/python/ns_inspect') + + self.assertEqual( + ret['body']['FileExists'], True, 'application exists in rootfs', + ) + + +if __name__ == '__main__': + TestPythonIsolation.main() diff --git a/test/test_python_isolation_chroot.py b/test/test_python_isolation_chroot.py new file mode 100644 index 00000000..7761128e --- /dev/null +++ b/test/test_python_isolation_chroot.py @@ -0,0 +1,57 @@ +import unittest + +from unit.applications.lang.python import TestApplicationPython +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() + + isolation = { + 'rootfs': self.testdir, + } + + self.load('empty', isolation=isolation) + + self.assertEqual(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', + ) + + ret = self.getjson(url='/?path=/app/python/ns_inspect') + + self.assertEqual( + ret['body']['FileExists'], True, 'application exists in rootfs', + ) + + +if __name__ == '__main__': + TestPythonIsolation.main() diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py new file mode 100644 index 00000000..9bac162e --- /dev/null +++ b/test/test_ruby_isolation.py @@ -0,0 +1,71 @@ +import os +import shutil +import unittest + +from unit.applications.lang.ruby import TestApplicationRuby +from unit.feature.isolation import TestFeatureIsolation + + +class TestRubyIsolation(TestApplicationRuby): + prerequisites = {'modules': {'ruby': 'any'}, 'features': ['isolation']} + + isolation = TestFeatureIsolation() + + @classmethod + def setUpClass(cls, complete_check=True): + unit = super().setUpClass(complete_check=False) + + TestFeatureIsolation().check(cls.available, unit.testdir) + + return unit if not complete_check else unit.complete() + + def test_ruby_isolation_rootfs(self): + isolation_features = self.available['features']['isolation'].keys() + + if 'mnt' not in isolation_features: + print('requires mnt ns') + raise unittest.SkipTest() + + 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() + + os.mkdir(self.testdir + '/ruby') + + shutil.copytree( + self.current_dir + '/ruby/status_int', + self.testdir + '/ruby/status_int', + ) + isolation = { + 'namespaces': {'credential': not self.is_su, 'mount': True}, + 'rootfs': self.testdir, + } + + self.load('status_int', isolation=isolation) + + self.assertIn( + 'success', + self.conf( + '"/ruby/status_int/config.ru"', + 'applications/status_int/script', + ), + ) + + self.assertIn( + 'success', + self.conf( + '"/ruby/status_int"', + 'applications/status_int/working_directory', + ), + ) + + self.assertEqual(self.get()['status'], 200, 'status int') + + +if __name__ == '__main__': + TestRubyIsolation.main() diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 9070beb6..83bde4d8 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -19,26 +19,36 @@ class TestApplicationGo(TestApplicationProto): return unit if not complete_check else unit.complete() - def prepare_env(self, script, name): + def prepare_env(self, script, name, static=False): if not os.path.exists(self.testdir + '/go'): os.mkdir(self.testdir + '/go') env = os.environ.copy() env['GOPATH'] = self.pardir + '/build/go' - try: - process = subprocess.Popen( - [ - 'go', - 'build', - '-o', - self.testdir + '/go/' + name, - self.current_dir + '/go/' + script + '/' + name + '.go', - ], - env=env, - stderr=subprocess.STDOUT, - ) + if static: + args = [ + 'go', + 'build', + '-tags', + 'netgo', + '-ldflags', + '-extldflags "-static"', + '-o', + self.testdir + '/go/' + name, + self.current_dir + '/go/' + script + '/' + name + '.go', + ] + else: + args = [ + 'go', + 'build', + '-o', + self.testdir + '/go/' + name, + self.current_dir + '/go/' + script + '/' + name + '.go', + ] + try: + process = subprocess.Popen(args, env=env) process.communicate() except: @@ -47,21 +57,28 @@ class TestApplicationGo(TestApplicationProto): return process def load(self, script, name='app', **kwargs): - self.prepare_env(script, name) - - self._load_conf( - { - "listeners": {"*:7080": {"pass": "applications/" + script}}, - "applications": { - script: { - "type": "external", - "processes": {"spare": 0}, - "working_directory": self.current_dir - + "/go/" - + script, - "executable": self.testdir + "/go/" + name, - } + static_build = False + + wdir = self.current_dir + "/go/" + script + executable = self.testdir + "/go/" + name + + if 'isolation' in kwargs and 'rootfs' in kwargs['isolation']: + wdir = "/go/" + executable = "/go/" + name + static_build = True + + self.prepare_env(script, name, static=static_build) + + conf = { + "listeners": {"*:7080": {"pass": "applications/" + script}}, + "applications": { + script: { + "type": "external", + "processes": {"spare": 0}, + "working_directory": wdir, + "executable": executable, }, }, - **kwargs - ) + } + + self._load_conf(conf, **kwargs) diff --git a/test/unit/applications/lang/python.py b/test/unit/applications/lang/python.py index fdda024a..31a04107 100644 --- a/test/unit/applications/lang/python.py +++ b/test/unit/applications/lang/python.py @@ -1,3 +1,6 @@ +import shutil +import os + from unit.applications.proto import TestApplicationProto @@ -8,7 +11,21 @@ class TestApplicationPython(TestApplicationProto): if name is None: name = script - script_path = self.current_dir + '/python/' + script + if script[0] == '/': + script_path = script + else: + script_path = self.current_dir + '/python/' + script + + if kwargs.get('isolation') and kwargs['isolation'].get('rootfs'): + rootfs = kwargs['isolation']['rootfs'] + + if not os.path.exists(rootfs + '/app/python/'): + os.makedirs(rootfs + '/app/python/') + + if not os.path.exists(rootfs + '/app/python/' + name): + shutil.copytree(script_path, rootfs + '/app/python/' + name) + + script_path = '/app/python/' + name self._load_conf( { diff --git a/test/unit/main.py b/test/unit/main.py index d415f58f..408cf31c 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -58,6 +58,7 @@ class TestUnit(unittest.TestCase): if prereq_version == 'all': for version in available_versions: self.application_type = type + ' ' + version + self.application_version = version super().run(result) elif prereq_version == 'any': self.application_type = type + ' ' + available_versions[0] @@ -165,7 +166,7 @@ class TestUnit(unittest.TestCase): self._run() def _run(self): - build_dir = self.pardir + '/build' + build_dir = os.path.join(self.pardir, 'build') self.unitd = build_dir + '/unitd' if not os.path.isfile(self.unitd): -- cgit