Tests: refactored prerequisites model.

This commit is contained in:
Andrey Zelenkov
2019-09-14 14:44:35 +03:00
parent 962cdb6659
commit 65ca2d7b19
24 changed files with 146 additions and 113 deletions

View File

@@ -7,7 +7,7 @@ from unit.applications.lang.python import TestApplicationPython
class TestAccessLog(TestApplicationPython): class TestAccessLog(TestApplicationPython):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
def load(self, script): def load(self, script):
super().load(script) super().load(script)

View File

@@ -3,7 +3,7 @@ from unit.control import TestControl
class TestConfiguration(TestControl): class TestConfiguration(TestControl):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
def test_json_empty(self): def test_json_empty(self):
self.assertIn('error', self.conf(''), 'empty') self.assertIn('error', self.conf(''), 'empty')

View File

@@ -2,7 +2,7 @@ from unit.applications.lang.go import TestApplicationGo
class TestGoApplication(TestApplicationGo): class TestGoApplication(TestApplicationGo):
prerequisites = ['go'] prerequisites = {'modules': ['go']}
def test_go_application_variables(self): def test_go_application_variables(self):
self.load('variables') self.load('variables')

View File

@@ -3,7 +3,7 @@ from unit.applications.lang.python import TestApplicationPython
class TestHTTPHeader(TestApplicationPython): class TestHTTPHeader(TestApplicationPython):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
def test_http_header_value_leading_sp(self): def test_http_header_value_leading_sp(self):
self.load('custom_header') self.load('custom_header')

View File

@@ -4,7 +4,7 @@ from unit.applications.lang.java import TestApplicationJava
class TestJavaApplication(TestApplicationJava): class TestJavaApplication(TestApplicationJava):
prerequisites = ['java'] prerequisites = {'modules': ['java']}
def test_java_conf_error(self): def test_java_conf_error(self):
self.skip_alerts.extend( self.skip_alerts.extend(

View File

@@ -6,7 +6,7 @@ from unit.applications.websockets import TestApplicationWebsocket
class TestJavaWebsockets(TestApplicationJava): class TestJavaWebsockets(TestApplicationJava):
prerequisites = ['java'] prerequisites = {'modules': ['java']}
ws = TestApplicationWebsocket(True) ws = TestApplicationWebsocket(True)

View File

@@ -3,7 +3,7 @@ from unit.applications.lang.node import TestApplicationNode
class TestNodeApplication(TestApplicationNode): class TestNodeApplication(TestApplicationNode):
prerequisites = ['node'] prerequisites = {'modules': ['node']}
def test_node_application_basic(self): def test_node_application_basic(self):
self.load('basic') self.load('basic')

View File

@@ -6,7 +6,7 @@ from unit.applications.websockets import TestApplicationWebsocket
class TestNodeWebsockets(TestApplicationNode): class TestNodeWebsockets(TestApplicationNode):
prerequisites = ['node'] prerequisites = {'modules': ['node']}
ws = TestApplicationWebsocket() ws = TestApplicationWebsocket()

View File

@@ -3,7 +3,7 @@ from unit.applications.lang.perl import TestApplicationPerl
class TestPerlApplication(TestApplicationPerl): class TestPerlApplication(TestApplicationPerl):
prerequisites = ['perl'] prerequisites = {'modules': ['perl']}
def test_perl_application(self): def test_perl_application(self):
self.load('variables') self.load('variables')

View File

@@ -3,7 +3,7 @@ import unittest
from unit.applications.lang.php import TestApplicationPHP from unit.applications.lang.php import TestApplicationPHP
class TestPHPApplication(TestApplicationPHP): class TestPHPApplication(TestApplicationPHP):
prerequisites = ['php'] prerequisites = {'modules': ['php']}
def before_disable_functions(self): def before_disable_functions(self):
body = self.get()['body'] body = self.get()['body']

View File

@@ -2,7 +2,7 @@ from unit.control import TestControl
class TestPHPBasic(TestControl): class TestPHPBasic(TestControl):
prerequisites = ['php'] prerequisites = {'modules': ['php']}
conf_app = { conf_app = {
"app": { "app": {

View File

@@ -4,7 +4,7 @@ from unit.applications.lang.python import TestApplicationPython
class TestPythonApplication(TestApplicationPython): class TestPythonApplication(TestApplicationPython):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
def test_python_application_variables(self): def test_python_application_variables(self):
self.load('variables') self.load('variables')

View File

@@ -2,7 +2,7 @@ from unit.control import TestControl
class TestPythonBasic(TestControl): class TestPythonBasic(TestControl):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
conf_app = { conf_app = {
"app": { "app": {

View File

@@ -2,7 +2,7 @@ from unit.applications.lang.python import TestApplicationPython
class TestPythonEnvironment(TestApplicationPython): class TestPythonEnvironment(TestApplicationPython):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
def test_python_environment_name_null(self): def test_python_environment_name_null(self):
self.load('environment') self.load('environment')

View File

@@ -6,7 +6,7 @@ from unit.applications.lang.python import TestApplicationPython
class TestPythonProcman(TestApplicationPython): class TestPythonProcman(TestApplicationPython):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
def pids_for_process(self): def pids_for_process(self):
time.sleep(0.2) time.sleep(0.2)

View File

@@ -3,7 +3,7 @@ from unit.applications.proto import TestApplicationProto
class TestRouting(TestApplicationProto): class TestRouting(TestApplicationProto):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
def setUp(self): def setUp(self):
super().setUp() super().setUp()

View File

@@ -2,7 +2,7 @@ from unit.applications.tls import TestApplicationTLS
class TestRoutingTLS(TestApplicationTLS): class TestRoutingTLS(TestApplicationTLS):
prerequisites = ['python', 'openssl'] prerequisites = {'modules': ['python', 'openssl']}
def test_routes_match_scheme(self): def test_routes_match_scheme(self):
self.certificate() self.certificate()

View File

@@ -3,7 +3,7 @@ from unit.applications.lang.ruby import TestApplicationRuby
class TestRubyApplication(TestApplicationRuby): class TestRubyApplication(TestApplicationRuby):
prerequisites = ['ruby'] prerequisites = {'modules': ['ruby']}
def test_ruby_application(self): def test_ruby_application(self):
self.load('variables') self.load('variables')

View File

@@ -5,7 +5,7 @@ from unit.applications.lang.python import TestApplicationPython
class TestSettings(TestApplicationPython): class TestSettings(TestApplicationPython):
prerequisites = ['python'] prerequisites = {'modules': ['python']}
def test_settings_header_read_timeout(self): def test_settings_header_read_timeout(self):
self.load('empty') self.load('empty')

View File

@@ -6,7 +6,7 @@ from unit.applications.tls import TestApplicationTLS
class TestTLS(TestApplicationTLS): class TestTLS(TestApplicationTLS):
prerequisites = ['python', 'openssl'] prerequisites = {'modules': ['python', 'openssl']}
def findall(self, pattern): def findall(self, pattern):
with open(self.testdir + '/unit.log', 'r', errors='ignore') as f: with open(self.testdir + '/unit.log', 'r', errors='ignore') as f:

View File

@@ -4,6 +4,19 @@ from unit.applications.proto import TestApplicationProto
class TestApplicationGo(TestApplicationProto): class TestApplicationGo(TestApplicationProto):
@classmethod
def setUpClass(cls, complete_check=True):
unit = super().setUpClass(complete_check=False)
# check go module
go_app = TestApplicationGo()
go_app.testdir = unit.testdir
if go_app.prepare_env('empty', 'app').returncode == 0:
cls.available['modules']['go'] = []
return unit if not complete_check else unit.complete()
def prepare_env(self, script, name): def prepare_env(self, script, name):
if not os.path.exists(self.testdir + '/go'): if not os.path.exists(self.testdir + '/go'):
os.mkdir(self.testdir + '/go') os.mkdir(self.testdir + '/go')

View File

@@ -4,6 +4,17 @@ from unit.applications.proto import TestApplicationProto
class TestApplicationNode(TestApplicationProto): class TestApplicationNode(TestApplicationProto):
@classmethod
def setUpClass(cls, complete_check=True):
unit = super().setUpClass(complete_check=False)
# check node module
if os.path.exists(unit.pardir + '/node/node_modules'):
cls.available['modules']['node'] = []
return unit if not complete_check else unit.complete()
def load(self, script, name='app.js'): def load(self, script, name='app.js'):
# copy application # copy application

View File

@@ -1,4 +1,5 @@
import os import os
import re
import ssl import ssl
import subprocess import subprocess
from unit.applications.proto import TestApplicationProto from unit.applications.proto import TestApplicationProto
@@ -12,6 +13,27 @@ class TestApplicationTLS(TestApplicationProto):
self.context.check_hostname = False self.context.check_hostname = False
self.context.verify_mode = ssl.CERT_NONE self.context.verify_mode = ssl.CERT_NONE
@classmethod
def setUpClass(cls, complete_check=True):
unit = super().setUpClass(complete_check=False)
# check tls module
try:
subprocess.check_output(['which', 'openssl'])
output = subprocess.check_output(
[unit.unitd, '--version'], stderr=subprocess.STDOUT
)
if re.search('--openssl', output.decode()):
cls.available['modules']['openssl'] = []
except:
pass
return unit if not complete_check else unit.complete()
def certificate(self, name='default', load=True): def certificate(self, name='default', load=True):
self.openssl_conf() self.openssl_conf()

View File

@@ -12,8 +12,6 @@ import subprocess
from multiprocessing import Process from multiprocessing import Process
available_modules = {}
class TestUnit(unittest.TestCase): class TestUnit(unittest.TestCase):
current_dir = os.path.abspath( current_dir = os.path.abspath(
@@ -45,9 +43,9 @@ class TestUnit(unittest.TestCase):
# rerun test for each available module version # rerun test for each available module version
type = self.application_type type = self.application_type
for prerequisite in self.prerequisites: for module in self.prerequisites['modules']:
if prerequisite in available_modules: if module in self.available['modules']:
for version in available_modules[prerequisite]: for version in self.available['modules'][module]:
self.application_type = type + ' ' + version self.application_type = type + ' ' + version
super().run(result) super().run(result)
@@ -66,8 +64,83 @@ class TestUnit(unittest.TestCase):
unittest.main() unittest.main()
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls, complete_check=True):
TestUnit().check_modules(*cls.prerequisites) cls.available = {'modules': {}, 'features': {}}
unit = TestUnit()
unit._run()
# read unit.log
for i in range(50):
with open(unit.testdir + '/unit.log', 'r') as f:
log = f.read()
m = re.search('controller started', log)
if m is None:
time.sleep(0.1)
else:
break
if m is None:
unit.stop()
exit("Unit is writing log too long")
# discover available modules from unit.log
for module in re.findall(r'module: ([a-zA-Z]+) (.*) ".*"$', log, re.M):
if module[0] not in cls.available['modules']:
cls.available['modules'][module[0]] = [module[1]]
else:
cls.available['modules'][module[0]].append(module[1])
def check(available, prerequisites):
missed = []
# check modules
if 'modules' in prerequisites:
available_modules = list(available['modules'].keys())
for module in prerequisites['modules']:
if module in available_modules:
continue
missed.append(module)
if missed:
print('Unit has no ' + ', '.join(missed) + ' module(s)')
raise unittest.SkipTest()
# check features
if 'features' in prerequisites:
available_features = list(available['modules'].keys())
for feature in prerequisites['features']:
if feature in available_features:
continue
missed.append(feature)
if missed:
print(', '.join(missed) + ' feature(s) not supported')
raise unittest.SkipTest()
def destroy():
unit.stop()
unit._check_alerts(log)
shutil.rmtree(unit.testdir)
def complete():
destroy()
check(cls.available, cls.prerequisites)
if complete_check:
complete()
else:
unit.complete = complete
return unit
def setUp(self): def setUp(self):
self._run() self._run()
@@ -108,92 +181,6 @@ class TestUnit(unittest.TestCase):
else: else:
self._print_path_to_log() self._print_path_to_log()
def check_modules(self, *modules):
self._run()
for i in range(50):
with open(self.testdir + '/unit.log', 'r') as f:
log = f.read()
m = re.search('controller started', log)
if m is None:
time.sleep(0.1)
else:
break
if m is None:
self.stop()
exit("Unit is writing log too long")
# discover all available modules
global available_modules
available_modules = {}
for module in re.findall(r'module: ([a-zA-Z]+) (.*) ".*"$', log, re.M):
if module[0] not in available_modules:
available_modules[module[0]] = [module[1]]
else:
available_modules[module[0]].append(module[1])
missed_module = ''
for module in modules:
if module == 'go':
env = os.environ.copy()
env['GOPATH'] = self.pardir + '/go'
try:
process = subprocess.Popen(
[
'go',
'build',
'-o',
self.testdir + '/go/check_module',
self.current_dir + '/go/empty/app.go',
],
env=env,
)
process.communicate()
m = module if process.returncode == 0 else None
except:
m = None
elif module == 'node':
if os.path.isdir(self.pardir + '/node/node_modules'):
m = module
else:
m = None
elif module == 'openssl':
try:
subprocess.check_output(['which', 'openssl'])
output = subprocess.check_output(
[self.unitd, '--version'],
stderr=subprocess.STDOUT,
)
m = re.search('--openssl', output.decode())
except:
m = None
else:
if module not in available_modules:
m = None
if m is None:
missed_module = module
break
self.stop()
self._check_alerts(log)
shutil.rmtree(self.testdir)
if missed_module:
raise unittest.SkipTest('Unit has no ' + missed_module + ' module')
def stop(self): def stop(self):
if self._started: if self._started:
self._stop() self._stop()