Tests: more fixtures.
Common methods from applications/proto.py converted to the fixtures. sysctl check moved to the specific file where it is using. Some options moved to the constructor to have early access.
This commit is contained in:
124
test/conftest.py
124
test/conftest.py
@@ -2,7 +2,6 @@ import fcntl
|
|||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import platform
|
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
@@ -109,8 +108,6 @@ def pytest_configure(config):
|
|||||||
os.path.join(os.path.dirname(__file__), os.pardir)
|
os.path.join(os.path.dirname(__file__), os.pardir)
|
||||||
)
|
)
|
||||||
option.test_dir = f'{option.current_dir}/test'
|
option.test_dir = f'{option.current_dir}/test'
|
||||||
option.architecture = platform.architecture()[0]
|
|
||||||
option.system = platform.system()
|
|
||||||
|
|
||||||
option.cache_dir = tempfile.mkdtemp(prefix='unit-test-cache-')
|
option.cache_dir = tempfile.mkdtemp(prefix='unit-test-cache-')
|
||||||
public_dir(option.cache_dir)
|
public_dir(option.cache_dir)
|
||||||
@@ -173,25 +170,15 @@ def pytest_sessionstart():
|
|||||||
[unit['unitd'], '--version'], stderr=subprocess.STDOUT
|
[unit['unitd'], '--version'], stderr=subprocess.STDOUT
|
||||||
).decode()
|
).decode()
|
||||||
|
|
||||||
# read unit.log
|
if not _wait_for_record(r'controller started'):
|
||||||
|
Log.print_log()
|
||||||
for _ in range(50):
|
|
||||||
with open(Log.get_path(), '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:
|
|
||||||
Log.print_log(log)
|
|
||||||
exit("Unit is writing log too long")
|
exit("Unit is writing log too long")
|
||||||
|
|
||||||
# discover available modules from unit.log
|
# discover available modules from unit.log
|
||||||
|
|
||||||
for module in re.findall(r'module: ([a-zA-Z]+) (.*) ".*"$', log, re.M):
|
for module in re.findall(
|
||||||
|
r'module: ([a-zA-Z]+) (.*) ".*"$', Log.read(), re.M
|
||||||
|
):
|
||||||
versions = option.available['modules'].setdefault(module[0], [])
|
versions = option.available['modules'].setdefault(module[0], [])
|
||||||
if module[1] not in versions:
|
if module[1] not in versions:
|
||||||
versions.append(module[1])
|
versions.append(module[1])
|
||||||
@@ -489,6 +476,7 @@ def _clear_conf(sock, *, log=None):
|
|||||||
for script in scripts:
|
for script in scripts:
|
||||||
assert 'success' in delete(f'/js_modules/{script}'), 'delete script'
|
assert 'success' in delete(f'/js_modules/{script}'), 'delete script'
|
||||||
|
|
||||||
|
|
||||||
def _clear_temp_dir():
|
def _clear_temp_dir():
|
||||||
temp_dir = unit_instance['temp_dir']
|
temp_dir = unit_instance['temp_dir']
|
||||||
|
|
||||||
@@ -633,6 +621,19 @@ def _count_fds(pid):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_record(pattern, name='unit.log', wait=150, flags=re.M):
|
||||||
|
with Log.open(name) as file:
|
||||||
|
for _ in range(wait):
|
||||||
|
found = re.search(pattern, file.read(), flags)
|
||||||
|
|
||||||
|
if found is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
def run_process(target, *args):
|
def run_process(target, *args):
|
||||||
global _processes
|
global _processes
|
||||||
|
|
||||||
@@ -669,6 +670,61 @@ def find_proc(name, ps_output):
|
|||||||
return re.findall(f'{unit_instance["pid"]}.*{name}', ps_output)
|
return re.findall(f'{unit_instance["pid"]}.*{name}', ps_output)
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_sessionfinish():
|
||||||
|
if not option.restart and option.save_log:
|
||||||
|
Log.print_path()
|
||||||
|
|
||||||
|
option.restart = True
|
||||||
|
|
||||||
|
unit_stop()
|
||||||
|
|
||||||
|
public_dir(option.cache_dir)
|
||||||
|
shutil.rmtree(option.cache_dir)
|
||||||
|
|
||||||
|
if not option.save_log and os.path.isdir(option.temp_dir):
|
||||||
|
public_dir(option.temp_dir)
|
||||||
|
shutil.rmtree(option.temp_dir)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def date_to_sec_epoch():
|
||||||
|
def _date_to_sec_epoch(date, template='%a, %d %b %Y %X %Z'):
|
||||||
|
return time.mktime(time.strptime(date, template))
|
||||||
|
|
||||||
|
return _date_to_sec_epoch
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def findall():
|
||||||
|
def _findall(pattern, name='unit.log', flags=re.M):
|
||||||
|
return re.findall(pattern, Log.read(name), flags)
|
||||||
|
|
||||||
|
return _findall
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def is_su():
|
||||||
|
return option.is_privileged
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def is_unsafe(request):
|
||||||
|
return request.config.getoption("--unsafe")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def search_in_file():
|
||||||
|
def _search_in_file(pattern, name='unit.log', flags=re.M):
|
||||||
|
return re.search(pattern, Log.read(name), flags)
|
||||||
|
|
||||||
|
return _search_in_file
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def sec_epoch():
|
||||||
|
return time.mktime(time.gmtime())
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def skip_alert():
|
def skip_alert():
|
||||||
def _skip(*alerts):
|
def _skip(*alerts):
|
||||||
@@ -687,37 +743,21 @@ def skip_fds_check():
|
|||||||
return _skip
|
return _skip
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def system():
|
||||||
|
return option.system
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def temp_dir():
|
def temp_dir():
|
||||||
return unit_instance['temp_dir']
|
return unit_instance['temp_dir']
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def is_unsafe(request):
|
|
||||||
return request.config.getoption("--unsafe")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def is_su():
|
|
||||||
return os.geteuid() == 0
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def unit_pid():
|
def unit_pid():
|
||||||
return unit_instance['process'].pid
|
return unit_instance['process'].pid
|
||||||
|
|
||||||
|
|
||||||
def pytest_sessionfinish():
|
@pytest.fixture
|
||||||
if not option.restart and option.save_log:
|
def wait_for_record():
|
||||||
Log.print_path()
|
return _wait_for_record
|
||||||
|
|
||||||
option.restart = True
|
|
||||||
|
|
||||||
unit_stop()
|
|
||||||
|
|
||||||
public_dir(option.cache_dir)
|
|
||||||
shutil.rmtree(option.cache_dir)
|
|
||||||
|
|
||||||
if not option.save_log and os.path.isdir(option.temp_dir):
|
|
||||||
public_dir(option.temp_dir)
|
|
||||||
shutil.rmtree(option.temp_dir)
|
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ class TestAccessLog(TestApplicationPython):
|
|||||||
'access_log',
|
'access_log',
|
||||||
), 'access_log format'
|
), 'access_log format'
|
||||||
|
|
||||||
def wait_for_record(self, pattern, name='access.log'):
|
def test_access_log_keepalive(self, wait_for_record):
|
||||||
return super().wait_for_record(pattern, name)
|
|
||||||
|
|
||||||
def test_access_log_keepalive(self):
|
|
||||||
self.load('mirror')
|
self.load('mirror')
|
||||||
|
|
||||||
assert self.get()['status'] == 200, 'init'
|
assert self.get()['status'] == 200, 'init'
|
||||||
@@ -43,16 +40,18 @@ class TestAccessLog(TestApplicationPython):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"POST / HTTP/1.1" 200 5') is not None
|
wait_for_record(r'"POST / HTTP/1.1" 200 5', 'access.log')
|
||||||
|
is not None
|
||||||
), 'keepalive 1'
|
), 'keepalive 1'
|
||||||
|
|
||||||
_ = self.post(sock=sock, body='0123456789')
|
_ = self.post(sock=sock, body='0123456789')
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"POST / HTTP/1.1" 200 10') is not None
|
wait_for_record(r'"POST / HTTP/1.1" 200 10', 'access.log')
|
||||||
|
is not None
|
||||||
), 'keepalive 2'
|
), 'keepalive 2'
|
||||||
|
|
||||||
def test_access_log_pipeline(self):
|
def test_access_log_pipeline(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
self.http(
|
self.http(
|
||||||
@@ -75,19 +74,25 @@ Connection: close
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"')
|
wait_for_record(
|
||||||
|
r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"', 'access.log'
|
||||||
|
)
|
||||||
is not None
|
is not None
|
||||||
), 'pipeline 1'
|
), 'pipeline 1'
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-2" "-"')
|
wait_for_record(
|
||||||
|
r'"GET / HTTP/1.1" 200 0 "Referer-2" "-"', 'access.log'
|
||||||
|
)
|
||||||
is not None
|
is not None
|
||||||
), 'pipeline 2'
|
), 'pipeline 2'
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "Referer-3" "-"')
|
wait_for_record(
|
||||||
|
r'"GET / HTTP/1.1" 200 0 "Referer-3" "-"', 'access.log'
|
||||||
|
)
|
||||||
is not None
|
is not None
|
||||||
), 'pipeline 3'
|
), 'pipeline 3'
|
||||||
|
|
||||||
def test_access_log_ipv6(self):
|
def test_access_log_ipv6(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
assert 'success' in self.conf(
|
assert 'success' in self.conf(
|
||||||
@@ -97,13 +102,13 @@ Connection: close
|
|||||||
self.get(sock_type='ipv6')
|
self.get(sock_type='ipv6')
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(
|
wait_for_record(
|
||||||
r'::1 - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"'
|
r'::1 - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"', 'access.log'
|
||||||
)
|
)
|
||||||
is not None
|
is not None
|
||||||
), 'ipv6'
|
), 'ipv6'
|
||||||
|
|
||||||
def test_access_log_unix(self, temp_dir):
|
def test_access_log_unix(self, temp_dir, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
addr = f'{temp_dir}/sock'
|
addr = f'{temp_dir}/sock'
|
||||||
@@ -115,13 +120,13 @@ Connection: close
|
|||||||
self.get(sock_type='unix', addr=addr)
|
self.get(sock_type='unix', addr=addr)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(
|
wait_for_record(
|
||||||
r'unix: - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"'
|
r'unix: - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"', 'access.log'
|
||||||
)
|
)
|
||||||
is not None
|
is not None
|
||||||
), 'unix'
|
), 'unix'
|
||||||
|
|
||||||
def test_access_log_referer(self):
|
def test_access_log_referer(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
self.get(
|
self.get(
|
||||||
@@ -133,11 +138,13 @@ Connection: close
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "referer-value" "-"')
|
wait_for_record(
|
||||||
|
r'"GET / HTTP/1.1" 200 0 "referer-value" "-"', 'access.log'
|
||||||
|
)
|
||||||
is not None
|
is not None
|
||||||
), 'referer'
|
), 'referer'
|
||||||
|
|
||||||
def test_access_log_user_agent(self):
|
def test_access_log_user_agent(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
self.get(
|
self.get(
|
||||||
@@ -149,22 +156,23 @@ Connection: close
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(
|
wait_for_record(
|
||||||
r'"GET / HTTP/1.1" 200 0 "-" "user-agent-value"'
|
r'"GET / HTTP/1.1" 200 0 "-" "user-agent-value"', 'access.log'
|
||||||
)
|
)
|
||||||
is not None
|
is not None
|
||||||
), 'user agent'
|
), 'user agent'
|
||||||
|
|
||||||
def test_access_log_http10(self):
|
def test_access_log_http10(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
self.get(http_10=True)
|
self.get(http_10=True)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET / HTTP/1.0" 200 0 "-" "-"') is not None
|
wait_for_record(r'"GET / HTTP/1.0" 200 0 "-" "-"', 'access.log')
|
||||||
|
is not None
|
||||||
), 'http 1.0'
|
), 'http 1.0'
|
||||||
|
|
||||||
def test_access_log_partial(self):
|
def test_access_log_partial(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
assert self.post()['status'] == 200, 'init'
|
assert self.post()['status'] == 200, 'init'
|
||||||
@@ -174,10 +182,10 @@ Connection: close
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"-" 400 0 "-" "-"') is not None
|
wait_for_record(r'"-" 400 0 "-" "-"', 'access.log') is not None
|
||||||
), 'partial'
|
), 'partial'
|
||||||
|
|
||||||
def test_access_log_partial_2(self):
|
def test_access_log_partial_2(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
assert self.post()['status'] == 200, 'init'
|
assert self.post()['status'] == 200, 'init'
|
||||||
@@ -185,10 +193,10 @@ Connection: close
|
|||||||
self.http(b"""GET /\n""", raw=True)
|
self.http(b"""GET /\n""", raw=True)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"-" 400 \d+ "-" "-"') is not None
|
wait_for_record(r'"-" 400 \d+ "-" "-"', 'access.log') is not None
|
||||||
), 'partial 2'
|
), 'partial 2'
|
||||||
|
|
||||||
def test_access_log_partial_3(self):
|
def test_access_log_partial_3(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
assert self.post()['status'] == 200, 'init'
|
assert self.post()['status'] == 200, 'init'
|
||||||
@@ -198,10 +206,10 @@ Connection: close
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"-" 400 0 "-" "-"') is not None
|
wait_for_record(r'"-" 400 0 "-" "-"', 'access.log') is not None
|
||||||
), 'partial 3'
|
), 'partial 3'
|
||||||
|
|
||||||
def test_access_log_partial_4(self):
|
def test_access_log_partial_4(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
assert self.post()['status'] == 200, 'init'
|
assert self.post()['status'] == 200, 'init'
|
||||||
@@ -211,11 +219,11 @@ Connection: close
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"-" 400 0 "-" "-"') is not None
|
wait_for_record(r'"-" 400 0 "-" "-"', 'access.log') is not None
|
||||||
), 'partial 4'
|
), 'partial 4'
|
||||||
|
|
||||||
@pytest.mark.skip('not yet')
|
@pytest.mark.skip('not yet')
|
||||||
def test_access_log_partial_5(self):
|
def test_access_log_partial_5(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
assert self.post()['status'] == 200, 'init'
|
assert self.post()['status'] == 200, 'init'
|
||||||
@@ -223,32 +231,32 @@ Connection: close
|
|||||||
self.get(headers={'Connection': 'close'})
|
self.get(headers={'Connection': 'close'})
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET / HTTP/1.1" 400 \d+ "-" "-"')
|
wait_for_record(r'"GET / HTTP/1.1" 400 \d+ "-" "-"', 'access.log')
|
||||||
is not None
|
is not None
|
||||||
), 'partial 5'
|
), 'partial 5'
|
||||||
|
|
||||||
def test_access_log_get_parameters(self):
|
def test_access_log_get_parameters(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
self.get(url='/?blah&var=val')
|
self.get(url='/?blah&var=val')
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(
|
wait_for_record(
|
||||||
r'"GET /\?blah&var=val HTTP/1.1" 200 0 "-" "-"'
|
r'"GET /\?blah&var=val HTTP/1.1" 200 0 "-" "-"', 'access.log'
|
||||||
)
|
)
|
||||||
is not None
|
is not None
|
||||||
), 'get parameters'
|
), 'get parameters'
|
||||||
|
|
||||||
def test_access_log_delete(self):
|
def test_access_log_delete(self, search_in_file):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
assert 'success' in self.conf_delete('access_log')
|
assert 'success' in self.conf_delete('access_log')
|
||||||
|
|
||||||
self.get(url='/delete')
|
self.get(url='/delete')
|
||||||
|
|
||||||
assert self.search_in_log(r'/delete', 'access.log') is None, 'delete'
|
assert search_in_file(r'/delete', 'access.log') is None, 'delete'
|
||||||
|
|
||||||
def test_access_log_change(self, temp_dir):
|
def test_access_log_change(self, temp_dir, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
@@ -258,24 +266,24 @@ Connection: close
|
|||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log')
|
wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log')
|
||||||
is not None
|
is not None
|
||||||
), 'change'
|
), 'change'
|
||||||
|
|
||||||
def test_access_log_format(self):
|
def test_access_log_format(self, wait_for_record):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
def check_format(format, expect, url='/'):
|
def check_format(format, expect, url='/'):
|
||||||
self.set_format(format)
|
self.set_format(format)
|
||||||
|
|
||||||
assert self.get(url=url)['status'] == 200
|
assert self.get(url=url)['status'] == 200
|
||||||
assert self.wait_for_record(expect) is not None, 'found'
|
assert wait_for_record(expect, 'access.log') is not None, 'found'
|
||||||
|
|
||||||
format = 'BLAH\t0123456789'
|
format = 'BLAH\t0123456789'
|
||||||
check_format(format, format)
|
check_format(format, format)
|
||||||
check_format('$uri $status $uri $status', '/ 200 / 200')
|
check_format('$uri $status $uri $status', '/ 200 / 200')
|
||||||
|
|
||||||
def test_access_log_variables(self):
|
def test_access_log_variables(self, wait_for_record):
|
||||||
self.load('mirror')
|
self.load('mirror')
|
||||||
|
|
||||||
# $body_bytes_sent
|
# $body_bytes_sent
|
||||||
@@ -284,7 +292,7 @@ Connection: close
|
|||||||
body = '0123456789' * 50
|
body = '0123456789' * 50
|
||||||
self.post(url='/bbs', body=body, read_timeout=1)
|
self.post(url='/bbs', body=body, read_timeout=1)
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(fr'^\/bbs {len(body)}$') is not None
|
wait_for_record(fr'^\/bbs {len(body)}$', 'access.log') is not None
|
||||||
), '$body_bytes_sent'
|
), '$body_bytes_sent'
|
||||||
|
|
||||||
def test_access_log_incorrect(self, temp_dir, skip_alert):
|
def test_access_log_incorrect(self, temp_dir, skip_alert):
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class TestASGIApplication(TestApplicationPython):
|
|||||||
}
|
}
|
||||||
load_module = 'asgi'
|
load_module = 'asgi'
|
||||||
|
|
||||||
def test_asgi_application_variables(self):
|
def test_asgi_application_variables(self, date_to_sec_epoch, sec_epoch):
|
||||||
self.load('variables')
|
self.load('variables')
|
||||||
|
|
||||||
body = 'Test body string.'
|
body = 'Test body string.'
|
||||||
@@ -40,9 +40,7 @@ custom-header: BLAH
|
|||||||
|
|
||||||
date = headers.pop('Date')
|
date = headers.pop('Date')
|
||||||
assert date[-4:] == ' GMT', 'date header timezone'
|
assert date[-4:] == ' GMT', 'date header timezone'
|
||||||
assert (
|
assert abs(date_to_sec_epoch(date) - sec_epoch) < 5, 'date header'
|
||||||
abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5
|
|
||||||
), 'date header'
|
|
||||||
|
|
||||||
assert headers == {
|
assert headers == {
|
||||||
'Connection': 'close',
|
'Connection': 'close',
|
||||||
@@ -382,7 +380,7 @@ Connection: close
|
|||||||
|
|
||||||
assert self.get()['status'] == 503, 'loading error'
|
assert self.get()['status'] == 503, 'loading error'
|
||||||
|
|
||||||
def test_asgi_application_threading(self):
|
def test_asgi_application_threading(self, wait_for_record):
|
||||||
"""wait_for_record() timeouts after 5s while every thread works at
|
"""wait_for_record() timeouts after 5s while every thread works at
|
||||||
least 3s. So without releasing GIL test should fail.
|
least 3s. So without releasing GIL test should fail.
|
||||||
"""
|
"""
|
||||||
@@ -393,7 +391,7 @@ Connection: close
|
|||||||
self.get(no_recv=True)
|
self.get(no_recv=True)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\(5\) Thread: 100', wait=50) is not None
|
wait_for_record(r'\(5\) Thread: 100', wait=50) is not None
|
||||||
), 'last thread finished'
|
), 'last thread finished'
|
||||||
|
|
||||||
def test_asgi_application_threads(self):
|
def test_asgi_application_threads(self):
|
||||||
|
|||||||
@@ -98,27 +98,27 @@ class TestASGILifespan(TestApplicationPython):
|
|||||||
self.assert_cookies('')
|
self.assert_cookies('')
|
||||||
self.assert_cookies('app2_')
|
self.assert_cookies('app2_')
|
||||||
|
|
||||||
def test_asgi_lifespan_failed(self):
|
def test_asgi_lifespan_failed(self, wait_for_record):
|
||||||
self.load('lifespan/failed')
|
self.load('lifespan/failed')
|
||||||
|
|
||||||
assert self.get()['status'] == 503
|
assert self.get()['status'] == 503
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].*Application startup failed')
|
wait_for_record(r'\[error\].*Application startup failed')
|
||||||
is not None
|
is not None
|
||||||
), 'error message'
|
), 'error message'
|
||||||
assert self.wait_for_record(r'Exception blah') is not None, 'exception'
|
assert wait_for_record(r'Exception blah') is not None, 'exception'
|
||||||
|
|
||||||
def test_asgi_lifespan_error(self):
|
def test_asgi_lifespan_error(self, wait_for_record):
|
||||||
self.load('lifespan/error')
|
self.load('lifespan/error')
|
||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
assert self.wait_for_record(r'Exception blah') is not None, 'exception'
|
assert wait_for_record(r'Exception blah') is not None, 'exception'
|
||||||
|
|
||||||
def test_asgi_lifespan_error_auto(self):
|
def test_asgi_lifespan_error_auto(self, wait_for_record):
|
||||||
self.load('lifespan/error_auto')
|
self.load('lifespan/error_auto')
|
||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
assert self.wait_for_record(r'AssertionError') is not None, 'assertion'
|
assert wait_for_record(r'AssertionError') is not None, 'assertion'
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import pytest
|
|||||||
from packaging import version
|
from packaging import version
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.applications.websockets import TestApplicationWebsocket
|
from unit.applications.websockets import TestApplicationWebsocket
|
||||||
from unit.option import option
|
|
||||||
|
|
||||||
|
|
||||||
class TestASGIWebsockets(TestApplicationPython):
|
class TestASGIWebsockets(TestApplicationPython):
|
||||||
@@ -1314,7 +1313,7 @@ class TestASGIWebsockets(TestApplicationPython):
|
|||||||
self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
|
self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
|
||||||
self.check_close(sock, 1002)
|
self.check_close(sock, 1002)
|
||||||
|
|
||||||
def test_asgi_websockets_9_1_1__9_6_6(self, is_unsafe):
|
def test_asgi_websockets_9_1_1__9_6_6(self, is_unsafe, system):
|
||||||
if not is_unsafe:
|
if not is_unsafe:
|
||||||
pytest.skip('unsafe, long run')
|
pytest.skip('unsafe, long run')
|
||||||
|
|
||||||
@@ -1371,7 +1370,7 @@ class TestASGIWebsockets(TestApplicationPython):
|
|||||||
check_payload(op_binary, 8 * 2**20) # 9_2_5
|
check_payload(op_binary, 8 * 2**20) # 9_2_5
|
||||||
check_payload(op_binary, 16 * 2**20) # 9_2_6
|
check_payload(op_binary, 16 * 2**20) # 9_2_6
|
||||||
|
|
||||||
if option.system != 'Darwin' and option.system != 'FreeBSD':
|
if system not in ['Darwin', 'FreeBSD']:
|
||||||
check_message(op_text, 64) # 9_3_1
|
check_message(op_text, 64) # 9_3_1
|
||||||
check_message(op_text, 256) # 9_3_2
|
check_message(op_text, 256) # 9_3_2
|
||||||
check_message(op_text, 2**10) # 9_3_3
|
check_message(op_text, 2**10) # 9_3_3
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import socket
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from unit.control import TestControl
|
from unit.control import TestControl
|
||||||
from unit.option import option
|
|
||||||
|
|
||||||
|
|
||||||
class TestConfiguration(TestControl):
|
class TestConfiguration(TestControl):
|
||||||
@@ -227,8 +226,8 @@ class TestConfiguration(TestControl):
|
|||||||
{"*:7080": {"pass": "applications/app"}}, 'listeners'
|
{"*:7080": {"pass": "applications/app"}}, 'listeners'
|
||||||
), 'listeners no app'
|
), 'listeners no app'
|
||||||
|
|
||||||
def test_listeners_unix_abstract(self):
|
def test_listeners_unix_abstract(self, system):
|
||||||
if option.system != 'Linux':
|
if system != 'Linux':
|
||||||
assert 'error' in self.try_addr("unix:@sock"), 'abstract at'
|
assert 'error' in self.try_addr("unix:@sock"), 'abstract at'
|
||||||
|
|
||||||
pytest.skip('not yet')
|
pytest.skip('not yet')
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class TestGoApplication(TestApplicationGo):
|
|||||||
def setup_method_fixture(self, skip_alert):
|
def setup_method_fixture(self, skip_alert):
|
||||||
skip_alert(r'\[unit\] close\(\d+\) failed: Bad file descriptor')
|
skip_alert(r'\[unit\] close\(\d+\) failed: Bad file descriptor')
|
||||||
|
|
||||||
def test_go_application_variables(self):
|
def test_go_application_variables(self, date_to_sec_epoch, sec_epoch):
|
||||||
self.load('variables')
|
self.load('variables')
|
||||||
|
|
||||||
body = 'Test body string.'
|
body = 'Test body string.'
|
||||||
@@ -33,9 +33,7 @@ class TestGoApplication(TestApplicationGo):
|
|||||||
|
|
||||||
date = headers.pop('Date')
|
date = headers.pop('Date')
|
||||||
assert date[-4:] == ' GMT', 'date header timezone'
|
assert date[-4:] == ' GMT', 'date header timezone'
|
||||||
assert (
|
assert abs(date_to_sec_epoch(date) - sec_epoch) < 5, 'date header'
|
||||||
abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5
|
|
||||||
), 'date header'
|
|
||||||
|
|
||||||
assert headers == {
|
assert headers == {
|
||||||
'Content-Length': str(len(body)),
|
'Content-Length': str(len(body)),
|
||||||
|
|||||||
@@ -128,7 +128,9 @@ class TestJavaApplication(TestApplicationJava):
|
|||||||
assert headers['X-Session-New'] == 'false', 'session resume'
|
assert headers['X-Session-New'] == 'false', 'session resume'
|
||||||
assert session_id == headers['X-Session-Id'], 'session same id'
|
assert session_id == headers['X-Session-Id'], 'session same id'
|
||||||
|
|
||||||
def test_java_application_session_active(self):
|
def test_java_application_session_active(
|
||||||
|
self, date_to_sec_epoch, sec_epoch
|
||||||
|
):
|
||||||
self.load('session_inactive')
|
self.load('session_inactive')
|
||||||
|
|
||||||
resp = self.get(
|
resp = self.get(
|
||||||
@@ -144,10 +146,8 @@ class TestJavaApplication(TestApplicationJava):
|
|||||||
assert resp['headers']['X-Session-Interval'] == '4', 'session interval'
|
assert resp['headers']['X-Session-Interval'] == '4', 'session interval'
|
||||||
assert (
|
assert (
|
||||||
abs(
|
abs(
|
||||||
self.date_to_sec_epoch(
|
date_to_sec_epoch(resp['headers']['X-Session-Last-Access-Time'])
|
||||||
resp['headers']['X-Session-Last-Access-Time']
|
- sec_epoch
|
||||||
)
|
|
||||||
- self.sec_epoch()
|
|
||||||
)
|
)
|
||||||
< 5
|
< 5
|
||||||
), 'session last access time'
|
), 'session last access time'
|
||||||
@@ -943,7 +943,7 @@ class TestJavaApplication(TestApplicationJava):
|
|||||||
), 'set date header'
|
), 'set date header'
|
||||||
assert headers['X-Get-Date'] == date, 'get date header'
|
assert headers['X-Get-Date'] == date, 'get date header'
|
||||||
|
|
||||||
def test_java_application_multipart(self, temp_dir):
|
def test_java_application_multipart(self, search_in_file, temp_dir):
|
||||||
self.load('multipart')
|
self.load('multipart')
|
||||||
|
|
||||||
reldst = '/uploads'
|
reldst = '/uploads'
|
||||||
@@ -979,7 +979,7 @@ class TestJavaApplication(TestApplicationJava):
|
|||||||
assert resp['status'] == 200, 'multipart status'
|
assert resp['status'] == 200, 'multipart status'
|
||||||
assert re.search(r'sample\.txt created', resp['body']), 'multipart body'
|
assert re.search(r'sample\.txt created', resp['body']), 'multipart body'
|
||||||
assert (
|
assert (
|
||||||
self.search_in_log(
|
search_in_file(
|
||||||
r'^Data from sample file$', name=f'{reldst}/sample.txt'
|
r'^Data from sample file$', name=f'{reldst}/sample.txt'
|
||||||
)
|
)
|
||||||
is not None
|
is not None
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import time
|
|||||||
import pytest
|
import pytest
|
||||||
from unit.applications.lang.java import TestApplicationJava
|
from unit.applications.lang.java import TestApplicationJava
|
||||||
from unit.applications.websockets import TestApplicationWebsocket
|
from unit.applications.websockets import TestApplicationWebsocket
|
||||||
from unit.option import option
|
|
||||||
|
|
||||||
|
|
||||||
class TestJavaWebsockets(TestApplicationJava):
|
class TestJavaWebsockets(TestApplicationJava):
|
||||||
@@ -1241,7 +1240,7 @@ class TestJavaWebsockets(TestApplicationJava):
|
|||||||
self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
|
self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
|
||||||
self.check_close(sock, 1002)
|
self.check_close(sock, 1002)
|
||||||
|
|
||||||
def test_java_websockets_9_1_1__9_6_6(self, is_unsafe):
|
def test_java_websockets_9_1_1__9_6_6(self, is_unsafe, system):
|
||||||
if not is_unsafe:
|
if not is_unsafe:
|
||||||
pytest.skip('unsafe, long run')
|
pytest.skip('unsafe, long run')
|
||||||
|
|
||||||
@@ -1298,7 +1297,7 @@ class TestJavaWebsockets(TestApplicationJava):
|
|||||||
check_payload(op_binary, 8 * 2**20) # 9_2_5
|
check_payload(op_binary, 8 * 2**20) # 9_2_5
|
||||||
check_payload(op_binary, 16 * 2**20) # 9_2_6
|
check_payload(op_binary, 16 * 2**20) # 9_2_6
|
||||||
|
|
||||||
if option.system != 'Darwin' and option.system != 'FreeBSD':
|
if system not in ['Darwin', 'FreeBSD']:
|
||||||
check_message(op_text, 64) # 9_3_1
|
check_message(op_text, 64) # 9_3_1
|
||||||
check_message(op_text, 256) # 9_3_2
|
check_message(op_text, 256) # 9_3_2
|
||||||
check_message(op_text, 2**10) # 9_3_3
|
check_message(op_text, 2**10) # 9_3_3
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class TestNodeApplication(TestApplicationNode):
|
|||||||
assert self.get()['status'] == 200, 'seq'
|
assert self.get()['status'] == 200, 'seq'
|
||||||
assert self.get()['status'] == 200, 'seq 2'
|
assert self.get()['status'] == 200, 'seq 2'
|
||||||
|
|
||||||
def test_node_application_variables(self):
|
def test_node_application_variables(self, date_to_sec_epoch, sec_epoch):
|
||||||
self.load('variables')
|
self.load('variables')
|
||||||
|
|
||||||
body = 'Test body string.'
|
body = 'Test body string.'
|
||||||
@@ -56,9 +56,7 @@ class TestNodeApplication(TestApplicationNode):
|
|||||||
|
|
||||||
date = headers.pop('Date')
|
date = headers.pop('Date')
|
||||||
assert date[-4:] == ' GMT', 'date header timezone'
|
assert date[-4:] == ' GMT', 'date header timezone'
|
||||||
assert (
|
assert abs(date_to_sec_epoch(date) - sec_epoch) < 5, 'date header'
|
||||||
abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5
|
|
||||||
), 'date header'
|
|
||||||
|
|
||||||
raw_headers = headers.pop('Request-Raw-Headers')
|
raw_headers = headers.pop('Request-Raw-Headers')
|
||||||
assert re.search(
|
assert re.search(
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import time
|
|||||||
import pytest
|
import pytest
|
||||||
from unit.applications.lang.node import TestApplicationNode
|
from unit.applications.lang.node import TestApplicationNode
|
||||||
from unit.applications.websockets import TestApplicationWebsocket
|
from unit.applications.websockets import TestApplicationWebsocket
|
||||||
from unit.option import option
|
|
||||||
|
|
||||||
|
|
||||||
class TestNodeWebsockets(TestApplicationNode):
|
class TestNodeWebsockets(TestApplicationNode):
|
||||||
@@ -1260,7 +1259,7 @@ class TestNodeWebsockets(TestApplicationNode):
|
|||||||
self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
|
self.ws.frame_write(sock, self.ws.OP_CLOSE, payload)
|
||||||
self.check_close(sock, 1002)
|
self.check_close(sock, 1002)
|
||||||
|
|
||||||
def test_node_websockets_9_1_1__9_6_6(self, is_unsafe):
|
def test_node_websockets_9_1_1__9_6_6(self, is_unsafe, system):
|
||||||
if not is_unsafe:
|
if not is_unsafe:
|
||||||
pytest.skip('unsafe, long run')
|
pytest.skip('unsafe, long run')
|
||||||
|
|
||||||
@@ -1317,7 +1316,7 @@ class TestNodeWebsockets(TestApplicationNode):
|
|||||||
check_payload(op_binary, 8 * 2**20) # 9_2_5
|
check_payload(op_binary, 8 * 2**20) # 9_2_5
|
||||||
check_payload(op_binary, 16 * 2**20) # 9_2_6
|
check_payload(op_binary, 16 * 2**20) # 9_2_6
|
||||||
|
|
||||||
if option.system != 'Darwin' and option.system != 'FreeBSD':
|
if system not in ['Darwin', 'FreeBSD']:
|
||||||
check_message(op_text, 64) # 9_3_1
|
check_message(op_text, 64) # 9_3_1
|
||||||
check_message(op_text, 256) # 9_3_2
|
check_message(op_text, 256) # 9_3_2
|
||||||
check_message(op_text, 2**10) # 9_3_3
|
check_message(op_text, 2**10) # 9_3_3
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from unit.applications.lang.perl import TestApplicationPerl
|
|||||||
class TestPerlApplication(TestApplicationPerl):
|
class TestPerlApplication(TestApplicationPerl):
|
||||||
prerequisites = {'modules': {'perl': 'all'}}
|
prerequisites = {'modules': {'perl': 'all'}}
|
||||||
|
|
||||||
def test_perl_application(self):
|
def test_perl_application(self, date_to_sec_epoch, sec_epoch):
|
||||||
self.load('variables')
|
self.load('variables')
|
||||||
|
|
||||||
body = 'Test body string.'
|
body = 'Test body string.'
|
||||||
@@ -32,9 +32,7 @@ class TestPerlApplication(TestApplicationPerl):
|
|||||||
|
|
||||||
date = headers.pop('Date')
|
date = headers.pop('Date')
|
||||||
assert date[-4:] == ' GMT', 'date header timezone'
|
assert date[-4:] == ' GMT', 'date header timezone'
|
||||||
assert (
|
assert abs(date_to_sec_epoch(date) - sec_epoch) < 5, 'date header'
|
||||||
abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5
|
|
||||||
), 'date header'
|
|
||||||
|
|
||||||
assert headers == {
|
assert headers == {
|
||||||
'Connection': 'close',
|
'Connection': 'close',
|
||||||
@@ -128,13 +126,13 @@ class TestPerlApplication(TestApplicationPerl):
|
|||||||
body = '0123456789'
|
body = '0123456789'
|
||||||
assert self.post(body=body)['body'] == body, 'input copy'
|
assert self.post(body=body)['body'] == body, 'input copy'
|
||||||
|
|
||||||
def test_perl_application_errors_print(self):
|
def test_perl_application_errors_print(self, wait_for_record):
|
||||||
self.load('errors_print')
|
self.load('errors_print')
|
||||||
|
|
||||||
assert self.get()['body'] == '1', 'errors result'
|
assert self.get()['body'] == '1', 'errors result'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+Error in application') is not None
|
wait_for_record(r'\[error\].+Error in application') is not None
|
||||||
), 'errors print'
|
), 'errors print'
|
||||||
|
|
||||||
def test_perl_application_header_equal_names(self):
|
def test_perl_application_header_equal_names(self):
|
||||||
@@ -223,19 +221,18 @@ class TestPerlApplication(TestApplicationPerl):
|
|||||||
|
|
||||||
assert resp['body'] == body, 'keep-alive 2'
|
assert resp['body'] == body, 'keep-alive 2'
|
||||||
|
|
||||||
def test_perl_body_io_fake(self):
|
def test_perl_body_io_fake(self, wait_for_record):
|
||||||
self.load('body_io_fake')
|
self.load('body_io_fake')
|
||||||
|
|
||||||
assert self.get()['body'] == '21', 'body io fake'
|
assert self.get()['body'] == '21', 'body io fake'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+IOFake getline\(\) \$\/ is \d+')
|
wait_for_record(r'\[error\].+IOFake getline\(\) \$\/ is \d+')
|
||||||
is not None
|
is not None
|
||||||
), 'body io fake $/ value'
|
), 'body io fake $/ value'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+IOFake close\(\) called')
|
wait_for_record(r'\[error\].+IOFake close\(\) called') is not None
|
||||||
is not None
|
|
||||||
), 'body io fake close'
|
), 'body io fake close'
|
||||||
|
|
||||||
def test_perl_delayed_response(self):
|
def test_perl_delayed_response(self):
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ opcache.preload_user = {option.user or getpass.getuser()}
|
|||||||
'applications/opcache/options',
|
'applications/opcache/options',
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_php_application_variables(self):
|
def test_php_application_variables(self, date_to_sec_epoch, sec_epoch):
|
||||||
self.load('variables')
|
self.load('variables')
|
||||||
|
|
||||||
body = 'Test body string.'
|
body = 'Test body string.'
|
||||||
@@ -79,9 +79,7 @@ opcache.preload_user = {option.user or getpass.getuser()}
|
|||||||
|
|
||||||
date = headers.pop('Date')
|
date = headers.pop('Date')
|
||||||
assert date[-4:] == ' GMT', 'date header timezone'
|
assert date[-4:] == ' GMT', 'date header timezone'
|
||||||
assert (
|
assert abs(date_to_sec_epoch(date) - sec_epoch) < 5, 'date header'
|
||||||
abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5
|
|
||||||
), 'date header'
|
|
||||||
|
|
||||||
if 'X-Powered-By' in headers:
|
if 'X-Powered-By' in headers:
|
||||||
headers.pop('X-Powered-By')
|
headers.pop('X-Powered-By')
|
||||||
@@ -116,7 +114,7 @@ opcache.preload_user = {option.user or getpass.getuser()}
|
|||||||
assert resp['status'] == 200, 'query string empty status'
|
assert resp['status'] == 200, 'query string empty status'
|
||||||
assert resp['headers']['Query-String'] == '', 'query string empty'
|
assert resp['headers']['Query-String'] == '', 'query string empty'
|
||||||
|
|
||||||
def test_php_application_fastcgi_finish_request(self, unit_pid):
|
def test_php_application_fastcgi_finish_request(self, findall, unit_pid):
|
||||||
self.load('fastcgi_finish_request')
|
self.load('fastcgi_finish_request')
|
||||||
|
|
||||||
assert 'success' in self.conf(
|
assert 'success' in self.conf(
|
||||||
@@ -128,11 +126,11 @@ opcache.preload_user = {option.user or getpass.getuser()}
|
|||||||
|
|
||||||
os.kill(unit_pid, signal.SIGUSR1)
|
os.kill(unit_pid, signal.SIGUSR1)
|
||||||
|
|
||||||
errs = self.findall(r'Error in fastcgi_finish_request')
|
errs = findall(r'Error in fastcgi_finish_request')
|
||||||
|
|
||||||
assert len(errs) == 0, 'no error'
|
assert len(errs) == 0, 'no error'
|
||||||
|
|
||||||
def test_php_application_fastcgi_finish_request_2(self, unit_pid):
|
def test_php_application_fastcgi_finish_request_2(self, findall, unit_pid):
|
||||||
self.load('fastcgi_finish_request')
|
self.load('fastcgi_finish_request')
|
||||||
|
|
||||||
assert 'success' in self.conf(
|
assert 'success' in self.conf(
|
||||||
@@ -146,7 +144,7 @@ opcache.preload_user = {option.user or getpass.getuser()}
|
|||||||
|
|
||||||
os.kill(unit_pid, signal.SIGUSR1)
|
os.kill(unit_pid, signal.SIGUSR1)
|
||||||
|
|
||||||
errs = self.findall(r'Error in fastcgi_finish_request')
|
errs = findall(r'Error in fastcgi_finish_request')
|
||||||
|
|
||||||
assert len(errs) == 0, 'no error'
|
assert len(errs) == 0, 'no error'
|
||||||
|
|
||||||
@@ -556,7 +554,7 @@ opcache.preload_user = {option.user or getpass.getuser()}
|
|||||||
r'012345', self.get()['body']
|
r'012345', self.get()['body']
|
||||||
), 'disable_classes before'
|
), 'disable_classes before'
|
||||||
|
|
||||||
def test_php_application_error_log(self):
|
def test_php_application_error_log(self, findall, wait_for_record):
|
||||||
self.load('error_log')
|
self.load('error_log')
|
||||||
|
|
||||||
assert self.get()['status'] == 200, 'status'
|
assert self.get()['status'] == 200, 'status'
|
||||||
@@ -567,9 +565,9 @@ opcache.preload_user = {option.user or getpass.getuser()}
|
|||||||
|
|
||||||
pattern = r'\d{4}\/\d\d\/\d\d\s\d\d:.+\[notice\].+Error in application'
|
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'
|
assert wait_for_record(pattern) is not None, 'errors print'
|
||||||
|
|
||||||
errs = self.findall(pattern)
|
errs = findall(pattern)
|
||||||
|
|
||||||
assert len(errs) == 2, 'error_log count'
|
assert len(errs) == 2, 'error_log count'
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from unit.applications.lang.python import TestApplicationPython
|
|||||||
class TestPythonApplication(TestApplicationPython):
|
class TestPythonApplication(TestApplicationPython):
|
||||||
prerequisites = {'modules': {'python': 'all'}}
|
prerequisites = {'modules': {'python': 'all'}}
|
||||||
|
|
||||||
def test_python_application_variables(self):
|
def test_python_application_variables(self, date_to_sec_epoch, sec_epoch):
|
||||||
self.load('variables')
|
self.load('variables')
|
||||||
|
|
||||||
body = 'Test body string.'
|
body = 'Test body string.'
|
||||||
@@ -43,9 +43,7 @@ custom-header: BLAH
|
|||||||
|
|
||||||
date = headers.pop('Date')
|
date = headers.pop('Date')
|
||||||
assert date[-4:] == ' GMT', 'date header timezone'
|
assert date[-4:] == ' GMT', 'date header timezone'
|
||||||
assert (
|
assert abs(date_to_sec_epoch(date) - sec_epoch) < 5, 'date header'
|
||||||
abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5
|
|
||||||
), 'date header'
|
|
||||||
|
|
||||||
assert headers == {
|
assert headers == {
|
||||||
'Connection': 'close',
|
'Connection': 'close',
|
||||||
@@ -175,7 +173,7 @@ custom-header: BLAH
|
|||||||
'Transfer-Encoding' not in self.get()['headers']
|
'Transfer-Encoding' not in self.get()['headers']
|
||||||
), '204 header transfer encoding'
|
), '204 header transfer encoding'
|
||||||
|
|
||||||
def test_python_application_ctx_iter_atexit(self):
|
def test_python_application_ctx_iter_atexit(self, wait_for_record):
|
||||||
self.load('ctx_iter_atexit')
|
self.load('ctx_iter_atexit')
|
||||||
|
|
||||||
resp = self.post(body='0123456789')
|
resp = self.post(body='0123456789')
|
||||||
@@ -185,9 +183,7 @@ custom-header: BLAH
|
|||||||
|
|
||||||
assert 'success' in self.conf({"listeners": {}, "applications": {}})
|
assert 'success' in self.conf({"listeners": {}, "applications": {}})
|
||||||
|
|
||||||
assert (
|
assert wait_for_record(r'RuntimeError') is not None, 'ctx iter atexit'
|
||||||
self.wait_for_record(r'RuntimeError') is not None
|
|
||||||
), 'ctx iter atexit'
|
|
||||||
|
|
||||||
def test_python_keepalive_body(self):
|
def test_python_keepalive_body(self):
|
||||||
self.load('mirror')
|
self.load('mirror')
|
||||||
@@ -297,14 +293,14 @@ custom-header: BLAH
|
|||||||
|
|
||||||
assert resp == {}, 'reconfigure 2 keep-alive 3'
|
assert resp == {}, 'reconfigure 2 keep-alive 3'
|
||||||
|
|
||||||
def test_python_atexit(self):
|
def test_python_atexit(self, wait_for_record):
|
||||||
self.load('atexit')
|
self.load('atexit')
|
||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
assert 'success' in self.conf({"listeners": {}, "applications": {}})
|
assert 'success' in self.conf({"listeners": {}, "applications": {}})
|
||||||
|
|
||||||
assert self.wait_for_record(r'At exit called\.') is not None, 'atexit'
|
assert wait_for_record(r'At exit called\.') is not None, 'atexit'
|
||||||
|
|
||||||
def test_python_process_switch(self):
|
def test_python_process_switch(self):
|
||||||
self.load('delayed', processes=2)
|
self.load('delayed', processes=2)
|
||||||
@@ -456,14 +452,13 @@ last line: 987654321
|
|||||||
assert resp['body'] == body, 'input read length negative'
|
assert resp['body'] == body, 'input read length negative'
|
||||||
|
|
||||||
@pytest.mark.skip('not yet')
|
@pytest.mark.skip('not yet')
|
||||||
def test_python_application_errors_write(self):
|
def test_python_application_errors_write(self, wait_for_record):
|
||||||
self.load('errors_write')
|
self.load('errors_write')
|
||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+Error in application\.')
|
wait_for_record(r'\[error\].+Error in application\.') is not None
|
||||||
is not None
|
|
||||||
), 'errors write'
|
), 'errors write'
|
||||||
|
|
||||||
def test_python_application_body_array(self):
|
def test_python_application_body_array(self):
|
||||||
@@ -495,29 +490,27 @@ last line: 987654321
|
|||||||
|
|
||||||
assert self.get()['status'] == 503, 'loading error'
|
assert self.get()['status'] == 503, 'loading error'
|
||||||
|
|
||||||
def test_python_application_close(self):
|
def test_python_application_close(self, wait_for_record):
|
||||||
self.load('close')
|
self.load('close')
|
||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
assert self.wait_for_record(r'Close called\.') is not None, 'close'
|
assert wait_for_record(r'Close called\.') is not None, 'close'
|
||||||
|
|
||||||
def test_python_application_close_error(self):
|
def test_python_application_close_error(self, wait_for_record):
|
||||||
self.load('close_error')
|
self.load('close_error')
|
||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
assert (
|
assert wait_for_record(r'Close called\.') is not None, 'close error'
|
||||||
self.wait_for_record(r'Close called\.') is not None
|
|
||||||
), 'close error'
|
|
||||||
|
|
||||||
def test_python_application_not_iterable(self):
|
def test_python_application_not_iterable(self, wait_for_record):
|
||||||
self.load('not_iterable')
|
self.load('not_iterable')
|
||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(
|
wait_for_record(
|
||||||
r'\[error\].+the application returned not an iterable object'
|
r'\[error\].+the application returned not an iterable object'
|
||||||
)
|
)
|
||||||
is not None
|
is not None
|
||||||
@@ -603,7 +596,7 @@ last line: 987654321
|
|||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_python_application_threading(self):
|
def test_python_application_threading(self, wait_for_record):
|
||||||
"""wait_for_record() timeouts after 5s while every thread works at
|
"""wait_for_record() timeouts after 5s while every thread works at
|
||||||
least 3s. So without releasing GIL test should fail.
|
least 3s. So without releasing GIL test should fail.
|
||||||
"""
|
"""
|
||||||
@@ -614,10 +607,10 @@ last line: 987654321
|
|||||||
self.get(no_recv=True)
|
self.get(no_recv=True)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\(5\) Thread: 100', wait=50) is not None
|
wait_for_record(r'\(5\) Thread: 100', wait=50) is not None
|
||||||
), 'last thread finished'
|
), 'last thread finished'
|
||||||
|
|
||||||
def test_python_application_iter_exception(self):
|
def test_python_application_iter_exception(self, findall, wait_for_record):
|
||||||
self.load('iter_exception')
|
self.load('iter_exception')
|
||||||
|
|
||||||
# Default request doesn't lead to the exception.
|
# Default request doesn't lead to the exception.
|
||||||
@@ -637,12 +630,11 @@ last line: 987654321
|
|||||||
|
|
||||||
assert self.get()['status'] == 503, 'error'
|
assert self.get()['status'] == 503, 'error'
|
||||||
|
|
||||||
assert self.wait_for_record(r'Traceback') is not None, 'traceback'
|
assert wait_for_record(r'Traceback') is not None, 'traceback'
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r"raise Exception\('first exception'\)")
|
wait_for_record(r"raise Exception\('first exception'\)") is not None
|
||||||
is not None
|
|
||||||
), 'first exception raise'
|
), 'first exception raise'
|
||||||
assert len(self.findall(r'Traceback')) == 1, 'traceback count 1'
|
assert len(findall(r'Traceback')) == 1, 'traceback count 1'
|
||||||
|
|
||||||
# Exception after start_response(), before first write().
|
# Exception after start_response(), before first write().
|
||||||
|
|
||||||
@@ -658,10 +650,10 @@ last line: 987654321
|
|||||||
), 'error 2'
|
), 'error 2'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r"raise Exception\('second exception'\)")
|
wait_for_record(r"raise Exception\('second exception'\)")
|
||||||
is not None
|
is not None
|
||||||
), 'exception raise second'
|
), 'exception raise second'
|
||||||
assert len(self.findall(r'Traceback')) == 2, 'traceback count 2'
|
assert len(findall(r'Traceback')) == 2, 'traceback count 2'
|
||||||
|
|
||||||
# Exception after first write(), before first __next__().
|
# Exception after first write(), before first __next__().
|
||||||
|
|
||||||
@@ -675,10 +667,9 @@ last line: 987654321
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r"raise Exception\('third exception'\)")
|
wait_for_record(r"raise Exception\('third exception'\)") is not None
|
||||||
is not None
|
|
||||||
), 'exception raise third'
|
), 'exception raise third'
|
||||||
assert len(self.findall(r'Traceback')) == 3, 'traceback count 3'
|
assert len(findall(r'Traceback')) == 3, 'traceback count 3'
|
||||||
|
|
||||||
assert self.get(sock=sock) == {}, 'closed connection'
|
assert self.get(sock=sock) == {}, 'closed connection'
|
||||||
|
|
||||||
@@ -696,7 +687,7 @@ last line: 987654321
|
|||||||
)
|
)
|
||||||
if resp:
|
if resp:
|
||||||
assert resp[-5:] != '0\r\n\r\n', 'incomplete body'
|
assert resp[-5:] != '0\r\n\r\n', 'incomplete body'
|
||||||
assert len(self.findall(r'Traceback')) == 4, 'traceback count 4'
|
assert len(findall(r'Traceback')) == 4, 'traceback count 4'
|
||||||
|
|
||||||
# Exception in __next__().
|
# Exception in __next__().
|
||||||
|
|
||||||
@@ -710,10 +701,9 @@ last line: 987654321
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r"raise Exception\('next exception'\)")
|
wait_for_record(r"raise Exception\('next exception'\)") is not None
|
||||||
is not None
|
|
||||||
), 'exception raise next'
|
), 'exception raise next'
|
||||||
assert len(self.findall(r'Traceback')) == 5, 'traceback count 5'
|
assert len(findall(r'Traceback')) == 5, 'traceback count 5'
|
||||||
|
|
||||||
assert self.get(sock=sock) == {}, 'closed connection 2'
|
assert self.get(sock=sock) == {}, 'closed connection 2'
|
||||||
|
|
||||||
@@ -730,7 +720,7 @@ last line: 987654321
|
|||||||
)
|
)
|
||||||
if resp:
|
if resp:
|
||||||
assert resp[-5:] != '0\r\n\r\n', 'incomplete body 2'
|
assert resp[-5:] != '0\r\n\r\n', 'incomplete body 2'
|
||||||
assert len(self.findall(r'Traceback')) == 6, 'traceback count 6'
|
assert len(findall(r'Traceback')) == 6, 'traceback count 6'
|
||||||
|
|
||||||
# Exception before start_response() and in close().
|
# Exception before start_response() and in close().
|
||||||
|
|
||||||
@@ -746,10 +736,9 @@ last line: 987654321
|
|||||||
), 'error'
|
), 'error'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r"raise Exception\('close exception'\)")
|
wait_for_record(r"raise Exception\('close exception'\)") is not None
|
||||||
is not None
|
|
||||||
), 'exception raise close'
|
), 'exception raise close'
|
||||||
assert len(self.findall(r'Traceback')) == 8, 'traceback count 8'
|
assert len(findall(r'Traceback')) == 8, 'traceback count 8'
|
||||||
|
|
||||||
def test_python_user_group(self, is_su):
|
def test_python_user_group(self, is_su):
|
||||||
if not is_su:
|
if not is_su:
|
||||||
|
|||||||
@@ -37,14 +37,11 @@ class TestRewrite(TestApplicationProto):
|
|||||||
'routes',
|
'routes',
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_rewrite(self):
|
def test_rewrite(self, findall, wait_for_record):
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
assert (
|
assert wait_for_record(rf'\[notice\].*"routes/1" selected') is not None
|
||||||
self.wait_for_record(rf'\[notice\].*"routes/1" selected')
|
assert len(findall(rf'\[notice\].*URI rewritten to "/new"')) == 1
|
||||||
is not None
|
assert len(findall(rf'\[notice\].*URI rewritten')) == 1
|
||||||
)
|
|
||||||
assert len(self.findall(rf'\[notice\].*URI rewritten to "/new"')) == 1
|
|
||||||
assert len(self.findall(rf'\[notice\].*URI rewritten')) == 1
|
|
||||||
|
|
||||||
self.set_rewrite("", "")
|
self.set_rewrite("", "")
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from unit.applications.lang.ruby import TestApplicationRuby
|
|||||||
class TestRubyApplication(TestApplicationRuby):
|
class TestRubyApplication(TestApplicationRuby):
|
||||||
prerequisites = {'modules': {'ruby': 'all'}}
|
prerequisites = {'modules': {'ruby': 'all'}}
|
||||||
|
|
||||||
def test_ruby_application(self):
|
def test_ruby_application(self, date_to_sec_epoch, sec_epoch):
|
||||||
self.load('variables')
|
self.load('variables')
|
||||||
|
|
||||||
body = 'Test body string.'
|
body = 'Test body string.'
|
||||||
@@ -33,9 +33,7 @@ class TestRubyApplication(TestApplicationRuby):
|
|||||||
|
|
||||||
date = headers.pop('Date')
|
date = headers.pop('Date')
|
||||||
assert date[-4:] == ' GMT', 'date header timezone'
|
assert date[-4:] == ' GMT', 'date header timezone'
|
||||||
assert (
|
assert abs(date_to_sec_epoch(date) - sec_epoch) < 5, 'date header'
|
||||||
abs(self.date_to_sec_epoch(date) - self.sec_epoch()) < 5
|
|
||||||
), 'date header'
|
|
||||||
|
|
||||||
assert headers == {
|
assert headers == {
|
||||||
'Connection': 'close',
|
'Connection': 'close',
|
||||||
@@ -170,30 +168,30 @@ class TestRubyApplication(TestApplicationRuby):
|
|||||||
|
|
||||||
assert self.get()['status'] == 500, 'syntax error'
|
assert self.get()['status'] == 500, 'syntax error'
|
||||||
|
|
||||||
def test_ruby_application_errors_puts(self):
|
def test_ruby_application_errors_puts(self, wait_for_record):
|
||||||
self.load('errors_puts')
|
self.load('errors_puts')
|
||||||
|
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+Error in application') is not None
|
wait_for_record(r'\[error\].+Error in application') is not None
|
||||||
), 'errors puts'
|
), 'errors puts'
|
||||||
|
|
||||||
def test_ruby_application_errors_puts_int(self):
|
def test_ruby_application_errors_puts_int(self, wait_for_record):
|
||||||
self.load('errors_puts_int')
|
self.load('errors_puts_int')
|
||||||
|
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+1234567890') is not None
|
wait_for_record(r'\[error\].+1234567890') is not None
|
||||||
), 'errors puts int'
|
), 'errors puts int'
|
||||||
|
|
||||||
def test_ruby_application_errors_write(self):
|
def test_ruby_application_errors_write(self, wait_for_record):
|
||||||
self.load('errors_write')
|
self.load('errors_write')
|
||||||
|
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+Error in application') is not None
|
wait_for_record(r'\[error\].+Error in application') is not None
|
||||||
), 'errors write'
|
), 'errors write'
|
||||||
|
|
||||||
def test_ruby_application_errors_write_to_s_custom(self):
|
def test_ruby_application_errors_write_to_s_custom(self):
|
||||||
@@ -201,15 +199,15 @@ class TestRubyApplication(TestApplicationRuby):
|
|||||||
|
|
||||||
assert self.get()['status'] == 200, 'errors write to_s custom'
|
assert self.get()['status'] == 200, 'errors write to_s custom'
|
||||||
|
|
||||||
def test_ruby_application_errors_write_int(self):
|
def test_ruby_application_errors_write_int(self, wait_for_record):
|
||||||
self.load('errors_write_int')
|
self.load('errors_write_int')
|
||||||
|
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+1234567890') is not None
|
wait_for_record(r'\[error\].+1234567890') is not None
|
||||||
), 'errors write int'
|
), 'errors write int'
|
||||||
|
|
||||||
def test_ruby_application_at_exit(self):
|
def test_ruby_application_at_exit(self, wait_for_record):
|
||||||
self.load('at_exit')
|
self.load('at_exit')
|
||||||
|
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
@@ -217,7 +215,7 @@ class TestRubyApplication(TestApplicationRuby):
|
|||||||
assert 'success' in self.conf({"listeners": {}, "applications": {}})
|
assert 'success' in self.conf({"listeners": {}, "applications": {}})
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+At exit called\.') is not None
|
wait_for_record(r'\[error\].+At exit called\.') is not None
|
||||||
), 'at exit'
|
), 'at exit'
|
||||||
|
|
||||||
def test_ruby_application_encoding(self):
|
def test_ruby_application_encoding(self):
|
||||||
@@ -322,14 +320,13 @@ class TestRubyApplication(TestApplicationRuby):
|
|||||||
assert self.post(body=body)['body'] == body, 'body large'
|
assert self.post(body=body)['body'] == body, 'body large'
|
||||||
|
|
||||||
@pytest.mark.skip('not yet')
|
@pytest.mark.skip('not yet')
|
||||||
def test_ruby_application_body_each_error(self):
|
def test_ruby_application_body_each_error(self, wait_for_record):
|
||||||
self.load('body_each_error')
|
self.load('body_each_error')
|
||||||
|
|
||||||
assert self.get()['status'] == 500, 'body each error status'
|
assert self.get()['status'] == 500, 'body each error status'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+Failed to run ruby script')
|
wait_for_record(r'\[error\].+Failed to run ruby script') is not None
|
||||||
is not None
|
|
||||||
), 'body each error'
|
), 'body each error'
|
||||||
|
|
||||||
def test_ruby_application_body_file(self):
|
def test_ruby_application_body_file(self):
|
||||||
|
|||||||
@@ -1,15 +1,25 @@
|
|||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.utils import sysctl
|
|
||||||
|
|
||||||
|
|
||||||
class TestSettings(TestApplicationPython):
|
class TestSettings(TestApplicationPython):
|
||||||
prerequisites = {'modules': {'python': 'any'}}
|
prerequisites = {'modules': {'python': 'any'}}
|
||||||
|
|
||||||
|
def sysctl(self):
|
||||||
|
try:
|
||||||
|
out = subprocess.check_output(
|
||||||
|
['sysctl', '-a'], stderr=subprocess.STDOUT
|
||||||
|
).decode()
|
||||||
|
except FileNotFoundError:
|
||||||
|
pytest.skip('requires sysctl')
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
def test_settings_large_header_buffer_size(self):
|
def test_settings_large_header_buffer_size(self):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
@@ -263,7 +273,7 @@ Connection: close
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
sysctl_out = sysctl()
|
sysctl_out = self.sysctl()
|
||||||
values = re.findall(
|
values = re.findall(
|
||||||
r'net.core.[rw]mem_(?:max|default).*?(\d+)', sysctl_out
|
r'net.core.[rw]mem_(?:max|default).*?(\d+)', sysctl_out
|
||||||
)
|
)
|
||||||
@@ -409,15 +419,15 @@ Connection: close
|
|||||||
assert resp['status'] == 200, 'status 4'
|
assert resp['status'] == 200, 'status 4'
|
||||||
assert resp['body'] == body, 'body 4'
|
assert resp['body'] == body, 'body 4'
|
||||||
|
|
||||||
def test_settings_log_route(self):
|
def test_settings_log_route(self, findall, search_in_file, wait_for_record):
|
||||||
def count_fallbacks():
|
def count_fallbacks():
|
||||||
return len(self.findall(r'"fallback" taken'))
|
return len(findall(r'"fallback" taken'))
|
||||||
|
|
||||||
def check_record(template):
|
def check_record(template):
|
||||||
assert self.search_in_log(template) is not None
|
assert search_in_file(template) is not None
|
||||||
|
|
||||||
def check_no_record(template):
|
def check_no_record(template):
|
||||||
assert self.search_in_log(template) is None
|
assert search_in_file(template) is None
|
||||||
|
|
||||||
def template_req_line(url):
|
def template_req_line(url):
|
||||||
return rf'\[notice\].*http request line "GET {url} HTTP/1\.1"'
|
return rf'\[notice\].*http request line "GET {url} HTTP/1\.1"'
|
||||||
@@ -430,8 +440,8 @@ Connection: close
|
|||||||
|
|
||||||
def wait_for_request_log(status, uri, route):
|
def wait_for_request_log(status, uri, route):
|
||||||
assert self.get(url=uri)['status'] == status
|
assert self.get(url=uri)['status'] == status
|
||||||
assert self.wait_for_record(template_req_line(uri)) is not None
|
assert wait_for_record(template_req_line(uri)) is not None
|
||||||
assert self.wait_for_record(template_selected(route)) is not None
|
assert wait_for_record(template_selected(route)) is not None
|
||||||
|
|
||||||
# routes array
|
# routes array
|
||||||
|
|
||||||
@@ -559,6 +569,6 @@ Connection: close
|
|||||||
|
|
||||||
# total
|
# total
|
||||||
|
|
||||||
assert len(self.findall(r'\[notice\].*http request line')) == 7
|
assert len(findall(r'\[notice\].*http request line')) == 7
|
||||||
assert len(self.findall(r'\[notice\].*selected')) == 10
|
assert len(findall(r'\[notice\].*selected')) == 10
|
||||||
assert len(self.findall(r'\[info\].*discarded')) == 2
|
assert len(findall(r'\[info\].*discarded')) == 2
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ from unit.option import option
|
|||||||
class TestTLS(TestApplicationTLS):
|
class TestTLS(TestApplicationTLS):
|
||||||
prerequisites = {'modules': {'python': 'any', 'openssl': 'any'}}
|
prerequisites = {'modules': {'python': 'any', 'openssl': 'any'}}
|
||||||
|
|
||||||
def openssl_date_to_sec_epoch(self, date):
|
|
||||||
return self.date_to_sec_epoch(date, '%b %d %X %Y %Z')
|
|
||||||
|
|
||||||
def add_tls(self, application='empty', cert='default', port=7080):
|
def add_tls(self, application='empty', cert='default', port=7080):
|
||||||
assert 'success' in self.conf(
|
assert 'success' in self.conf(
|
||||||
{
|
{
|
||||||
@@ -254,8 +251,9 @@ basicConstraints = critical,CA:TRUE"""
|
|||||||
self.conf_get('/certificates/ec/key') == 'ECDH'
|
self.conf_get('/certificates/ec/key') == 'ECDH'
|
||||||
), 'certificate key ec'
|
), 'certificate key ec'
|
||||||
|
|
||||||
def test_tls_certificate_chain_options(self):
|
def test_tls_certificate_chain_options(self, date_to_sec_epoch, sec_epoch):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
date_format = '%b %d %X %Y %Z'
|
||||||
|
|
||||||
self.certificate()
|
self.certificate()
|
||||||
|
|
||||||
@@ -274,14 +272,14 @@ basicConstraints = critical,CA:TRUE"""
|
|||||||
|
|
||||||
assert (
|
assert (
|
||||||
abs(
|
abs(
|
||||||
self.sec_epoch()
|
sec_epoch
|
||||||
- self.openssl_date_to_sec_epoch(cert['validity']['since'])
|
- date_to_sec_epoch(cert['validity']['since'], date_format)
|
||||||
)
|
)
|
||||||
< 60
|
< 60
|
||||||
), 'certificate validity since'
|
), 'certificate validity since'
|
||||||
assert (
|
assert (
|
||||||
self.openssl_date_to_sec_epoch(cert['validity']['until'])
|
date_to_sec_epoch(cert['validity']['until'], date_format)
|
||||||
- self.openssl_date_to_sec_epoch(cert['validity']['since'])
|
- date_to_sec_epoch(cert['validity']['since'], date_format)
|
||||||
== 2592000
|
== 2592000
|
||||||
), 'certificate validity until'
|
), 'certificate validity until'
|
||||||
|
|
||||||
@@ -583,7 +581,9 @@ basicConstraints = critical,CA:TRUE"""
|
|||||||
'/certificates'
|
'/certificates'
|
||||||
), 'remove all certificates'
|
), 'remove all certificates'
|
||||||
|
|
||||||
def test_tls_application_respawn(self, skip_alert):
|
def test_tls_application_respawn(
|
||||||
|
self, findall, skip_alert, wait_for_record
|
||||||
|
):
|
||||||
self.load('mirror')
|
self.load('mirror')
|
||||||
|
|
||||||
self.certificate()
|
self.certificate()
|
||||||
@@ -602,13 +602,13 @@ basicConstraints = critical,CA:TRUE"""
|
|||||||
read_timeout=1,
|
read_timeout=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
app_id = self.findall(r'(\d+)#\d+ "mirror" application started')[0]
|
app_id = findall(r'(\d+)#\d+ "mirror" application started')[0]
|
||||||
|
|
||||||
subprocess.check_output(['kill', '-9', app_id])
|
subprocess.check_output(['kill', '-9', app_id])
|
||||||
|
|
||||||
skip_alert(fr'process {app_id} exited on signal 9')
|
skip_alert(fr'process {app_id} exited on signal 9')
|
||||||
|
|
||||||
self.wait_for_record(
|
wait_for_record(
|
||||||
fr' (?!{app_id}#)(\d+)#\d+ "mirror" application started'
|
fr' (?!{app_id}#)(\d+)#\d+ "mirror" application started'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,6 @@ class TestTLSSNI(TestApplicationTLS):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def openssl_date_to_sec_epoch(self, date):
|
|
||||||
return self.date_to_sec_epoch(date, '%b %d %X %Y %Z')
|
|
||||||
|
|
||||||
def add_tls(self, cert='default'):
|
def add_tls(self, cert='default'):
|
||||||
assert 'success' in self.conf(
|
assert 'success' in self.conf(
|
||||||
{"pass": "routes", "tls": {"certificate": cert}},
|
{"pass": "routes", "tls": {"certificate": cert}},
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ from unit.utils import waitforfiles
|
|||||||
class TestUSR1(TestApplicationPython):
|
class TestUSR1(TestApplicationPython):
|
||||||
prerequisites = {'modules': {'python': 'any'}}
|
prerequisites = {'modules': {'python': 'any'}}
|
||||||
|
|
||||||
def test_usr1_access_log(self, temp_dir, unit_pid):
|
def test_usr1_access_log(
|
||||||
|
self, search_in_file, temp_dir, unit_pid, wait_for_record
|
||||||
|
):
|
||||||
self.load('empty')
|
self.load('empty')
|
||||||
|
|
||||||
log = 'access.log'
|
log = 'access.log'
|
||||||
@@ -27,7 +29,7 @@ class TestUSR1(TestApplicationPython):
|
|||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', log_new)
|
wait_for_record(r'"GET / HTTP/1.1" 200 0 "-" "-"', log_new)
|
||||||
is not None
|
is not None
|
||||||
), 'rename new'
|
), 'rename new'
|
||||||
assert not os.path.isfile(log_path), 'rename old'
|
assert not os.path.isfile(log_path), 'rename old'
|
||||||
@@ -39,12 +41,14 @@ class TestUSR1(TestApplicationPython):
|
|||||||
assert self.get(url='/usr1')['status'] == 200
|
assert self.get(url='/usr1')['status'] == 200
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'"GET /usr1 HTTP/1.1" 200 0 "-" "-"', log)
|
wait_for_record(r'"GET /usr1 HTTP/1.1" 200 0 "-" "-"', log)
|
||||||
is not None
|
is not None
|
||||||
), 'reopen 2'
|
), 'reopen 2'
|
||||||
assert self.search_in_log(r'/usr1', log_new) is None, 'rename new 2'
|
assert search_in_file(r'/usr1', log_new) is None, 'rename new 2'
|
||||||
|
|
||||||
def test_usr1_unit_log(self, temp_dir, unit_pid):
|
def test_usr1_unit_log(
|
||||||
|
self, search_in_file, temp_dir, unit_pid, wait_for_record
|
||||||
|
):
|
||||||
self.load('log_body')
|
self.load('log_body')
|
||||||
|
|
||||||
log_new = 'new.log'
|
log_new = 'new.log'
|
||||||
@@ -59,7 +63,7 @@ class TestUSR1(TestApplicationPython):
|
|||||||
body = 'body_for_a_log_new\n'
|
body = 'body_for_a_log_new\n'
|
||||||
assert self.post(body=body)['status'] == 200
|
assert self.post(body=body)['status'] == 200
|
||||||
|
|
||||||
assert self.wait_for_record(body, log_new) is not None, 'rename new'
|
assert wait_for_record(body, log_new) is not None, 'rename new'
|
||||||
assert not os.path.isfile(log_path), 'rename old'
|
assert not os.path.isfile(log_path), 'rename old'
|
||||||
|
|
||||||
os.kill(unit_pid, signal.SIGUSR1)
|
os.kill(unit_pid, signal.SIGUSR1)
|
||||||
@@ -69,8 +73,8 @@ class TestUSR1(TestApplicationPython):
|
|||||||
body = 'body_for_a_log_unit\n'
|
body = 'body_for_a_log_unit\n'
|
||||||
assert self.post(body=body)['status'] == 200
|
assert self.post(body=body)['status'] == 200
|
||||||
|
|
||||||
assert self.wait_for_record(body) is not None, 'rename new'
|
assert wait_for_record(body) is not None, 'rename new'
|
||||||
assert self.search_in_log(body, log_new) is None, 'rename new 2'
|
assert search_in_file(body, log_new) is None, 'rename new 2'
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# merge two log files into unit.log to check alerts
|
# merge two log files into unit.log to check alerts
|
||||||
|
|||||||
@@ -27,12 +27,6 @@ class TestVariables(TestApplicationProto):
|
|||||||
'access_log',
|
'access_log',
|
||||||
), 'access_log format'
|
), 'access_log format'
|
||||||
|
|
||||||
def wait_for_record(self, pattern, name='access.log'):
|
|
||||||
return super().wait_for_record(pattern, name)
|
|
||||||
|
|
||||||
def search_in_log(self, pattern, name='access.log'):
|
|
||||||
return super().search_in_log(pattern, name)
|
|
||||||
|
|
||||||
def test_variables_dollar(self):
|
def test_variables_dollar(self):
|
||||||
assert 'success' in self.conf("301", 'routes/0/action/return')
|
assert 'success' in self.conf("301", 'routes/0/action/return')
|
||||||
|
|
||||||
@@ -49,7 +43,7 @@ class TestVariables(TestApplicationProto):
|
|||||||
)
|
)
|
||||||
check_dollar('path$dollar${dollar}', 'path$$')
|
check_dollar('path$dollar${dollar}', 'path$$')
|
||||||
|
|
||||||
def test_variables_request_time(self):
|
def test_variables_request_time(self, wait_for_record):
|
||||||
self.set_format('$uri $request_time')
|
self.set_format('$uri $request_time')
|
||||||
|
|
||||||
sock = self.http(b'', raw=True, no_recv=True)
|
sock = self.http(b'', raw=True, no_recv=True)
|
||||||
@@ -57,7 +51,7 @@ class TestVariables(TestApplicationProto):
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
assert self.get(url='/r_time_1', sock=sock)['status'] == 200
|
assert self.get(url='/r_time_1', sock=sock)['status'] == 200
|
||||||
assert self.wait_for_record(r'\/r_time_1 0\.\d{3}') is not None
|
assert wait_for_record(r'\/r_time_1 0\.\d{3}', 'access.log') is not None
|
||||||
|
|
||||||
sock = self.http(
|
sock = self.http(
|
||||||
b"""G""",
|
b"""G""",
|
||||||
@@ -76,67 +70,70 @@ Connection: close
|
|||||||
sock=sock,
|
sock=sock,
|
||||||
raw=True,
|
raw=True,
|
||||||
)
|
)
|
||||||
assert self.wait_for_record(r'\/r_time_2 [1-9]\.\d{3}') is not None
|
assert (
|
||||||
|
wait_for_record(r'\/r_time_2 [1-9]\.\d{3}', 'access.log')
|
||||||
|
is not None
|
||||||
|
)
|
||||||
|
|
||||||
def test_variables_method(self):
|
def test_variables_method(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$method')
|
self.set_format('$method')
|
||||||
|
|
||||||
reg = r'^GET$'
|
reg = r'^GET$'
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
assert self.wait_for_record(reg) is not None, 'method GET'
|
assert wait_for_record(reg, 'access.log') is not None, 'method GET'
|
||||||
|
|
||||||
reg = r'^POST$'
|
reg = r'^POST$'
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.post()['status'] == 200
|
assert self.post()['status'] == 200
|
||||||
assert self.wait_for_record(reg) is not None, 'method POST'
|
assert wait_for_record(reg, 'access.log') is not None, 'method POST'
|
||||||
|
|
||||||
def test_variables_request_uri(self):
|
def test_variables_request_uri(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$request_uri')
|
self.set_format('$request_uri')
|
||||||
|
|
||||||
def check_request_uri(req_uri):
|
def check_request_uri(req_uri):
|
||||||
reg = fr'^{re.escape(req_uri)}$'
|
reg = fr'^{re.escape(req_uri)}$'
|
||||||
|
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.get(url=req_uri)['status'] == 200
|
assert self.get(url=req_uri)['status'] == 200
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
check_request_uri('/3')
|
check_request_uri('/3')
|
||||||
check_request_uri('/4*')
|
check_request_uri('/4*')
|
||||||
check_request_uri('/4%2A')
|
check_request_uri('/4%2A')
|
||||||
check_request_uri('/9?q#a')
|
check_request_uri('/9?q#a')
|
||||||
|
|
||||||
def test_variables_uri(self):
|
def test_variables_uri(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$uri')
|
self.set_format('$uri')
|
||||||
|
|
||||||
def check_uri(uri, expect=None):
|
def check_uri(uri, expect=None):
|
||||||
expect = uri if expect is None else expect
|
expect = uri if expect is None else expect
|
||||||
reg = fr'^{re.escape(expect)}$'
|
reg = fr'^{re.escape(expect)}$'
|
||||||
|
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.get(url=uri)['status'] == 200
|
assert self.get(url=uri)['status'] == 200
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
check_uri('/3')
|
check_uri('/3')
|
||||||
check_uri('/4*')
|
check_uri('/4*')
|
||||||
check_uri('/5%2A', '/5*')
|
check_uri('/5%2A', '/5*')
|
||||||
check_uri('/9?q#a', '/9')
|
check_uri('/9?q#a', '/9')
|
||||||
|
|
||||||
def test_variables_host(self):
|
def test_variables_host(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$host')
|
self.set_format('$host')
|
||||||
|
|
||||||
def check_host(host, expect=None):
|
def check_host(host, expect=None):
|
||||||
expect = host if expect is None else expect
|
expect = host if expect is None else expect
|
||||||
reg = fr'^{re.escape(expect)}$'
|
reg = fr'^{re.escape(expect)}$'
|
||||||
|
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert (
|
assert (
|
||||||
self.get(headers={'Host': host, 'Connection': 'close'})[
|
self.get(headers={'Host': host, 'Connection': 'close'})[
|
||||||
'status'
|
'status'
|
||||||
]
|
]
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
check_host('localhost')
|
check_host('localhost')
|
||||||
check_host('localhost1.', 'localhost1')
|
check_host('localhost1.', 'localhost1')
|
||||||
@@ -144,63 +141,67 @@ Connection: close
|
|||||||
check_host('.localhost')
|
check_host('.localhost')
|
||||||
check_host('www.localhost')
|
check_host('www.localhost')
|
||||||
|
|
||||||
def test_variables_remote_addr(self):
|
def test_variables_remote_addr(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$remote_addr')
|
self.set_format('$remote_addr')
|
||||||
|
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
assert self.wait_for_record(r'^127\.0\.0\.1$') is not None
|
assert wait_for_record(r'^127\.0\.0\.1$', 'access.log') is not None
|
||||||
|
|
||||||
assert 'success' in self.conf(
|
assert 'success' in self.conf(
|
||||||
{"[::1]:7080": {"pass": "routes"}}, 'listeners'
|
{"[::1]:7080": {"pass": "routes"}}, 'listeners'
|
||||||
)
|
)
|
||||||
|
|
||||||
reg = r'^::1$'
|
reg = r'^::1$'
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.get(sock_type='ipv6')['status'] == 200
|
assert self.get(sock_type='ipv6')['status'] == 200
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
def test_variables_time_local(self):
|
def test_variables_time_local(
|
||||||
|
self, date_to_sec_epoch, search_in_file, wait_for_record
|
||||||
|
):
|
||||||
self.set_format('$uri $time_local $uri')
|
self.set_format('$uri $time_local $uri')
|
||||||
|
|
||||||
assert self.search_in_log(r'/time_local') is None
|
assert search_in_file(r'/time_local', 'access.log') is None
|
||||||
assert self.get(url='/time_local')['status'] == 200
|
assert self.get(url='/time_local')['status'] == 200
|
||||||
assert self.wait_for_record(r'/time_local') is not None, 'time log'
|
assert (
|
||||||
date = self.search_in_log(
|
wait_for_record(r'/time_local', 'access.log') is not None
|
||||||
|
), 'time log'
|
||||||
|
date = search_in_file(
|
||||||
r'^\/time_local (.*) \/time_local$', 'access.log'
|
r'^\/time_local (.*) \/time_local$', 'access.log'
|
||||||
)[1]
|
)[1]
|
||||||
assert (
|
assert (
|
||||||
abs(
|
abs(
|
||||||
self.date_to_sec_epoch(date, '%d/%b/%Y:%X %z')
|
date_to_sec_epoch(date, '%d/%b/%Y:%X %z')
|
||||||
- time.mktime(time.localtime())
|
- time.mktime(time.localtime())
|
||||||
)
|
)
|
||||||
< 5
|
< 5
|
||||||
), '$time_local'
|
), '$time_local'
|
||||||
|
|
||||||
def test_variables_request_line(self):
|
def test_variables_request_line(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$request_line')
|
self.set_format('$request_line')
|
||||||
|
|
||||||
reg = r'^GET \/r_line HTTP\/1\.1$'
|
reg = r'^GET \/r_line HTTP\/1\.1$'
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.get(url='/r_line')['status'] == 200
|
assert self.get(url='/r_line')['status'] == 200
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
def test_variables_status(self):
|
def test_variables_status(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$status')
|
self.set_format('$status')
|
||||||
|
|
||||||
assert 'success' in self.conf("418", 'routes/0/action/return')
|
assert 'success' in self.conf("418", 'routes/0/action/return')
|
||||||
|
|
||||||
reg = r'^418$'
|
reg = r'^418$'
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.get()['status'] == 418
|
assert self.get()['status'] == 418
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
def test_variables_header_referer(self):
|
def test_variables_header_referer(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$method $header_referer')
|
self.set_format('$method $header_referer')
|
||||||
|
|
||||||
def check_referer(referer):
|
def check_referer(referer):
|
||||||
reg = fr'^GET {re.escape(referer)}$'
|
reg = fr'^GET {re.escape(referer)}$'
|
||||||
|
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert (
|
assert (
|
||||||
self.get(
|
self.get(
|
||||||
headers={
|
headers={
|
||||||
@@ -211,19 +212,19 @@ Connection: close
|
|||||||
)['status']
|
)['status']
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
check_referer('referer-value')
|
check_referer('referer-value')
|
||||||
check_referer('')
|
check_referer('')
|
||||||
check_referer('no')
|
check_referer('no')
|
||||||
|
|
||||||
def test_variables_header_user_agent(self):
|
def test_variables_header_user_agent(self, search_in_file, wait_for_record):
|
||||||
self.set_format('$method $header_user_agent')
|
self.set_format('$method $header_user_agent')
|
||||||
|
|
||||||
def check_user_agent(user_agent):
|
def check_user_agent(user_agent):
|
||||||
reg = fr'^GET {re.escape(user_agent)}$'
|
reg = fr'^GET {re.escape(user_agent)}$'
|
||||||
|
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert (
|
assert (
|
||||||
self.get(
|
self.get(
|
||||||
headers={
|
headers={
|
||||||
@@ -234,19 +235,19 @@ Connection: close
|
|||||||
)['status']
|
)['status']
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
check_user_agent('MSIE')
|
check_user_agent('MSIE')
|
||||||
check_user_agent('')
|
check_user_agent('')
|
||||||
check_user_agent('no')
|
check_user_agent('no')
|
||||||
|
|
||||||
def test_variables_many(self):
|
def test_variables_many(self, search_in_file, wait_for_record):
|
||||||
def check_vars(uri, expect):
|
def check_vars(uri, expect):
|
||||||
reg = fr'^{re.escape(expect)}$'
|
reg = fr'^{re.escape(expect)}$'
|
||||||
|
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.get(url=uri)['status'] == 200
|
assert self.get(url=uri)['status'] == 200
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
self.set_format('$uri$method')
|
self.set_format('$uri$method')
|
||||||
check_vars('/1', '/1GET')
|
check_vars('/1', '/1GET')
|
||||||
@@ -260,7 +261,7 @@ Connection: close
|
|||||||
self.set_format('$method$method')
|
self.set_format('$method$method')
|
||||||
check_vars('/', 'GETGET')
|
check_vars('/', 'GETGET')
|
||||||
|
|
||||||
def test_variables_dynamic(self):
|
def test_variables_dynamic(self, wait_for_record):
|
||||||
self.set_format('$header_foo$cookie_foo$arg_foo')
|
self.set_format('$header_foo$cookie_foo$arg_foo')
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
@@ -270,20 +271,20 @@ Connection: close
|
|||||||
)['status']
|
)['status']
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
assert self.wait_for_record(r'^blah$') is not None
|
assert wait_for_record(r'^blah$', 'access.log') is not None
|
||||||
|
|
||||||
def test_variables_dynamic_arguments(self):
|
def test_variables_dynamic_arguments(self, search_in_file, wait_for_record):
|
||||||
def check_arg(url, expect=None):
|
def check_arg(url, expect=None):
|
||||||
expect = url if expect is None else expect
|
expect = url if expect is None else expect
|
||||||
reg = fr'^{re.escape(expect)}$'
|
reg = fr'^{re.escape(expect)}$'
|
||||||
|
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert self.get(url=url)['status'] == 200
|
assert self.get(url=url)['status'] == 200
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
def check_no_arg(url):
|
def check_no_arg(url):
|
||||||
assert self.get(url=url)['status'] == 200
|
assert self.get(url=url)['status'] == 200
|
||||||
assert self.search_in_log(r'^0$') is None
|
assert search_in_file(r'^0$', 'access.log') is None
|
||||||
|
|
||||||
self.set_format('$arg_foo_bar')
|
self.set_format('$arg_foo_bar')
|
||||||
check_arg('/?foo_bar=1', '1')
|
check_arg('/?foo_bar=1', '1')
|
||||||
@@ -304,25 +305,25 @@ Connection: close
|
|||||||
check_no_arg('/?f=0')
|
check_no_arg('/?f=0')
|
||||||
check_no_arg('/?f!~=0')
|
check_no_arg('/?f!~=0')
|
||||||
|
|
||||||
def test_variables_dynamic_headers(self):
|
def test_variables_dynamic_headers(self, search_in_file, wait_for_record):
|
||||||
def check_header(header, value):
|
def check_header(header, value):
|
||||||
reg = fr'^{value}$'
|
reg = fr'^{value}$'
|
||||||
|
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert (
|
assert (
|
||||||
self.get(headers={header: value, 'Connection': 'close'})[
|
self.get(headers={header: value, 'Connection': 'close'})[
|
||||||
'status'
|
'status'
|
||||||
]
|
]
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
def check_no_header(header):
|
def check_no_header(header):
|
||||||
assert (
|
assert (
|
||||||
self.get(headers={header: '0', 'Connection': 'close'})['status']
|
self.get(headers={header: '0', 'Connection': 'close'})['status']
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
assert self.search_in_log(r'^0$') is None
|
assert search_in_file(r'^0$', 'access.log') is None
|
||||||
|
|
||||||
self.set_format('$header_foo_bar')
|
self.set_format('$header_foo_bar')
|
||||||
check_header('foo-bar', '1')
|
check_header('foo-bar', '1')
|
||||||
@@ -336,7 +337,7 @@ Connection: close
|
|||||||
check_no_header('foo_bar')
|
check_no_header('foo_bar')
|
||||||
check_no_header('foobar')
|
check_no_header('foobar')
|
||||||
|
|
||||||
def test_variables_dynamic_cookies(self):
|
def test_variables_dynamic_cookies(self, search_in_file, wait_for_record):
|
||||||
def check_no_cookie(cookie):
|
def check_no_cookie(cookie):
|
||||||
assert (
|
assert (
|
||||||
self.get(
|
self.get(
|
||||||
@@ -348,12 +349,12 @@ Connection: close
|
|||||||
)['status']
|
)['status']
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
assert self.search_in_log(r'^0$') is None
|
assert search_in_file(r'^0$', 'access.log') is None
|
||||||
|
|
||||||
self.set_format('$cookie_foo_bar')
|
self.set_format('$cookie_foo_bar')
|
||||||
|
|
||||||
reg = r'^1$'
|
reg = r'^1$'
|
||||||
assert self.search_in_log(reg) is None
|
assert search_in_file(reg, 'access.log') is None
|
||||||
assert (
|
assert (
|
||||||
self.get(
|
self.get(
|
||||||
headers={
|
headers={
|
||||||
@@ -364,7 +365,7 @@ Connection: close
|
|||||||
)['status']
|
)['status']
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
assert self.wait_for_record(reg) is not None
|
assert wait_for_record(reg, 'access.log') is not None
|
||||||
|
|
||||||
check_no_cookie('fOo_bar=0')
|
check_no_cookie('fOo_bar=0')
|
||||||
check_no_cookie('foo_bar=')
|
check_no_cookie('foo_bar=')
|
||||||
|
|||||||
@@ -10,30 +10,6 @@ from unit.option import option
|
|||||||
class TestApplicationProto(TestControl):
|
class TestApplicationProto(TestControl):
|
||||||
application_type = None
|
application_type = None
|
||||||
|
|
||||||
def sec_epoch(self):
|
|
||||||
return time.mktime(time.gmtime())
|
|
||||||
|
|
||||||
def date_to_sec_epoch(self, date, template='%a, %d %b %Y %X %Z'):
|
|
||||||
return time.mktime(time.strptime(date, template))
|
|
||||||
|
|
||||||
def findall(self, pattern, name='unit.log', flags=re.M):
|
|
||||||
return re.findall(pattern, Log.read(name), flags)
|
|
||||||
|
|
||||||
def search_in_log(self, pattern, name='unit.log', flags=re.M):
|
|
||||||
return re.search(pattern, Log.read(name), flags)
|
|
||||||
|
|
||||||
def wait_for_record(self, pattern, name='unit.log', wait=150, flags=re.M):
|
|
||||||
with Log.open(name) as f:
|
|
||||||
for _ in range(wait):
|
|
||||||
found = re.search(pattern, f.read(), flags)
|
|
||||||
|
|
||||||
if found is not None:
|
|
||||||
break
|
|
||||||
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
return found
|
|
||||||
|
|
||||||
def get_application_type(self):
|
def get_application_type(self):
|
||||||
current_test = (
|
current_test = (
|
||||||
os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0]
|
os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0]
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
|
import os
|
||||||
|
import platform
|
||||||
|
|
||||||
class Options:
|
class Options:
|
||||||
_options = {
|
_options = {
|
||||||
|
'architecture': platform.architecture()[0],
|
||||||
|
'is_privileged': os.geteuid() == 0,
|
||||||
'skip_alerts': [],
|
'skip_alerts': [],
|
||||||
'skip_sanitizer': False,
|
'skip_sanitizer': False,
|
||||||
|
'system': platform.system()
|
||||||
}
|
}
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
|
|||||||
@@ -90,17 +90,6 @@ def findmnt():
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def sysctl():
|
|
||||||
try:
|
|
||||||
out = subprocess.check_output(
|
|
||||||
['sysctl', '-a'], stderr=subprocess.STDOUT
|
|
||||||
).decode()
|
|
||||||
except FileNotFoundError:
|
|
||||||
pytest.skip('requires sysctl')
|
|
||||||
|
|
||||||
return out
|
|
||||||
|
|
||||||
|
|
||||||
def waitformount(template, timeout=50):
|
def waitformount(template, timeout=50):
|
||||||
for _ in range(timeout):
|
for _ in range(timeout):
|
||||||
if findmnt().find(template) != -1:
|
if findmnt().find(template) != -1:
|
||||||
|
|||||||
Reference in New Issue
Block a user