From 07789a23e9c513dba87b020fae2989a57955e8a6 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Sun, 6 Dec 2020 16:01:59 +0000 Subject: Tests: options moved to the separate class. This change is necessary to separate the logic and prevent possible circular dependency. --- test/conftest.py | 13 +++++++++---- test/test_access_log.py | 2 +- test/test_asgi_application.py | 2 +- test/test_asgi_lifespan.py | 2 +- test/test_asgi_websockets.py | 2 +- test/test_go_isolation.py | 2 +- test/test_java_application.py | 2 +- test/test_java_isolation_rootfs.py | 2 +- test/test_java_websockets.py | 2 +- test/test_node_websockets.py | 2 +- test/test_php_application.py | 2 +- test/test_php_isolation.py | 2 +- test/test_php_targets.py | 2 +- test/test_proxy.py | 2 +- test/test_proxy_chunked.py | 2 +- test/test_python_application.py | 2 +- test/test_python_isolation.py | 2 +- test/test_python_procman.py | 2 +- test/test_respawn.py | 2 +- test/test_routing.py | 2 +- test/test_ruby_isolation.py | 2 +- test/test_share_fallback.py | 2 +- test/test_static.py | 2 +- test/test_tls.py | 2 +- test/test_upstreams_rr.py | 2 +- test/unit/applications/lang/go.py | 2 +- test/unit/applications/lang/java.py | 2 +- test/unit/applications/lang/node.py | 2 +- test/unit/applications/lang/perl.py | 2 +- test/unit/applications/lang/php.py | 2 +- test/unit/applications/lang/python.py | 2 +- test/unit/applications/lang/ruby.py | 2 +- test/unit/applications/proto.py | 2 +- test/unit/applications/tls.py | 2 +- test/unit/control.py | 2 +- test/unit/feature/isolation.py | 2 +- test/unit/http.py | 2 +- test/unit/main.py | 2 +- test/unit/option.py | 16 ++++++++++++++++ 39 files changed, 62 insertions(+), 41 deletions(-) create mode 100644 test/unit/option.py (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 3edc471d..8ca8c1d3 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -17,6 +17,7 @@ import pytest from unit.check.go import check_go from unit.check.node import check_node from unit.check.tls import check_openssl +from unit.option import option def pytest_addoption(parser): @@ -48,12 +49,14 @@ def pytest_addoption(parser): unit_instance = {} _processes = [] -option = None - def pytest_configure(config): - global option - option = config.option + option.config = config.option + + option.detailed = config.option.detailed + option.print_log = config.option.print_log + option.save_log = config.option.save_log + option.unsafe = config.option.unsafe option.generated_tests = {} option.current_dir = os.path.abspath( @@ -162,6 +165,8 @@ def pytest_sessionstart(session): unit_stop() + _check_alerts() + shutil.rmtree(unit_instance['temp_dir']) diff --git a/test/test_access_log.py b/test/test_access_log.py index 511ce6c5..0a0a6633 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -2,9 +2,9 @@ import time import pytest -from conftest import option from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestAccessLog(TestApplicationPython): diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index e90d78bc..80b64029 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -4,9 +4,9 @@ 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.option import option class TestASGIApplication(TestApplicationPython): diff --git a/test/test_asgi_lifespan.py b/test/test_asgi_lifespan.py index 3f29c7e7..409634bb 100644 --- a/test/test_asgi_lifespan.py +++ b/test/test_asgi_lifespan.py @@ -3,10 +3,10 @@ from distutils.version import LooseVersion import pytest -from conftest import option from conftest import public_dir from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestASGILifespan(TestApplicationPython): diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py index 54984526..766e53ed 100644 --- a/test/test_asgi_websockets.py +++ b/test/test_asgi_websockets.py @@ -4,10 +4,10 @@ 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 unit.option import option class TestASGIWebsockets(TestApplicationPython): diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index 8c4a6b9c..ac12c8ca 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -5,11 +5,11 @@ import shutil import pytest -from conftest import option from conftest import unit_run from conftest import unit_stop from unit.applications.lang.go import TestApplicationGo from unit.feature.isolation import TestFeatureIsolation +from unit.option import option class TestGoIsolation(TestApplicationGo): prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']} diff --git a/test/test_java_application.py b/test/test_java_application.py index 41345e87..04210ebf 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -3,10 +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 unit.option import option class TestJavaApplication(TestApplicationJava): prerequisites = {'modules': {'java': 'all'}} diff --git a/test/test_java_isolation_rootfs.py b/test/test_java_isolation_rootfs.py index 02d35a62..a401e23b 100644 --- a/test/test_java_isolation_rootfs.py +++ b/test/test_java_isolation_rootfs.py @@ -3,8 +3,8 @@ import subprocess import pytest -from conftest import option from unit.applications.lang.java import TestApplicationJava +from unit.option import option class TestJavaIsolationRootfs(TestApplicationJava): diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index 7586d4aa..5739e236 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -3,10 +3,10 @@ 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 unit.option import option class TestJavaWebsockets(TestApplicationJava): diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index 7b65b5c1..84eb4c42 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -3,10 +3,10 @@ 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 unit.option import option class TestNodeWebsockets(TestApplicationNode): diff --git a/test/test_php_application.py b/test/test_php_application.py index 578de0b7..463ec35b 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -5,9 +5,9 @@ import time import pytest -from conftest import option from conftest import unit_stop from unit.applications.lang.php import TestApplicationPHP +from unit.option import option class TestPHPApplication(TestApplicationPHP): prerequisites = {'modules': {'php': 'all'}} diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index cc660e04..1d0b0614 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -2,11 +2,11 @@ import shutil import pytest -from conftest import option from conftest import unit_run from conftest import unit_stop from unit.applications.lang.php import TestApplicationPHP from unit.feature.isolation import TestFeatureIsolation +from unit.option import option class TestPHPIsolation(TestApplicationPHP): diff --git a/test/test_php_targets.py b/test/test_php_targets.py index e64cd6b6..76326131 100644 --- a/test/test_php_targets.py +++ b/test/test_php_targets.py @@ -1,5 +1,5 @@ -from conftest import option from unit.applications.lang.php import TestApplicationPHP +from unit.option import option class TestPHPTargets(TestApplicationPHP): diff --git a/test/test_proxy.py b/test/test_proxy.py index be3e93fd..90b6b657 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -4,11 +4,11 @@ import time import pytest -from conftest import option from conftest import run_process from conftest import skip_alert from conftest import waitforsocket from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestProxy(TestApplicationPython): diff --git a/test/test_proxy_chunked.py b/test/test_proxy_chunked.py index ae2228fa..5529b397 100644 --- a/test/test_proxy_chunked.py +++ b/test/test_proxy_chunked.py @@ -3,10 +3,10 @@ import select import socket import time -from conftest import option from conftest import run_process from conftest import waitforsocket from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestProxyChunked(TestApplicationPython): diff --git a/test/test_python_application.py b/test/test_python_application.py index 83b0c8f4..b28e8c11 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -5,10 +5,10 @@ import time import pytest -from conftest import option from conftest import skip_alert from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestPythonApplication(TestApplicationPython): diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index 1a157528..66ff2f16 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -2,11 +2,11 @@ import shutil import pytest -from conftest import option from conftest import unit_run from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython from unit.feature.isolation import TestFeatureIsolation +from unit.option import option class TestPythonIsolation(TestApplicationPython): diff --git a/test/test_python_procman.py b/test/test_python_procman.py index ff914fc8..42a197a7 100644 --- a/test/test_python_procman.py +++ b/test/test_python_procman.py @@ -4,8 +4,8 @@ import time import pytest -from conftest import option from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestPythonProcman(TestApplicationPython): diff --git a/test/test_respawn.py b/test/test_respawn.py index 09a806d4..fbaad666 100644 --- a/test/test_respawn.py +++ b/test/test_respawn.py @@ -2,9 +2,9 @@ import re import subprocess import time -from conftest import option from conftest import skip_alert from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestRespawn(TestApplicationPython): diff --git a/test/test_routing.py b/test/test_routing.py index 83852273..a49075ae 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- import pytest -from conftest import option from conftest import skip_alert from unit.applications.proto import TestApplicationProto +from unit.option import option class TestRouting(TestApplicationProto): diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py index 69e25de9..56fccbd0 100644 --- a/test/test_ruby_isolation.py +++ b/test/test_ruby_isolation.py @@ -2,11 +2,11 @@ import shutil import pytest -from conftest import option from conftest import unit_run from conftest import unit_stop from unit.applications.lang.ruby import TestApplicationRuby from unit.feature.isolation import TestFeatureIsolation +from unit.option import option class TestRubyIsolation(TestApplicationRuby): diff --git a/test/test_share_fallback.py b/test/test_share_fallback.py index 462da9de..151d3ae5 100644 --- a/test/test_share_fallback.py +++ b/test/test_share_fallback.py @@ -1,8 +1,8 @@ import os -from conftest import option from conftest import skip_alert from unit.applications.proto import TestApplicationProto +from unit.option import option class TestStatic(TestApplicationProto): diff --git a/test/test_static.py b/test/test_static.py index a65928ca..1df0c902 100644 --- a/test/test_static.py +++ b/test/test_static.py @@ -3,9 +3,9 @@ import socket import pytest -from conftest import option from conftest import waitforfiles from unit.applications.proto import TestApplicationProto +from unit.option import option class TestStatic(TestApplicationProto): diff --git a/test/test_tls.py b/test/test_tls.py index 4cf8d22c..32b97895 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -5,9 +5,9 @@ import subprocess import pytest -from conftest import option from conftest import skip_alert from unit.applications.tls import TestApplicationTLS +from unit.option import option class TestTLS(TestApplicationTLS): diff --git a/test/test_upstreams_rr.py b/test/test_upstreams_rr.py index c20d6054..163eb646 100644 --- a/test/test_upstreams_rr.py +++ b/test/test_upstreams_rr.py @@ -1,8 +1,8 @@ import os import re -from conftest import option from unit.applications.lang.python import TestApplicationPython +from unit.option import option class TestUpstreamsRR(TestApplicationPython): diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 866dec47..70f9d58c 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -1,8 +1,8 @@ import os import subprocess -from conftest import option from unit.applications.proto import TestApplicationProto +from unit.option import option class TestApplicationGo(TestApplicationProto): diff --git a/test/unit/applications/lang/java.py b/test/unit/applications/lang/java.py index 0ff85187..b2e17f23 100644 --- a/test/unit/applications/lang/java.py +++ b/test/unit/applications/lang/java.py @@ -4,8 +4,8 @@ import shutil import subprocess import pytest -from conftest import option from unit.applications.proto import TestApplicationProto +from unit.option import option class TestApplicationJava(TestApplicationProto): diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index 98fd9ffc..baccef7e 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -1,9 +1,9 @@ import shutil from urllib.parse import quote -from conftest import option from conftest import public_dir from unit.applications.proto import TestApplicationProto +from unit.option import option class TestApplicationNode(TestApplicationProto): diff --git a/test/unit/applications/lang/perl.py b/test/unit/applications/lang/perl.py index 9dc24ace..58b867f0 100644 --- a/test/unit/applications/lang/perl.py +++ b/test/unit/applications/lang/perl.py @@ -1,5 +1,5 @@ -from conftest import option from unit.applications.proto import TestApplicationProto +from unit.option import option class TestApplicationPerl(TestApplicationProto): diff --git a/test/unit/applications/lang/php.py b/test/unit/applications/lang/php.py index 3dbb32f5..90c0078c 100644 --- a/test/unit/applications/lang/php.py +++ b/test/unit/applications/lang/php.py @@ -1,8 +1,8 @@ -from conftest import option import os import shutil from unit.applications.proto import TestApplicationProto +from unit.option import option class TestApplicationPHP(TestApplicationProto): diff --git a/test/unit/applications/lang/python.py b/test/unit/applications/lang/python.py index 792a86fa..287d23f0 100644 --- a/test/unit/applications/lang/python.py +++ b/test/unit/applications/lang/python.py @@ -3,8 +3,8 @@ import shutil from urllib.parse import quote import pytest -from conftest import option from unit.applications.proto import TestApplicationProto +from unit.option import option class TestApplicationPython(TestApplicationProto): diff --git a/test/unit/applications/lang/ruby.py b/test/unit/applications/lang/ruby.py index 82d66e65..02644584 100644 --- a/test/unit/applications/lang/ruby.py +++ b/test/unit/applications/lang/ruby.py @@ -1,5 +1,5 @@ -from conftest import option from unit.applications.proto import TestApplicationProto +from unit.option import option class TestApplicationRuby(TestApplicationProto): diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index 6e760c70..af05d071 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -2,8 +2,8 @@ import os import re import time -from conftest import option from unit.control import TestControl +from unit.option import option class TestApplicationProto(TestControl): diff --git a/test/unit/applications/tls.py b/test/unit/applications/tls.py index fb1b112c..b0cd5abb 100644 --- a/test/unit/applications/tls.py +++ b/test/unit/applications/tls.py @@ -2,8 +2,8 @@ import os import ssl import subprocess -from conftest import option from unit.applications.proto import TestApplicationProto +from unit.option import option class TestApplicationTLS(TestApplicationProto): diff --git a/test/unit/control.py b/test/unit/control.py index f05aa827..3008a64b 100644 --- a/test/unit/control.py +++ b/test/unit/control.py @@ -1,7 +1,7 @@ import json -from conftest import option from unit.http import TestHTTP +from unit.option import option def args_handler(conf_func): diff --git a/test/unit/feature/isolation.py b/test/unit/feature/isolation.py index 7877c03a..d8f68919 100644 --- a/test/unit/feature/isolation.py +++ b/test/unit/feature/isolation.py @@ -4,7 +4,7 @@ from unit.applications.lang.go import TestApplicationGo from unit.applications.lang.java import TestApplicationJava from unit.applications.lang.node import TestApplicationNode from unit.applications.proto import TestApplicationProto -from conftest import option +from unit.option import option class TestFeatureIsolation(TestApplicationProto): diff --git a/test/unit/http.py b/test/unit/http.py index 8d964978..ae74eac3 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -7,8 +7,8 @@ import select import socket import pytest -from conftest import option from unit.main import TestUnit +from unit.option import option class TestHTTP(TestUnit): diff --git a/test/unit/main.py b/test/unit/main.py index 488b3f4d..fce6a322 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -1,5 +1,5 @@ import pytest -from conftest import option +from unit.option import option class TestUnit(): diff --git a/test/unit/option.py b/test/unit/option.py new file mode 100644 index 00000000..677d806e --- /dev/null +++ b/test/unit/option.py @@ -0,0 +1,16 @@ +class Options(): + _options = { + 'skip_alerts': [], + 'skip_sanitizer': False, + } + + def __setattr__(self, name, value): + Options._options[name] = value + + def __getattr__(self, name): + if name in Options._options: + return Options._options[name] + + raise AttributeError + +option = Options() -- cgit From 8f916285639d7f9aac9ef03cace5e4dcbcca70cd Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 8 Dec 2020 14:37:25 +0000 Subject: Tests: utils module introduced. --- test/conftest.py | 51 ++----------------------------------- test/test_asgi_lifespan.py | 1 - test/test_java_application.py | 2 +- test/test_node_application.py | 2 +- test/test_proxy.py | 2 +- test/test_proxy_chunked.py | 2 +- test/test_static.py | 2 +- test/test_usr1.py | 2 +- test/unit/applications/lang/node.py | 2 +- test/unit/utils.py | 50 ++++++++++++++++++++++++++++++++++++ 10 files changed, 59 insertions(+), 57 deletions(-) create mode 100644 test/unit/utils.py (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 8ca8c1d3..982e43c9 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -18,6 +18,8 @@ from unit.check.go import check_go from unit.check.node import check_node from unit.check.tls import check_openssl from unit.option import option +from unit.utils import public_dir +from unit.utils import waitforfiles def pytest_addoption(parser): @@ -298,34 +300,6 @@ def unit_stop(): 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 _check_alerts(path=None): @@ -404,27 +378,6 @@ def stop_processes(): return 'Fail to stop process(es)' -def waitforsocket(port): - ret = False - - for i in range(50): - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect(('127.0.0.1', port)) - ret = True - break - - except KeyboardInterrupt: - raise - - except: - sock.close() - time.sleep(0.1) - - sock.close() - - assert ret, 'socket connected' - @pytest.fixture def temp_dir(request): return unit_instance['temp_dir'] diff --git a/test/test_asgi_lifespan.py b/test/test_asgi_lifespan.py index 409634bb..43286e22 100644 --- a/test/test_asgi_lifespan.py +++ b/test/test_asgi_lifespan.py @@ -3,7 +3,6 @@ from distutils.version import LooseVersion import pytest -from conftest import public_dir from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython from unit.option import option diff --git a/test/test_java_application.py b/test/test_java_application.py index 04210ebf..572e18e8 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -3,10 +3,10 @@ import os import re import time -from conftest import public_dir from conftest import skip_alert from unit.applications.lang.java import TestApplicationJava from unit.option import option +from unit.utils import public_dir class TestJavaApplication(TestApplicationJava): prerequisites = {'modules': {'java': 'all'}} diff --git a/test/test_node_application.py b/test/test_node_application.py index c8c3a444..f13a01e1 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -2,8 +2,8 @@ import re import pytest -from conftest import waitforfiles from unit.applications.lang.node import TestApplicationNode +from unit.utils import waitforfiles class TestNodeApplication(TestApplicationNode): diff --git a/test/test_proxy.py b/test/test_proxy.py index 90b6b657..975a76a0 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -6,9 +6,9 @@ import pytest from conftest import run_process from conftest import skip_alert -from conftest import waitforsocket from unit.applications.lang.python import TestApplicationPython from unit.option import option +from unit.utils import waitforsocket class TestProxy(TestApplicationPython): diff --git a/test/test_proxy_chunked.py b/test/test_proxy_chunked.py index 5529b397..73d94332 100644 --- a/test/test_proxy_chunked.py +++ b/test/test_proxy_chunked.py @@ -4,9 +4,9 @@ import socket import time from conftest import run_process -from conftest import waitforsocket from unit.applications.lang.python import TestApplicationPython from unit.option import option +from unit.utils import waitforsocket class TestProxyChunked(TestApplicationPython): diff --git a/test/test_static.py b/test/test_static.py index 1df0c902..4591aa03 100644 --- a/test/test_static.py +++ b/test/test_static.py @@ -3,9 +3,9 @@ import socket import pytest -from conftest import waitforfiles from unit.applications.proto import TestApplicationProto from unit.option import option +from unit.utils import waitforfiles class TestStatic(TestApplicationProto): diff --git a/test/test_usr1.py b/test/test_usr1.py index 3e44e4c5..44f19d23 100644 --- a/test/test_usr1.py +++ b/test/test_usr1.py @@ -2,8 +2,8 @@ import os from subprocess import call from conftest import unit_stop -from conftest import waitforfiles from unit.applications.lang.python import TestApplicationPython +from unit.utils import waitforfiles class TestUSR1(TestApplicationPython): diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index baccef7e..cc6d06ef 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -1,9 +1,9 @@ import shutil from urllib.parse import quote -from conftest import public_dir from unit.applications.proto import TestApplicationProto from unit.option import option +from unit.utils import public_dir class TestApplicationNode(TestApplicationProto): diff --git a/test/unit/utils.py b/test/unit/utils.py new file mode 100644 index 00000000..f24e9728 --- /dev/null +++ b/test/unit/utils.py @@ -0,0 +1,50 @@ +import os +import socket +import time + +import pytest + + +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 + + for f in files: + if not os.path.exists(f): + wait = True + break + + if not wait: + return True + + time.sleep(0.1) + + return False + + +def waitforsocket(port): + for i in range(50): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + try: + sock.settimeout(5) + sock.connect(('127.0.0.1', port)) + return + + except ConnectionRefusedError: + time.sleep(0.1) + + except KeyboardInterrupt: + raise + + pytest.fail('Can\'t connect to the 127.0.0.1:' + port) + -- cgit From b2e767819f04153944d525ef8d97d2f3a7a9af74 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 8 Dec 2020 14:37:33 +0000 Subject: Tests: skip_alert() converted to the fixture. --- test/conftest.py | 14 +++++++++----- test/test_asgi_application.py | 3 +-- test/test_asgi_websockets.py | 4 ++-- test/test_configuration.py | 3 +-- test/test_java_application.py | 3 +-- test/test_java_websockets.py | 4 ++-- test/test_node_websockets.py | 4 ++-- test/test_perl_application.py | 3 +-- test/test_proxy.py | 3 +-- test/test_python_application.py | 7 +++---- test/test_respawn.py | 7 +++---- test/test_routing.py | 7 +++---- test/test_ruby_application.py | 3 +-- test/test_share_fallback.py | 3 +-- test/test_tls.py | 3 +-- 15 files changed, 32 insertions(+), 39 deletions(-) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 982e43c9..6783f16d 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -74,10 +74,6 @@ def pytest_configure(config): fcntl.fcntl(sys.stdout.fileno(), fcntl.F_SETFL, 0) -def skip_alert(*alerts): - option.skip_alerts.extend(alerts) - - def pytest_generate_tests(metafunc): cls = metafunc.cls if (not hasattr(cls, 'application_type') @@ -314,7 +310,7 @@ def _check_alerts(path=None): alerts = re.findall(r'.+\[alert\].+', log) if alerts: - print('All alerts/sanitizer errors found in log:') + print('\nAll alerts/sanitizer errors found in log:') [print(alert) for alert in alerts] found = True @@ -378,6 +374,14 @@ def stop_processes(): return 'Fail to stop process(es)' +@pytest.fixture() +def skip_alert(): + def _skip(*alerts): + option.skip_alerts.extend(alerts) + + return _skip + + @pytest.fixture def temp_dir(request): return unit_instance['temp_dir'] diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index 80b64029..9f4b70a4 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -4,7 +4,6 @@ from distutils.version import LooseVersion import pytest -from conftest import skip_alert from unit.applications.lang.python import TestApplicationPython from unit.option import option @@ -361,7 +360,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): skip_alert(r'Python failed to import module "blah"') self.load('empty', module="blah") diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py index 766e53ed..76cd8e80 100644 --- a/test/test_asgi_websockets.py +++ b/test/test_asgi_websockets.py @@ -4,7 +4,6 @@ from distutils.version import LooseVersion import pytest -from conftest import skip_alert from unit.applications.lang.python import TestApplicationPython from unit.applications.websockets import TestApplicationWebsocket from unit.option import option @@ -17,7 +16,8 @@ class TestASGIWebsockets(TestApplicationPython): ws = TestApplicationWebsocket() - def setup_method(self): + @pytest.fixture(autouse=True) + def setup_method_fixture(self, request, skip_alert): assert 'success' in self.conf( {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' ), 'clear keepalive_interval' diff --git a/test/test_configuration.py b/test/test_configuration.py index d1e6f000..7feb3adb 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -1,6 +1,5 @@ import pytest -from conftest import skip_alert from unit.control import TestControl @@ -337,7 +336,7 @@ class TestConfiguration(TestControl): assert 'success' in self.conf(conf) - def test_unprivileged_user_error(self, is_su): + def test_unprivileged_user_error(self, is_su, skip_alert): skip_alert(r'cannot set user "root"', r'failed to apply new conf') if is_su: pytest.skip('unprivileged tests') diff --git a/test/test_java_application.py b/test/test_java_application.py index 572e18e8..4a67f291 100644 --- a/test/test_java_application.py +++ b/test/test_java_application.py @@ -3,7 +3,6 @@ import os import re import time -from conftest import skip_alert from unit.applications.lang.java import TestApplicationJava from unit.option import option from unit.utils import public_dir @@ -11,7 +10,7 @@ from unit.utils import public_dir class TestJavaApplication(TestApplicationJava): prerequisites = {'modules': {'java': 'all'}} - def test_java_conf_error(self, temp_dir): + def test_java_conf_error(self, temp_dir, skip_alert): skip_alert( r'realpath.*failed', r'failed to apply new conf', diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index 5739e236..729aa31d 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -3,7 +3,6 @@ import time import pytest -from conftest import skip_alert from unit.applications.lang.java import TestApplicationJava from unit.applications.websockets import TestApplicationWebsocket from unit.option import option @@ -14,7 +13,8 @@ class TestJavaWebsockets(TestApplicationJava): ws = TestApplicationWebsocket() - def setup_method(self): + @pytest.fixture(autouse=True) + def setup_method_fixture(self, request, skip_alert): assert 'success' in self.conf( {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' ), 'clear keepalive_interval' diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index 84eb4c42..d7444bf7 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -3,7 +3,6 @@ import time import pytest -from conftest import skip_alert from unit.applications.lang.node import TestApplicationNode from unit.applications.websockets import TestApplicationWebsocket from unit.option import option @@ -14,7 +13,8 @@ class TestNodeWebsockets(TestApplicationNode): ws = TestApplicationWebsocket() - def setup_method(self): + @pytest.fixture(autouse=True) + def setup_method_fixture(self, request, skip_alert): assert 'success' in self.conf( {'http': {'websocket': {'keepalive_interval': 0}}}, 'settings' ), 'clear keepalive_interval' diff --git a/test/test_perl_application.py b/test/test_perl_application.py index 78f2dd90..ad91965f 100644 --- a/test/test_perl_application.py +++ b/test/test_perl_application.py @@ -2,7 +2,6 @@ import re import pytest -from conftest import skip_alert from conftest import unit_stop from unit.applications.lang.perl import TestApplicationPerl @@ -170,7 +169,7 @@ class TestPerlApplication(TestApplicationPerl): assert self.get()['body'] == 'body\n', 'body io file' @pytest.mark.skip('not yet') - def test_perl_application_syntax_error(self): + def test_perl_application_syntax_error(self, skip_alert): skip_alert(r'PSGI: Failed to parse script') self.load('syntax_error') diff --git a/test/test_proxy.py b/test/test_proxy.py index 975a76a0..0eebab1e 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -5,7 +5,6 @@ import time import pytest from conftest import run_process -from conftest import skip_alert from unit.applications.lang.python import TestApplicationPython from unit.option import option from unit.utils import waitforsocket @@ -482,7 +481,7 @@ Content-Length: 10 check_proxy('http://[:]:7080') check_proxy('http://[::7080') - def test_proxy_loop(self): + def test_proxy_loop(self, skip_alert): skip_alert( r'socket.*failed', r'accept.*failed', diff --git a/test/test_python_application.py b/test/test_python_application.py index b28e8c11..b7cec831 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -5,7 +5,6 @@ import time import pytest -from conftest import skip_alert from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython from unit.option import option @@ -520,13 +519,13 @@ last line: 987654321 assert self.get()['body'] == 'body\n', 'body io file' @pytest.mark.skip('not yet') - def test_python_application_syntax_error(self): + def test_python_application_syntax_error(self, skip_alert): skip_alert(r'Python failed to import module "wsgi"') self.load('syntax_error') assert self.get()['status'] == 500, 'syntax error' - def test_python_application_loading_error(self): + def test_python_application_loading_error(self, skip_alert): skip_alert(r'Python failed to import module "blah"') self.load('empty', module="blah") @@ -791,7 +790,7 @@ last line: 987654321 assert obj['UID'] == nobody_uid, 'root uid group=root' assert obj['GID'] == 0, 'root gid group=root' - def test_python_application_callable(self): + def test_python_application_callable(self, skip_alert): skip_alert(r'Python failed to get "blah" from module') self.load('callable') diff --git a/test/test_respawn.py b/test/test_respawn.py index fbaad666..eef2cb56 100644 --- a/test/test_respawn.py +++ b/test/test_respawn.py @@ -2,7 +2,6 @@ import re import subprocess import time -from conftest import skip_alert from unit.applications.lang.python import TestApplicationPython from unit.option import option @@ -56,7 +55,7 @@ class TestRespawn(TestApplicationPython): assert len(re.findall(self.PATTERN_CONTROLLER, output)) == 1 assert len(re.findall(self.app_name, output)) == 1 - def test_respawn_router(self): + def test_respawn_router(self, skip_alert): pid = self.pid_by_name(self.PATTERN_ROUTER) self.kill_pids(pid) @@ -66,7 +65,7 @@ class TestRespawn(TestApplicationPython): self.smoke_test() - def test_respawn_controller(self): + def test_respawn_controller(self, skip_alert): pid = self.pid_by_name(self.PATTERN_CONTROLLER) self.kill_pids(pid) @@ -78,7 +77,7 @@ class TestRespawn(TestApplicationPython): self.smoke_test() - def test_respawn_application(self): + def test_respawn_application(self, skip_alert): pid = self.pid_by_name(self.app_name) self.kill_pids(pid) diff --git a/test/test_routing.py b/test/test_routing.py index a49075ae..30f25a9c 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import pytest -from conftest import skip_alert from unit.applications.proto import TestApplicationProto from unit.option import option @@ -366,7 +365,7 @@ class TestRouting(TestApplicationProto): assert self.get()['status'] == 200, 'route match absent' - def test_routes_route_action_absent(self): + def test_routes_route_action_absent(self, skip_alert): skip_alert(r'failed to apply new conf') assert 'error' in self.conf( @@ -755,7 +754,7 @@ class TestRouting(TestApplicationProto): 'routes/main' ), 'route edit configure 9' - def test_match_edit(self): + def test_match_edit(self, skip_alert): skip_alert(r'failed to apply new conf') self.route_match({"method": ["GET", "POST"]}) @@ -1352,7 +1351,7 @@ class TestRouting(TestApplicationProto): 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): + def test_routes_match_arguments_invalid(self, skip_alert): # TODO remove it after controller fixed skip_alert(r'failed to apply new conf') diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index e42fb97f..6a0c9c9f 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -2,7 +2,6 @@ import re import pytest -from conftest import skip_alert from conftest import unit_stop from unit.applications.lang.ruby import TestApplicationRuby @@ -160,7 +159,7 @@ class TestRubyApplication(TestApplicationRuby): assert self.post(body=body)['body'] == body, 'input rewind' @pytest.mark.skip('not yet') - def test_ruby_application_syntax_error(self): + def test_ruby_application_syntax_error(self, skip_alert): skip_alert( r'Failed to parse rack script', r'syntax error', diff --git a/test/test_share_fallback.py b/test/test_share_fallback.py index 151d3ae5..a02cb1a3 100644 --- a/test/test_share_fallback.py +++ b/test/test_share_fallback.py @@ -1,6 +1,5 @@ import os -from conftest import skip_alert from unit.applications.proto import TestApplicationProto from unit.option import option @@ -117,7 +116,7 @@ class TestStatic(TestApplicationProto): assert resp['status'] == 200, 'fallback proxy status' assert resp['body'] == '', 'fallback proxy' - def test_fallback_proxy_loop(self): + def test_fallback_proxy_loop(self, skip_alert): skip_alert( r'open.*/blah/index.html.*failed', r'accept.*failed', diff --git a/test/test_tls.py b/test/test_tls.py index 32b97895..5a408ee2 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -5,7 +5,6 @@ import subprocess import pytest -from conftest import skip_alert from unit.applications.tls import TestApplicationTLS from unit.option import option @@ -505,7 +504,7 @@ basicConstraints = critical,CA:TRUE""" '/certificates' ), 'remove all certificates' - def test_tls_application_respawn(self): + def test_tls_application_respawn(self, skip_alert): self.load('mirror') self.certificate() -- cgit From c7bd96b4769abb11a92a081061bc83171d5ed6ac Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Tue, 8 Dec 2020 16:38:41 +0000 Subject: Tests: fixed ruby isolation. While alternating between running priv and unpriv tests locally, it happens that unpriv tests can't bind mount or create sub directories inside directories created by root. This patch fixes this by pointing "rootfs" to temporary directory. Now the priv and unpriv test uses the same test function. --- test/test_ruby_isolation.py | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'test') diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py index 56fccbd0..8c382e5a 100644 --- a/test/test_ruby_isolation.py +++ b/test/test_ruby_isolation.py @@ -1,5 +1,6 @@ import shutil +import os import pytest from conftest import unit_run @@ -26,7 +27,7 @@ class TestRubyIsolation(TestApplicationRuby): return check if not complete_check else check() - def test_ruby_isolation_rootfs_mount_namespace(self, is_su): + def test_ruby_isolation_rootfs(self, is_su): isolation_features = option.available['features']['isolation'].keys() if not is_su: @@ -42,34 +43,22 @@ class TestRubyIsolation(TestApplicationRuby): if 'pid' not in isolation_features: pytest.skip('pid namespace is not supported') - isolation = {'rootfs': option.test_dir} + isolation = {'rootfs': option.temp_dir} if not is_su: isolation['namespaces'] = { 'mount': True, 'credential': True, - 'pid': True + 'pid': True, } - self.load('status_int', isolation=isolation) + os.mkdir(option.temp_dir + '/ruby') - assert 'success' in self.conf( - '"/ruby/status_int/config.ru"', 'applications/status_int/script', - ) - - assert 'success' in self.conf( - '"/ruby/status_int"', 'applications/status_int/working_directory', + shutil.copytree( + option.test_dir + '/ruby/status_int', + option.temp_dir + '/ruby/status_int', ) - assert self.get()['status'] == 200, 'status int' - - def test_ruby_isolation_rootfs(self, is_su): - if not is_su: - pytest.skip('requires root') - return - - isolation = {'rootfs': option.test_dir} - self.load('status_int', isolation=isolation) assert 'success' in self.conf( -- cgit From 4c846ae69308983050a55f6467c2d53e78120e0b Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 9 Dec 2020 16:15:50 +0000 Subject: Tests: isolation check moved to the pytest_sessionstart(). This change eliminates the need for some classes to run Unit one more time before running tests. --- test/conftest.py | 4 + test/test_go_isolation.py | 24 +----- test/test_php_isolation.py | 17 ---- test/test_python_isolation.py | 17 ---- test/test_python_isolation_chroot.py | 1 - test/test_ruby_isolation.py | 17 ---- test/unit/check/isolation.py | 158 ++++++++++++++++++++++++++++++++++ test/unit/feature/isolation.py | 160 ----------------------------------- test/unit/main.py | 46 +++++----- test/unit/utils.py | 12 +++ 10 files changed, 197 insertions(+), 259 deletions(-) create mode 100644 test/unit/check/isolation.py delete mode 100644 test/unit/feature/isolation.py (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 6783f16d..07d5f059 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -17,6 +17,7 @@ import pytest from unit.check.go import check_go from unit.check.node import check_node from unit.check.tls import check_openssl +from unit.check.isolation import check_isolation from unit.option import option from unit.utils import public_dir from unit.utils import waitforfiles @@ -123,6 +124,7 @@ def pytest_sessionstart(session): option.available = {'modules': {}, 'features': {}} unit = unit_run() + option.temp_dir = unit['temp_dir'] # read unit.log @@ -161,6 +163,8 @@ def pytest_sessionstart(session): k: v for k, v in option.available['modules'].items() if v is not None } + check_isolation() + unit_stop() _check_alerts() diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index ac12c8ca..48c1b80c 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -5,31 +5,13 @@ import shutil import pytest -from conftest import unit_run -from conftest import unit_stop from unit.applications.lang.go import TestApplicationGo -from unit.feature.isolation import TestFeatureIsolation from unit.option import option +from unit.utils import getns class TestGoIsolation(TestApplicationGo): prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']} - isolation = TestFeatureIsolation() - - @classmethod - def setup_class(cls, complete_check=True): - check = super().setup_class(complete_check=False) - - unit = unit_run() - option.temp_dir = unit['temp_dir'] - - TestFeatureIsolation().check(option.available, unit['temp_dir']) - - assert unit_stop() is None - shutil.rmtree(unit['temp_dir']) - - return check if not complete_check else check() - def unpriv_creds(self): nobody_uid = pwd.getpwnam('nobody').pw_uid @@ -219,8 +201,8 @@ class TestGoIsolation(TestApplicationGo): == option.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' + assert obj['NS']['MNT'] != getns('mnt'), 'mnt set' + assert obj['NS']['USER'] != getns('user'), 'user set' def test_isolation_pid(self, is_su): if not self.isolation_key('pid'): diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index 1d0b0614..b0fea383 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -2,30 +2,13 @@ import shutil import pytest -from conftest import unit_run -from conftest import unit_stop from unit.applications.lang.php import TestApplicationPHP -from unit.feature.isolation import TestFeatureIsolation from unit.option import option class TestPHPIsolation(TestApplicationPHP): prerequisites = {'modules': {'php': 'any'}, 'features': ['isolation']} - @classmethod - def setup_class(cls, complete_check=True): - check = super().setup_class(complete_check=False) - - unit = unit_run() - option.temp_dir = unit['temp_dir'] - - TestFeatureIsolation().check(option.available, unit['temp_dir']) - - assert unit_stop() is None - shutil.rmtree(unit['temp_dir']) - - return check if not complete_check else check() - def test_php_isolation_rootfs(self, is_su, temp_dir): isolation_features = option.available['features']['isolation'].keys() diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index 66ff2f16..ad830269 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -2,30 +2,13 @@ import shutil import pytest -from conftest import unit_run -from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython -from unit.feature.isolation import TestFeatureIsolation from unit.option import option class TestPythonIsolation(TestApplicationPython): prerequisites = {'modules': {'python': 'any'}, 'features': ['isolation']} - @classmethod - def setup_class(cls, complete_check=True): - check = super().setup_class(complete_check=False) - - unit = unit_run() - option.temp_dir = unit['temp_dir'] - - TestFeatureIsolation().check(option.available, unit['temp_dir']) - - assert unit_stop() is None - shutil.rmtree(unit['temp_dir']) - - return check if not complete_check else check() - def test_python_isolation_rootfs(self, is_su, temp_dir): isolation_features = option.available['features']['isolation'].keys() diff --git a/test/test_python_isolation_chroot.py b/test/test_python_isolation_chroot.py index 8018d5b9..7f559bcc 100644 --- a/test/test_python_isolation_chroot.py +++ b/test/test_python_isolation_chroot.py @@ -1,7 +1,6 @@ import pytest from unit.applications.lang.python import TestApplicationPython -from unit.feature.isolation import TestFeatureIsolation class TestPythonIsolation(TestApplicationPython): diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py index 8c382e5a..fab428e9 100644 --- a/test/test_ruby_isolation.py +++ b/test/test_ruby_isolation.py @@ -3,30 +3,13 @@ import shutil import os import pytest -from conftest import unit_run -from conftest import unit_stop from unit.applications.lang.ruby import TestApplicationRuby -from unit.feature.isolation import TestFeatureIsolation from unit.option import option class TestRubyIsolation(TestApplicationRuby): prerequisites = {'modules': {'ruby': 'any'}, 'features': ['isolation']} - @classmethod - def setup_class(cls, complete_check=True): - check = super().setup_class(complete_check=False) - - unit = unit_run() - option.temp_dir = unit['temp_dir'] - - TestFeatureIsolation().check(option.available, unit['temp_dir']) - - assert unit_stop() is None - shutil.rmtree(unit['temp_dir']) - - return check if not complete_check else check() - def test_ruby_isolation_rootfs(self, is_su): isolation_features = option.available['features']['isolation'].keys() diff --git a/test/unit/check/isolation.py b/test/unit/check/isolation.py new file mode 100644 index 00000000..bb8feed1 --- /dev/null +++ b/test/unit/check/isolation.py @@ -0,0 +1,158 @@ +import json +import os + +from unit.applications.lang.go import TestApplicationGo +from unit.applications.lang.java import TestApplicationJava +from unit.applications.lang.node import TestApplicationNode +from unit.applications.proto import TestApplicationProto +from unit.http import TestHTTP +from unit.option import option +from unit.utils import getns + +allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net'] +http = TestHTTP() + +def check_isolation(): + test_conf = {"namespaces": {"credential": True}} + available = option.available + + conf = '' + if 'go' in available['modules']: + TestApplicationGo().prepare_env('empty', 'app') + + conf = { + "listeners": {"*:7080": {"pass": "applications/empty"}}, + "applications": { + "empty": { + "type": "external", + "processes": {"spare": 0}, + "working_directory": option.test_dir + "/go/empty", + "executable": option.temp_dir + "/go/app", + "isolation": {"namespaces": {"credential": True}}, + }, + }, + } + + elif 'python' in available['modules']: + conf = { + "listeners": {"*:7080": {"pass": "applications/empty"}}, + "applications": { + "empty": { + "type": "python", + "processes": {"spare": 0}, + "path": option.test_dir + "/python/empty", + "working_directory": option.test_dir + "/python/empty", + "module": "wsgi", + "isolation": {"namespaces": {"credential": True}}, + } + }, + } + + elif 'php' in available['modules']: + conf = { + "listeners": {"*:7080": {"pass": "applications/phpinfo"}}, + "applications": { + "phpinfo": { + "type": "php", + "processes": {"spare": 0}, + "root": option.test_dir + "/php/phpinfo", + "working_directory": option.test_dir + "/php/phpinfo", + "index": "index.php", + "isolation": {"namespaces": {"credential": True}}, + } + }, + } + + elif 'ruby' in available['modules']: + conf = { + "listeners": {"*:7080": {"pass": "applications/empty"}}, + "applications": { + "empty": { + "type": "ruby", + "processes": {"spare": 0}, + "working_directory": option.test_dir + "/ruby/empty", + "script": option.test_dir + "/ruby/empty/config.ru", + "isolation": {"namespaces": {"credential": True}}, + } + }, + } + + elif 'java' in available['modules']: + TestApplicationJava().prepare_env('empty') + + conf = { + "listeners": {"*:7080": {"pass": "applications/empty"}}, + "applications": { + "empty": { + "unit_jars": option.current_dir + "/build", + "type": "java", + "processes": {"spare": 0}, + "working_directory": option.test_dir + "/java/empty/", + "webapp": option.temp_dir + "/java", + "isolation": {"namespaces": {"credential": True}}, + } + }, + } + + elif 'node' in available['modules']: + TestApplicationNode().prepare_env('basic') + + conf = { + "listeners": {"*:7080": {"pass": "applications/basic"}}, + "applications": { + "basic": { + "type": "external", + "processes": {"spare": 0}, + "working_directory": option.temp_dir + "/node", + "executable": "app.js", + "isolation": {"namespaces": {"credential": True}}, + } + }, + } + + elif 'perl' in available['modules']: + conf = { + "listeners": {"*:7080": {"pass": "applications/body_empty"}}, + "applications": { + "body_empty": { + "type": "perl", + "processes": {"spare": 0}, + "working_directory": option.test_dir + + "/perl/body_empty", + "script": option.test_dir + "/perl/body_empty/psgi.pl", + "isolation": {"namespaces": {"credential": True}}, + } + }, + } + + else: + return + + resp = http.put( + url='/config', + sock_type='unix', + addr=option.temp_dir + '/control.unit.sock', + body=json.dumps(conf), + ) + + if 'success' not in resp: + return + + userns = getns('user') + if not userns: + return + + available['features']['isolation'] = {'user': userns} + + unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone' + if os.path.exists(unp_clone_path): + with open(unp_clone_path, 'r') as f: + if str(f.read()).rstrip() == '1': + available['features']['isolation'][ + 'unprivileged_userns_clone' + ] = True + + for ns in allns: + ns_value = getns(ns) + if ns_value: + available['features']['isolation'][ns] = ns_value diff --git a/test/unit/feature/isolation.py b/test/unit/feature/isolation.py deleted file mode 100644 index d8f68919..00000000 --- a/test/unit/feature/isolation.py +++ /dev/null @@ -1,160 +0,0 @@ -import os - -from unit.applications.lang.go import TestApplicationGo -from unit.applications.lang.java import TestApplicationJava -from unit.applications.lang.node import TestApplicationNode -from unit.applications.proto import TestApplicationProto -from unit.option import option - - -class TestFeatureIsolation(TestApplicationProto): - allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net'] - - def check(self, available, temp_dir): - test_conf = {"namespaces": {"credential": True}} - - conf = '' - if 'go' in available['modules']: - TestApplicationGo().prepare_env('empty', 'app') - - conf = { - "listeners": {"*:7080": {"pass": "applications/empty"}}, - "applications": { - "empty": { - "type": "external", - "processes": {"spare": 0}, - "working_directory": option.test_dir + "/go/empty", - "executable": option.temp_dir + "/go/app", - "isolation": {"namespaces": {"credential": True}}, - }, - }, - } - - elif 'python' in available['modules']: - conf = { - "listeners": {"*:7080": {"pass": "applications/empty"}}, - "applications": { - "empty": { - "type": "python", - "processes": {"spare": 0}, - "path": option.test_dir + "/python/empty", - "working_directory": option.test_dir + "/python/empty", - "module": "wsgi", - "isolation": {"namespaces": {"credential": True}}, - } - }, - } - - elif 'php' in available['modules']: - conf = { - "listeners": {"*:7080": {"pass": "applications/phpinfo"}}, - "applications": { - "phpinfo": { - "type": "php", - "processes": {"spare": 0}, - "root": option.test_dir + "/php/phpinfo", - "working_directory": option.test_dir + "/php/phpinfo", - "index": "index.php", - "isolation": {"namespaces": {"credential": True}}, - } - }, - } - - elif 'ruby' in available['modules']: - conf = { - "listeners": {"*:7080": {"pass": "applications/empty"}}, - "applications": { - "empty": { - "type": "ruby", - "processes": {"spare": 0}, - "working_directory": option.test_dir + "/ruby/empty", - "script": option.test_dir + "/ruby/empty/config.ru", - "isolation": {"namespaces": {"credential": True}}, - } - }, - } - - elif 'java' in available['modules']: - TestApplicationJava().prepare_env('empty') - - conf = { - "listeners": {"*:7080": {"pass": "applications/empty"}}, - "applications": { - "empty": { - "unit_jars": option.current_dir + "/build", - "type": "java", - "processes": {"spare": 0}, - "working_directory": option.test_dir + "/java/empty/", - "webapp": option.temp_dir + "/java", - "isolation": {"namespaces": {"credential": True}}, - } - }, - } - - elif 'node' in available['modules']: - TestApplicationNode().prepare_env('basic') - - conf = { - "listeners": {"*:7080": {"pass": "applications/basic"}}, - "applications": { - "basic": { - "type": "external", - "processes": {"spare": 0}, - "working_directory": option.temp_dir + "/node", - "executable": "app.js", - "isolation": {"namespaces": {"credential": True}}, - } - }, - } - - elif 'perl' in available['modules']: - conf = { - "listeners": {"*:7080": {"pass": "applications/body_empty"}}, - "applications": { - "body_empty": { - "type": "perl", - "processes": {"spare": 0}, - "working_directory": option.test_dir - + "/perl/body_empty", - "script": option.test_dir + "/perl/body_empty/psgi.pl", - "isolation": {"namespaces": {"credential": True}}, - } - }, - } - - else: - return - - if 'success' not in self.conf(conf): - return - - userns = self.getns('user') - if not userns: - return - - available['features']['isolation'] = {'user': userns} - - unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone' - if os.path.exists(unp_clone_path): - with open(unp_clone_path, 'r') as f: - if str(f.read()).rstrip() == '1': - available['features']['isolation'][ - 'unprivileged_userns_clone' - ] = True - - for ns in self.allns: - ns_value = self.getns(ns) - if ns_value: - available['features']['isolation'][ns] = ns_value - - def getns(self, nstype): - # read namespace id from symlink file: - # it points to: ':[]' - # # eg.: 'pid:[4026531836]' - nspath = '/proc/self/ns/' + nstype - data = None - - if os.path.exists(nspath): - data = int(os.readlink(nspath)[len(nstype) + 2 : -1]) - - return data diff --git a/test/unit/main.py b/test/unit/main.py index fce6a322..749ff3ab 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -4,39 +4,33 @@ from unit.option import option class TestUnit(): @classmethod - def setup_class(cls, complete_check=True): - def check(): - missed = [] + def setup_class(cls): + missed = [] - # check modules + # check modules - if 'modules' in cls.prerequisites: - available_modules = list(option.available['modules'].keys()) + if 'modules' in cls.prerequisites: + available_modules = list(option.available['modules'].keys()) - for module in cls.prerequisites['modules']: - if module in available_modules: - continue + for module in cls.prerequisites['modules']: + if module in available_modules: + continue - missed.append(module) + missed.append(module) - if missed: - pytest.skip('Unit has no ' + ', '.join(missed) + ' module(s)') + if missed: + pytest.skip('Unit has no ' + ', '.join(missed) + ' module(s)') - # check features + # check features - if 'features' in cls.prerequisites: - available_features = list(option.available['features'].keys()) + if 'features' in cls.prerequisites: + available_features = list(option.available['features'].keys()) - for feature in cls.prerequisites['features']: - if feature in available_features: - continue + for feature in cls.prerequisites['features']: + if feature in available_features: + continue - missed.append(feature) + missed.append(feature) - if missed: - pytest.skip(', '.join(missed) + ' feature(s) not supported') - - if complete_check: - check() - else: - return check + if missed: + pytest.skip(', '.join(missed) + ' feature(s) not supported') diff --git a/test/unit/utils.py b/test/unit/utils.py index f24e9728..1307a4f6 100644 --- a/test/unit/utils.py +++ b/test/unit/utils.py @@ -48,3 +48,15 @@ def waitforsocket(port): pytest.fail('Can\'t connect to the 127.0.0.1:' + port) + +def getns(nstype): + # read namespace id from symlink file: + # it points to: ':[]' + # # eg.: 'pid:[4026531836]' + nspath = '/proc/self/ns/' + nstype + data = None + + if os.path.exists(nspath): + data = int(os.readlink(nspath)[len(nstype) + 2 : -1]) + + return data -- cgit From 7be62c3c213c3da1da1a45c8db16192eb0ed14d8 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 9 Dec 2020 16:17:46 +0000 Subject: Tests: TestUnit class removed. Prerequisite checks moved to the fixture in conftest.py. --- test/conftest.py | 34 ++++++++++++++++++++++++++++++++++ test/unit/http.py | 3 +-- test/unit/main.py | 36 ------------------------------------ 3 files changed, 35 insertions(+), 38 deletions(-) delete mode 100644 test/unit/main.py (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 07d5f059..5c8da65f 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -184,6 +184,40 @@ def pytest_runtest_makereport(item, call): setattr(item, "rep_" + rep.when, rep) +@pytest.fixture(scope='class', autouse=True) +def check_prerequisites(request): + cls = request.cls + missed = [] + + # check modules + + if 'modules' in cls.prerequisites: + available_modules = list(option.available['modules'].keys()) + + for module in cls.prerequisites['modules']: + if module in available_modules: + continue + + missed.append(module) + + if missed: + pytest.skip('Unit has no ' + ', '.join(missed) + ' module(s)') + + # check features + + if 'features' in cls.prerequisites: + available_features = list(option.available['features'].keys()) + + for feature in cls.prerequisites['features']: + if feature in available_features: + continue + + missed.append(feature) + + if missed: + pytest.skip(', '.join(missed) + ' feature(s) not supported') + + @pytest.fixture(autouse=True) def run(request): unit = unit_run() diff --git a/test/unit/http.py b/test/unit/http.py index ae74eac3..57e6ed3a 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -7,11 +7,10 @@ import select import socket import pytest -from unit.main import TestUnit from unit.option import option -class TestHTTP(TestUnit): +class TestHTTP(): def http(self, start_str, **kwargs): sock_type = kwargs.get('sock_type', 'ipv4') port = kwargs.get('port', 7080) diff --git a/test/unit/main.py b/test/unit/main.py deleted file mode 100644 index 749ff3ab..00000000 --- a/test/unit/main.py +++ /dev/null @@ -1,36 +0,0 @@ -import pytest -from unit.option import option - - -class TestUnit(): - @classmethod - def setup_class(cls): - missed = [] - - # check modules - - if 'modules' in cls.prerequisites: - available_modules = list(option.available['modules'].keys()) - - for module in cls.prerequisites['modules']: - if module in available_modules: - continue - - missed.append(module) - - if missed: - pytest.skip('Unit has no ' + ', '.join(missed) + ' module(s)') - - # check features - - if 'features' in cls.prerequisites: - available_features = list(option.available['features'].keys()) - - for feature in cls.prerequisites['features']: - if feature in available_features: - continue - - missed.append(feature) - - if missed: - pytest.skip(', '.join(missed) + ' feature(s) not supported') -- cgit From 16ac829c8f902d847ba63604052cc16aa4bed9ce Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 10 Dec 2020 19:28:41 +0000 Subject: Tests: added tests for PHP_AUTH_* variables. --- test/php/auth/index.php | 7 ++++++ test/test_php_application.py | 58 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 test/php/auth/index.php (limited to 'test') diff --git a/test/php/auth/index.php b/test/php/auth/index.php new file mode 100644 index 00000000..d77076d8 --- /dev/null +++ b/test/php/auth/index.php @@ -0,0 +1,7 @@ + diff --git a/test/test_php_application.py b/test/test_php_application.py index 463ec35b..ad74faa8 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -384,6 +384,64 @@ class TestPHPApplication(TestApplicationPHP): r'exec: \/\w+', body ), 'disable_functions comma exec' + def test_php_application_auth(self): + self.load('auth') + + resp = self.get() + assert resp['status'] == 200, 'status' + assert resp['headers']['X-Digest'] == 'not set', 'digest' + assert resp['headers']['X-User'] == 'not set', 'user' + assert resp['headers']['X-Password'] == 'not set', 'password' + + resp = self.get( + headers={ + 'Host': 'localhost', + 'Authorization': 'Basic dXNlcjpwYXNzd29yZA==', + 'Connection': 'close', + } + ) + assert resp['status'] == 200, 'basic status' + assert resp['headers']['X-Digest'] == 'not set', 'basic digest' + assert resp['headers']['X-User'] == 'user', 'basic user' + assert resp['headers']['X-Password'] == 'password', 'basic password' + + resp = self.get( + headers={ + 'Host': 'localhost', + 'Authorization': 'Digest username="blah", realm="", uri="/"', + 'Connection': 'close', + } + ) + assert resp['status'] == 200, 'digest status' + assert ( + resp['headers']['X-Digest'] == 'username="blah", realm="", uri="/"' + ), 'digest digest' + assert resp['headers']['X-User'] == 'not set', 'digest user' + assert resp['headers']['X-Password'] == 'not set', 'digest password' + + def test_php_application_auth_invalid(self): + self.load('auth') + + def check_auth(auth): + resp = self.get(headers={ + 'Host': 'localhost', + 'Authorization': auth, + 'Connection': 'close', + }) + + assert resp['status'] == 200, 'status' + assert resp['headers']['X-Digest'] == 'not set', 'Digest' + assert resp['headers']['X-User'] == 'not set', 'User' + assert resp['headers']['X-Password'] == 'not set', 'Password' + + check_auth('Basic dXN%cjpwYXNzd29yZA==') + check_auth('Basic XNlcjpwYXNzd29yZA==') + check_auth('Basic DdXNlcjpwYXNzd29yZA==') + check_auth('Basic blah') + check_auth('Basic') + check_auth('Digest') + check_auth('blah') + def test_php_application_disable_functions_space(self): self.load('time_exec') -- cgit From 425ffc9416391e5e41236708b655d941f560c661 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Sat, 12 Dec 2020 20:08:03 +0000 Subject: Tests: hyphen sign used unstead of underscore as more common. --- test/conftest.py | 4 ++-- test/pytest.ini | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 5c8da65f..c14e3f68 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -31,13 +31,13 @@ def pytest_addoption(parser): help="Detailed output for tests", ) parser.addoption( - "--print_log", + "--print-log", default=False, action="store_true", help="Print unit.log to stdout in case of errors", ) parser.addoption( - "--save_log", + "--save-log", default=False, action="store_true", help="Save unit.log after the test execution", diff --git a/test/pytest.ini b/test/pytest.ini index fe86cef2..8952e8c6 100644 --- a/test/pytest.ini +++ b/test/pytest.ini @@ -1,3 +1,3 @@ [pytest] -addopts = -vvv -s --print_log +addopts = -vvv -s --print-log python_functions = test_* -- cgit From 66ac35e9b941500a95a069066d896793b5df3a2a Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Tue, 15 Dec 2020 11:06:49 +0000 Subject: Tests: fixed bug that disabled isolation tests. --- test/unit/check/isolation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/unit/check/isolation.py b/test/unit/check/isolation.py index bb8feed1..fe5a41f8 100644 --- a/test/unit/check/isolation.py +++ b/test/unit/check/isolation.py @@ -135,7 +135,7 @@ def check_isolation(): body=json.dumps(conf), ) - if 'success' not in resp: + if 'success' not in resp['body']: return userns = getns('user') -- cgit From 03436d2ec2ab485b4f3196690e9a267bf0d42d30 Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Mon, 21 Dec 2020 11:00:46 +0000 Subject: Tests: introduced a separate cache directory for Go builds. The Go compiler can't detect changes to C header files when compiling CGO applications, and then this leads to Go test samples being linked with wrong libunit. This patch creates a new cache directory reused throughout the test suite. --- test/conftest.py | 4 ++++ test/unit/applications/lang/go.py | 1 + 2 files changed, 5 insertions(+) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index c14e3f68..c2a320de 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -69,6 +69,9 @@ def pytest_configure(config): option.architecture = platform.architecture()[0] option.system = platform.system() + option.cache_dir = tempfile.mkdtemp(prefix='unit-test-cache-') + public_dir(option.cache_dir) + # set stdout to non-blocking if option.detailed or option.print_log: @@ -434,3 +437,4 @@ def is_su(request): def pytest_sessionfinish(session): unit_stop() + shutil.rmtree(option.cache_dir) diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 70f9d58c..a17b1af4 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -12,6 +12,7 @@ class TestApplicationGo(TestApplicationProto): env = os.environ.copy() env['GOPATH'] = option.current_dir + '/build/go' + env['GOCACHE'] = option.cache_dir + '/go' if static: args = [ -- cgit From 53af12def0623006509c08a3e081371a697acbd1 Mon Sep 17 00:00:00 2001 From: Andrei Belov Date: Wed, 23 Dec 2020 18:30:17 +0300 Subject: Tests: ability to run unitd with specified "--user" option. --- test/conftest.py | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index c2a320de..d87e648b 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -48,6 +48,11 @@ def pytest_addoption(parser): action="store_true", help="Run unsafe tests", ) + parser.addoption( + "--user", + type=str, + help="Default user for non-privileged processes of unitd", + ) unit_instance = {} @@ -60,6 +65,7 @@ def pytest_configure(config): option.print_log = config.option.print_log option.save_log = config.option.save_log option.unsafe = config.option.unsafe + option.user = config.option.user option.generated_tests = {} option.current_dir = os.path.abspath( @@ -283,26 +289,28 @@ def unit_run(): os.mkdir(temp_dir + '/state') + unitd_args = [ + 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, + ] + + if option.user: + unitd_args.extend(['--user', option.user]) + 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, - ) + unit_instance['process'] = subprocess.Popen(unitd_args, stderr=log) if not waitforfiles(temp_dir + '/control.unit.sock'): _print_log() -- cgit From d3d6864bdc64f34924e686ff65da704b29aaaa93 Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Tue, 29 Dec 2020 19:00:54 +0300 Subject: Node.js: ServerRequest and ServerResponse compliance to Stream API. ServerRequest now inherit stream Readable object. ServerResponse provides 'writable' property. Thanks to Wu Jian Ping (@wujjpp). This closes #274, closes #317 issues and closes #502 PR on GitHub. --- test/test_node_application.py | 45 ------------------------------------------- 1 file changed, 45 deletions(-) (limited to 'test') diff --git a/test/test_node_application.py b/test/test_node_application.py index f13a01e1..da29847a 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -222,22 +222,6 @@ class TestNodeApplication(TestApplicationNode): assert 'X-Header' not in headers, 'insensitive' assert 'X-header' not in headers, 'insensitive 2' - def test_node_application_promise_handler(self, temp_dir): - self.load('promise_handler') - - assert ( - self.post( - headers={ - 'Host': 'localhost', - 'Content-Type': 'text/html', - 'Connection': 'close', - }, - body='callback', - )['status'] - == 200 - ), 'promise handler request' - assert waitforfiles(temp_dir + '/node/callback'), 'promise handler' - def test_node_application_promise_handler_write_after_end(self): self.load('promise_handler') @@ -270,35 +254,6 @@ class TestNodeApplication(TestApplicationNode): ), 'promise end request' assert waitforfiles(temp_dir + '/node/callback'), 'promise end' - def test_node_application_promise_multiple_calls(self, temp_dir): - self.load('promise_handler') - - self.post( - headers={ - 'Host': 'localhost', - 'Content-Type': 'text/html', - 'Connection': 'close', - }, - body='callback1', - ) - - assert waitforfiles( - temp_dir + '/node/callback1' - ), 'promise first call' - - self.post( - headers={ - 'Host': 'localhost', - 'Content-Type': 'text/html', - 'Connection': 'close', - }, - body='callback2', - ) - - assert waitforfiles( - temp_dir + '/node/callback2' - ), 'promise second call' - @pytest.mark.skip('not yet') def test_node_application_header_name_valid(self): self.load('header_name_valid') -- cgit From 13a06497def68d8157dfe2b6e0a7f7edcc2ef477 Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Thu, 7 Jan 2021 16:51:27 +0000 Subject: Tests: reordered asserts to avoid a test race. The mount points are unmounted in the main process after it detects the app process died. By testing the `tmpfs: true` first, it happens that main could start the `tmpfs: false` test case before main cleans the old process mount points. --- test/test_go_isolation.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index 48c1b80c..0cd83056 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -342,16 +342,20 @@ class TestGoIsolation(TestApplicationGo): 'pid': True } + isolation['automount'] = { + 'tmpfs': False + } + self.load('ns_inspect', isolation=isolation) obj = self.getjson(url='/?mounts=true')['body'] assert ( - "/ /tmp" in obj['Mounts'] and "tmpfs" in obj['Mounts'] - ), 'app has /tmp mounted on /' + "/ /tmp" not in obj['Mounts'] and "tmpfs" not in obj['Mounts'] + ), 'app has no /tmp mounted' isolation['automount'] = { - 'tmpfs': False + 'tmpfs': True } self.load('ns_inspect', isolation=isolation) @@ -359,5 +363,5 @@ class TestGoIsolation(TestApplicationGo): obj = self.getjson(url='/?mounts=true')['body'] assert ( - "/ /tmp" not in obj['Mounts'] and "tmpfs" not in obj['Mounts'] - ), 'app has no /tmp mounted' + "/ /tmp" in obj['Mounts'] and "tmpfs" in obj['Mounts'] + ), 'app has /tmp mounted on /' -- cgit From a0bc946db306b921fd2db909377e72bf6671e843 Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Fri, 8 Jan 2021 10:38:46 +0000 Subject: Tests: fixed test_respawn.py to act upon test processes. Running `test_respawn_` test cases on a machine with Unit daemon in background would fail tests because `ps ax` was used without filtering out other unit instances. This patch also prevents from tests killing other Unit processes not related to tests. --- test/conftest.py | 4 ++++ test/test_respawn.py | 51 ++++++++++++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 23 deletions(-) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index d87e648b..0a4b541d 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -443,6 +443,10 @@ def is_unsafe(request): def is_su(request): return os.geteuid() == 0 +@pytest.fixture +def unit_pid(request): + return unit_instance['process'].pid + def pytest_sessionfinish(session): unit_stop() shutil.rmtree(option.cache_dir) diff --git a/test/test_respawn.py b/test/test_respawn.py index eef2cb56..ed85ee95 100644 --- a/test/test_respawn.py +++ b/test/test_respawn.py @@ -21,17 +21,17 @@ class TestRespawn(TestApplicationPython): '1', 'applications/' + self.app_name + '/processes' ) - def pid_by_name(self, name): - output = subprocess.check_output(['ps', 'ax']).decode() - m = re.search(r'\s*(\d+).*' + name, output) - return m if m is None else m.group(1) + def pid_by_name(self, name, ppid): + output = subprocess.check_output(['ps', 'ax', '-O', 'ppid']).decode() + m = re.search(r'\s*(\d+)\s*' + str(ppid) + r'.*' + name, output) + return None 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): + def wait_for_process(self, process, unit_pid): for i in range(50): - found = self.pid_by_name(process) + found = self.pid_by_name(process, unit_pid) if found is not None: break @@ -40,7 +40,10 @@ class TestRespawn(TestApplicationPython): return found - def smoke_test(self): + def find_proc(self, name, ppid, ps_output): + return re.findall(str(ppid) + r'.*' + name, ps_output) + + def smoke_test(self, unit_pid): for _ in range(5): assert 'success' in self.conf( '1', 'applications/' + self.app_name + '/processes' @@ -50,39 +53,41 @@ class TestRespawn(TestApplicationPython): # Check if the only one router, controller, # and application processes running. - output = subprocess.check_output(['ps', 'ax']).decode() - 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 + out = subprocess.check_output(['ps', 'ax', '-O', 'ppid']).decode() + assert len(self.find_proc(self.PATTERN_ROUTER, unit_pid, out)) == 1 + assert len(self.find_proc(self.PATTERN_CONTROLLER, unit_pid, out)) == 1 + assert len(self.find_proc(self.app_name, unit_pid, out)) == 1 - def test_respawn_router(self, skip_alert): - pid = self.pid_by_name(self.PATTERN_ROUTER) + def test_respawn_router(self, skip_alert, unit_pid): + pid = self.pid_by_name(self.PATTERN_ROUTER, unit_pid) self.kill_pids(pid) skip_alert(r'process %s exited on signal 9' % pid) - assert self.wait_for_process(self.PATTERN_ROUTER) is not None + assert self.wait_for_process(self.PATTERN_ROUTER, unit_pid) is not None - self.smoke_test() + self.smoke_test(unit_pid) - def test_respawn_controller(self, skip_alert): - pid = self.pid_by_name(self.PATTERN_CONTROLLER) + def test_respawn_controller(self, skip_alert, unit_pid): + pid = self.pid_by_name(self.PATTERN_CONTROLLER, unit_pid) self.kill_pids(pid) skip_alert(r'process %s exited on signal 9' % pid) - assert self.wait_for_process(self.PATTERN_CONTROLLER) is not None + assert self.wait_for_process( + self.PATTERN_CONTROLLER, unit_pid + ) is not None assert self.get()['status'] == 200 - self.smoke_test() + self.smoke_test(unit_pid) - def test_respawn_application(self, skip_alert): - pid = self.pid_by_name(self.app_name) + def test_respawn_application(self, skip_alert, unit_pid): + pid = self.pid_by_name(self.app_name, unit_pid) self.kill_pids(pid) skip_alert(r'process %s exited on signal 9' % pid) - assert self.wait_for_process(self.app_name) is not None + assert self.wait_for_process(self.app_name, unit_pid) is not None - self.smoke_test() + self.smoke_test(unit_pid) -- cgit From f5ac1432463e58873b2c801b6db64dbe4d0e8f1c Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Tue, 12 Jan 2021 06:20:23 +0000 Subject: Tests: unit_stop() removed where possible. Since wait_for_record() was introduced there is no need to stop Unit before parsing unit.log. --- test/test_access_log.py | 31 ------------------------------- test/test_perl_application.py | 3 --- test/test_php_application.py | 16 ++++++++++------ test/test_python_application.py | 13 ------------- test/test_ruby_application.py | 12 ------------ test/test_usr1.py | 5 ----- 6 files changed, 10 insertions(+), 70 deletions(-) (limited to 'test') diff --git a/test/test_access_log.py b/test/test_access_log.py index 0a0a6633..e82e42e3 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -2,7 +2,6 @@ import time import pytest -from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython from unit.option import option @@ -50,8 +49,6 @@ class TestAccessLog(TestApplicationPython): body='0123456789', ) - unit_stop() - assert ( self.wait_for_record(r'"POST / HTTP/1.1" 200 10') is not None ), 'keepalive 2' @@ -78,8 +75,6 @@ Connection: close raw=True, ) - unit_stop() - assert ( self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"') is not None @@ -100,8 +95,6 @@ Connection: close self.get(sock_type='ipv6') - unit_stop() - assert ( self.wait_for_record( r'::1 - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"' @@ -120,8 +113,6 @@ Connection: close self.get(sock_type='unix', addr=addr) - unit_stop() - assert ( self.wait_for_record( r'unix: - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"' @@ -140,8 +131,6 @@ Connection: close } ) - unit_stop() - assert ( self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "referer-value" "-"') is not None @@ -158,8 +147,6 @@ Connection: close } ) - unit_stop() - assert ( self.wait_for_record( r'"GET / HTTP/1.1" 200 0 "-" "user-agent-value"' @@ -172,8 +159,6 @@ Connection: close self.get(http_10=True) - unit_stop() - assert ( self.wait_for_record(r'"GET / HTTP/1.0" 200 0 "-" "-"') is not None ), 'http 1.0' @@ -187,8 +172,6 @@ Connection: close time.sleep(1) - unit_stop() - assert ( self.wait_for_record(r'"GE" 400 0 "-" "-"') is not None ), 'partial' @@ -200,8 +183,6 @@ Connection: close self.http(b"""GET /\n""", raw=True) - unit_stop() - assert ( self.wait_for_record(r'"GET /" 400 \d+ "-" "-"') is not None ), 'partial 2' @@ -215,8 +196,6 @@ Connection: close time.sleep(1) - unit_stop() - assert ( self.wait_for_record(r'"GET /" 400 0 "-" "-"') is not None ), 'partial 3' @@ -230,8 +209,6 @@ Connection: close time.sleep(1) - unit_stop() - assert ( self.wait_for_record(r'"GET / HTTP/1.1" 400 0 "-" "-"') is not None ), 'partial 4' @@ -244,8 +221,6 @@ Connection: close self.get(headers={'Connection': 'close'}) - unit_stop() - assert ( self.wait_for_record(r'"GET / HTTP/1.1" 400 \d+ "-" "-"') is not None @@ -256,8 +231,6 @@ Connection: close self.get(url='/?blah&var=val') - unit_stop() - assert ( self.wait_for_record( r'"GET /\?blah&var=val HTTP/1.1" 200 0 "-" "-"' @@ -272,8 +245,6 @@ Connection: close self.get(url='/delete') - unit_stop() - assert self.search_in_log(r'/delete', 'access.log') is None, 'delete' def test_access_log_change(self, temp_dir): @@ -285,8 +256,6 @@ Connection: close self.get() - unit_stop() - assert ( self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log') is not None diff --git a/test/test_perl_application.py b/test/test_perl_application.py index ad91965f..e906aaca 100644 --- a/test/test_perl_application.py +++ b/test/test_perl_application.py @@ -2,7 +2,6 @@ import re import pytest -from conftest import unit_stop from unit.applications.lang.perl import TestApplicationPerl @@ -119,8 +118,6 @@ class TestPerlApplication(TestApplicationPerl): assert self.get()['body'] == '1', 'errors result' - unit_stop() - assert ( self.wait_for_record(r'\[error\].+Error in application') is not None diff --git a/test/test_php_application.py b/test/test_php_application.py index ad74faa8..9f0da531 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -2,10 +2,10 @@ import os import re import shutil import time +from subprocess import call import pytest -from conftest import unit_stop from unit.applications.lang.php import TestApplicationPHP from unit.option import option @@ -20,7 +20,7 @@ class TestPHPApplication(TestApplicationPHP): def set_opcache(self, app, val): assert 'success' in self.conf( - {"admin": {"opcache.enable": val, "opcache.enable_cli": val,},}, + {"admin": {"opcache.enable": val, "opcache.enable_cli": val}}, 'applications/' + app + '/options', ) @@ -99,7 +99,10 @@ class TestPHPApplication(TestApplicationPHP): assert self.get()['body'] == '0123' - unit_stop() + with open(temp_dir + '/unit.pid', 'r') as f: + pid = f.read().rstrip() + + call(['kill', '-s', 'USR1', pid]) with open(temp_dir + '/unit.log', 'r', errors='ignore') as f: errs = re.findall(r'Error in fastcgi_finish_request', f.read()) @@ -113,7 +116,10 @@ class TestPHPApplication(TestApplicationPHP): assert resp['status'] == 200 assert resp['body'] == '' - unit_stop() + with open(temp_dir + '/unit.pid', 'r') as f: + pid = f.read().rstrip() + + call(['kill', '-s', 'USR1', pid]) with open(temp_dir + '/unit.log', 'r', errors='ignore') as f: errs = re.findall(r'Error in fastcgi_finish_request', f.read()) @@ -538,8 +544,6 @@ class TestPHPApplication(TestApplicationPHP): assert self.get()['status'] == 200, 'status 2' - unit_stop() - pattern = r'\d{4}\/\d\d\/\d\d\s\d\d:.+\[notice\].+Error in application' assert self.wait_for_record(pattern) is not None, 'errors print' diff --git a/test/test_python_application.py b/test/test_python_application.py index b7cec831..01f53f8d 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -5,7 +5,6 @@ import time import pytest -from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython from unit.option import option @@ -157,8 +156,6 @@ custom-header: BLAH self.conf({"listeners": {}, "applications": {}}) - unit_stop() - assert ( self.wait_for_record(r'RuntimeError') is not None ), 'ctx iter atexit' @@ -337,8 +334,6 @@ Connection: close self.conf({"listeners": {}, "applications": {}}) - unit_stop() - assert self.wait_for_record(r'At exit called\.') is not None, 'atexit' def test_python_process_switch(self): @@ -496,8 +491,6 @@ last line: 987654321 self.get() - unit_stop() - assert ( self.wait_for_record(r'\[error\].+Error in application\.') is not None @@ -537,8 +530,6 @@ last line: 987654321 self.get() - unit_stop() - assert self.wait_for_record(r'Close called\.') is not None, 'close' def test_python_application_close_error(self): @@ -546,8 +537,6 @@ last line: 987654321 self.get() - unit_stop() - assert ( self.wait_for_record(r'Close called\.') is not None ), 'close error' @@ -557,8 +546,6 @@ last line: 987654321 self.get() - unit_stop() - assert ( self.wait_for_record( r'\[error\].+the application returned not an iterable object' diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index 6a0c9c9f..8311f52f 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -2,7 +2,6 @@ import re import pytest -from conftest import unit_stop from unit.applications.lang.ruby import TestApplicationRuby @@ -175,8 +174,6 @@ class TestRubyApplication(TestApplicationRuby): self.get() - unit_stop() - assert ( self.wait_for_record(r'\[error\].+Error in application') is not None @@ -187,8 +184,6 @@ class TestRubyApplication(TestApplicationRuby): self.get() - unit_stop() - assert ( self.wait_for_record(r'\[error\].+1234567890') is not None ), 'errors puts int' @@ -198,8 +193,6 @@ class TestRubyApplication(TestApplicationRuby): self.get() - unit_stop() - assert ( self.wait_for_record(r'\[error\].+Error in application') is not None @@ -215,7 +208,6 @@ class TestRubyApplication(TestApplicationRuby): self.get() - unit_stop() assert ( self.wait_for_record(r'\[error\].+1234567890') is not None @@ -228,8 +220,6 @@ class TestRubyApplication(TestApplicationRuby): self.conf({"listeners": {}, "applications": {}}) - unit_stop() - assert ( self.wait_for_record(r'\[error\].+At exit called\.') is not None ), 'at exit' @@ -289,8 +279,6 @@ class TestRubyApplication(TestApplicationRuby): assert self.get()['status'] == 500, 'body each error status' - unit_stop() - assert ( self.wait_for_record(r'\[error\].+Failed to run ruby script') is not None diff --git a/test/test_usr1.py b/test/test_usr1.py index 44f19d23..dbb5265c 100644 --- a/test/test_usr1.py +++ b/test/test_usr1.py @@ -1,7 +1,6 @@ import os from subprocess import call -from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython from unit.utils import waitforfiles @@ -41,8 +40,6 @@ class TestUSR1(TestApplicationPython): assert self.get(url='/usr1')['status'] == 200 - unit_stop() - assert ( self.wait_for_record(r'"GET /usr1 HTTP/1.1" 200 0 "-" "-"', log) is not None @@ -74,8 +71,6 @@ class TestUSR1(TestApplicationPython): body = 'body_for_a_log_unit' assert self.post(body=body)['status'] == 200 - unit_stop() - assert self.wait_for_record(body) is not None, 'rename new' assert self.search_in_log(body, log_new) is None, 'rename new 2' -- cgit From 6dc9c47ccd26b23b61b7522803a667c2e515e260 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 13 Jan 2021 06:22:43 +0000 Subject: Tests: style. --- test/conftest.py | 4 +--- test/test_access_log.py | 1 - test/test_asgi_application.py | 1 - test/test_asgi_lifespan.py | 1 - test/test_asgi_websockets.py | 1 - test/test_configuration.py | 1 - test/test_go_isolation.py | 2 -- test/test_go_isolation_rootfs.py | 1 - test/test_http_header.py | 1 - test/test_java_isolation_rootfs.py | 1 - test/test_java_websockets.py | 1 - test/test_node_application.py | 1 - test/test_node_websockets.py | 1 - test/test_perl_application.py | 1 - test/test_php_application.py | 1 - test/test_php_isolation.py | 3 --- test/test_proxy.py | 1 - test/test_python_application.py | 1 - test/test_python_isolation.py | 2 -- test/test_python_isolation_chroot.py | 1 - test/test_python_procman.py | 1 - test/test_routing.py | 1 - test/test_ruby_application.py | 1 - test/test_ruby_isolation.py | 3 +-- test/test_settings.py | 2 -- test/test_static.py | 1 - test/test_tls.py | 1 - 27 files changed, 2 insertions(+), 35 deletions(-) (limited to 'test') diff --git a/test/conftest.py b/test/conftest.py index 0a4b541d..b36aabad 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -4,7 +4,6 @@ import platform import re import shutil import signal -import socket import stat import subprocess import sys @@ -13,11 +12,10 @@ import time from multiprocessing import Process import pytest - from unit.check.go import check_go +from unit.check.isolation import check_isolation from unit.check.node import check_node from unit.check.tls import check_openssl -from unit.check.isolation import check_isolation from unit.option import option from unit.utils import public_dir from unit.utils import waitforfiles diff --git a/test/test_access_log.py b/test/test_access_log.py index e82e42e3..045473ae 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -1,7 +1,6 @@ import time import pytest - from unit.applications.lang.python import TestApplicationPython from unit.option import option diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index 9f4b70a4..5770265d 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -3,7 +3,6 @@ import time from distutils.version import LooseVersion import pytest - from unit.applications.lang.python import TestApplicationPython from unit.option import option diff --git a/test/test_asgi_lifespan.py b/test/test_asgi_lifespan.py index 43286e22..3ecece43 100644 --- a/test/test_asgi_lifespan.py +++ b/test/test_asgi_lifespan.py @@ -2,7 +2,6 @@ import os from distutils.version import LooseVersion import pytest - from conftest import unit_stop from unit.applications.lang.python import TestApplicationPython from unit.option import option diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py index 76cd8e80..7c9ec555 100644 --- a/test/test_asgi_websockets.py +++ b/test/test_asgi_websockets.py @@ -3,7 +3,6 @@ import time from distutils.version import LooseVersion import pytest - from unit.applications.lang.python import TestApplicationPython from unit.applications.websockets import TestApplicationWebsocket from unit.option import option diff --git a/test/test_configuration.py b/test/test_configuration.py index 7feb3adb..b7417264 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -1,5 +1,4 @@ import pytest - from unit.control import TestControl diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py index 0cd83056..e8fa26c6 100644 --- a/test/test_go_isolation.py +++ b/test/test_go_isolation.py @@ -1,10 +1,8 @@ import grp import os import pwd -import shutil import pytest - from unit.applications.lang.go import TestApplicationGo from unit.option import option from unit.utils import getns diff --git a/test/test_go_isolation_rootfs.py b/test/test_go_isolation_rootfs.py index 1cc59c67..2bded5ec 100644 --- a/test/test_go_isolation_rootfs.py +++ b/test/test_go_isolation_rootfs.py @@ -1,7 +1,6 @@ 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 fdb557cf..ca355eb7 100644 --- a/test/test_http_header.py +++ b/test/test_http_header.py @@ -1,5 +1,4 @@ import pytest - from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_java_isolation_rootfs.py b/test/test_java_isolation_rootfs.py index a401e23b..91773981 100644 --- a/test/test_java_isolation_rootfs.py +++ b/test/test_java_isolation_rootfs.py @@ -2,7 +2,6 @@ import os import subprocess import pytest - from unit.applications.lang.java import TestApplicationJava from unit.option import option diff --git a/test/test_java_websockets.py b/test/test_java_websockets.py index 729aa31d..315c496d 100644 --- a/test/test_java_websockets.py +++ b/test/test_java_websockets.py @@ -2,7 +2,6 @@ import struct import time import pytest - from unit.applications.lang.java import TestApplicationJava from unit.applications.websockets import TestApplicationWebsocket from unit.option import option diff --git a/test/test_node_application.py b/test/test_node_application.py index da29847a..b277dc3a 100644 --- a/test/test_node_application.py +++ b/test/test_node_application.py @@ -1,7 +1,6 @@ import re import pytest - from unit.applications.lang.node import TestApplicationNode from unit.utils import waitforfiles diff --git a/test/test_node_websockets.py b/test/test_node_websockets.py index d7444bf7..4f1e5906 100644 --- a/test/test_node_websockets.py +++ b/test/test_node_websockets.py @@ -2,7 +2,6 @@ import struct import time import pytest - from unit.applications.lang.node import TestApplicationNode from unit.applications.websockets import TestApplicationWebsocket from unit.option import option diff --git a/test/test_perl_application.py b/test/test_perl_application.py index e906aaca..dfd8be6c 100644 --- a/test/test_perl_application.py +++ b/test/test_perl_application.py @@ -1,7 +1,6 @@ import re import pytest - from unit.applications.lang.perl import TestApplicationPerl diff --git a/test/test_php_application.py b/test/test_php_application.py index 9f0da531..981d9e95 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -5,7 +5,6 @@ import time from subprocess import call import pytest - from unit.applications.lang.php import TestApplicationPHP from unit.option import option diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index b0fea383..2e458023 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -1,7 +1,4 @@ -import shutil - import pytest - from unit.applications.lang.php import TestApplicationPHP from unit.option import option diff --git a/test/test_proxy.py b/test/test_proxy.py index 0eebab1e..b7c34390 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -3,7 +3,6 @@ import socket import time import pytest - from conftest import run_process from unit.applications.lang.python import TestApplicationPython from unit.option import option diff --git a/test/test_python_application.py b/test/test_python_application.py index 01f53f8d..5aa60712 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -4,7 +4,6 @@ import re import time import pytest - from unit.applications.lang.python import TestApplicationPython from unit.option import option diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index ad830269..aa96af51 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -1,7 +1,5 @@ -import shutil import pytest - from unit.applications.lang.python import TestApplicationPython from unit.option import option diff --git a/test/test_python_isolation_chroot.py b/test/test_python_isolation_chroot.py index 7f559bcc..7281f5f6 100644 --- a/test/test_python_isolation_chroot.py +++ b/test/test_python_isolation_chroot.py @@ -1,5 +1,4 @@ import pytest - from unit.applications.lang.python import TestApplicationPython diff --git a/test/test_python_procman.py b/test/test_python_procman.py index 42a197a7..bfc218a9 100644 --- a/test/test_python_procman.py +++ b/test/test_python_procman.py @@ -3,7 +3,6 @@ import subprocess import time import pytest - from unit.applications.lang.python import TestApplicationPython from unit.option import option diff --git a/test/test_routing.py b/test/test_routing.py index 30f25a9c..21c1899e 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- import pytest - from unit.applications.proto import TestApplicationProto from unit.option import option diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index 8311f52f..a84b2990 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -1,7 +1,6 @@ import re import pytest - from unit.applications.lang.ruby import TestApplicationRuby diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py index fab428e9..c49b6732 100644 --- a/test/test_ruby_isolation.py +++ b/test/test_ruby_isolation.py @@ -1,8 +1,7 @@ +import os import shutil -import os import pytest - from unit.applications.lang.ruby import TestApplicationRuby from unit.option import option diff --git a/test/test_settings.py b/test/test_settings.py index 22830a3b..c59ca8b9 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -3,7 +3,6 @@ import socket import time import pytest - from unit.applications.lang.python import TestApplicationPython @@ -297,4 +296,3 @@ Connection: close assert bool(resp), 'response from application 4' assert resp['status'] == 200, 'status 4' assert resp['body'] == body, 'body 4' - diff --git a/test/test_static.py b/test/test_static.py index 4591aa03..3e85b435 100644 --- a/test/test_static.py +++ b/test/test_static.py @@ -2,7 +2,6 @@ import os import socket import pytest - from unit.applications.proto import TestApplicationProto from unit.option import option from unit.utils import waitforfiles diff --git a/test/test_tls.py b/test/test_tls.py index 5a408ee2..f5df5ee1 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -4,7 +4,6 @@ import ssl import subprocess import pytest - from unit.applications.tls import TestApplicationTLS from unit.option import option -- cgit From db9b70932b2e3e4df8b4bcdb24fedce042da15aa Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 13 Jan 2021 06:24:26 +0000 Subject: Tests: waitformount() and waitforunmount() introduced. --- test/unit/utils.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'test') diff --git a/test/unit/utils.py b/test/unit/utils.py index 1307a4f6..7a0a3fe5 100644 --- a/test/unit/utils.py +++ b/test/unit/utils.py @@ -1,5 +1,6 @@ import os import socket +import subprocess import time import pytest @@ -49,6 +50,37 @@ def waitforsocket(port): pytest.fail('Can\'t connect to the 127.0.0.1:' + port) +def findmnt(): + try: + out = subprocess.check_output( + ['findmnt', '--raw'], stderr=subprocess.STDOUT + ).decode() + except FileNotFoundError: + pytest.skip('requires findmnt') + + return out + + +def waitformount(template, wait=50): + for i in range(wait): + if findmnt().find(template) != -1: + return True + + time.sleep(0.1) + + return False + + +def waitforunmount(template, wait=50): + for i in range(wait): + if findmnt().find(template) == -1: + return True + + time.sleep(0.1) + + return False + + def getns(nstype): # read namespace id from symlink file: # it points to: ':[]' -- cgit From 22dac5bd62d19c0f8743b63ec8c47b3b071eb000 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 13 Jan 2021 06:24:32 +0000 Subject: Tests: "language_deps" option checked more carefully. --- test/test_python_isolation.py | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'test') diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index aa96af51..e1a42c98 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -2,6 +2,9 @@ import pytest from unit.applications.lang.python import TestApplicationPython from unit.option import option +from unit.utils import findmnt +from unit.utils import waitformount +from unit.utils import waitforunmount class TestPythonIsolation(TestApplicationPython): @@ -60,39 +63,28 @@ class TestPythonIsolation(TestApplicationPython): ), 'application exists in rootfs' def test_python_isolation_rootfs_no_language_deps(self, is_su, temp_dir): - isolation_features = option.available['features']['isolation'].keys() - if not is_su: - if not 'unprivileged_userns_clone' in isolation_features: - pytest.skip('requires unprivileged userns or root') - - if 'user' not in isolation_features: - pytest.skip('user namespace is not supported') - - if 'mnt' not in isolation_features: - pytest.skip('mnt namespace is not supported') - - if 'pid' not in isolation_features: - pytest.skip('pid namespace is not supported') + pytest.skip('requires root') isolation = { 'rootfs': temp_dir, 'automount': {'language_deps': False} } - if not is_su: - isolation['namespaces'] = { - 'mount': True, - 'credential': True, - 'pid': True - } - self.load('empty', isolation=isolation) + assert findmnt().find(temp_dir) == -1 assert (self.get()['status'] != 200), 'disabled language_deps' + assert findmnt().find(temp_dir) == -1 isolation['automount']['language_deps'] = True self.load('empty', isolation=isolation) + assert findmnt().find(temp_dir) == -1 assert (self.get()['status'] == 200), 'enabled language_deps' + assert waitformount(temp_dir), 'language_deps mount' + + self.conf({"listeners": {}, "applications": {}}) + + assert waitforunmount(temp_dir), 'language_deps unmount' -- cgit From 5d983ea762eba5fe26a07defbc09eeec8ecc5aeb Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Wed, 13 Jan 2021 06:24:41 +0000 Subject: Tests: added test for "procfs" option. --- test/test_python_isolation.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'test') diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index e1a42c98..680f2c03 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -88,3 +88,26 @@ class TestPythonIsolation(TestApplicationPython): self.conf({"listeners": {}, "applications": {}}) assert waitforunmount(temp_dir), 'language_deps unmount' + + def test_python_isolation_procfs(self, is_su, temp_dir): + isolation_features = option.available['features']['isolation'].keys() + + if not is_su: + pytest.skip('requires root') + + isolation = {'rootfs': temp_dir, 'automount': {'procfs': False}} + + self.load('ns_inspect', isolation=isolation) + + assert ( + self.getjson(url='/?path=/proc/self')['body']['FileExists'] + == False + ), 'no /proc/self' + + isolation['automount']['procfs'] = True + + self.load('ns_inspect', isolation=isolation) + + assert ( + self.getjson(url='/?path=/proc/self')['body']['FileExists'] == True + ), '/proc/self' -- cgit From d43a84139d1adedbae8def67c8bbee09d8cf4581 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 14 Jan 2021 03:04:20 +0000 Subject: Tests: added missing checks for configuration results. --- test/test_access_log.py | 12 ++++++++---- test/test_go_application.py | 8 ++++---- test/test_php_application.py | 30 +++++++++++++++--------------- test/test_php_basic.py | 26 +++++++++++++++----------- test/test_proxy.py | 6 ++++-- test/test_python_application.py | 4 ++-- test/test_python_basic.py | 24 ++++++++++++++---------- test/test_python_procman.py | 2 +- test/test_routing.py | 2 +- test/test_ruby_application.py | 2 +- test/test_tls.py | 12 +++++++----- 11 files changed, 72 insertions(+), 56 deletions(-) (limited to 'test') diff --git a/test/test_access_log.py b/test/test_access_log.py index 045473ae..65d5e50a 100644 --- a/test/test_access_log.py +++ b/test/test_access_log.py @@ -90,7 +90,9 @@ Connection: close def test_access_log_ipv6(self): self.load('empty') - self.conf({"[::1]:7080": {"pass": "applications/empty"}}, 'listeners') + assert 'success' in self.conf( + {"[::1]:7080": {"pass": "applications/empty"}}, 'listeners' + ) self.get(sock_type='ipv6') @@ -106,7 +108,7 @@ Connection: close addr = option.temp_dir + '/sock' - self.conf( + assert 'success' in self.conf( {"unix:" + addr: {"pass": "applications/empty"}}, 'listeners' ) @@ -240,7 +242,7 @@ Connection: close def test_access_log_delete(self): self.load('empty') - self.conf_delete('access_log') + assert 'success' in self.conf_delete('access_log') self.get(url='/delete') @@ -251,7 +253,9 @@ Connection: close self.get() - self.conf('"' + option.temp_dir + '/new.log"', 'access_log') + assert 'success' in self.conf( + '"' + option.temp_dir + '/new.log"', 'access_log' + ) self.get() diff --git a/test/test_go_application.py b/test/test_go_application.py index 8c77dfc5..e833d190 100644 --- a/test/test_go_application.py +++ b/test/test_go_application.py @@ -149,7 +149,7 @@ class TestGoApplication(TestApplicationGo): arg2 = '--cc-opt=\'-O0 -DNXT_DEBUG_MEMORY=1 -fsanitize=address\'' arg3 = '--debug' - self.conf( + assert 'success' in self.conf( '["' + arg1 + '", "' + arg2 + '", "' + arg3 + '"]', 'applications/command_line_arguments/arguments', ) @@ -163,15 +163,15 @@ class TestGoApplication(TestApplicationGo): args_path = 'applications/command_line_arguments/arguments' - self.conf('["0", "a", "$", ""]', args_path) + assert 'success' in self.conf('["0", "a", "$", ""]', args_path) assert self.get()['body'] == '0,a,$,', 'arguments' - self.conf('["-1", "b", "%"]', args_path) + assert 'success' in self.conf('["-1", "b", "%"]', args_path) assert self.get()['body'] == '-1,b,%', 'arguments change' - self.conf('[]', args_path) + assert 'success' in self.conf('[]', args_path) assert ( self.get()['headers']['Content-Length'] == '0' diff --git a/test/test_php_application.py b/test/test_php_application.py index 981d9e95..e73c67ba 100644 --- a/test/test_php_application.py +++ b/test/test_php_application.py @@ -268,7 +268,7 @@ class TestPHPApplication(TestApplicationPHP): assert self.get()['headers']['X-Precision'] != '4', 'ini value default' - self.conf( + assert 'success' in self.conf( {"file": "ini/php.ini"}, 'applications/ini_precision/options' ) @@ -290,7 +290,7 @@ class TestPHPApplication(TestApplicationPHP): def test_php_application_ini_admin(self): self.load('ini_precision') - self.conf( + assert 'success' in self.conf( {"file": "php.ini", "admin": {"precision": "5"}}, 'applications/ini_precision/options', ) @@ -300,7 +300,7 @@ class TestPHPApplication(TestApplicationPHP): def test_php_application_ini_user(self): self.load('ini_precision') - self.conf( + assert 'success' in self.conf( {"file": "php.ini", "user": {"precision": "5"}}, 'applications/ini_precision/options', ) @@ -310,13 +310,13 @@ class TestPHPApplication(TestApplicationPHP): def test_php_application_ini_user_2(self): self.load('ini_precision') - self.conf( + assert 'success' in self.conf( {"file": "ini/php.ini"}, 'applications/ini_precision/options' ) assert self.get()['headers']['X-Precision'] == '4', 'ini user file' - self.conf( + assert 'success' in self.conf( {"precision": "5"}, 'applications/ini_precision/options/user' ) @@ -325,7 +325,7 @@ class TestPHPApplication(TestApplicationPHP): def test_php_application_ini_set_admin(self): self.load('ini_precision') - self.conf( + assert 'success' in self.conf( {"admin": {"precision": "5"}}, 'applications/ini_precision/options' ) @@ -336,7 +336,7 @@ class TestPHPApplication(TestApplicationPHP): def test_php_application_ini_set_user(self): self.load('ini_precision') - self.conf( + assert 'success' in self.conf( {"user": {"precision": "5"}}, 'applications/ini_precision/options' ) @@ -347,7 +347,7 @@ class TestPHPApplication(TestApplicationPHP): def test_php_application_ini_repeat(self): self.load('ini_precision') - self.conf( + assert 'success' in self.conf( {"user": {"precision": "5"}}, 'applications/ini_precision/options' ) @@ -360,7 +360,7 @@ class TestPHPApplication(TestApplicationPHP): self.before_disable_functions() - self.conf( + assert 'success' in self.conf( {"admin": {"disable_functions": "exec"}}, 'applications/time_exec/options', ) @@ -375,7 +375,7 @@ class TestPHPApplication(TestApplicationPHP): self.before_disable_functions() - self.conf( + assert 'success' in self.conf( {"admin": {"disable_functions": "exec,time"}}, 'applications/time_exec/options', ) @@ -452,7 +452,7 @@ class TestPHPApplication(TestApplicationPHP): self.before_disable_functions() - self.conf( + assert 'success' in self.conf( {"admin": {"disable_functions": "exec time"}}, 'applications/time_exec/options', ) @@ -471,7 +471,7 @@ class TestPHPApplication(TestApplicationPHP): self.before_disable_functions() - self.conf( + assert 'success' in self.conf( {"user": {"disable_functions": "exec"}}, 'applications/time_exec/options', ) @@ -488,7 +488,7 @@ class TestPHPApplication(TestApplicationPHP): self.before_disable_functions() - self.conf( + assert 'success' in self.conf( {"admin": {"disable_functions": "blah"}}, 'applications/time_exec/options', ) @@ -509,7 +509,7 @@ class TestPHPApplication(TestApplicationPHP): r'012345', self.get()['body'] ), 'disable_classes before' - self.conf( + assert 'success' in self.conf( {"admin": {"disable_classes": "DateTime"}}, 'applications/date_time/options', ) @@ -525,7 +525,7 @@ class TestPHPApplication(TestApplicationPHP): r'012345', self.get()['body'] ), 'disable_classes before' - self.conf( + assert 'success' in self.conf( {"user": {"disable_classes": "DateTime"}}, 'applications/date_time/options', ) diff --git a/test/test_php_basic.py b/test/test_php_basic.py index 1420ec21..bcd66173 100644 --- a/test/test_php_basic.py +++ b/test/test_php_basic.py @@ -19,7 +19,7 @@ class TestPHPBasic(TestControl): } def test_php_get_applications(self): - self.conf(self.conf_app, 'applications') + assert 'success' in self.conf(self.conf_app, 'applications') conf = self.conf_get() @@ -55,7 +55,7 @@ class TestPHPBasic(TestControl): ), 'spare processes' def test_php_get_listeners(self): - self.conf(self.conf_basic) + assert 'success' in self.conf(self.conf_basic) assert self.conf_get()['listeners'] == { "*:7080": {"pass": "applications/app"} @@ -70,16 +70,20 @@ class TestPHPBasic(TestControl): }, 'listeners prefix 2' def test_php_change_listener(self): - self.conf(self.conf_basic) - self.conf({"*:7081": {"pass": "applications/app"}}, 'listeners') + assert 'success' in self.conf(self.conf_basic) + assert 'success' in self.conf( + {"*:7081": {"pass": "applications/app"}}, 'listeners' + ) 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') + assert 'success' in self.conf(self.conf_basic) + assert 'success' in self.conf( + {"pass": "applications/app"}, 'listeners/*:7082' + ) assert self.conf_get('listeners') == { "*:7080": {"pass": "applications/app"}, @@ -87,20 +91,20 @@ class TestPHPBasic(TestControl): }, 'add listener' def test_php_change_application(self): - self.conf(self.conf_basic) + assert 'success' in self.conf(self.conf_basic) - self.conf('30', 'applications/app/processes/max') + assert 'success' in self.conf('30', 'applications/app/processes/max') assert ( self.conf_get('applications/app/processes/max') == 30 ), 'change application max' - self.conf('"/www"', 'applications/app/root') + assert 'success' in self.conf('"/www"', 'applications/app/root') assert ( self.conf_get('applications/app/root') == '/www' ), 'change application root' def test_php_delete(self): - self.conf(self.conf_basic) + assert 'success' in self.conf(self.conf_basic) assert 'error' in self.conf_delete('applications/app') assert 'success' in self.conf_delete('listeners/*:7080') @@ -108,7 +112,7 @@ class TestPHPBasic(TestControl): assert 'error' in self.conf_delete('applications/app') def test_php_delete_blocks(self): - self.conf(self.conf_basic) + assert 'success' in self.conf(self.conf_basic) assert 'success' in self.conf_delete('listeners') assert 'success' in self.conf_delete('applications') diff --git a/test/test_proxy.py b/test/test_proxy.py index b7c34390..2d305e98 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -172,7 +172,9 @@ Content-Length: 10 assert resp['status'] == 200, 'status' assert resp['body'] == payload, 'body' - self.conf({'http': {'max_body_size': 32 * 1024 * 1024}}, 'settings') + assert 'success' in 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) @@ -486,7 +488,7 @@ Content-Length: 10 r'accept.*failed', r'new connections are not accepted', ) - self.conf( + assert 'success' in self.conf( { "listeners": { "*:7080": {"pass": "routes"}, diff --git a/test/test_python_application.py b/test/test_python_application.py index 5aa60712..5ad0901d 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -153,7 +153,7 @@ custom-header: BLAH assert resp['status'] == 200, 'ctx iter status' assert resp['body'] == '0123456789', 'ctx iter body' - self.conf({"listeners": {}, "applications": {}}) + assert 'success' in self.conf({"listeners": {}, "applications": {}}) assert ( self.wait_for_record(r'RuntimeError') is not None @@ -331,7 +331,7 @@ Connection: close self.get() - self.conf({"listeners": {}, "applications": {}}) + assert 'success' in self.conf({"listeners": {}, "applications": {}}) assert self.wait_for_record(r'At exit called\.') is not None, 'atexit' diff --git a/test/test_python_basic.py b/test/test_python_basic.py index 0cc70e51..e661a89c 100644 --- a/test/test_python_basic.py +++ b/test/test_python_basic.py @@ -58,7 +58,7 @@ class TestPythonBasic(TestControl): assert self.conf_get('applications/app/processes/spare') == 0, 'spare' def test_python_get_listeners(self): - self.conf(self.conf_basic) + assert 'success' in self.conf(self.conf_basic) assert self.conf_get()['listeners'] == { "*:7080": {"pass": "applications/app"} @@ -73,16 +73,20 @@ class TestPythonBasic(TestControl): }, 'listeners prefix 2' def test_python_change_listener(self): - self.conf(self.conf_basic) - self.conf({"*:7081": {"pass": "applications/app"}}, 'listeners') + assert 'success' in self.conf(self.conf_basic) + assert 'success' in self.conf( + {"*:7081": {"pass": "applications/app"}}, 'listeners' + ) 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') + assert 'success' in self.conf(self.conf_basic) + assert 'success' in self.conf( + {"pass": "applications/app"}, 'listeners/*:7082' + ) assert self.conf_get('listeners') == { "*:7080": {"pass": "applications/app"}, @@ -90,20 +94,20 @@ class TestPythonBasic(TestControl): }, 'add listener' def test_python_change_application(self): - self.conf(self.conf_basic) + assert 'success' in self.conf(self.conf_basic) - self.conf('30', 'applications/app/processes/max') + assert 'success' in self.conf('30', 'applications/app/processes/max') assert ( self.conf_get('applications/app/processes/max') == 30 ), 'change application max' - self.conf('"/www"', 'applications/app/path') + assert 'success' in self.conf('"/www"', 'applications/app/path') assert ( self.conf_get('applications/app/path') == '/www' ), 'change application path' def test_python_delete(self): - self.conf(self.conf_basic) + assert 'success' in self.conf(self.conf_basic) assert 'error' in self.conf_delete('applications/app') assert 'success' in self.conf_delete('listeners/*:7080') @@ -111,7 +115,7 @@ class TestPythonBasic(TestControl): assert 'error' in self.conf_delete('applications/app') def test_python_delete_blocks(self): - self.conf(self.conf_basic) + assert 'success' in self.conf(self.conf_basic) assert 'success' in self.conf_delete('listeners') assert 'success' in self.conf_delete('applications') diff --git a/test/test_python_procman.py b/test/test_python_procman.py index bfc218a9..ac403ce4 100644 --- a/test/test_python_procman.py +++ b/test/test_python_procman.py @@ -197,6 +197,6 @@ class TestPythonProcman(TestApplicationPython): ), 'max zero' def stop_all(self): - self.conf({"listeners": {}, "applications": {}}) + assert 'success' in self.conf({"listeners": {}, "applications": {}}) assert len(self.pids_for_process()) == 0, 'stop all' diff --git a/test/test_routing.py b/test/test_routing.py index 21c1899e..4d27cb61 100644 --- a/test/test_routing.py +++ b/test/test_routing.py @@ -316,7 +316,7 @@ class TestRouting(TestApplicationProto): check_pass_error("%1", "%1") def test_routes_absent(self): - self.conf( + assert 'success' in self.conf( { "listeners": {"*:7081": {"pass": "applications/empty"}}, "applications": { diff --git a/test/test_ruby_application.py b/test/test_ruby_application.py index a84b2990..b18a6cee 100644 --- a/test/test_ruby_application.py +++ b/test/test_ruby_application.py @@ -217,7 +217,7 @@ class TestRubyApplication(TestApplicationRuby): self.get() - self.conf({"listeners": {}, "applications": {}}) + assert 'success' in self.conf({"listeners": {}, "applications": {}}) assert ( self.wait_for_record(r'\[error\].+At exit called\.') is not None diff --git a/test/test_tls.py b/test/test_tls.py index f5df5ee1..89c57d07 100644 --- a/test/test_tls.py +++ b/test/test_tls.py @@ -19,7 +19,7 @@ class TestTLS(TestApplicationTLS): return self.date_to_sec_epoch(date, '%b %d %H:%M:%S %Y %Z') def add_tls(self, application='empty', cert='default', port=7080): - self.conf( + assert 'success' in self.conf( { "pass": "applications/" + application, "tls": {"certificate": cert} @@ -28,7 +28,7 @@ class TestTLS(TestApplicationTLS): ) def remove_tls(self, application='empty', port=7080): - self.conf( + assert 'success' in self.conf( {"pass": "applications/" + application}, 'listeners/*:' + str(port) ) @@ -477,8 +477,10 @@ basicConstraints = critical,CA:TRUE""" read_timeout=1, ) - self.conf({"pass": "applications/empty"}, 'listeners/*:7080') - self.conf_delete('/certificates/default') + assert 'success' in self.conf( + {"pass": "applications/empty"}, 'listeners/*:7080' + ) + assert 'success' in self.conf_delete('/certificates/default') try: resp = self.get_ssl( @@ -508,7 +510,7 @@ basicConstraints = critical,CA:TRUE""" self.certificate() - self.conf('1', 'applications/mirror/processes') + assert 'success' in self.conf('1', 'applications/mirror/processes') self.add_tls(application='mirror') -- cgit From e4e444b82701de0c984a72eb9c2657f72d7171ae Mon Sep 17 00:00:00 2001 From: Max Romanov Date: Thu, 28 Jan 2021 17:13:52 +0300 Subject: Router: fixing crash after WebSocket processing. After WebSocket processing, the application port was released with incorrect reason ("got request"), unnecessarily decrementing the active request counter. The assertion was triggered only on application removal; a test was added for this case. --- test/test_asgi_websockets.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'test') diff --git a/test/test_asgi_websockets.py b/test/test_asgi_websockets.py index 7c9ec555..6121fcc5 100644 --- a/test/test_asgi_websockets.py +++ b/test/test_asgi_websockets.py @@ -63,6 +63,9 @@ class TestASGIWebsockets(TestApplicationPython): key ), 'key' + # remove "mirror" application + self.load('websockets/subprotocol') + def test_asgi_websockets_subprotocol(self): self.load('websockets/subprotocol') @@ -92,6 +95,27 @@ class TestASGIWebsockets(TestApplicationPython): sock.close() + def test_asgi_websockets_mirror_app_change(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.load('websockets/subprotocol') + + 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') -- cgit From 42725137f7a19991680c78a0b2d69bcbf1f9ab63 Mon Sep 17 00:00:00 2001 From: Andrei Zeliankou Date: Thu, 4 Feb 2021 15:09:54 +0000 Subject: Tests: added tests for "path" option in Python application. --- test/python/path/wsgi.py | 8 ++++++++ test/test_python_application.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 test/python/path/wsgi.py (limited to 'test') diff --git a/test/python/path/wsgi.py b/test/python/path/wsgi.py new file mode 100644 index 00000000..2807f6ef --- /dev/null +++ b/test/python/path/wsgi.py @@ -0,0 +1,8 @@ +import os +import sys + +def application(environ, start_response): + body = os.pathsep.join(sys.path).encode() + + start_response('200', [('Content-Length', str(len(body)))]) + return [body] diff --git a/test/test_python_application.py b/test/test_python_application.py index 5ad0901d..709df3ff 100644 --- a/test/test_python_application.py +++ b/test/test_python_application.py @@ -1,4 +1,5 @@ import grp +import os import pwd import re import time @@ -790,6 +791,42 @@ last line: 987654321 assert self.get()['status'] not in [200, 204], 'callable response inv' + def test_python_application_path(self): + self.load('path') + + def set_path(path): + assert 'success' in self.conf(path, 'applications/path/path') + + def get_path(): + return self.get()['body'].split(os.pathsep) + + default_path = self.conf_get('/config/applications/path/path') + assert 'success' in self.conf( + {"PYTHONPATH": default_path}, + '/config/applications/path/environment', + ) + + self.conf_delete('/config/applications/path/path') + sys_path = get_path() + + set_path('"/blah"') + assert ['/blah', *sys_path] == get_path(), 'check path' + + set_path('"/new"') + assert ['/new', *sys_path] == get_path(), 'check path update' + + set_path('["/blah1", "/blah2"]') + assert ['/blah1', '/blah2', *sys_path] == get_path(), 'check path array' + + def test_python_application_path_invalid(self): + self.load('path') + + def check_path(path): + assert 'error' in self.conf(path, 'applications/path/path') + + check_path('{}') + check_path('["/blah", []]') + def test_python_application_threads(self): self.load('threads', threads=4) -- cgit