summaryrefslogtreecommitdiffhomepage
path: root/test/conftest.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/conftest.py')
-rw-r--r--test/conftest.py137
1 files changed, 117 insertions, 20 deletions
diff --git a/test/conftest.py b/test/conftest.py
index b62264ca..0b9adf69 100644
--- a/test/conftest.py
+++ b/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")