Tests: fixed unit.log print.
This commit is contained in:
137
test/conftest.py
137
test/conftest.py
@@ -4,11 +4,13 @@ import platform
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from multiprocessing import Process
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -45,6 +47,7 @@ def pytest_addoption(parser):
|
||||
|
||||
|
||||
unit_instance = {}
|
||||
_processes = []
|
||||
option = None
|
||||
|
||||
|
||||
@@ -66,6 +69,10 @@ 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'):
|
||||
@@ -127,7 +134,7 @@ def pytest_sessionstart(session):
|
||||
break
|
||||
|
||||
if m is None:
|
||||
_print_log()
|
||||
_print_log(log)
|
||||
exit("Unit is writing log too long")
|
||||
|
||||
# discover available modules from unit.log
|
||||
@@ -154,8 +161,26 @@ def pytest_sessionstart(session):
|
||||
|
||||
unit_stop()
|
||||
|
||||
shutil.rmtree(unit_instance['temp_dir'])
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
# execute all other hooks to obtain the report object
|
||||
outcome = yield
|
||||
rep = outcome.get_result()
|
||||
|
||||
# set a report attribute for each phase of a call, which can
|
||||
# be "setup", "call", "teardown"
|
||||
|
||||
setattr(item, "rep_" + rep.when, rep)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def run(request):
|
||||
unit = unit_run()
|
||||
option.temp_dir = unit['temp_dir']
|
||||
|
||||
def setup_method(self):
|
||||
option.skip_alerts = [
|
||||
r'read signalfd\(4\) failed',
|
||||
r'sendmsg.+failed',
|
||||
@@ -163,6 +188,40 @@ def setup_method(self):
|
||||
]
|
||||
option.skip_sanitizer = False
|
||||
|
||||
yield
|
||||
|
||||
# stop unit
|
||||
|
||||
error = unit_stop()
|
||||
|
||||
if error:
|
||||
_print_log()
|
||||
|
||||
assert error is None, 'stop unit'
|
||||
|
||||
# stop all processes
|
||||
|
||||
error = stop_processes()
|
||||
|
||||
if error:
|
||||
_print_log()
|
||||
|
||||
assert error is None, 'stop unit'
|
||||
|
||||
# check unit.log for alerts
|
||||
|
||||
_check_alerts()
|
||||
|
||||
# print unit.log in case of error
|
||||
|
||||
if request.node.rep_call.failed:
|
||||
_print_log()
|
||||
|
||||
# remove unit.log
|
||||
|
||||
if not option.save_log:
|
||||
shutil.rmtree(unit['temp_dir'])
|
||||
|
||||
def unit_run():
|
||||
global unit_instance
|
||||
build_dir = option.current_dir + '/build'
|
||||
@@ -204,14 +263,6 @@ def unit_run():
|
||||
_print_log()
|
||||
exit('Could not start unit')
|
||||
|
||||
# dumb (TODO: remove)
|
||||
option.skip_alerts = [
|
||||
r'read signalfd\(4\) failed',
|
||||
r'sendmsg.+failed',
|
||||
r'recvmsg.+failed',
|
||||
]
|
||||
option.skip_sanitizer = False
|
||||
|
||||
unit_instance['temp_dir'] = temp_dir
|
||||
unit_instance['log'] = temp_dir + '/unit.log'
|
||||
unit_instance['control_sock'] = temp_dir + '/control.unit.sock'
|
||||
@@ -236,8 +287,6 @@ def unit_stop():
|
||||
p.kill()
|
||||
return 'Could not terminate unit'
|
||||
|
||||
shutil.rmtree(unit_instance['temp_dir'])
|
||||
|
||||
def public_dir(path):
|
||||
os.chmod(path, 0o777)
|
||||
|
||||
@@ -267,11 +316,14 @@ def waitforfiles(*files):
|
||||
return ret
|
||||
|
||||
|
||||
def skip_alert(*alerts):
|
||||
option.skip_alerts.extend(alerts)
|
||||
|
||||
def _check_alerts(path=None):
|
||||
if path is None:
|
||||
path = unit_instance['log']
|
||||
|
||||
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
|
||||
log = f.read()
|
||||
|
||||
def _check_alerts(log):
|
||||
found = False
|
||||
|
||||
alerts = re.findall(r'.+\[alert\].+', log)
|
||||
@@ -286,23 +338,22 @@ def _check_alerts(log):
|
||||
alerts = [al for al in alerts if re.search(skip, al) is None]
|
||||
|
||||
if alerts:
|
||||
_print_log(data=log)
|
||||
_print_log(log)
|
||||
assert not alerts, 'alert(s)'
|
||||
|
||||
if not option.skip_sanitizer:
|
||||
sanitizer_errors = re.findall('.+Sanitizer.+', log)
|
||||
|
||||
if sanitizer_errors:
|
||||
_print_log(data=log)
|
||||
_print_log(log)
|
||||
assert not sanitizer_errors, 'sanitizer error(s)'
|
||||
|
||||
if found:
|
||||
print('skipped.')
|
||||
|
||||
|
||||
def _print_log(path=None, data=None):
|
||||
if path is None:
|
||||
path = unit_instance['log']
|
||||
def _print_log(data=None):
|
||||
path = unit_instance['log']
|
||||
|
||||
print('Path to unit.log:\n' + path + '\n')
|
||||
|
||||
@@ -317,6 +368,52 @@ def _print_log(path=None, data=None):
|
||||
sys.stdout.write(data)
|
||||
|
||||
|
||||
def run_process(target, *args):
|
||||
global _processes
|
||||
|
||||
process = Process(target=target, args=args)
|
||||
process.start()
|
||||
|
||||
_processes.append(process)
|
||||
|
||||
def stop_processes():
|
||||
if not _processes:
|
||||
return
|
||||
|
||||
fail = False
|
||||
for process in _processes:
|
||||
if process.is_alive():
|
||||
process.terminate()
|
||||
process.join(timeout=15)
|
||||
|
||||
if process.is_alive():
|
||||
fail = True
|
||||
|
||||
if fail:
|
||||
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:
|
||||
sock.close()
|
||||
time.sleep(0.1)
|
||||
|
||||
sock.close()
|
||||
|
||||
assert ret, 'socket connected'
|
||||
|
||||
@pytest.fixture
|
||||
def temp_dir(request):
|
||||
return unit_instance['temp_dir']
|
||||
|
||||
@pytest.fixture
|
||||
def is_unsafe(request):
|
||||
return request.config.getoption("--unsafe")
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[pytest]
|
||||
addopts = -rs -vvv
|
||||
addopts = -vvv -s --detailed --print_log
|
||||
python_functions = test_*
|
||||
|
||||
@@ -2,6 +2,8 @@ import time
|
||||
|
||||
import pytest
|
||||
|
||||
from conftest import option
|
||||
from conftest import unit_stop
|
||||
from unit.applications.lang.python import TestApplicationPython
|
||||
|
||||
|
||||
@@ -12,7 +14,7 @@ class TestAccessLog(TestApplicationPython):
|
||||
super().load(script)
|
||||
|
||||
assert 'success' in self.conf(
|
||||
'"' + self.temp_dir + '/access.log"', 'access_log'
|
||||
'"' + option.temp_dir + '/access.log"', 'access_log'
|
||||
), 'access_log configure'
|
||||
|
||||
def wait_for_record(self, pattern, name='access.log'):
|
||||
@@ -48,7 +50,7 @@ class TestAccessLog(TestApplicationPython):
|
||||
body='0123456789',
|
||||
)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"POST / HTTP/1.1" 200 10') is not None
|
||||
@@ -76,7 +78,7 @@ Connection: close
|
||||
raw=True,
|
||||
)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"')
|
||||
@@ -98,7 +100,7 @@ Connection: close
|
||||
|
||||
self.get(sock_type='ipv6')
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(
|
||||
@@ -110,7 +112,7 @@ Connection: close
|
||||
def test_access_log_unix(self):
|
||||
self.load('empty')
|
||||
|
||||
addr = self.temp_dir + '/sock'
|
||||
addr = option.temp_dir + '/sock'
|
||||
|
||||
self.conf(
|
||||
{"unix:" + addr: {"pass": "applications/empty"}}, 'listeners'
|
||||
@@ -118,7 +120,7 @@ Connection: close
|
||||
|
||||
self.get(sock_type='unix', addr=addr)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(
|
||||
@@ -138,7 +140,7 @@ Connection: close
|
||||
}
|
||||
)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "referer-value" "-"')
|
||||
@@ -156,7 +158,7 @@ Connection: close
|
||||
}
|
||||
)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(
|
||||
@@ -170,7 +172,7 @@ Connection: close
|
||||
|
||||
self.get(http_10=True)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET / HTTP/1.0" 200 0 "-" "-"') is not None
|
||||
@@ -185,7 +187,7 @@ Connection: close
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GE" 400 0 "-" "-"') is not None
|
||||
@@ -198,7 +200,7 @@ Connection: close
|
||||
|
||||
self.http(b"""GET /\n""", raw=True)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET /" 400 \d+ "-" "-"') is not None
|
||||
@@ -213,7 +215,7 @@ Connection: close
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET /" 400 0 "-" "-"') is not None
|
||||
@@ -228,7 +230,7 @@ Connection: close
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET / HTTP/1.1" 400 0 "-" "-"') is not None
|
||||
@@ -242,7 +244,7 @@ Connection: close
|
||||
|
||||
self.get(headers={'Connection': 'close'})
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET / HTTP/1.1" 400 \d+ "-" "-"')
|
||||
@@ -254,7 +256,7 @@ Connection: close
|
||||
|
||||
self.get(url='/?blah&var=val')
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(
|
||||
@@ -270,20 +272,20 @@ Connection: close
|
||||
|
||||
self.get(url='/delete')
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert self.search_in_log(r'/delete', 'access.log') is None, 'delete'
|
||||
|
||||
def test_access_log_change(self):
|
||||
def test_access_log_change(self, temp_dir):
|
||||
self.load('empty')
|
||||
|
||||
self.get()
|
||||
|
||||
self.conf('"' + self.temp_dir + '/new.log"', 'access_log')
|
||||
self.conf('"' + option.temp_dir + '/new.log"', 'access_log')
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log')
|
||||
|
||||
@@ -4,6 +4,7 @@ from distutils.version import LooseVersion
|
||||
|
||||
import pytest
|
||||
|
||||
from conftest import option
|
||||
from conftest import skip_alert
|
||||
from unit.applications.lang.python import TestApplicationPython
|
||||
|
||||
@@ -14,7 +15,7 @@ class TestASGIApplication(TestApplicationPython):
|
||||
load_module = 'asgi'
|
||||
|
||||
def findall(self, pattern):
|
||||
with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f:
|
||||
with open(option.temp_dir + '/unit.log', 'r', errors='ignore') as f:
|
||||
return re.findall(pattern, f.read())
|
||||
|
||||
def test_asgi_application_variables(self):
|
||||
|
||||
@@ -5,6 +5,7 @@ import pytest
|
||||
|
||||
from conftest import option
|
||||
from conftest import public_dir
|
||||
from conftest import unit_stop
|
||||
from unit.applications.lang.python import TestApplicationPython
|
||||
|
||||
|
||||
@@ -34,7 +35,7 @@ class TestASGILifespan(TestApplicationPython):
|
||||
|
||||
assert self.get()['status'] == 204
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
is_startup = os.path.isfile(startup_path)
|
||||
is_shutdown = os.path.isfile(shutdown_path)
|
||||
|
||||
@@ -18,8 +18,6 @@ class TestASGIWebsockets(TestApplicationPython):
|
||||
ws = TestApplicationWebsocket()
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{'http': {'websocket': {'keepalive_interval': 0}}}, 'settings'
|
||||
), 'clear keepalive_interval'
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import grp
|
||||
import os
|
||||
import pwd
|
||||
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
|
||||
|
||||
@@ -14,11 +18,17 @@ class TestGoIsolation(TestApplicationGo):
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls, complete_check=True):
|
||||
unit = super().setup_class(complete_check=False)
|
||||
check = super().setup_class(complete_check=False)
|
||||
|
||||
TestFeatureIsolation().check(cls.available, unit.temp_dir)
|
||||
unit = unit_run()
|
||||
option.temp_dir = unit['temp_dir']
|
||||
|
||||
return unit if not complete_check else unit.complete()
|
||||
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
|
||||
@@ -33,14 +43,14 @@ class TestGoIsolation(TestApplicationGo):
|
||||
return (nobody_uid, nogroup_gid, nogroup)
|
||||
|
||||
def isolation_key(self, key):
|
||||
return key in self.available['features']['isolation'].keys()
|
||||
return key in option.available['features']['isolation'].keys()
|
||||
|
||||
def test_isolation_values(self):
|
||||
self.load('ns_inspect')
|
||||
|
||||
obj = self.getjson()['body']
|
||||
|
||||
for ns, ns_value in self.available['features']['isolation'].items():
|
||||
for ns, ns_value in option.available['features']['isolation'].items():
|
||||
if ns.upper() in obj['NS']:
|
||||
assert obj['NS'][ns.upper()] == ns_value, '%s match' % ns
|
||||
|
||||
@@ -198,7 +208,7 @@ class TestGoIsolation(TestApplicationGo):
|
||||
obj = self.getjson()['body']
|
||||
|
||||
# all but user and mnt
|
||||
allns = list(self.available['features']['isolation'].keys())
|
||||
allns = list(option.available['features']['isolation'].keys())
|
||||
allns.remove('user')
|
||||
allns.remove('mnt')
|
||||
|
||||
@@ -206,7 +216,7 @@ class TestGoIsolation(TestApplicationGo):
|
||||
if ns.upper() in obj['NS']:
|
||||
assert (
|
||||
obj['NS'][ns.upper()]
|
||||
== self.available['features']['isolation'][ns]
|
||||
== option.available['features']['isolation'][ns]
|
||||
), ('%s match' % ns)
|
||||
|
||||
assert obj['NS']['MNT'] != self.isolation.getns('mnt'), 'mnt set'
|
||||
@@ -230,7 +240,7 @@ class TestGoIsolation(TestApplicationGo):
|
||||
|
||||
def test_isolation_namespace_false(self):
|
||||
self.load('ns_inspect')
|
||||
allns = list(self.available['features']['isolation'].keys())
|
||||
allns = list(option.available['features']['isolation'].keys())
|
||||
|
||||
remove_list = ['unprivileged_userns_clone', 'ipc', 'cgroup']
|
||||
allns = [ns for ns in allns if ns not in remove_list]
|
||||
@@ -256,10 +266,10 @@ class TestGoIsolation(TestApplicationGo):
|
||||
if ns.upper() in obj['NS']:
|
||||
assert (
|
||||
obj['NS'][ns.upper()]
|
||||
== self.available['features']['isolation'][ns]
|
||||
== option.available['features']['isolation'][ns]
|
||||
), ('%s match' % ns)
|
||||
|
||||
def test_go_isolation_rootfs_container(self):
|
||||
def test_go_isolation_rootfs_container(self, temp_dir):
|
||||
if not self.isolation_key('unprivileged_userns_clone'):
|
||||
pytest.skip('unprivileged clone is not available')
|
||||
|
||||
@@ -268,7 +278,7 @@ class TestGoIsolation(TestApplicationGo):
|
||||
|
||||
isolation = {
|
||||
'namespaces': {'mount': True, 'credential': True},
|
||||
'rootfs': self.temp_dir,
|
||||
'rootfs': temp_dir,
|
||||
}
|
||||
|
||||
self.load('ns_inspect', isolation=isolation)
|
||||
@@ -280,7 +290,7 @@ class TestGoIsolation(TestApplicationGo):
|
||||
obj = self.getjson(url='/?file=/bin/sh')['body']
|
||||
assert obj['FileExists'] == False, 'file should not exists'
|
||||
|
||||
def test_go_isolation_rootfs_container_priv(self, is_su):
|
||||
def test_go_isolation_rootfs_container_priv(self, is_su, temp_dir):
|
||||
if not is_su:
|
||||
pytest.skip('requires root')
|
||||
|
||||
@@ -289,7 +299,7 @@ class TestGoIsolation(TestApplicationGo):
|
||||
|
||||
isolation = {
|
||||
'namespaces': {'mount': True},
|
||||
'rootfs': self.temp_dir,
|
||||
'rootfs': temp_dir,
|
||||
}
|
||||
|
||||
self.load('ns_inspect', isolation=isolation)
|
||||
@@ -301,7 +311,7 @@ class TestGoIsolation(TestApplicationGo):
|
||||
obj = self.getjson(url='/?file=/bin/sh')['body']
|
||||
assert obj['FileExists'] == False, 'file should not exists'
|
||||
|
||||
def test_go_isolation_rootfs_default_tmpfs(self):
|
||||
def test_go_isolation_rootfs_default_tmpfs(self, temp_dir):
|
||||
if not self.isolation_key('unprivileged_userns_clone'):
|
||||
pytest.skip('unprivileged clone is not available')
|
||||
|
||||
@@ -310,7 +320,7 @@ class TestGoIsolation(TestApplicationGo):
|
||||
|
||||
isolation = {
|
||||
'namespaces': {'mount': True, 'credential': True},
|
||||
'rootfs': self.temp_dir,
|
||||
'rootfs': temp_dir,
|
||||
}
|
||||
|
||||
self.load('ns_inspect', isolation=isolation)
|
||||
|
||||
@@ -8,7 +8,7 @@ from unit.applications.lang.go import TestApplicationGo
|
||||
class TestGoIsolationRootfs(TestApplicationGo):
|
||||
prerequisites = {'modules': {'go': 'all'}}
|
||||
|
||||
def test_go_isolation_rootfs_chroot(self, is_su):
|
||||
def test_go_isolation_rootfs_chroot(self, is_su, temp_dir):
|
||||
if not is_su:
|
||||
pytest.skip('requires root')
|
||||
|
||||
@@ -16,7 +16,7 @@ class TestGoIsolationRootfs(TestApplicationGo):
|
||||
pytest.skip('chroot tests not supported on OSX')
|
||||
|
||||
isolation = {
|
||||
'rootfs': self.temp_dir,
|
||||
'rootfs': temp_dir,
|
||||
}
|
||||
|
||||
self.load('ns_inspect', isolation=isolation)
|
||||
|
||||
@@ -11,7 +11,7 @@ from unit.applications.lang.java import TestApplicationJava
|
||||
class TestJavaApplication(TestApplicationJava):
|
||||
prerequisites = {'modules': {'java': 'all'}}
|
||||
|
||||
def test_java_conf_error(self):
|
||||
def test_java_conf_error(self, temp_dir):
|
||||
skip_alert(
|
||||
r'realpath.*failed',
|
||||
r'failed to apply new conf',
|
||||
@@ -25,18 +25,18 @@ class TestJavaApplication(TestApplicationJava):
|
||||
"type": "java",
|
||||
"processes": 1,
|
||||
"working_directory": option.test_dir + "/java/empty",
|
||||
"webapp": self.temp_dir + "/java",
|
||||
"unit_jars": self.temp_dir + "/no_such_dir",
|
||||
"webapp": temp_dir + "/java",
|
||||
"unit_jars": temp_dir + "/no_such_dir",
|
||||
}
|
||||
},
|
||||
}
|
||||
), 'conf error'
|
||||
|
||||
def test_java_war(self):
|
||||
def test_java_war(self, temp_dir):
|
||||
self.load('empty_war')
|
||||
|
||||
assert 'success' in self.conf(
|
||||
'"' + self.temp_dir + '/java/empty.war"',
|
||||
'"' + temp_dir + '/java/empty.war"',
|
||||
'/config/applications/empty_war/webapp',
|
||||
), 'configure war'
|
||||
|
||||
@@ -969,11 +969,11 @@ class TestJavaApplication(TestApplicationJava):
|
||||
), 'set date header'
|
||||
assert headers['X-Get-Date'] == date, 'get date header'
|
||||
|
||||
def test_java_application_multipart(self):
|
||||
def test_java_application_multipart(self, temp_dir):
|
||||
self.load('multipart')
|
||||
|
||||
reldst = '/uploads'
|
||||
fulldst = self.temp_dir + reldst
|
||||
fulldst = temp_dir + reldst
|
||||
os.mkdir(fulldst)
|
||||
public_dir(fulldst)
|
||||
|
||||
|
||||
@@ -11,14 +11,12 @@ class TestJavaIsolationRootfs(TestApplicationJava):
|
||||
prerequisites = {'modules': {'java': 'all'}}
|
||||
|
||||
def setup_method(self, is_su):
|
||||
super().setup_method()
|
||||
|
||||
if not is_su:
|
||||
return
|
||||
|
||||
os.makedirs(self.temp_dir + '/jars')
|
||||
os.makedirs(self.temp_dir + '/tmp')
|
||||
os.chmod(self.temp_dir + '/tmp', 0o777)
|
||||
os.makedirs(option.temp_dir + '/jars')
|
||||
os.makedirs(option.temp_dir + '/tmp')
|
||||
os.chmod(option.temp_dir + '/tmp', 0o777)
|
||||
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
@@ -26,7 +24,7 @@ class TestJavaIsolationRootfs(TestApplicationJava):
|
||||
"mount",
|
||||
"--bind",
|
||||
option.current_dir + "/build",
|
||||
self.temp_dir + "/jars",
|
||||
option.temp_dir + "/jars",
|
||||
],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
@@ -42,7 +40,7 @@ class TestJavaIsolationRootfs(TestApplicationJava):
|
||||
|
||||
try:
|
||||
process = subprocess.Popen(
|
||||
["umount", "--lazy", self.temp_dir + "/jars"],
|
||||
["umount", "--lazy", option.temp_dir + "/jars"],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
|
||||
@@ -51,15 +49,12 @@ class TestJavaIsolationRootfs(TestApplicationJava):
|
||||
except:
|
||||
pytest.fail('Cann\'t run mount process.')
|
||||
|
||||
# super teardown must happen after unmount to avoid deletion of /build
|
||||
super().teardown_method()
|
||||
|
||||
def test_java_isolation_rootfs_chroot_war(self, is_su):
|
||||
def test_java_isolation_rootfs_chroot_war(self, is_su, temp_dir):
|
||||
if not is_su:
|
||||
pytest.skip('require root')
|
||||
|
||||
isolation = {
|
||||
'rootfs': self.temp_dir,
|
||||
'rootfs': temp_dir,
|
||||
}
|
||||
|
||||
self.load('empty_war', isolation=isolation)
|
||||
|
||||
@@ -15,8 +15,6 @@ class TestJavaWebsockets(TestApplicationJava):
|
||||
ws = TestApplicationWebsocket()
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{'http': {'websocket': {'keepalive_interval': 0}}}, 'settings'
|
||||
), 'clear keepalive_interval'
|
||||
|
||||
@@ -139,11 +139,11 @@ class TestNodeApplication(TestApplicationNode):
|
||||
|
||||
assert self.get()['body'] == 'buffer', 'write buffer'
|
||||
|
||||
def test_node_application_write_callback(self):
|
||||
def test_node_application_write_callback(self, temp_dir):
|
||||
self.load('write_callback')
|
||||
|
||||
assert self.get()['body'] == 'helloworld', 'write callback order'
|
||||
assert waitforfiles(self.temp_dir + '/node/callback'), 'write callback'
|
||||
assert waitforfiles(temp_dir + '/node/callback'), 'write callback'
|
||||
|
||||
def test_node_application_write_before_write_head(self):
|
||||
self.load('write_before_write_head')
|
||||
@@ -222,7 +222,7 @@ 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):
|
||||
def test_node_application_promise_handler(self, temp_dir):
|
||||
self.load('promise_handler')
|
||||
|
||||
assert (
|
||||
@@ -236,7 +236,7 @@ class TestNodeApplication(TestApplicationNode):
|
||||
)['status']
|
||||
== 200
|
||||
), 'promise handler request'
|
||||
assert waitforfiles(self.temp_dir + '/node/callback'), 'promise handler'
|
||||
assert waitforfiles(temp_dir + '/node/callback'), 'promise handler'
|
||||
|
||||
def test_node_application_promise_handler_write_after_end(self):
|
||||
self.load('promise_handler')
|
||||
@@ -254,7 +254,7 @@ class TestNodeApplication(TestApplicationNode):
|
||||
== 200
|
||||
), 'promise handler request write after end'
|
||||
|
||||
def test_node_application_promise_end(self):
|
||||
def test_node_application_promise_end(self, temp_dir):
|
||||
self.load('promise_end')
|
||||
|
||||
assert (
|
||||
@@ -268,9 +268,9 @@ class TestNodeApplication(TestApplicationNode):
|
||||
)['status']
|
||||
== 200
|
||||
), 'promise end request'
|
||||
assert waitforfiles(self.temp_dir + '/node/callback'), 'promise end'
|
||||
assert waitforfiles(temp_dir + '/node/callback'), 'promise end'
|
||||
|
||||
def test_node_application_promise_multiple_calls(self):
|
||||
def test_node_application_promise_multiple_calls(self, temp_dir):
|
||||
self.load('promise_handler')
|
||||
|
||||
self.post(
|
||||
@@ -283,7 +283,7 @@ class TestNodeApplication(TestApplicationNode):
|
||||
)
|
||||
|
||||
assert waitforfiles(
|
||||
self.temp_dir + '/node/callback1'
|
||||
temp_dir + '/node/callback1'
|
||||
), 'promise first call'
|
||||
|
||||
self.post(
|
||||
@@ -296,7 +296,7 @@ class TestNodeApplication(TestApplicationNode):
|
||||
)
|
||||
|
||||
assert waitforfiles(
|
||||
self.temp_dir + '/node/callback2'
|
||||
temp_dir + '/node/callback2'
|
||||
), 'promise second call'
|
||||
|
||||
@pytest.mark.skip('not yet')
|
||||
|
||||
@@ -15,8 +15,6 @@ class TestNodeWebsockets(TestApplicationNode):
|
||||
ws = TestApplicationWebsocket()
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{'http': {'websocket': {'keepalive_interval': 0}}}, 'settings'
|
||||
), 'clear keepalive_interval'
|
||||
|
||||
@@ -3,6 +3,7 @@ import re
|
||||
import pytest
|
||||
|
||||
from conftest import skip_alert
|
||||
from conftest import unit_stop
|
||||
from unit.applications.lang.perl import TestApplicationPerl
|
||||
|
||||
|
||||
@@ -119,7 +120,7 @@ class TestPerlApplication(TestApplicationPerl):
|
||||
|
||||
assert self.get()['body'] == '1', 'errors result'
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'\[error\].+Error in application')
|
||||
|
||||
@@ -6,6 +6,7 @@ import time
|
||||
import pytest
|
||||
|
||||
from conftest import option
|
||||
from conftest import unit_stop
|
||||
from unit.applications.lang.php import TestApplicationPHP
|
||||
|
||||
class TestPHPApplication(TestApplicationPHP):
|
||||
@@ -444,7 +445,7 @@ class TestPHPApplication(TestApplicationPHP):
|
||||
r'012345', self.get()['body']
|
||||
), 'disable_classes before'
|
||||
|
||||
def test_php_application_error_log(self):
|
||||
def test_php_application_error_log(self, temp_dir):
|
||||
self.load('error_log')
|
||||
|
||||
assert self.get()['status'] == 200, 'status'
|
||||
@@ -453,13 +454,13 @@ class TestPHPApplication(TestApplicationPHP):
|
||||
|
||||
assert self.get()['status'] == 200, 'status 2'
|
||||
|
||||
self.stop()
|
||||
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'
|
||||
|
||||
with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f:
|
||||
with open(temp_dir + '/unit.log', 'r', errors='ignore') as f:
|
||||
errs = re.findall(pattern, f.read())
|
||||
|
||||
assert len(errs) == 2, 'error_log count'
|
||||
@@ -507,12 +508,12 @@ class TestPHPApplication(TestApplicationPHP):
|
||||
assert resp['status'] == 200, 'status'
|
||||
assert resp['body'] != '', 'body not empty'
|
||||
|
||||
def test_php_application_extension_check(self):
|
||||
def test_php_application_extension_check(self, temp_dir):
|
||||
self.load('phpinfo')
|
||||
|
||||
assert self.get(url='/index.wrong')['status'] != 200, 'status'
|
||||
|
||||
new_root = self.temp_dir + "/php"
|
||||
new_root = temp_dir + "/php"
|
||||
os.mkdir(new_root)
|
||||
shutil.copy(option.test_dir + '/php/phpinfo/index.wrong', new_root)
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
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
|
||||
|
||||
@@ -8,18 +12,22 @@ from unit.feature.isolation import TestFeatureIsolation
|
||||
class TestPHPIsolation(TestApplicationPHP):
|
||||
prerequisites = {'modules': {'php': 'any'}, 'features': ['isolation']}
|
||||
|
||||
isolation = TestFeatureIsolation()
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls, complete_check=True):
|
||||
unit = super().setup_class(complete_check=False)
|
||||
check = super().setup_class(complete_check=False)
|
||||
|
||||
TestFeatureIsolation().check(cls.available, unit.temp_dir)
|
||||
unit = unit_run()
|
||||
option.temp_dir = unit['temp_dir']
|
||||
|
||||
return unit if not complete_check else unit.complete()
|
||||
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):
|
||||
isolation_features = self.available['features']['isolation'].keys()
|
||||
isolation_features = option.available['features']['isolation'].keys()
|
||||
|
||||
if 'mnt' not in isolation_features:
|
||||
pytest.skip('requires mnt ns')
|
||||
@@ -48,7 +56,7 @@ class TestPHPIsolation(TestApplicationPHP):
|
||||
assert self.get()['status'] == 200, 'empty rootfs'
|
||||
|
||||
def test_php_isolation_rootfs_extensions(self, is_su):
|
||||
isolation_features = self.available['features']['isolation'].keys()
|
||||
isolation_features = option.available['features']['isolation'].keys()
|
||||
|
||||
if not is_su:
|
||||
if 'user' not in isolation_features:
|
||||
|
||||
@@ -5,7 +5,9 @@ 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
|
||||
|
||||
|
||||
@@ -60,10 +62,8 @@ Content-Length: 10
|
||||
return self.post(*args, http_10=True, **kwargs)
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
self.run_process(self.run_server, self.SERVER_PORT)
|
||||
self.waitforsocket(self.SERVER_PORT)
|
||||
run_process(self.run_server, self.SERVER_PORT)
|
||||
waitforsocket(self.SERVER_PORT)
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{
|
||||
@@ -346,8 +346,8 @@ Content-Length: 10
|
||||
|
||||
assert self.get_http10()['status'] == 200, 'status'
|
||||
|
||||
def test_proxy_unix(self):
|
||||
addr = self.temp_dir + '/sock'
|
||||
def test_proxy_unix(self, temp_dir):
|
||||
addr = temp_dir + '/sock'
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{
|
||||
|
||||
@@ -3,6 +3,9 @@ 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
|
||||
|
||||
|
||||
@@ -82,10 +85,8 @@ class TestProxyChunked(TestApplicationPython):
|
||||
return self.get(*args, http_10=True, **kwargs)
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
self.run_process(self.run_server, self.SERVER_PORT, self.temp_dir)
|
||||
self.waitforsocket(self.SERVER_PORT)
|
||||
run_process(self.run_server, self.SERVER_PORT, option.temp_dir)
|
||||
waitforsocket(self.SERVER_PORT)
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{
|
||||
|
||||
@@ -5,7 +5,9 @@ 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
|
||||
|
||||
|
||||
@@ -13,7 +15,7 @@ class TestPythonApplication(TestApplicationPython):
|
||||
prerequisites = {'modules': {'python': 'all'}}
|
||||
|
||||
def findall(self, pattern):
|
||||
with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f:
|
||||
with open(option.temp_dir + '/unit.log', 'r', errors='ignore') as f:
|
||||
return re.findall(pattern, f.read())
|
||||
|
||||
def test_python_application_variables(self):
|
||||
@@ -156,7 +158,7 @@ custom-header: BLAH
|
||||
|
||||
self.conf({"listeners": {}, "applications": {}})
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'RuntimeError') is not None
|
||||
@@ -344,7 +346,7 @@ Connection: close
|
||||
|
||||
self.conf({"listeners": {}, "applications": {}})
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert self.wait_for_record(r'At exit called\.') is not None, 'atexit'
|
||||
|
||||
@@ -507,7 +509,7 @@ last line: 987654321
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'\[error\].+Error in application\.')
|
||||
@@ -550,7 +552,7 @@ last line: 987654321
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert self.wait_for_record(r'Close called\.') is not None, 'close'
|
||||
|
||||
@@ -559,7 +561,7 @@ last line: 987654321
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'Close called\.') is not None
|
||||
@@ -570,7 +572,7 @@ last line: 987654321
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
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
|
||||
|
||||
@@ -7,18 +12,22 @@ from unit.feature.isolation import TestFeatureIsolation
|
||||
class TestPythonIsolation(TestApplicationPython):
|
||||
prerequisites = {'modules': {'python': 'any'}, 'features': ['isolation']}
|
||||
|
||||
isolation = TestFeatureIsolation()
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls, complete_check=True):
|
||||
unit = super().setup_class(complete_check=False)
|
||||
check = super().setup_class(complete_check=False)
|
||||
|
||||
TestFeatureIsolation().check(cls.available, unit.temp_dir)
|
||||
unit = unit_run()
|
||||
option.temp_dir = unit['temp_dir']
|
||||
|
||||
return unit if not complete_check else unit.complete()
|
||||
TestFeatureIsolation().check(option.available, unit['temp_dir'])
|
||||
|
||||
def test_python_isolation_rootfs(self, is_su):
|
||||
isolation_features = self.available['features']['isolation'].keys()
|
||||
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()
|
||||
|
||||
if 'mnt' not in isolation_features:
|
||||
pytest.skip('requires mnt ns')
|
||||
@@ -32,7 +41,7 @@ class TestPythonIsolation(TestApplicationPython):
|
||||
|
||||
isolation = {
|
||||
'namespaces': {'credential': not is_su, 'mount': True},
|
||||
'rootfs': self.temp_dir,
|
||||
'rootfs': temp_dir,
|
||||
}
|
||||
|
||||
self.load('empty', isolation=isolation)
|
||||
@@ -42,7 +51,7 @@ class TestPythonIsolation(TestApplicationPython):
|
||||
self.load('ns_inspect', isolation=isolation)
|
||||
|
||||
assert (
|
||||
self.getjson(url='/?path=' + self.temp_dir)['body']['FileExists']
|
||||
self.getjson(url='/?path=' + temp_dir)['body']['FileExists']
|
||||
== False
|
||||
), 'temp_dir does not exists in rootfs'
|
||||
|
||||
@@ -66,8 +75,8 @@ class TestPythonIsolation(TestApplicationPython):
|
||||
ret['body']['FileExists'] == True
|
||||
), 'application exists in rootfs'
|
||||
|
||||
def test_python_isolation_rootfs_no_language_deps(self, is_su):
|
||||
isolation_features = self.available['features']['isolation'].keys()
|
||||
def test_python_isolation_rootfs_no_language_deps(self, is_su, temp_dir):
|
||||
isolation_features = option.available['features']['isolation'].keys()
|
||||
|
||||
if 'mnt' not in isolation_features:
|
||||
pytest.skip('requires mnt ns')
|
||||
@@ -81,7 +90,7 @@ class TestPythonIsolation(TestApplicationPython):
|
||||
|
||||
isolation = {
|
||||
'namespaces': {'credential': not is_su, 'mount': True},
|
||||
'rootfs': self.temp_dir,
|
||||
'rootfs': temp_dir,
|
||||
'automount': {'language_deps': False}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ from unit.feature.isolation import TestFeatureIsolation
|
||||
class TestPythonIsolation(TestApplicationPython):
|
||||
prerequisites = {'modules': {'python': 'any'}}
|
||||
|
||||
def test_python_isolation_chroot(self, is_su):
|
||||
def test_python_isolation_chroot(self, is_su, temp_dir):
|
||||
if not is_su:
|
||||
pytest.skip('requires root')
|
||||
|
||||
isolation = {
|
||||
'rootfs': self.temp_dir,
|
||||
'rootfs': temp_dir,
|
||||
}
|
||||
|
||||
self.load('empty', isolation=isolation)
|
||||
@@ -22,7 +22,7 @@ class TestPythonIsolation(TestApplicationPython):
|
||||
self.load('ns_inspect', isolation=isolation)
|
||||
|
||||
assert (
|
||||
self.getjson(url='/?path=' + self.temp_dir)['body']['FileExists']
|
||||
self.getjson(url='/?path=' + temp_dir)['body']['FileExists']
|
||||
== False
|
||||
), 'temp_dir does not exists in rootfs'
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import time
|
||||
|
||||
import pytest
|
||||
|
||||
from conftest import option
|
||||
from unit.applications.lang.python import TestApplicationPython
|
||||
|
||||
|
||||
@@ -11,9 +12,7 @@ class TestPythonProcman(TestApplicationPython):
|
||||
prerequisites = {'modules': {'python': 'any'}}
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
self.app_name = "app-" + self.temp_dir.split('/')[-1]
|
||||
self.app_name = "app-" + option.temp_dir.split('/')[-1]
|
||||
self.app_proc = 'applications/' + self.app_name + '/processes'
|
||||
self.load('empty', self.app_name)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import re
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from conftest import option
|
||||
from conftest import skip_alert
|
||||
from unit.applications.lang.python import TestApplicationPython
|
||||
|
||||
@@ -13,9 +14,7 @@ class TestRespawn(TestApplicationPython):
|
||||
PATTERN_CONTROLLER = 'unit: controller'
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
self.app_name = "app-" + self.temp_dir.split('/')[-1]
|
||||
self.app_name = "app-" + option.temp_dir.split('/')[-1]
|
||||
|
||||
self.load('empty', self.app_name)
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ class TestReturn(TestApplicationProto):
|
||||
prerequisites = {}
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
self._load_conf(
|
||||
{
|
||||
"listeners": {"*:7080": {"pass": "routes"}},
|
||||
|
||||
@@ -10,8 +10,6 @@ class TestRouting(TestApplicationProto):
|
||||
prerequisites = {'modules': {'python': 'any'}}
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{
|
||||
"listeners": {"*:7080": {"pass": "routes"}},
|
||||
@@ -417,7 +415,7 @@ class TestRouting(TestApplicationProto):
|
||||
[{"action": {"pass": "upstreams/blah"}}], 'routes'
|
||||
), 'route pass upstreams invalid'
|
||||
|
||||
def test_routes_action_unique(self):
|
||||
def test_routes_action_unique(self, temp_dir):
|
||||
assert 'success' in self.conf(
|
||||
{
|
||||
"listeners": {
|
||||
@@ -437,7 +435,7 @@ class TestRouting(TestApplicationProto):
|
||||
)
|
||||
|
||||
assert 'error' in self.conf(
|
||||
{"proxy": "http://127.0.0.1:7081", "share": self.temp_dir},
|
||||
{"proxy": "http://127.0.0.1:7081", "share": temp_dir},
|
||||
'routes/0/action',
|
||||
), 'proxy share'
|
||||
assert 'error' in self.conf(
|
||||
@@ -445,7 +443,7 @@ class TestRouting(TestApplicationProto):
|
||||
'routes/0/action',
|
||||
), 'proxy pass'
|
||||
assert 'error' in self.conf(
|
||||
{"share": self.temp_dir, "pass": "applications/app"},
|
||||
{"share": temp_dir, "pass": "applications/app"},
|
||||
'routes/0/action',
|
||||
), 'share pass'
|
||||
|
||||
@@ -1665,8 +1663,8 @@ class TestRouting(TestApplicationProto):
|
||||
assert self.get(sock_type='ipv6')['status'] == 200, '0'
|
||||
assert self.get(port=7081)['status'] == 404, '0 ipv4'
|
||||
|
||||
def test_routes_source_unix(self):
|
||||
addr = self.temp_dir + '/sock'
|
||||
def test_routes_source_unix(self, temp_dir):
|
||||
addr = temp_dir + '/sock'
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{"unix:" + addr: {"pass": "routes"}}, 'listeners'
|
||||
|
||||
@@ -3,6 +3,7 @@ import re
|
||||
import pytest
|
||||
|
||||
from conftest import skip_alert
|
||||
from conftest import unit_stop
|
||||
from unit.applications.lang.ruby import TestApplicationRuby
|
||||
|
||||
|
||||
@@ -175,7 +176,7 @@ class TestRubyApplication(TestApplicationRuby):
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'\[error\].+Error in application')
|
||||
@@ -187,7 +188,7 @@ class TestRubyApplication(TestApplicationRuby):
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'\[error\].+1234567890') is not None
|
||||
@@ -198,7 +199,7 @@ class TestRubyApplication(TestApplicationRuby):
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'\[error\].+Error in application')
|
||||
@@ -215,7 +216,7 @@ class TestRubyApplication(TestApplicationRuby):
|
||||
|
||||
self.get()
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'\[error\].+1234567890') is not None
|
||||
@@ -228,7 +229,7 @@ class TestRubyApplication(TestApplicationRuby):
|
||||
|
||||
self.conf({"listeners": {}, "applications": {}})
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'\[error\].+At exit called\.') is not None
|
||||
@@ -289,7 +290,7 @@ class TestRubyApplication(TestApplicationRuby):
|
||||
|
||||
assert self.get()['status'] == 500, 'body each error status'
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'\[error\].+Failed to run ruby script')
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
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
|
||||
|
||||
@@ -9,18 +12,22 @@ from unit.feature.isolation import TestFeatureIsolation
|
||||
class TestRubyIsolation(TestApplicationRuby):
|
||||
prerequisites = {'modules': {'ruby': 'any'}, 'features': ['isolation']}
|
||||
|
||||
isolation = TestFeatureIsolation()
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls, complete_check=True):
|
||||
unit = super().setup_class(complete_check=False)
|
||||
check = super().setup_class(complete_check=False)
|
||||
|
||||
TestFeatureIsolation().check(cls.available, unit.temp_dir)
|
||||
unit = unit_run()
|
||||
option.temp_dir = unit['temp_dir']
|
||||
|
||||
return unit if not complete_check else unit.complete()
|
||||
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 = self.available['features']['isolation'].keys()
|
||||
isolation_features = option.available['features']['isolation'].keys()
|
||||
|
||||
if 'mnt' not in isolation_features:
|
||||
pytest.skip('requires mnt ns')
|
||||
|
||||
@@ -146,14 +146,14 @@ Connection: close
|
||||
|
||||
assert resp['status'] == 200, 'status body read timeout update'
|
||||
|
||||
def test_settings_send_timeout(self):
|
||||
def test_settings_send_timeout(self, temp_dir):
|
||||
self.load('mirror')
|
||||
|
||||
data_len = 1048576
|
||||
|
||||
self.conf({'http': {'send_timeout': 1}}, 'settings')
|
||||
|
||||
addr = self.temp_dir + '/sock'
|
||||
addr = temp_dir + '/sock'
|
||||
|
||||
self.conf({"unix:" + addr: {'application': 'mirror'}}, 'listeners')
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
|
||||
from conftest import option
|
||||
from conftest import skip_alert
|
||||
from unit.applications.proto import TestApplicationProto
|
||||
|
||||
@@ -8,14 +9,12 @@ class TestStatic(TestApplicationProto):
|
||||
prerequisites = {}
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
os.makedirs(self.temp_dir + '/assets/dir')
|
||||
with open(self.temp_dir + '/assets/index.html', 'w') as index:
|
||||
os.makedirs(option.temp_dir + '/assets/dir')
|
||||
with open(option.temp_dir + '/assets/index.html', 'w') as index:
|
||||
index.write('0123456789')
|
||||
|
||||
os.makedirs(self.temp_dir + '/assets/403')
|
||||
os.chmod(self.temp_dir + '/assets/403', 0o000)
|
||||
os.makedirs(option.temp_dir + '/assets/403')
|
||||
os.chmod(option.temp_dir + '/assets/403', 0o000)
|
||||
|
||||
self._load_conf(
|
||||
{
|
||||
@@ -23,15 +22,13 @@ class TestStatic(TestApplicationProto):
|
||||
"*:7080": {"pass": "routes"},
|
||||
"*:7081": {"pass": "routes"},
|
||||
},
|
||||
"routes": [{"action": {"share": self.temp_dir + "/assets"}}],
|
||||
"routes": [{"action": {"share": option.temp_dir + "/assets"}}],
|
||||
"applications": {},
|
||||
}
|
||||
)
|
||||
|
||||
def teardown_method(self):
|
||||
os.chmod(self.temp_dir + '/assets/403', 0o777)
|
||||
|
||||
super().teardown_method()
|
||||
os.chmod(option.temp_dir + '/assets/403', 0o777)
|
||||
|
||||
def action_update(self, conf):
|
||||
assert 'success' in self.conf(conf, 'routes/0/action')
|
||||
@@ -46,9 +43,9 @@ class TestStatic(TestApplicationProto):
|
||||
assert resp['status'] == 200, 'bad path fallback status'
|
||||
assert resp['body'] == '', 'bad path fallback'
|
||||
|
||||
def test_fallback_valid_path(self):
|
||||
def test_fallback_valid_path(self, temp_dir):
|
||||
self.action_update(
|
||||
{"share": self.temp_dir + "/assets", "fallback": {"return": 200}}
|
||||
{"share": temp_dir + "/assets", "fallback": {"return": 200}}
|
||||
)
|
||||
resp = self.get()
|
||||
assert resp['status'] == 200, 'fallback status'
|
||||
@@ -79,11 +76,11 @@ class TestStatic(TestApplicationProto):
|
||||
assert resp['status'] == 200, 'fallback nested status'
|
||||
assert resp['body'] == '', 'fallback nested'
|
||||
|
||||
def test_fallback_share(self):
|
||||
def test_fallback_share(self, temp_dir):
|
||||
self.action_update(
|
||||
{
|
||||
"share": "/blah",
|
||||
"fallback": {"share": self.temp_dir + "/assets"},
|
||||
"fallback": {"share": temp_dir + "/assets"},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import socket
|
||||
|
||||
import pytest
|
||||
|
||||
from conftest import option
|
||||
from conftest import waitforfiles
|
||||
from unit.applications.proto import TestApplicationProto
|
||||
|
||||
@@ -11,13 +12,13 @@ class TestStatic(TestApplicationProto):
|
||||
prerequisites = {}
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
os.makedirs(self.temp_dir + '/assets/dir')
|
||||
with open(self.temp_dir + '/assets/index.html', 'w') as index, open(
|
||||
self.temp_dir + '/assets/README', 'w'
|
||||
) as readme, open(self.temp_dir + '/assets/log.log', 'w') as log, open(
|
||||
self.temp_dir + '/assets/dir/file', 'w'
|
||||
os.makedirs(option.temp_dir + '/assets/dir')
|
||||
with open(option.temp_dir + '/assets/index.html', 'w') as index, open(
|
||||
option.temp_dir + '/assets/README', 'w'
|
||||
) as readme, open(
|
||||
option.temp_dir + '/assets/log.log', 'w'
|
||||
) as log, open(
|
||||
option.temp_dir + '/assets/dir/file', 'w'
|
||||
) as file:
|
||||
index.write('0123456789')
|
||||
readme.write('readme')
|
||||
@@ -27,7 +28,7 @@ class TestStatic(TestApplicationProto):
|
||||
self._load_conf(
|
||||
{
|
||||
"listeners": {"*:7080": {"pass": "routes"}},
|
||||
"routes": [{"action": {"share": self.temp_dir + "/assets"}}],
|
||||
"routes": [{"action": {"share": option.temp_dir + "/assets"}}],
|
||||
"settings": {
|
||||
"http": {
|
||||
"static": {
|
||||
@@ -54,9 +55,9 @@ class TestStatic(TestApplicationProto):
|
||||
resp['headers']['Content-Type'] == 'text/html'
|
||||
), 'index not found 2 Content-Type'
|
||||
|
||||
def test_static_large_file(self):
|
||||
def test_static_large_file(self, temp_dir):
|
||||
file_size = 32 * 1024 * 1024
|
||||
with open(self.temp_dir + '/assets/large', 'wb') as f:
|
||||
with open(temp_dir + '/assets/large', 'wb') as f:
|
||||
f.seek(file_size - 1)
|
||||
f.write(b'\0')
|
||||
|
||||
@@ -65,14 +66,14 @@ class TestStatic(TestApplicationProto):
|
||||
== file_size
|
||||
), 'large file'
|
||||
|
||||
def test_static_etag(self):
|
||||
def test_static_etag(self, temp_dir):
|
||||
etag = self.get(url='/')['headers']['ETag']
|
||||
etag_2 = self.get(url='/README')['headers']['ETag']
|
||||
|
||||
assert etag != etag_2, 'different ETag'
|
||||
assert etag == self.get(url='/')['headers']['ETag'], 'same ETag'
|
||||
|
||||
with open(self.temp_dir + '/assets/index.html', 'w') as f:
|
||||
with open(temp_dir + '/assets/index.html', 'w') as f:
|
||||
f.write('blah')
|
||||
|
||||
assert etag != self.get(url='/')['headers']['ETag'], 'new ETag'
|
||||
@@ -83,22 +84,22 @@ class TestStatic(TestApplicationProto):
|
||||
assert resp['headers']['Location'] == '/dir/', 'redirect Location'
|
||||
assert 'Content-Type' not in resp['headers'], 'redirect Content-Type'
|
||||
|
||||
def test_static_space_in_name(self):
|
||||
def test_static_space_in_name(self, temp_dir):
|
||||
os.rename(
|
||||
self.temp_dir + '/assets/dir/file',
|
||||
self.temp_dir + '/assets/dir/fi le',
|
||||
temp_dir + '/assets/dir/file',
|
||||
temp_dir + '/assets/dir/fi le',
|
||||
)
|
||||
assert waitforfiles(self.temp_dir + '/assets/dir/fi le')
|
||||
assert waitforfiles(temp_dir + '/assets/dir/fi le')
|
||||
assert self.get(url='/dir/fi le')['body'] == 'blah', 'file name'
|
||||
|
||||
os.rename(self.temp_dir + '/assets/dir', self.temp_dir + '/assets/di r')
|
||||
assert waitforfiles(self.temp_dir + '/assets/di r/fi le')
|
||||
os.rename(temp_dir + '/assets/dir', temp_dir + '/assets/di r')
|
||||
assert waitforfiles(temp_dir + '/assets/di r/fi le')
|
||||
assert self.get(url='/di r/fi le')['body'] == 'blah', 'dir name'
|
||||
|
||||
os.rename(
|
||||
self.temp_dir + '/assets/di r', self.temp_dir + '/assets/ di r '
|
||||
temp_dir + '/assets/di r', temp_dir + '/assets/ di r '
|
||||
)
|
||||
assert waitforfiles(self.temp_dir + '/assets/ di r /fi le')
|
||||
assert waitforfiles(temp_dir + '/assets/ di r /fi le')
|
||||
assert (
|
||||
self.get(url='/ di r /fi le')['body'] == 'blah'
|
||||
), 'dir name enclosing'
|
||||
@@ -121,16 +122,16 @@ class TestStatic(TestApplicationProto):
|
||||
), 'encoded 2'
|
||||
|
||||
os.rename(
|
||||
self.temp_dir + '/assets/ di r /fi le',
|
||||
self.temp_dir + '/assets/ di r / fi le ',
|
||||
temp_dir + '/assets/ di r /fi le',
|
||||
temp_dir + '/assets/ di r / fi le ',
|
||||
)
|
||||
assert waitforfiles(self.temp_dir + '/assets/ di r / fi le ')
|
||||
assert waitforfiles(temp_dir + '/assets/ di r / fi le ')
|
||||
assert (
|
||||
self.get(url='/%20di%20r%20/%20fi%20le%20')['body'] == 'blah'
|
||||
), 'file name enclosing'
|
||||
|
||||
try:
|
||||
open(self.temp_dir + '/ф а', 'a').close()
|
||||
open(temp_dir + '/ф а', 'a').close()
|
||||
utf8 = True
|
||||
|
||||
except:
|
||||
@@ -138,38 +139,38 @@ class TestStatic(TestApplicationProto):
|
||||
|
||||
if utf8:
|
||||
os.rename(
|
||||
self.temp_dir + '/assets/ di r / fi le ',
|
||||
self.temp_dir + '/assets/ di r /фа йл',
|
||||
temp_dir + '/assets/ di r / fi le ',
|
||||
temp_dir + '/assets/ di r /фа йл',
|
||||
)
|
||||
assert waitforfiles(self.temp_dir + '/assets/ di r /фа йл')
|
||||
assert waitforfiles(temp_dir + '/assets/ di r /фа йл')
|
||||
assert (
|
||||
self.get(url='/ di r /фа йл')['body'] == 'blah'
|
||||
), 'file name 2'
|
||||
|
||||
os.rename(
|
||||
self.temp_dir + '/assets/ di r ',
|
||||
self.temp_dir + '/assets/ди ректория',
|
||||
temp_dir + '/assets/ di r ',
|
||||
temp_dir + '/assets/ди ректория',
|
||||
)
|
||||
assert waitforfiles(self.temp_dir + '/assets/ди ректория/фа йл')
|
||||
assert waitforfiles(temp_dir + '/assets/ди ректория/фа йл')
|
||||
assert (
|
||||
self.get(url='/ди ректория/фа йл')['body'] == 'blah'
|
||||
), 'dir name 2'
|
||||
|
||||
def test_static_unix_socket(self):
|
||||
def test_static_unix_socket(self, temp_dir):
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
sock.bind(self.temp_dir + '/assets/unix_socket')
|
||||
sock.bind(temp_dir + '/assets/unix_socket')
|
||||
|
||||
assert self.get(url='/unix_socket')['status'] == 404, 'socket'
|
||||
|
||||
sock.close()
|
||||
|
||||
def test_static_unix_fifo(self):
|
||||
os.mkfifo(self.temp_dir + '/assets/fifo')
|
||||
def test_static_unix_fifo(self, temp_dir):
|
||||
os.mkfifo(temp_dir + '/assets/fifo')
|
||||
|
||||
assert self.get(url='/fifo')['status'] == 404, 'fifo'
|
||||
|
||||
def test_static_symlink(self):
|
||||
os.symlink(self.temp_dir + '/assets/dir', self.temp_dir + '/assets/link')
|
||||
def test_static_symlink(self, temp_dir):
|
||||
os.symlink(temp_dir + '/assets/dir', temp_dir + '/assets/link')
|
||||
|
||||
assert self.get(url='/dir')['status'] == 301, 'dir'
|
||||
assert self.get(url='/dir/file')['status'] == 200, 'file'
|
||||
@@ -312,7 +313,7 @@ class TestStatic(TestApplicationProto):
|
||||
), 'mime_types same extensions case insensitive'
|
||||
|
||||
@pytest.mark.skip('not yet')
|
||||
def test_static_mime_types_invalid(self):
|
||||
def test_static_mime_types_invalid(self, temp_dir):
|
||||
assert 'error' in self.http(
|
||||
b"""PUT /config/settings/http/static/mime_types/%0%00% HTTP/1.1\r
|
||||
Host: localhost\r
|
||||
@@ -323,5 +324,5 @@ Content-Length: 6\r
|
||||
raw_resp=True,
|
||||
raw=True,
|
||||
sock_type='unix',
|
||||
addr=self.temp_dir + '/control.unit.sock',
|
||||
addr=temp_dir + '/control.unit.sock',
|
||||
), 'mime_types invalid'
|
||||
|
||||
@@ -5,6 +5,7 @@ import subprocess
|
||||
|
||||
import pytest
|
||||
|
||||
from conftest import option
|
||||
from conftest import skip_alert
|
||||
from unit.applications.tls import TestApplicationTLS
|
||||
|
||||
@@ -13,7 +14,7 @@ class TestTLS(TestApplicationTLS):
|
||||
prerequisites = {'modules': {'python': 'any', 'openssl': 'any'}}
|
||||
|
||||
def findall(self, pattern):
|
||||
with open(self.temp_dir + '/unit.log', 'r', errors='ignore') as f:
|
||||
with open(option.temp_dir + '/unit.log', 'r', errors='ignore') as f:
|
||||
return re.findall(pattern, f.read())
|
||||
|
||||
def openssl_date_to_sec_epoch(self, date):
|
||||
@@ -134,7 +135,7 @@ class TestTLS(TestApplicationTLS):
|
||||
self.conf_get('/certificates/default/key') == 'RSA (2048 bits)'
|
||||
), 'certificate key rsa'
|
||||
|
||||
def test_tls_certificate_key_ec(self):
|
||||
def test_tls_certificate_key_ec(self, temp_dir):
|
||||
self.load('empty')
|
||||
|
||||
self.openssl_conf()
|
||||
@@ -146,7 +147,7 @@ class TestTLS(TestApplicationTLS):
|
||||
'-noout',
|
||||
'-genkey',
|
||||
'-out',
|
||||
self.temp_dir + '/ec.key',
|
||||
temp_dir + '/ec.key',
|
||||
'-name',
|
||||
'prime256v1',
|
||||
],
|
||||
@@ -162,11 +163,11 @@ class TestTLS(TestApplicationTLS):
|
||||
'-subj',
|
||||
'/CN=ec/',
|
||||
'-config',
|
||||
self.temp_dir + '/openssl.conf',
|
||||
temp_dir + '/openssl.conf',
|
||||
'-key',
|
||||
self.temp_dir + '/ec.key',
|
||||
temp_dir + '/ec.key',
|
||||
'-out',
|
||||
self.temp_dir + '/ec.crt',
|
||||
temp_dir + '/ec.crt',
|
||||
],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
@@ -208,7 +209,7 @@ class TestTLS(TestApplicationTLS):
|
||||
== 2592000
|
||||
), 'certificate validity until'
|
||||
|
||||
def test_tls_certificate_chain(self):
|
||||
def test_tls_certificate_chain(self, temp_dir):
|
||||
self.load('empty')
|
||||
|
||||
self.certificate('root', False)
|
||||
@@ -221,11 +222,11 @@ class TestTLS(TestApplicationTLS):
|
||||
'-subj',
|
||||
'/CN=int/',
|
||||
'-config',
|
||||
self.temp_dir + '/openssl.conf',
|
||||
temp_dir + '/openssl.conf',
|
||||
'-out',
|
||||
self.temp_dir + '/int.csr',
|
||||
temp_dir + '/int.csr',
|
||||
'-keyout',
|
||||
self.temp_dir + '/int.key',
|
||||
temp_dir + '/int.key',
|
||||
],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
@@ -238,16 +239,16 @@ class TestTLS(TestApplicationTLS):
|
||||
'-subj',
|
||||
'/CN=end/',
|
||||
'-config',
|
||||
self.temp_dir + '/openssl.conf',
|
||||
temp_dir + '/openssl.conf',
|
||||
'-out',
|
||||
self.temp_dir + '/end.csr',
|
||||
temp_dir + '/end.csr',
|
||||
'-keyout',
|
||||
self.temp_dir + '/end.key',
|
||||
temp_dir + '/end.key',
|
||||
],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
|
||||
with open(self.temp_dir + '/ca.conf', 'w') as f:
|
||||
with open(temp_dir + '/ca.conf', 'w') as f:
|
||||
f.write(
|
||||
"""[ ca ]
|
||||
default_ca = myca
|
||||
@@ -267,16 +268,16 @@ commonName = supplied
|
||||
[ myca_extensions ]
|
||||
basicConstraints = critical,CA:TRUE"""
|
||||
% {
|
||||
'dir': self.temp_dir,
|
||||
'database': self.temp_dir + '/certindex',
|
||||
'certserial': self.temp_dir + '/certserial',
|
||||
'dir': temp_dir,
|
||||
'database': temp_dir + '/certindex',
|
||||
'certserial': temp_dir + '/certserial',
|
||||
}
|
||||
)
|
||||
|
||||
with open(self.temp_dir + '/certserial', 'w') as f:
|
||||
with open(temp_dir + '/certserial', 'w') as f:
|
||||
f.write('1000')
|
||||
|
||||
with open(self.temp_dir + '/certindex', 'w') as f:
|
||||
with open(temp_dir + '/certindex', 'w') as f:
|
||||
f.write('')
|
||||
|
||||
subprocess.call(
|
||||
@@ -287,15 +288,15 @@ basicConstraints = critical,CA:TRUE"""
|
||||
'-subj',
|
||||
'/CN=int/',
|
||||
'-config',
|
||||
self.temp_dir + '/ca.conf',
|
||||
temp_dir + '/ca.conf',
|
||||
'-keyfile',
|
||||
self.temp_dir + '/root.key',
|
||||
temp_dir + '/root.key',
|
||||
'-cert',
|
||||
self.temp_dir + '/root.crt',
|
||||
temp_dir + '/root.crt',
|
||||
'-in',
|
||||
self.temp_dir + '/int.csr',
|
||||
temp_dir + '/int.csr',
|
||||
'-out',
|
||||
self.temp_dir + '/int.crt',
|
||||
temp_dir + '/int.crt',
|
||||
],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
@@ -308,22 +309,22 @@ basicConstraints = critical,CA:TRUE"""
|
||||
'-subj',
|
||||
'/CN=end/',
|
||||
'-config',
|
||||
self.temp_dir + '/ca.conf',
|
||||
temp_dir + '/ca.conf',
|
||||
'-keyfile',
|
||||
self.temp_dir + '/int.key',
|
||||
temp_dir + '/int.key',
|
||||
'-cert',
|
||||
self.temp_dir + '/int.crt',
|
||||
temp_dir + '/int.crt',
|
||||
'-in',
|
||||
self.temp_dir + '/end.csr',
|
||||
temp_dir + '/end.csr',
|
||||
'-out',
|
||||
self.temp_dir + '/end.crt',
|
||||
temp_dir + '/end.crt',
|
||||
],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
|
||||
crt_path = self.temp_dir + '/end-int.crt'
|
||||
end_path = self.temp_dir + '/end.crt'
|
||||
int_path = self.temp_dir + '/int.crt'
|
||||
crt_path = temp_dir + '/end-int.crt'
|
||||
end_path = temp_dir + '/end.crt'
|
||||
int_path = temp_dir + '/int.crt'
|
||||
|
||||
with open(crt_path, 'wb') as crt, open(end_path, 'rb') as end, open(
|
||||
int_path, 'rb'
|
||||
@@ -333,7 +334,7 @@ basicConstraints = critical,CA:TRUE"""
|
||||
self.context = ssl.create_default_context()
|
||||
self.context.check_hostname = False
|
||||
self.context.verify_mode = ssl.CERT_REQUIRED
|
||||
self.context.load_verify_locations(self.temp_dir + '/root.crt')
|
||||
self.context.load_verify_locations(temp_dir + '/root.crt')
|
||||
|
||||
# incomplete chain
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ class TestUpstreamsRR(TestApplicationPython):
|
||||
prerequisites = {'modules': {'python': 'any'}}
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{
|
||||
"listeners": {
|
||||
@@ -391,9 +389,9 @@ Connection: close
|
||||
assert sum(resps) == 100, 'post sum'
|
||||
assert abs(resps[0] - resps[1]) <= self.cpu_count, 'post'
|
||||
|
||||
def test_upstreams_rr_unix(self):
|
||||
addr_0 = self.temp_dir + '/sock_0'
|
||||
addr_1 = self.temp_dir + '/sock_1'
|
||||
def test_upstreams_rr_unix(self, temp_dir):
|
||||
addr_0 = temp_dir + '/sock_0'
|
||||
addr_1 = temp_dir + '/sock_1'
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
from subprocess import call
|
||||
|
||||
from conftest import unit_stop
|
||||
from conftest import waitforfiles
|
||||
from unit.applications.lang.python import TestApplicationPython
|
||||
|
||||
@@ -8,12 +9,12 @@ from unit.applications.lang.python import TestApplicationPython
|
||||
class TestUSR1(TestApplicationPython):
|
||||
prerequisites = {'modules': {'python': 'any'}}
|
||||
|
||||
def test_usr1_access_log(self):
|
||||
def test_usr1_access_log(self, temp_dir):
|
||||
self.load('empty')
|
||||
|
||||
log = 'access.log'
|
||||
log_new = 'new.log'
|
||||
log_path = self.temp_dir + '/' + log
|
||||
log_path = temp_dir + '/' + log
|
||||
|
||||
assert 'success' in self.conf(
|
||||
'"' + log_path + '"', 'access_log'
|
||||
@@ -21,7 +22,7 @@ class TestUSR1(TestApplicationPython):
|
||||
|
||||
assert waitforfiles(log_path), 'open'
|
||||
|
||||
os.rename(log_path, self.temp_dir + '/' + log_new)
|
||||
os.rename(log_path, temp_dir + '/' + log_new)
|
||||
|
||||
assert self.get()['status'] == 200
|
||||
|
||||
@@ -31,7 +32,7 @@ class TestUSR1(TestApplicationPython):
|
||||
), 'rename new'
|
||||
assert not os.path.isfile(log_path), 'rename old'
|
||||
|
||||
with open(self.temp_dir + '/unit.pid', 'r') as f:
|
||||
with open(temp_dir + '/unit.pid', 'r') as f:
|
||||
pid = f.read().rstrip()
|
||||
|
||||
call(['kill', '-s', 'USR1', pid])
|
||||
@@ -40,7 +41,7 @@ class TestUSR1(TestApplicationPython):
|
||||
|
||||
assert self.get(url='/usr1')['status'] == 200
|
||||
|
||||
self.stop()
|
||||
unit_stop()
|
||||
|
||||
assert (
|
||||
self.wait_for_record(r'"GET /usr1 HTTP/1.1" 200 0 "-" "-"', log)
|
||||
@@ -48,12 +49,12 @@ class TestUSR1(TestApplicationPython):
|
||||
), 'reopen 2'
|
||||
assert self.search_in_log(r'/usr1', log_new) is None, 'rename new 2'
|
||||
|
||||
def test_usr1_unit_log(self):
|
||||
def test_usr1_unit_log(self, temp_dir):
|
||||
self.load('log_body')
|
||||
|
||||
log_new = 'new.log'
|
||||
log_path = self.temp_dir + '/unit.log'
|
||||
log_path_new = self.temp_dir + '/' + log_new
|
||||
log_path = temp_dir + '/unit.log'
|
||||
log_path_new = temp_dir + '/' + log_new
|
||||
|
||||
os.rename(log_path, log_path_new)
|
||||
|
||||
@@ -63,7 +64,7 @@ class TestUSR1(TestApplicationPython):
|
||||
assert self.wait_for_record(body, log_new) is not None, 'rename new'
|
||||
assert not os.path.isfile(log_path), 'rename old'
|
||||
|
||||
with open(self.temp_dir + '/unit.pid', 'r') as f:
|
||||
with open(temp_dir + '/unit.pid', 'r') as f:
|
||||
pid = f.read().rstrip()
|
||||
|
||||
call(['kill', '-s', 'USR1', pid])
|
||||
@@ -73,7 +74,7 @@ class TestUSR1(TestApplicationPython):
|
||||
body = 'body_for_a_log_unit'
|
||||
assert self.post(body=body)['status'] == 200
|
||||
|
||||
self.stop()
|
||||
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'
|
||||
|
||||
@@ -5,8 +5,6 @@ class TestVariables(TestApplicationProto):
|
||||
prerequisites = {}
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
assert 'success' in self.conf(
|
||||
{
|
||||
"listeners": {"*:7080": {"pass": "routes/$method"}},
|
||||
|
||||
@@ -7,8 +7,8 @@ from unit.applications.proto import TestApplicationProto
|
||||
|
||||
class TestApplicationGo(TestApplicationProto):
|
||||
def prepare_env(self, script, name, static=False):
|
||||
if not os.path.exists(self.temp_dir + '/go'):
|
||||
os.mkdir(self.temp_dir + '/go')
|
||||
if not os.path.exists(option.temp_dir + '/go'):
|
||||
os.mkdir(option.temp_dir + '/go')
|
||||
|
||||
env = os.environ.copy()
|
||||
env['GOPATH'] = option.current_dir + '/build/go'
|
||||
@@ -22,7 +22,7 @@ class TestApplicationGo(TestApplicationProto):
|
||||
'-ldflags',
|
||||
'-extldflags "-static"',
|
||||
'-o',
|
||||
self.temp_dir + '/go/' + name,
|
||||
option.temp_dir + '/go/' + name,
|
||||
option.test_dir + '/go/' + script + '/' + name + '.go',
|
||||
]
|
||||
else:
|
||||
@@ -30,7 +30,7 @@ class TestApplicationGo(TestApplicationProto):
|
||||
'go',
|
||||
'build',
|
||||
'-o',
|
||||
self.temp_dir + '/go/' + name,
|
||||
option.temp_dir + '/go/' + name,
|
||||
option.test_dir + '/go/' + script + '/' + name + '.go',
|
||||
]
|
||||
|
||||
@@ -47,7 +47,7 @@ class TestApplicationGo(TestApplicationProto):
|
||||
static_build = False
|
||||
|
||||
wdir = option.test_dir + "/go/" + script
|
||||
executable = self.temp_dir + "/go/" + name
|
||||
executable = option.temp_dir + "/go/" + name
|
||||
|
||||
if 'isolation' in kwargs and 'rootfs' in kwargs['isolation']:
|
||||
wdir = "/go/"
|
||||
|
||||
@@ -10,7 +10,7 @@ from unit.applications.proto import TestApplicationProto
|
||||
|
||||
class TestApplicationJava(TestApplicationProto):
|
||||
def load(self, script, name='app', **kwargs):
|
||||
app_path = self.temp_dir + '/java'
|
||||
app_path = option.temp_dir + '/java'
|
||||
web_inf_path = app_path + '/WEB-INF/'
|
||||
classes_path = web_inf_path + 'classes/'
|
||||
script_path = option.test_dir + '/java/' + script + '/'
|
||||
|
||||
@@ -11,17 +11,17 @@ class TestApplicationNode(TestApplicationProto):
|
||||
# copy application
|
||||
|
||||
shutil.copytree(
|
||||
option.test_dir + '/node/' + script, self.temp_dir + '/node'
|
||||
option.test_dir + '/node/' + script, option.temp_dir + '/node'
|
||||
)
|
||||
|
||||
# copy modules
|
||||
|
||||
shutil.copytree(
|
||||
option.current_dir + '/node/node_modules',
|
||||
self.temp_dir + '/node/node_modules',
|
||||
option.temp_dir + '/node/node_modules',
|
||||
)
|
||||
|
||||
public_dir(self.temp_dir + '/node')
|
||||
public_dir(option.temp_dir + '/node')
|
||||
|
||||
self._load_conf(
|
||||
{
|
||||
@@ -32,7 +32,7 @@ class TestApplicationNode(TestApplicationProto):
|
||||
script: {
|
||||
"type": "external",
|
||||
"processes": {"spare": 0},
|
||||
"working_directory": self.temp_dir + '/node',
|
||||
"working_directory": option.temp_dir + '/node',
|
||||
"executable": name,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,7 +12,6 @@ class TestApplicationPython(TestApplicationProto):
|
||||
load_module = "wsgi"
|
||||
|
||||
def load(self, script, name=None, module=None, **kwargs):
|
||||
print()
|
||||
if name is None:
|
||||
name = script
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class TestApplicationProto(TestControl):
|
||||
return time.mktime(time.strptime(date, template))
|
||||
|
||||
def search_in_log(self, pattern, name='unit.log'):
|
||||
with open(self.temp_dir + '/' + name, 'r', errors='ignore') as f:
|
||||
with open(option.temp_dir + '/' + name, 'r', errors='ignore') as f:
|
||||
return re.search(pattern, f.read())
|
||||
|
||||
def wait_for_record(self, pattern, name='unit.log'):
|
||||
|
||||
@@ -8,8 +8,6 @@ from unit.applications.proto import TestApplicationProto
|
||||
|
||||
class TestApplicationTLS(TestApplicationProto):
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
|
||||
self.context = ssl.create_default_context()
|
||||
self.context.check_hostname = False
|
||||
self.context.verify_mode = ssl.CERT_NONE
|
||||
@@ -24,9 +22,9 @@ class TestApplicationTLS(TestApplicationProto):
|
||||
'-x509',
|
||||
'-new',
|
||||
'-subj', '/CN=' + name + '/',
|
||||
'-config', self.temp_dir + '/openssl.conf',
|
||||
'-out', self.temp_dir + '/' + name + '.crt',
|
||||
'-keyout', self.temp_dir + '/' + name + '.key',
|
||||
'-config', option.temp_dir + '/openssl.conf',
|
||||
'-out', option.temp_dir + '/' + name + '.crt',
|
||||
'-keyout', option.temp_dir + '/' + name + '.key',
|
||||
],
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
@@ -38,8 +36,8 @@ class TestApplicationTLS(TestApplicationProto):
|
||||
if key is None:
|
||||
key = crt
|
||||
|
||||
key_path = self.temp_dir + '/' + key + '.key'
|
||||
crt_path = self.temp_dir + '/' + crt + '.crt'
|
||||
key_path = option.temp_dir + '/' + key + '.key'
|
||||
crt_path = option.temp_dir + '/' + crt + '.crt'
|
||||
|
||||
with open(key_path, 'rb') as k, open(crt_path, 'rb') as c:
|
||||
return self.conf(k.read() + c.read(), '/certificates/' + crt)
|
||||
@@ -66,7 +64,7 @@ class TestApplicationTLS(TestApplicationProto):
|
||||
return ssl.get_server_certificate(addr, ssl_version=ssl_version)
|
||||
|
||||
def openssl_conf(self):
|
||||
conf_path = self.temp_dir + '/openssl.conf'
|
||||
conf_path = option.temp_dir + '/openssl.conf'
|
||||
|
||||
if os.path.exists(conf_path):
|
||||
return
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
|
||||
from conftest import option
|
||||
from unit.http import TestHTTP
|
||||
|
||||
|
||||
@@ -53,7 +54,7 @@ class TestControl(TestHTTP):
|
||||
args = {
|
||||
'url': url,
|
||||
'sock_type': 'unix',
|
||||
'addr': self.temp_dir + '/control.unit.sock',
|
||||
'addr': option.temp_dir + '/control.unit.sock',
|
||||
}
|
||||
|
||||
if conf is not None:
|
||||
|
||||
@@ -21,6 +21,16 @@ class TestFeatureIsolation(TestApplicationProto):
|
||||
if 'go' in available['modules']:
|
||||
module = TestApplicationGo()
|
||||
|
||||
elif 'python' in available['modules']:
|
||||
module = TestApplicationPython()
|
||||
|
||||
elif 'php' in available['modules']:
|
||||
module = TestApplicationPHP()
|
||||
app = 'phpinfo'
|
||||
|
||||
elif 'ruby' in available['modules']:
|
||||
module = TestApplicationRuby()
|
||||
|
||||
elif 'java' in available['modules']:
|
||||
module = TestApplicationJava()
|
||||
|
||||
@@ -32,16 +42,6 @@ class TestFeatureIsolation(TestApplicationProto):
|
||||
module = TestApplicationPerl()
|
||||
app = 'body_empty'
|
||||
|
||||
elif 'php' in available['modules']:
|
||||
module = TestApplicationPHP()
|
||||
app = 'phpinfo'
|
||||
|
||||
elif 'python' in available['modules']:
|
||||
module = TestApplicationPython()
|
||||
|
||||
elif 'ruby' in available['modules']:
|
||||
module = TestApplicationRuby()
|
||||
|
||||
if not module:
|
||||
return
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import os
|
||||
import re
|
||||
import select
|
||||
import socket
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from conftest import option
|
||||
@@ -283,23 +282,6 @@ class TestHTTP(TestUnit):
|
||||
def getjson(self, **kwargs):
|
||||
return self.get(json=True, **kwargs)
|
||||
|
||||
def waitforsocket(self, 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:
|
||||
sock.close()
|
||||
time.sleep(0.1)
|
||||
|
||||
sock.close()
|
||||
|
||||
assert ret, 'socket connected'
|
||||
|
||||
def form_encode(self, fields):
|
||||
is_multipart = False
|
||||
|
||||
|
||||
@@ -1,55 +1,19 @@
|
||||
import atexit
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import stat
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
from multiprocessing import Process
|
||||
|
||||
import pytest
|
||||
from conftest import _check_alerts
|
||||
from conftest import _print_log
|
||||
from conftest import option
|
||||
from conftest import public_dir
|
||||
from conftest import waitforfiles
|
||||
|
||||
|
||||
class TestUnit():
|
||||
@classmethod
|
||||
def setup_class(cls, complete_check=True):
|
||||
cls.available = option.available
|
||||
unit = TestUnit()
|
||||
|
||||
unit._run()
|
||||
|
||||
# read unit.log
|
||||
|
||||
for i in range(50):
|
||||
with open(unit.temp_dir + '/unit.log', 'r') as f:
|
||||
log = f.read()
|
||||
m = re.search('controller started', log)
|
||||
|
||||
if m is None:
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
break
|
||||
|
||||
if m is None:
|
||||
_print_log(path=unit.temp_dir + '/unit.log')
|
||||
exit("Unit is writing log too long")
|
||||
|
||||
def check(available, prerequisites):
|
||||
def check():
|
||||
missed = []
|
||||
|
||||
# check modules
|
||||
|
||||
if 'modules' in prerequisites:
|
||||
available_modules = list(available['modules'].keys())
|
||||
if 'modules' in cls.prerequisites:
|
||||
available_modules = list(option.available['modules'].keys())
|
||||
|
||||
for module in prerequisites['modules']:
|
||||
for module in cls.prerequisites['modules']:
|
||||
if module in available_modules:
|
||||
continue
|
||||
|
||||
@@ -60,10 +24,10 @@ class TestUnit():
|
||||
|
||||
# check features
|
||||
|
||||
if 'features' in prerequisites:
|
||||
available_features = list(available['features'].keys())
|
||||
if 'features' in cls.prerequisites:
|
||||
available_features = list(option.available['features'].keys())
|
||||
|
||||
for feature in prerequisites['features']:
|
||||
for feature in cls.prerequisites['features']:
|
||||
if feature in available_features:
|
||||
continue
|
||||
|
||||
@@ -72,132 +36,7 @@ class TestUnit():
|
||||
if missed:
|
||||
pytest.skip(', '.join(missed) + ' feature(s) not supported')
|
||||
|
||||
def destroy():
|
||||
unit.stop()
|
||||
_check_alerts(log)
|
||||
shutil.rmtree(unit.temp_dir)
|
||||
|
||||
def complete():
|
||||
destroy()
|
||||
check(cls.available, cls.prerequisites)
|
||||
|
||||
if complete_check:
|
||||
complete()
|
||||
check()
|
||||
else:
|
||||
unit.complete = complete
|
||||
return unit
|
||||
|
||||
def setup_method(self):
|
||||
self._run()
|
||||
|
||||
def _run(self):
|
||||
build_dir = option.current_dir + '/build'
|
||||
self.unitd = build_dir + '/unitd'
|
||||
|
||||
if not os.path.isfile(self.unitd):
|
||||
exit("Could not find unit")
|
||||
|
||||
self.temp_dir = tempfile.mkdtemp(prefix='unit-test-')
|
||||
|
||||
public_dir(self.temp_dir)
|
||||
|
||||
if oct(stat.S_IMODE(os.stat(build_dir).st_mode)) != '0o777':
|
||||
public_dir(build_dir)
|
||||
|
||||
os.mkdir(self.temp_dir + '/state')
|
||||
|
||||
with open(self.temp_dir + '/unit.log', 'w') as log:
|
||||
self._p = subprocess.Popen(
|
||||
[
|
||||
self.unitd,
|
||||
'--no-daemon',
|
||||
'--modules', build_dir,
|
||||
'--state', self.temp_dir + '/state',
|
||||
'--pid', self.temp_dir + '/unit.pid',
|
||||
'--log', self.temp_dir + '/unit.log',
|
||||
'--control', 'unix:' + self.temp_dir + '/control.unit.sock',
|
||||
'--tmp', self.temp_dir,
|
||||
],
|
||||
stderr=log,
|
||||
)
|
||||
|
||||
atexit.register(self.stop)
|
||||
|
||||
if not waitforfiles(self.temp_dir + '/control.unit.sock'):
|
||||
_print_log(path=self.temp_dir + '/unit.log')
|
||||
exit("Could not start unit")
|
||||
|
||||
self._started = True
|
||||
|
||||
def teardown_method(self):
|
||||
self.stop()
|
||||
|
||||
# check unit.log for alerts
|
||||
|
||||
unit_log = self.temp_dir + '/unit.log'
|
||||
|
||||
with open(unit_log, 'r', encoding='utf-8', errors='ignore') as f:
|
||||
_check_alerts(f.read())
|
||||
|
||||
# remove unit.log
|
||||
|
||||
if not option.save_log:
|
||||
shutil.rmtree(self.temp_dir)
|
||||
else:
|
||||
_print_log(path=self.temp_dir)
|
||||
|
||||
assert self.stop_errors == [None, None], 'stop errors'
|
||||
|
||||
def stop(self):
|
||||
if not self._started:
|
||||
return
|
||||
|
||||
self.stop_errors = []
|
||||
|
||||
self.stop_errors.append(self._stop())
|
||||
|
||||
self.stop_errors.append(self.stop_processes())
|
||||
|
||||
atexit.unregister(self.stop)
|
||||
|
||||
self._started = False
|
||||
|
||||
def _stop(self):
|
||||
if self._p.poll() is not None:
|
||||
return
|
||||
|
||||
with self._p as p:
|
||||
p.send_signal(signal.SIGQUIT)
|
||||
|
||||
try:
|
||||
retcode = p.wait(15)
|
||||
if retcode:
|
||||
return 'Child process terminated with code ' + str(retcode)
|
||||
except:
|
||||
p.kill()
|
||||
return 'Could not terminate unit'
|
||||
|
||||
def run_process(self, target, *args):
|
||||
if not hasattr(self, '_processes'):
|
||||
self._processes = []
|
||||
|
||||
process = Process(target=target, args=args)
|
||||
process.start()
|
||||
|
||||
self._processes.append(process)
|
||||
|
||||
def stop_processes(self):
|
||||
if not hasattr(self, '_processes'):
|
||||
return
|
||||
|
||||
fail = False
|
||||
for process in self._processes:
|
||||
if process.is_alive():
|
||||
process.terminate()
|
||||
process.join(timeout=15)
|
||||
|
||||
if process.is_alive():
|
||||
fail = True
|
||||
|
||||
if fail:
|
||||
return 'Fail to stop process'
|
||||
return check
|
||||
|
||||
Reference in New Issue
Block a user