Tests: style.
This commit is contained in:
@@ -6,7 +6,6 @@ import platform
|
|||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
import socket
|
|
||||||
import stat
|
import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@@ -15,11 +14,12 @@ import time
|
|||||||
from multiprocessing import Process
|
from multiprocessing import Process
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.check.go import check_go
|
from unit.check.go import check_go
|
||||||
from unit.check.isolation import check_isolation
|
from unit.check.isolation import check_isolation
|
||||||
from unit.check.node import check_node
|
from unit.check.node import check_node
|
||||||
from unit.check.tls import check_openssl
|
|
||||||
from unit.check.regex import check_regex
|
from unit.check.regex import check_regex
|
||||||
|
from unit.check.tls import check_openssl
|
||||||
from unit.http import TestHTTP
|
from unit.http import TestHTTP
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
from unit.utils import public_dir
|
from unit.utils import public_dir
|
||||||
@@ -85,6 +85,7 @@ _fds_check = {
|
|||||||
}
|
}
|
||||||
http = TestHTTP()
|
http = TestHTTP()
|
||||||
|
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
option.config = config.option
|
option.config = config.option
|
||||||
|
|
||||||
@@ -115,9 +116,11 @@ def pytest_configure(config):
|
|||||||
|
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
cls = metafunc.cls
|
cls = metafunc.cls
|
||||||
if (not hasattr(cls, 'application_type')
|
if (
|
||||||
|
not hasattr(cls, 'application_type')
|
||||||
or cls.application_type == None
|
or cls.application_type == None
|
||||||
or cls.application_type == 'external'):
|
or cls.application_type == 'external'
|
||||||
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
type = cls.application_type
|
type = cls.application_type
|
||||||
@@ -216,6 +219,7 @@ def pytest_sessionstart(session):
|
|||||||
elif option.save_log:
|
elif option.save_log:
|
||||||
open(unit_instance['temp_dir'] + '/' + unit_log_copy, 'w').close()
|
open(unit_instance['temp_dir'] + '/' + unit_log_copy, 'w').close()
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
|
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
|
||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
# execute all other hooks to obtain the report object
|
# execute all other hooks to obtain the report object
|
||||||
@@ -320,7 +324,9 @@ def run(request):
|
|||||||
|
|
||||||
public_dir(path)
|
public_dir(path)
|
||||||
|
|
||||||
if os.path.isfile(path) or stat.S_ISSOCK(os.stat(path).st_mode):
|
if os.path.isfile(path) or stat.S_ISSOCK(
|
||||||
|
os.stat(path).st_mode
|
||||||
|
):
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
else:
|
else:
|
||||||
shutil.rmtree(path)
|
shutil.rmtree(path)
|
||||||
@@ -384,6 +390,7 @@ def run(request):
|
|||||||
|
|
||||||
_check_alerts(log=log)
|
_check_alerts(log=log)
|
||||||
|
|
||||||
|
|
||||||
def unit_run():
|
def unit_run():
|
||||||
global unit_instance
|
global unit_instance
|
||||||
|
|
||||||
@@ -482,7 +489,6 @@ def unit_stop():
|
|||||||
return 'Could not terminate unit'
|
return 'Could not terminate unit'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _check_alerts(path=None, log=None):
|
def _check_alerts(path=None, log=None):
|
||||||
if path is None:
|
if path is None:
|
||||||
path = unit_instance['log']
|
path = unit_instance['log']
|
||||||
@@ -554,24 +560,21 @@ def _clear_conf(sock, log=None):
|
|||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
certs = json.loads(http.get(
|
certs = json.loads(
|
||||||
url='/certificates',
|
http.get(url='/certificates', sock_type='unix', addr=sock,)['body']
|
||||||
sock_type='unix',
|
).keys()
|
||||||
addr=sock,
|
|
||||||
)['body']).keys()
|
|
||||||
|
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
pytest.fail('Can\'t parse certificates list.')
|
pytest.fail('Can\'t parse certificates list.')
|
||||||
|
|
||||||
for cert in certs:
|
for cert in certs:
|
||||||
resp = http.delete(
|
resp = http.delete(
|
||||||
url='/certificates/' + cert,
|
url='/certificates/' + cert, sock_type='unix', addr=sock,
|
||||||
sock_type='unix',
|
|
||||||
addr=sock,
|
|
||||||
)['body']
|
)['body']
|
||||||
|
|
||||||
check_success(resp)
|
check_success(resp)
|
||||||
|
|
||||||
|
|
||||||
def _count_fds(pid):
|
def _count_fds(pid):
|
||||||
procfile = '/proc/%s/fd' % pid
|
procfile = '/proc/%s/fd' % pid
|
||||||
if os.path.isdir(procfile):
|
if os.path.isdir(procfile):
|
||||||
@@ -606,6 +609,7 @@ def run_process(target, *args):
|
|||||||
|
|
||||||
_processes.append(process)
|
_processes.append(process)
|
||||||
|
|
||||||
|
|
||||||
def stop_processes():
|
def stop_processes():
|
||||||
if not _processes:
|
if not _processes:
|
||||||
return
|
return
|
||||||
@@ -657,18 +661,22 @@ def skip_fds_check():
|
|||||||
def temp_dir(request):
|
def temp_dir(request):
|
||||||
return unit_instance['temp_dir']
|
return unit_instance['temp_dir']
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def is_unsafe(request):
|
def is_unsafe(request):
|
||||||
return request.config.getoption("--unsafe")
|
return request.config.getoption("--unsafe")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def is_su(request):
|
def is_su(request):
|
||||||
return os.geteuid() == 0
|
return os.geteuid() == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def unit_pid(request):
|
def unit_pid(request):
|
||||||
return unit_instance['process'].pid
|
return unit_instance['process'].pid
|
||||||
|
|
||||||
|
|
||||||
def pytest_sessionfinish(session):
|
def pytest_sessionfinish(session):
|
||||||
if not option.restart and option.save_log:
|
if not option.restart and option.save_log:
|
||||||
print('Path to unit.log:\n' + unit_instance['log'] + '\n')
|
print('Path to unit.log:\n' + unit_instance['log'] + '\n')
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import atexit
|
import atexit
|
||||||
|
|
||||||
|
|
||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
def at_exit():
|
def at_exit():
|
||||||
environ['wsgi.errors'].write('At exit called.\n')
|
environ['wsgi.errors'].write('At exit called.\n')
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import io
|
import io
|
||||||
|
|
||||||
|
|
||||||
def application(env, start_response):
|
def application(env, start_response):
|
||||||
start_response('200', [('Content-Length', '10')])
|
start_response('200', [('Content-Length', '10')])
|
||||||
f = io.BytesIO(b'0123456789')
|
f = io.BytesIO(b'0123456789')
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ def application(env, start_response):
|
|||||||
start_response('204', [('Content-Length', '0')])
|
start_response('204', [('Content-Length', '0')])
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def app(env, start_response):
|
def app(env, start_response):
|
||||||
start_response('200', [('Content-Length', '0')])
|
start_response('200', [('Content-Length', '0')])
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import atexit
|
import atexit
|
||||||
|
|
||||||
|
|
||||||
class application:
|
class application:
|
||||||
def __init__(self, environ, start_response):
|
def __init__(self, environ, start_response):
|
||||||
self.environ = environ
|
self.environ = environ
|
||||||
@@ -11,13 +12,14 @@ class application:
|
|||||||
content_length = int(self.environ.get('CONTENT_LENGTH', 0))
|
content_length = int(self.environ.get('CONTENT_LENGTH', 0))
|
||||||
body = bytes(self.environ['wsgi.input'].read(content_length))
|
body = bytes(self.environ['wsgi.input'].read(content_length))
|
||||||
|
|
||||||
self.start('200', [
|
self.start(
|
||||||
|
'200',
|
||||||
|
[
|
||||||
('Content-Type', self.environ.get('CONTENT_TYPE')),
|
('Content-Type', self.environ.get('CONTENT_TYPE')),
|
||||||
('Content-Length', str(len(body)))
|
('Content-Length', str(len(body))),
|
||||||
])
|
],
|
||||||
|
)
|
||||||
yield body
|
yield body
|
||||||
|
|
||||||
def _atexit(self):
|
def _atexit(self):
|
||||||
self.start('200', [
|
self.start('200', [('Content-Length', '0')])
|
||||||
('Content-Length', '0')
|
|
||||||
])
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
|
|
||||||
start_response('200', [
|
start_response(
|
||||||
|
'200',
|
||||||
|
[
|
||||||
('Content-Length', '0'),
|
('Content-Length', '0'),
|
||||||
('Custom-Header', environ.get('HTTP_CUSTOM_HEADER'))
|
('Custom-Header', environ.get('HTTP_CUSTOM_HEADER')),
|
||||||
])
|
],
|
||||||
|
)
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
async def application(scope, receive, send):
|
async def application(scope, receive, send):
|
||||||
assert scope['type'] == 'http'
|
assert scope['type'] == 'http'
|
||||||
|
|
||||||
@@ -28,13 +29,13 @@ async def application(scope, receive, send):
|
|||||||
loop.call_later(n, future.set_result, None)
|
loop.call_later(n, future.set_result, None)
|
||||||
await future
|
await future
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [(b'content-length', str(len(body)).encode()),],
|
||||||
(b'content-length', str(len(body)).encode()),
|
}
|
||||||
]
|
)
|
||||||
})
|
|
||||||
|
|
||||||
if not body:
|
if not body:
|
||||||
await sleep(delay)
|
await sleep(delay)
|
||||||
@@ -42,10 +43,12 @@ async def application(scope, receive, send):
|
|||||||
|
|
||||||
step = int(len(body) / parts)
|
step = int(len(body) / parts)
|
||||||
for i in range(0, len(body), step):
|
for i in range(0, len(body), step):
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.body',
|
'type': 'http.response.body',
|
||||||
'body': body[i : i + step],
|
'body': body[i : i + step],
|
||||||
'more_body': True,
|
'more_body': True,
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
await sleep(delay)
|
await sleep(delay)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
async def application(scope, receive, send):
|
async def application(scope, receive, send):
|
||||||
assert scope['type'] == 'http'
|
assert scope['type'] == 'http'
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [(b'content-length', b'0')],
|
||||||
(b'content-length', b'0'),
|
}
|
||||||
]
|
)
|
||||||
})
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def application(env, start_response):
|
def application(env, start_response):
|
||||||
body = ''
|
body = ''
|
||||||
vars = env.get('HTTP_X_VARIABLES').split(',')
|
vars = env.get('HTTP_X_VARIABLES').split(',')
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ def application(environ, start_response):
|
|||||||
|
|
||||||
h = (k for k, v in environ.items() if k.startswith('HTTP_'))
|
h = (k for k, v in environ.items() if k.startswith('HTTP_'))
|
||||||
|
|
||||||
start_response('200', [
|
start_response(
|
||||||
('Content-Length', '0'),
|
'200', [('Content-Length', '0'), ('All-Headers', ','.join(h))]
|
||||||
('All-Headers', ','.join(h))
|
)
|
||||||
])
|
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
def application(env, start_response):
|
def application(env, start_response):
|
||||||
start_response('200', [
|
start_response(
|
||||||
|
'200',
|
||||||
|
[
|
||||||
('Content-Length', '0'),
|
('Content-Length', '0'),
|
||||||
('X-Server-Name', env.get('SERVER_NAME')),
|
('X-Server-Name', env.get('SERVER_NAME')),
|
||||||
('X-Http-Host', str(env.get('HTTP_HOST')))
|
('X-Http-Host', str(env.get('HTTP_HOST'))),
|
||||||
])
|
],
|
||||||
|
)
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ class application:
|
|||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
self.__i = 0
|
self.__i = 0
|
||||||
self._skip_level = int(self.environ.get('HTTP_X_SKIP', 0))
|
self._skip_level = int(self.environ.get('HTTP_X_SKIP', 0))
|
||||||
self._not_skip_close = int(self.environ.get('HTTP_X_NOT_SKIP_CLOSE', 0))
|
self._not_skip_close = int(
|
||||||
|
self.environ.get('HTTP_X_NOT_SKIP_CLOSE', 0)
|
||||||
|
)
|
||||||
self._is_chunked = self.environ.get('HTTP_X_CHUNKED')
|
self._is_chunked = self.environ.get('HTTP_X_CHUNKED')
|
||||||
|
|
||||||
headers = [(('Content-Length', '10'))]
|
headers = [(('Content-Length', '10'))]
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ def application(scope):
|
|||||||
|
|
||||||
return app_http
|
return app_http
|
||||||
|
|
||||||
|
|
||||||
async def app_http(receive, send):
|
async def app_http(receive, send):
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [(b'content-length', b'0'),],
|
||||||
(b'content-length', b'0'),
|
}
|
||||||
]
|
)
|
||||||
})
|
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ def application(scope, receive=None, send=None):
|
|||||||
else:
|
else:
|
||||||
return app_http(receive, send)
|
return app_http(receive, send)
|
||||||
|
|
||||||
|
|
||||||
async def app_http(receive, send):
|
async def app_http(receive, send):
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [(b'content-length', b'0'),],
|
||||||
(b'content-length', b'0'),
|
}
|
||||||
]
|
)
|
||||||
})
|
|
||||||
|
|||||||
@@ -8,15 +8,12 @@ async def application(scope, receive, send):
|
|||||||
if not m.get('more_body', False):
|
if not m.get('more_body', False):
|
||||||
break
|
break
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [(b'content-length', str(len(body)).encode())],
|
||||||
(b'content-length', str(len(body)).encode()),
|
}
|
||||||
]
|
)
|
||||||
})
|
|
||||||
|
|
||||||
await send({
|
await send({'type': 'http.response.body', 'body': body})
|
||||||
'type': 'http.response.body',
|
|
||||||
'body': body,
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -3,7 +3,5 @@ def application(environ, start_response):
|
|||||||
content_length = int(environ.get('CONTENT_LENGTH', 0))
|
content_length = int(environ.get('CONTENT_LENGTH', 0))
|
||||||
body = bytes(environ['wsgi.input'].read(content_length))
|
body = bytes(environ['wsgi.input'].read(content_length))
|
||||||
|
|
||||||
start_response('200', [
|
start_response('200', [('Content-Length', str(len(body)))])
|
||||||
('Content-Length', str(len(body)))
|
|
||||||
])
|
|
||||||
return [body]
|
return [body]
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
body = os.pathsep.join(sys.path).encode()
|
body = os.pathsep.join(sys.path).encode()
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
async def application(scope, receive, send):
|
async def application(scope, receive, send):
|
||||||
assert scope['type'] == 'http'
|
assert scope['type'] == 'http'
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [
|
||||||
(b'content-length', b'0'),
|
(b'content-length', b'0'),
|
||||||
(b'query-string', scope['query_string']),
|
(b'query-string', scope['query_string']),
|
||||||
]
|
],
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
|
|
||||||
start_response('200', [
|
start_response(
|
||||||
|
'200',
|
||||||
|
[
|
||||||
('Content-Length', '0'),
|
('Content-Length', '0'),
|
||||||
('Query-String', environ.get('QUERY_STRING'))
|
('Query-String', environ.get('QUERY_STRING')),
|
||||||
])
|
],
|
||||||
|
)
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
async def application(scope, receive, send):
|
async def application(scope, receive, send):
|
||||||
assert scope['type'] == 'http'
|
assert scope['type'] == 'http'
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [
|
||||||
(b'content-length', b'0'),
|
(b'content-length', b'0'),
|
||||||
(b'server-port', str(scope['server'][1]).encode()),
|
(b'server-port', str(scope['server'][1]).encode()),
|
||||||
]
|
],
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
|
|
||||||
start_response('200', [
|
start_response(
|
||||||
('Content-Length', '0'),
|
'200',
|
||||||
('Server-Port', environ.get('SERVER_PORT'))
|
[('Content-Length', '0'), ('Server-Port', environ.get('SERVER_PORT'))],
|
||||||
])
|
)
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ async def application(scope, receive, send):
|
|||||||
Foo(Foo.num).start()
|
Foo(Foo.num).start()
|
||||||
Foo.num += 10
|
Foo.num += 10
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [(b'content-length', b'0')],
|
||||||
(b'content-length', b'0'),
|
}
|
||||||
]
|
)
|
||||||
})
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import asyncio
|
|||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
|
||||||
async def application(scope, receive, send):
|
async def application(scope, receive, send):
|
||||||
assert scope['type'] == 'http'
|
assert scope['type'] == 'http'
|
||||||
|
|
||||||
@@ -17,11 +18,13 @@ async def application(scope, receive, send):
|
|||||||
|
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [
|
||||||
(b'content-length', b'0'),
|
(b'content-length', b'0'),
|
||||||
(b'x-thread', str(threading.currentThread().ident).encode()),
|
(b'x-thread', str(threading.currentThread().ident).encode()),
|
||||||
]
|
],
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
|
||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
delay = float(environ.get('HTTP_X_DELAY', 0))
|
delay = float(environ.get('HTTP_X_DELAY', 0))
|
||||||
|
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
|
|
||||||
start_response('200', [
|
start_response(
|
||||||
|
'200',
|
||||||
|
[
|
||||||
('Content-Length', '0'),
|
('Content-Length', '0'),
|
||||||
('Wsgi-Multithread', str(environ['wsgi.multithread'])),
|
('Wsgi-Multithread', str(environ['wsgi.multithread'])),
|
||||||
('X-Thread', str(threading.currentThread().ident))
|
('X-Thread', str(threading.currentThread().ident)),
|
||||||
])
|
],
|
||||||
|
)
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from tempfile import TemporaryFile
|
from tempfile import TemporaryFile
|
||||||
import os, cgi
|
import os, cgi
|
||||||
|
|
||||||
|
|
||||||
def read(environ):
|
def read(environ):
|
||||||
length = int(environ.get('CONTENT_LENGTH', 0))
|
length = int(environ.get('CONTENT_LENGTH', 0))
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ def read(environ):
|
|||||||
environ['wsgi.input'] = body
|
environ['wsgi.input'] = body
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
|
||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
file = read(environ)
|
file = read(environ)
|
||||||
|
|
||||||
@@ -19,9 +21,9 @@ def application(environ, start_response):
|
|||||||
filename = form['file'].filename
|
filename = form['file'].filename
|
||||||
data = filename.encode() + form['file'].file.read()
|
data = filename.encode() + form['file'].file.read()
|
||||||
|
|
||||||
start_response('200 OK', [
|
start_response(
|
||||||
('Content-Type', 'text/plain'),
|
'200 OK',
|
||||||
('Content-Length', str(len(data))),
|
[('Content-Type', 'text/plain'), ('Content-Length', str(len(data)))],
|
||||||
])
|
)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
uid = os.geteuid()
|
uid = os.geteuid()
|
||||||
gid = os.getegid()
|
gid = os.getegid()
|
||||||
|
|
||||||
out = json.dumps({
|
out = json.dumps({'UID': uid, 'GID': gid,}).encode('utf-8')
|
||||||
'UID': uid,
|
|
||||||
'GID': gid,
|
|
||||||
}).encode('utf-8')
|
|
||||||
|
|
||||||
start_response('200 OK', [
|
start_response(
|
||||||
|
'200 OK',
|
||||||
|
[
|
||||||
('Content-Length', str(len(out))),
|
('Content-Length', str(len(out))),
|
||||||
('Content-Type', 'application/json')
|
('Content-Type', 'application/json'),
|
||||||
])
|
],
|
||||||
|
)
|
||||||
|
|
||||||
return [out]
|
return [out]
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ async def application(scope, receive, send):
|
|||||||
res.append(h[1])
|
res.append(h[1])
|
||||||
return b', '.join(res)
|
return b', '.join(res)
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'http.response.start',
|
'type': 'http.response.start',
|
||||||
'status': 200,
|
'status': 200,
|
||||||
'headers': [
|
'headers': [
|
||||||
@@ -31,10 +32,8 @@ async def application(scope, receive, send):
|
|||||||
(b'asgi-spec-version', scope['asgi']['spec_version'].encode()),
|
(b'asgi-spec-version', scope['asgi']['spec_version'].encode()),
|
||||||
(b'scheme', scope['scheme'].encode()),
|
(b'scheme', scope['scheme'].encode()),
|
||||||
(b'custom-header', get_header(b'custom-header')),
|
(b'custom-header', get_header(b'custom-header')),
|
||||||
]
|
],
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
await send({
|
await send({'type': 'http.response.body', 'body': body})
|
||||||
'type': 'http.response.body',
|
|
||||||
'body': body,
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ def application(environ, start_response):
|
|||||||
content_length = int(environ.get('CONTENT_LENGTH', 0))
|
content_length = int(environ.get('CONTENT_LENGTH', 0))
|
||||||
body = bytes(environ['wsgi.input'].read(content_length))
|
body = bytes(environ['wsgi.input'].read(content_length))
|
||||||
|
|
||||||
start_response('200', [
|
start_response(
|
||||||
|
'200',
|
||||||
|
[
|
||||||
('Content-Type', environ.get('CONTENT_TYPE')),
|
('Content-Type', environ.get('CONTENT_TYPE')),
|
||||||
('Content-Length', str(len(body))),
|
('Content-Length', str(len(body))),
|
||||||
('Request-Method', environ.get('REQUEST_METHOD')),
|
('Request-Method', environ.get('REQUEST_METHOD')),
|
||||||
@@ -16,6 +18,7 @@ def application(environ, start_response):
|
|||||||
('Wsgi-Url-Scheme', environ['wsgi.url_scheme']),
|
('Wsgi-Url-Scheme', environ['wsgi.url_scheme']),
|
||||||
('Wsgi-Multithread', str(environ['wsgi.multithread'])),
|
('Wsgi-Multithread', str(environ['wsgi.multithread'])),
|
||||||
('Wsgi-Multiprocess', str(environ['wsgi.multiprocess'])),
|
('Wsgi-Multiprocess', str(environ['wsgi.multiprocess'])),
|
||||||
('Wsgi-Run-Once', str(environ['wsgi.run_once']))
|
('Wsgi-Run-Once', str(environ['wsgi.run_once'])),
|
||||||
])
|
],
|
||||||
|
)
|
||||||
return [body]
|
return [body]
|
||||||
|
|||||||
@@ -3,16 +3,16 @@ async def application(scope, receive, send):
|
|||||||
while True:
|
while True:
|
||||||
m = await receive()
|
m = await receive()
|
||||||
if m['type'] == 'websocket.connect':
|
if m['type'] == 'websocket.connect':
|
||||||
await send({
|
await send({'type': 'websocket.accept'})
|
||||||
'type': 'websocket.accept',
|
|
||||||
})
|
|
||||||
|
|
||||||
if m['type'] == 'websocket.receive':
|
if m['type'] == 'websocket.receive':
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'websocket.send',
|
'type': 'websocket.send',
|
||||||
'bytes': m.get('bytes', None),
|
'bytes': m.get('bytes', None),
|
||||||
'text': m.get('text', None),
|
'text': m.get('text', None),
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if m['type'] == 'websocket.disconnect':
|
if m['type'] == 'websocket.disconnect':
|
||||||
break;
|
break
|
||||||
|
|||||||
@@ -6,20 +6,24 @@ async def application(scope, receive, send):
|
|||||||
if m['type'] == 'websocket.connect':
|
if m['type'] == 'websocket.connect':
|
||||||
subprotocols = scope['subprotocols']
|
subprotocols = scope['subprotocols']
|
||||||
|
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'websocket.accept',
|
'type': 'websocket.accept',
|
||||||
'headers': [
|
'headers': [
|
||||||
(b'x-subprotocols', str(subprotocols).encode()),
|
(b'x-subprotocols', str(subprotocols).encode()),
|
||||||
],
|
],
|
||||||
'subprotocol': subprotocols[0],
|
'subprotocol': subprotocols[0],
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if m['type'] == 'websocket.receive':
|
if m['type'] == 'websocket.receive':
|
||||||
await send({
|
await send(
|
||||||
|
{
|
||||||
'type': 'websocket.send',
|
'type': 'websocket.send',
|
||||||
'bytes': m.get('bytes', None),
|
'bytes': m.get('bytes', None),
|
||||||
'text': m.get('text', None),
|
'text': m.get('text', None),
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if m['type'] == 'websocket.disconnect':
|
if m['type'] == 'websocket.disconnect':
|
||||||
break;
|
break
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ import time
|
|||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|
||||||
class TestASGIApplication(TestApplicationPython):
|
class TestASGIApplication(TestApplicationPython):
|
||||||
prerequisites = {'modules': {'python':
|
prerequisites = {
|
||||||
lambda v: LooseVersion(v) >= LooseVersion('3.5')}}
|
'modules': {'python': lambda v: LooseVersion(v) >= LooseVersion('3.5')}
|
||||||
|
}
|
||||||
load_module = 'asgi'
|
load_module = 'asgi'
|
||||||
|
|
||||||
def findall(self, pattern):
|
def findall(self, pattern):
|
||||||
@@ -31,7 +33,8 @@ Content-Type: text/html
|
|||||||
Connection: close
|
Connection: close
|
||||||
custom-header: BLAH
|
custom-header: BLAH
|
||||||
|
|
||||||
%s""" % (len(body), body.encode()),
|
%s"""
|
||||||
|
% (len(body), body.encode()),
|
||||||
raw=True,
|
raw=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -145,7 +148,7 @@ custom-header: BLAH
|
|||||||
|
|
||||||
assert 'success' in self.conf(
|
assert 'success' in self.conf(
|
||||||
'{"http":{"max_body_size": ' + str(max_body_size) + ' }}',
|
'{"http":{"max_body_size": ' + str(max_body_size) + ' }}',
|
||||||
'settings'
|
'settings',
|
||||||
)
|
)
|
||||||
|
|
||||||
assert self.get()['status'] == 200, 'init'
|
assert self.get()['status'] == 200, 'init'
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import os
|
|||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from conftest import unit_stop
|
from conftest import unit_stop
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|||||||
@@ -3,14 +3,16 @@ import time
|
|||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
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
|
from unit.option import option
|
||||||
|
|
||||||
|
|
||||||
class TestASGIWebsockets(TestApplicationPython):
|
class TestASGIWebsockets(TestApplicationPython):
|
||||||
prerequisites = {'modules': {'python':
|
prerequisites = {
|
||||||
lambda v: LooseVersion(v) >= LooseVersion('3.5')}}
|
'modules': {'python': lambda v: LooseVersion(v) >= LooseVersion('3.5')}
|
||||||
|
}
|
||||||
load_module = 'asgi'
|
load_module = 'asgi'
|
||||||
|
|
||||||
ws = TestApplicationWebsocket()
|
ws = TestApplicationWebsocket()
|
||||||
@@ -74,7 +76,9 @@ class TestASGIWebsockets(TestApplicationPython):
|
|||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
assert resp['status'] == 101, 'status'
|
assert resp['status'] == 101, 'status'
|
||||||
assert resp['headers']['x-subprotocols'] == "('chat', 'phone', 'video')", 'subprotocols'
|
assert (
|
||||||
|
resp['headers']['x-subprotocols'] == "('chat', 'phone', 'video')"
|
||||||
|
), 'subprotocols'
|
||||||
assert resp['headers']['sec-websocket-protocol'] == 'chat', 'key'
|
assert resp['headers']['sec-websocket-protocol'] == 'chat', 'key'
|
||||||
|
|
||||||
def test_asgi_websockets_mirror(self):
|
def test_asgi_websockets_mirror(self):
|
||||||
@@ -231,7 +235,7 @@ class TestASGIWebsockets(TestApplicationPython):
|
|||||||
|
|
||||||
@pytest.mark.skip('not yet')
|
@pytest.mark.skip('not yet')
|
||||||
def test_asgi_websockets_handshake_upgrade_absent(
|
def test_asgi_websockets_handshake_upgrade_absent(
|
||||||
self
|
self,
|
||||||
): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
|
): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
|
||||||
self.load('websockets/mirror')
|
self.load('websockets/mirror')
|
||||||
|
|
||||||
@@ -324,7 +328,9 @@ class TestASGIWebsockets(TestApplicationPython):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert resp['status'] == 400, 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
|
assert (
|
||||||
|
resp['status'] == 400
|
||||||
|
), 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
|
||||||
|
|
||||||
def test_asgi_websockets_handshake_method_invalid(self):
|
def test_asgi_websockets_handshake_method_invalid(self):
|
||||||
self.load('websockets/mirror')
|
self.load('websockets/mirror')
|
||||||
@@ -935,7 +941,9 @@ class TestASGIWebsockets(TestApplicationPython):
|
|||||||
frame = self.ws.frame_read(sock)
|
frame = self.ws.frame_read(sock)
|
||||||
|
|
||||||
if frame['opcode'] == self.ws.OP_TEXT:
|
if frame['opcode'] == self.ws.OP_TEXT:
|
||||||
self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
|
self.check_frame(
|
||||||
|
frame, True, self.ws.OP_TEXT, 'fragment1fragment2'
|
||||||
|
)
|
||||||
frame = None
|
frame = None
|
||||||
|
|
||||||
self.check_close(sock, 1002, frame=frame)
|
self.check_close(sock, 1002, frame=frame)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.control import TestControl
|
from unit.control import TestControl
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -129,11 +129,9 @@ class TestGoApplication(TestApplicationGo):
|
|||||||
def test_go_application_command_line_arguments_type(self):
|
def test_go_application_command_line_arguments_type(self):
|
||||||
self.load('command_line_arguments')
|
self.load('command_line_arguments')
|
||||||
|
|
||||||
assert 'error' in \
|
assert 'error' in self.conf(
|
||||||
self.conf(
|
|
||||||
'' "a b c", 'applications/command_line_arguments/arguments'
|
'' "a b c", 'applications/command_line_arguments/arguments'
|
||||||
), \
|
), 'arguments type'
|
||||||
'arguments type'
|
|
||||||
|
|
||||||
def test_go_application_command_line_arguments_0(self):
|
def test_go_application_command_line_arguments_0(self):
|
||||||
self.load('command_line_arguments')
|
self.load('command_line_arguments')
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ import os
|
|||||||
import pwd
|
import pwd
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.go import TestApplicationGo
|
from unit.applications.lang.go import TestApplicationGo
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
from unit.utils import getns
|
from unit.utils import getns
|
||||||
|
|
||||||
|
|
||||||
class TestGoIsolation(TestApplicationGo):
|
class TestGoIsolation(TestApplicationGo):
|
||||||
prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']}
|
prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']}
|
||||||
|
|
||||||
@@ -279,7 +281,7 @@ class TestGoIsolation(TestApplicationGo):
|
|||||||
isolation['namespaces'] = {
|
isolation['namespaces'] = {
|
||||||
'mount': True,
|
'mount': True,
|
||||||
'credential': True,
|
'credential': True,
|
||||||
'pid': True
|
'pid': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.load('ns_inspect', isolation=isolation)
|
self.load('ns_inspect', isolation=isolation)
|
||||||
@@ -337,12 +339,10 @@ class TestGoIsolation(TestApplicationGo):
|
|||||||
isolation['namespaces'] = {
|
isolation['namespaces'] = {
|
||||||
'mount': True,
|
'mount': True,
|
||||||
'credential': True,
|
'credential': True,
|
||||||
'pid': True
|
'pid': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
isolation['automount'] = {
|
isolation['automount'] = {'tmpfs': False}
|
||||||
'tmpfs': False
|
|
||||||
}
|
|
||||||
|
|
||||||
self.load('ns_inspect', isolation=isolation)
|
self.load('ns_inspect', isolation=isolation)
|
||||||
|
|
||||||
@@ -352,9 +352,7 @@ class TestGoIsolation(TestApplicationGo):
|
|||||||
"/ /tmp" not in obj['Mounts'] and "tmpfs" not in obj['Mounts']
|
"/ /tmp" not in obj['Mounts'] and "tmpfs" not in obj['Mounts']
|
||||||
), 'app has no /tmp mounted'
|
), 'app has no /tmp mounted'
|
||||||
|
|
||||||
isolation['automount'] = {
|
isolation['automount'] = {'tmpfs': True}
|
||||||
'tmpfs': True
|
|
||||||
}
|
|
||||||
|
|
||||||
self.load('ns_inspect', isolation=isolation)
|
self.load('ns_inspect', isolation=isolation)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.go import TestApplicationGo
|
from unit.applications.lang.go import TestApplicationGo
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from unit.applications.lang.java import TestApplicationJava
|
|||||||
from unit.option import option
|
from unit.option import option
|
||||||
from unit.utils import public_dir
|
from unit.utils import public_dir
|
||||||
|
|
||||||
|
|
||||||
class TestJavaApplication(TestApplicationJava):
|
class TestJavaApplication(TestApplicationJava):
|
||||||
prerequisites = {'modules': {'java': 'all'}}
|
prerequisites = {'modules': {'java': 'all'}}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.java import TestApplicationJava
|
from unit.applications.lang.java import TestApplicationJava
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import struct
|
|||||||
import time
|
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
|
from unit.option import option
|
||||||
@@ -163,7 +164,7 @@ class TestJavaWebsockets(TestApplicationJava):
|
|||||||
|
|
||||||
@pytest.mark.skip('not yet')
|
@pytest.mark.skip('not yet')
|
||||||
def test_java_websockets_handshake_upgrade_absent(
|
def test_java_websockets_handshake_upgrade_absent(
|
||||||
self
|
self,
|
||||||
): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
|
): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
|
||||||
self.load('websockets_mirror')
|
self.load('websockets_mirror')
|
||||||
|
|
||||||
@@ -256,7 +257,9 @@ class TestJavaWebsockets(TestApplicationJava):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert resp['status'] == 400, 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
|
assert (
|
||||||
|
resp['status'] == 400
|
||||||
|
), 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
|
||||||
|
|
||||||
def test_java_websockets_handshake_method_invalid(self):
|
def test_java_websockets_handshake_method_invalid(self):
|
||||||
self.load('websockets_mirror')
|
self.load('websockets_mirror')
|
||||||
@@ -867,7 +870,9 @@ class TestJavaWebsockets(TestApplicationJava):
|
|||||||
frame = self.ws.frame_read(sock)
|
frame = self.ws.frame_read(sock)
|
||||||
|
|
||||||
if frame['opcode'] == self.ws.OP_TEXT:
|
if frame['opcode'] == self.ws.OP_TEXT:
|
||||||
self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
|
self.check_frame(
|
||||||
|
frame, True, self.ws.OP_TEXT, 'fragment1fragment2'
|
||||||
|
)
|
||||||
frame = None
|
frame = None
|
||||||
|
|
||||||
self.check_close(sock, 1002, frame=frame)
|
self.check_close(sock, 1002, frame=frame)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.node import TestApplicationNode
|
from unit.applications.lang.node import TestApplicationNode
|
||||||
from unit.utils import waitforfiles
|
from unit.utils import waitforfiles
|
||||||
|
|
||||||
@@ -205,7 +206,9 @@ class TestNodeApplication(TestApplicationNode):
|
|||||||
def test_node_application_status_message(self):
|
def test_node_application_status_message(self):
|
||||||
self.load('status_message')
|
self.load('status_message')
|
||||||
|
|
||||||
assert re.search(r'200 blah', self.get(raw_resp=True)), 'status message'
|
assert re.search(
|
||||||
|
r'200 blah', self.get(raw_resp=True)
|
||||||
|
), 'status message'
|
||||||
|
|
||||||
def test_node_application_get_header_type(self):
|
def test_node_application_get_header_type(self):
|
||||||
self.load('get_header_type')
|
self.load('get_header_type')
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import struct
|
|||||||
import time
|
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
|
from unit.option import option
|
||||||
@@ -182,7 +183,7 @@ class TestNodeWebsockets(TestApplicationNode):
|
|||||||
|
|
||||||
@pytest.mark.skip('not yet')
|
@pytest.mark.skip('not yet')
|
||||||
def test_node_websockets_handshake_upgrade_absent(
|
def test_node_websockets_handshake_upgrade_absent(
|
||||||
self
|
self,
|
||||||
): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
|
): # FAIL https://tools.ietf.org/html/rfc6455#section-4.2.1
|
||||||
self.load('websockets/mirror')
|
self.load('websockets/mirror')
|
||||||
|
|
||||||
@@ -275,7 +276,9 @@ class TestNodeWebsockets(TestApplicationNode):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert resp['status'] == 400, 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
|
assert (
|
||||||
|
resp['status'] == 400
|
||||||
|
), 'key double' # FAIL https://tools.ietf.org/html/rfc6455#section-11.3.1
|
||||||
|
|
||||||
def test_node_websockets_handshake_method_invalid(self):
|
def test_node_websockets_handshake_method_invalid(self):
|
||||||
self.load('websockets/mirror')
|
self.load('websockets/mirror')
|
||||||
@@ -886,7 +889,9 @@ class TestNodeWebsockets(TestApplicationNode):
|
|||||||
frame = self.ws.frame_read(sock)
|
frame = self.ws.frame_read(sock)
|
||||||
|
|
||||||
if frame['opcode'] == self.ws.OP_TEXT:
|
if frame['opcode'] == self.ws.OP_TEXT:
|
||||||
self.check_frame(frame, True, self.ws.OP_TEXT, 'fragment1fragment2')
|
self.check_frame(
|
||||||
|
frame, True, self.ws.OP_TEXT, 'fragment1fragment2'
|
||||||
|
)
|
||||||
frame = None
|
frame = None
|
||||||
|
|
||||||
self.check_close(sock, 1002, frame=frame)
|
self.check_close(sock, 1002, frame=frame)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.perl import TestApplicationPerl
|
from unit.applications.lang.perl import TestApplicationPerl
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import time
|
|||||||
from subprocess import call
|
from subprocess import call
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.php import TestApplicationPHP
|
from unit.applications.lang.php import TestApplicationPHP
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|
||||||
class TestPHPApplication(TestApplicationPHP):
|
class TestPHPApplication(TestApplicationPHP):
|
||||||
prerequisites = {'modules': {'php': 'all'}}
|
prerequisites = {'modules': {'php': 'all'}}
|
||||||
|
|
||||||
@@ -428,11 +430,13 @@ class TestPHPApplication(TestApplicationPHP):
|
|||||||
self.load('auth')
|
self.load('auth')
|
||||||
|
|
||||||
def check_auth(auth):
|
def check_auth(auth):
|
||||||
resp = self.get(headers={
|
resp = self.get(
|
||||||
|
headers={
|
||||||
'Host': 'localhost',
|
'Host': 'localhost',
|
||||||
'Authorization': auth,
|
'Authorization': auth,
|
||||||
'Connection': 'close',
|
'Connection': 'close',
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
assert resp['status'] == 200, 'status'
|
assert resp['status'] == 200, 'status'
|
||||||
assert resp['headers']['X-Digest'] == 'not set', 'Digest'
|
assert resp['headers']['X-Digest'] == 'not set', 'Digest'
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.php import TestApplicationPHP
|
from unit.applications.lang.php import TestApplicationPHP
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ class TestPHPIsolation(TestApplicationPHP):
|
|||||||
isolation['namespaces'] = {
|
isolation['namespaces'] = {
|
||||||
'mount': True,
|
'mount': True,
|
||||||
'credential': True,
|
'credential': True,
|
||||||
'pid': True
|
'pid': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.load('phpinfo', isolation=isolation)
|
self.load('phpinfo', isolation=isolation)
|
||||||
@@ -64,7 +65,7 @@ class TestPHPIsolation(TestApplicationPHP):
|
|||||||
isolation['namespaces'] = {
|
isolation['namespaces'] = {
|
||||||
'mount': True,
|
'mount': True,
|
||||||
'credential': True,
|
'credential': True,
|
||||||
'pid': True
|
'pid': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.load('list-extensions', isolation=isolation)
|
self.load('list-extensions', isolation=isolation)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import socket
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from conftest import run_process
|
from conftest import run_process
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
@@ -464,9 +465,9 @@ Content-Length: 10
|
|||||||
|
|
||||||
def test_proxy_invalid(self):
|
def test_proxy_invalid(self):
|
||||||
def check_proxy(proxy):
|
def check_proxy(proxy):
|
||||||
assert 'error' in \
|
assert 'error' in self.conf(
|
||||||
self.conf([{"action": {"proxy": proxy}}], 'routes'), \
|
[{"action": {"proxy": proxy}}], 'routes'
|
||||||
'proxy invalid'
|
), 'proxy invalid'
|
||||||
|
|
||||||
check_proxy('blah')
|
check_proxy('blah')
|
||||||
check_proxy('/blah')
|
check_proxy('/blah')
|
||||||
@@ -502,7 +503,8 @@ Content-Length: 10
|
|||||||
"type": "python",
|
"type": "python",
|
||||||
"processes": {"spare": 0},
|
"processes": {"spare": 0},
|
||||||
"path": option.test_dir + "/python/mirror",
|
"path": option.test_dir + "/python/mirror",
|
||||||
"working_directory": option.test_dir + "/python/mirror",
|
"working_directory": option.test_dir
|
||||||
|
+ "/python/mirror",
|
||||||
"module": "wsgi",
|
"module": "wsgi",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import re
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
@@ -31,7 +32,8 @@ Content-Type: text/html
|
|||||||
Connection: close
|
Connection: close
|
||||||
custom-header: BLAH
|
custom-header: BLAH
|
||||||
|
|
||||||
%s""" % (len(body), body.encode()),
|
%s"""
|
||||||
|
% (len(body), body.encode()),
|
||||||
raw=True,
|
raw=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -816,7 +818,11 @@ last line: 987654321
|
|||||||
assert ['/new', *sys_path] == get_path(), 'check path update'
|
assert ['/new', *sys_path] == get_path(), 'check path update'
|
||||||
|
|
||||||
set_path('["/blah1", "/blah2"]')
|
set_path('["/blah1", "/blah2"]')
|
||||||
assert ['/blah1', '/blah2', *sys_path] == get_path(), 'check path array'
|
assert [
|
||||||
|
'/blah1',
|
||||||
|
'/blah2',
|
||||||
|
*sys_path,
|
||||||
|
] == get_path(), 'check path array'
|
||||||
|
|
||||||
def test_python_application_path_invalid(self):
|
def test_python_application_path_invalid(self):
|
||||||
self.load('path')
|
self.load('path')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
from unit.utils import findmnt
|
from unit.utils import findmnt
|
||||||
@@ -32,7 +32,7 @@ class TestPythonIsolation(TestApplicationPython):
|
|||||||
isolation['namespaces'] = {
|
isolation['namespaces'] = {
|
||||||
'mount': True,
|
'mount': True,
|
||||||
'credential': True,
|
'credential': True,
|
||||||
'pid': True
|
'pid': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.load('ns_inspect', isolation=isolation)
|
self.load('ns_inspect', isolation=isolation)
|
||||||
@@ -43,8 +43,7 @@ class TestPythonIsolation(TestApplicationPython):
|
|||||||
), 'temp_dir does not exists in rootfs'
|
), 'temp_dir does not exists in rootfs'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.getjson(url='/?path=/proc/self')['body']['FileExists']
|
self.getjson(url='/?path=/proc/self')['body']['FileExists'] == True
|
||||||
== True
|
|
||||||
), 'no /proc/self'
|
), 'no /proc/self'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
@@ -66,15 +65,12 @@ class TestPythonIsolation(TestApplicationPython):
|
|||||||
if not is_su:
|
if not is_su:
|
||||||
pytest.skip('requires root')
|
pytest.skip('requires root')
|
||||||
|
|
||||||
isolation = {
|
isolation = {'rootfs': temp_dir, 'automount': {'language_deps': False}}
|
||||||
'rootfs': temp_dir,
|
|
||||||
'automount': {'language_deps': False}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.load('empty', isolation=isolation)
|
self.load('empty', isolation=isolation)
|
||||||
|
|
||||||
assert findmnt().find(temp_dir) == -1
|
assert findmnt().find(temp_dir) == -1
|
||||||
assert (self.get()['status'] != 200), 'disabled language_deps'
|
assert self.get()['status'] != 200, 'disabled language_deps'
|
||||||
assert findmnt().find(temp_dir) == -1
|
assert findmnt().find(temp_dir) == -1
|
||||||
|
|
||||||
isolation['automount']['language_deps'] = True
|
isolation['automount']['language_deps'] = True
|
||||||
@@ -82,7 +78,7 @@ class TestPythonIsolation(TestApplicationPython):
|
|||||||
self.load('empty', isolation=isolation)
|
self.load('empty', isolation=isolation)
|
||||||
|
|
||||||
assert findmnt().find(temp_dir) == -1
|
assert findmnt().find(temp_dir) == -1
|
||||||
assert (self.get()['status'] == 200), 'enabled language_deps'
|
assert self.get()['status'] == 200, 'enabled language_deps'
|
||||||
assert waitformount(temp_dir), 'language_deps mount'
|
assert waitformount(temp_dir), 'language_deps mount'
|
||||||
|
|
||||||
self.conf({"listeners": {}, "applications": {}})
|
self.conf({"listeners": {}, "applications": {}})
|
||||||
@@ -90,8 +86,6 @@ class TestPythonIsolation(TestApplicationPython):
|
|||||||
assert waitforunmount(temp_dir), 'language_deps unmount'
|
assert waitforunmount(temp_dir), 'language_deps unmount'
|
||||||
|
|
||||||
def test_python_isolation_procfs(self, is_su, temp_dir):
|
def test_python_isolation_procfs(self, is_su, temp_dir):
|
||||||
isolation_features = option.available['features']['isolation'].keys()
|
|
||||||
|
|
||||||
if not is_su:
|
if not is_su:
|
||||||
pytest.skip('requires root')
|
pytest.skip('requires root')
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
|
|
||||||
|
|
||||||
@@ -21,8 +22,7 @@ class TestPythonIsolation(TestApplicationPython):
|
|||||||
), 'temp_dir does not exists in rootfs'
|
), 'temp_dir does not exists in rootfs'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.getjson(url='/?path=/proc/self')['body']['FileExists']
|
self.getjson(url='/?path=/proc/self')['body']['FileExists'] == True
|
||||||
== True
|
|
||||||
), 'no /proc/self'
|
), 'no /proc/self'
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|||||||
@@ -76,9 +76,10 @@ class TestRespawn(TestApplicationPython):
|
|||||||
self.kill_pids(pid)
|
self.kill_pids(pid)
|
||||||
skip_alert(r'process %s exited on signal 9' % pid)
|
skip_alert(r'process %s exited on signal 9' % pid)
|
||||||
|
|
||||||
assert self.wait_for_process(
|
assert (
|
||||||
self.PATTERN_CONTROLLER, unit_pid
|
self.wait_for_process(self.PATTERN_CONTROLLER, unit_pid)
|
||||||
) is not None
|
is not None
|
||||||
|
)
|
||||||
|
|
||||||
assert self.get()['status'] == 200
|
assert self.get()['status'] == 200
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.proto import TestApplicationProto
|
from unit.applications.proto import TestApplicationProto
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
@@ -336,8 +337,7 @@ class TestRouting(TestApplicationProto):
|
|||||||
"type": "python",
|
"type": "python",
|
||||||
"processes": {"spare": 0},
|
"processes": {"spare": 0},
|
||||||
"path": option.test_dir + '/python/empty',
|
"path": option.test_dir + '/python/empty',
|
||||||
"working_directory": option.test_dir
|
"working_directory": option.test_dir + '/python/empty',
|
||||||
+ '/python/empty',
|
|
||||||
"module": "wsgi",
|
"module": "wsgi",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -495,8 +495,7 @@ class TestRouting(TestApplicationProto):
|
|||||||
'routes/0/action',
|
'routes/0/action',
|
||||||
), 'proxy pass'
|
), 'proxy pass'
|
||||||
assert 'error' in self.conf(
|
assert 'error' in self.conf(
|
||||||
{"share": temp_dir, "pass": "applications/app"},
|
{"share": temp_dir, "pass": "applications/app"}, 'routes/0/action',
|
||||||
'routes/0/action',
|
|
||||||
), 'share pass'
|
), 'share pass'
|
||||||
|
|
||||||
def test_routes_rules_two(self):
|
def test_routes_rules_two(self):
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import re
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.ruby import TestApplicationRuby
|
from unit.applications.lang.ruby import TestApplicationRuby
|
||||||
|
|
||||||
|
|
||||||
@@ -208,7 +209,6 @@ class TestRubyApplication(TestApplicationRuby):
|
|||||||
|
|
||||||
self.get()
|
self.get()
|
||||||
|
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
self.wait_for_record(r'\[error\].+1234567890') is not None
|
self.wait_for_record(r'\[error\].+1234567890') is not None
|
||||||
), 'errors write int'
|
), 'errors write int'
|
||||||
@@ -228,9 +228,13 @@ class TestRubyApplication(TestApplicationRuby):
|
|||||||
self.load('encoding')
|
self.load('encoding')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
locales = subprocess.check_output(
|
locales = (
|
||||||
|
subprocess.check_output(
|
||||||
['locale', '-a'], stderr=subprocess.STDOUT,
|
['locale', '-a'], stderr=subprocess.STDOUT,
|
||||||
).decode().split('\n')
|
)
|
||||||
|
.decode()
|
||||||
|
.split('\n')
|
||||||
|
)
|
||||||
|
|
||||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||||
pytest.skip('require locale')
|
pytest.skip('require locale')
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.ruby import TestApplicationRuby
|
from unit.applications.lang.ruby import TestApplicationRuby
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import socket
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.proto import TestApplicationProto
|
from unit.applications.proto import TestApplicationProto
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
@@ -81,10 +82,7 @@ class TestStatic(TestApplicationProto):
|
|||||||
|
|
||||||
def test_fallback_share(self, temp_dir):
|
def test_fallback_share(self, temp_dir):
|
||||||
self.action_update(
|
self.action_update(
|
||||||
{
|
{"share": "/blah", "fallback": {"share": temp_dir + "/assets"},}
|
||||||
"share": "/blah",
|
|
||||||
"fallback": {"share": temp_dir + "/assets"},
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
resp = self.get()
|
resp = self.get()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import os
|
|||||||
import socket
|
import socket
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.proto import TestApplicationProto
|
from unit.applications.proto import TestApplicationProto
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
from unit.utils import waitforfiles
|
from unit.utils import waitforfiles
|
||||||
@@ -85,8 +86,7 @@ class TestStatic(TestApplicationProto):
|
|||||||
|
|
||||||
def test_static_space_in_name(self, temp_dir):
|
def test_static_space_in_name(self, temp_dir):
|
||||||
os.rename(
|
os.rename(
|
||||||
temp_dir + '/assets/dir/file',
|
temp_dir + '/assets/dir/file', temp_dir + '/assets/dir/fi le',
|
||||||
temp_dir + '/assets/dir/fi le',
|
|
||||||
)
|
)
|
||||||
assert waitforfiles(temp_dir + '/assets/dir/fi le')
|
assert waitforfiles(temp_dir + '/assets/dir/fi le')
|
||||||
assert self.get(url='/dir/fi le')['body'] == 'blah', 'file name'
|
assert self.get(url='/dir/fi le')['body'] == 'blah', 'file name'
|
||||||
@@ -95,9 +95,7 @@ class TestStatic(TestApplicationProto):
|
|||||||
assert waitforfiles(temp_dir + '/assets/di r/fi le')
|
assert waitforfiles(temp_dir + '/assets/di r/fi le')
|
||||||
assert self.get(url='/di r/fi le')['body'] == 'blah', 'dir name'
|
assert self.get(url='/di r/fi le')['body'] == 'blah', 'dir name'
|
||||||
|
|
||||||
os.rename(
|
os.rename(temp_dir + '/assets/di r', temp_dir + '/assets/ di r ')
|
||||||
temp_dir + '/assets/di r', temp_dir + '/assets/ di r '
|
|
||||||
)
|
|
||||||
assert waitforfiles(temp_dir + '/assets/ di r /fi le')
|
assert waitforfiles(temp_dir + '/assets/ di r /fi le')
|
||||||
assert (
|
assert (
|
||||||
self.get(url='/ di r /fi le')['body'] == 'blah'
|
self.get(url='/ di r /fi le')['body'] == 'blah'
|
||||||
@@ -150,8 +148,7 @@ class TestStatic(TestApplicationProto):
|
|||||||
), 'file name 2'
|
), 'file name 2'
|
||||||
|
|
||||||
os.rename(
|
os.rename(
|
||||||
temp_dir + '/assets/ di r ',
|
temp_dir + '/assets/ di r ', temp_dir + '/assets/ди ректория',
|
||||||
temp_dir + '/assets/ди ректория',
|
|
||||||
)
|
)
|
||||||
assert waitforfiles(temp_dir + '/assets/ди ректория/фа йл')
|
assert waitforfiles(temp_dir + '/assets/ди ректория/фа йл')
|
||||||
assert (
|
assert (
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ssl
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.tls import TestApplicationTLS
|
from unit.applications.tls import TestApplicationTLS
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ class TestTLS(TestApplicationTLS):
|
|||||||
assert 'success' in self.conf(
|
assert 'success' in self.conf(
|
||||||
{
|
{
|
||||||
"pass": "applications/" + application,
|
"pass": "applications/" + application,
|
||||||
"tls": {"certificate": cert}
|
"tls": {"certificate": cert},
|
||||||
},
|
},
|
||||||
'listeners/*:' + str(port),
|
'listeners/*:' + str(port),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import subprocess
|
|
||||||
import ssl
|
import ssl
|
||||||
|
import subprocess
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.tls import TestApplicationTLS
|
from unit.applications.tls import TestApplicationTLS
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
@@ -23,10 +24,7 @@ class TestTLSSNI(TestApplicationTLS):
|
|||||||
|
|
||||||
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}
|
|
||||||
},
|
|
||||||
'listeners/*:7080',
|
'listeners/*:7080',
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -153,10 +151,7 @@ basicConstraints = critical,CA:TRUE"""
|
|||||||
|
|
||||||
def test_tls_sni(self):
|
def test_tls_sni(self):
|
||||||
bundles = {
|
bundles = {
|
||||||
"default": {
|
"default": {"subj": "default", "alt_names": ["default"]},
|
||||||
"subj": "default",
|
|
||||||
"alt_names": ["default"],
|
|
||||||
},
|
|
||||||
"localhost.com": {
|
"localhost.com": {
|
||||||
"subj": "localhost.com",
|
"subj": "localhost.com",
|
||||||
"alt_names": ["alt1.localhost.com"],
|
"alt_names": ["alt1.localhost.com"],
|
||||||
@@ -205,10 +200,7 @@ basicConstraints = critical,CA:TRUE"""
|
|||||||
|
|
||||||
def test_tls_sni_wildcard(self):
|
def test_tls_sni_wildcard(self):
|
||||||
bundles = {
|
bundles = {
|
||||||
"localhost.com": {
|
"localhost.com": {"subj": "localhost.com", "alt_names": []},
|
||||||
"subj": "localhost.com",
|
|
||||||
"alt_names": [],
|
|
||||||
},
|
|
||||||
"example.com": {
|
"example.com": {
|
||||||
"subj": "example.com",
|
"subj": "example.com",
|
||||||
"alt_names": ["*.example.com", "*.alt.example.com"],
|
"alt_names": ["*.example.com", "*.alt.example.com"],
|
||||||
@@ -248,11 +240,7 @@ basicConstraints = critical,CA:TRUE"""
|
|||||||
self.check_cert('example', bundles['localhost']['subj'])
|
self.check_cert('example', bundles['localhost']['subj'])
|
||||||
|
|
||||||
def test_tls_sni_empty_cn(self):
|
def test_tls_sni_empty_cn(self):
|
||||||
bundles = {
|
bundles = {"localhost": {"alt_names": ["alt.localhost.com"]}}
|
||||||
"localhost": {
|
|
||||||
"alt_names": ["alt.localhost.com"],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.config_bundles(bundles)
|
self.config_bundles(bundles)
|
||||||
self.add_tls(["localhost"])
|
self.add_tls(["localhost"])
|
||||||
|
|
||||||
@@ -266,7 +254,9 @@ basicConstraints = critical,CA:TRUE"""
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert resp['status'] == 200
|
assert resp['status'] == 200
|
||||||
assert sock.getpeercert()['subjectAltName'][0][1] == 'alt.localhost.com'
|
assert (
|
||||||
|
sock.getpeercert()['subjectAltName'][0][1] == 'alt.localhost.com'
|
||||||
|
)
|
||||||
|
|
||||||
def test_tls_sni_invalid(self):
|
def test_tls_sni_invalid(self):
|
||||||
self.config_bundles({"localhost": {"subj": "subj1", "alt_names": ''}})
|
self.config_bundles({"localhost": {"subj": "subj1", "alt_names": ''}})
|
||||||
|
|||||||
@@ -92,16 +92,8 @@ class TestVariables(TestApplicationProto):
|
|||||||
"*:7080": {"pass": "upstreams$uri"},
|
"*:7080": {"pass": "upstreams$uri"},
|
||||||
"*:7081": {"pass": "routes/one"},
|
"*:7081": {"pass": "routes/one"},
|
||||||
},
|
},
|
||||||
"upstreams": {
|
"upstreams": {"1": {"servers": {"127.0.0.1:7081": {}}}},
|
||||||
"1": {
|
"routes": {"one": [{"action": {"return": 200}}]},
|
||||||
"servers": {
|
|
||||||
"127.0.0.1:7081": {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"routes": {
|
|
||||||
"one": [{"action": {"return": 200}}],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
), 'upstreams initial configuration'
|
), 'upstreams initial configuration'
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,14 @@ class TestApplicationTLS(TestApplicationProto):
|
|||||||
'req',
|
'req',
|
||||||
'-x509',
|
'-x509',
|
||||||
'-new',
|
'-new',
|
||||||
'-subj', '/CN=' + name + '/',
|
'-subj',
|
||||||
'-config', option.temp_dir + '/openssl.conf',
|
'/CN=' + name + '/',
|
||||||
'-out', option.temp_dir + '/' + name + '.crt',
|
'-config',
|
||||||
'-keyout', option.temp_dir + '/' + name + '.key',
|
option.temp_dir + '/openssl.conf',
|
||||||
|
'-out',
|
||||||
|
option.temp_dir + '/' + name + '.crt',
|
||||||
|
'-keyout',
|
||||||
|
option.temp_dir + '/' + name + '.key',
|
||||||
],
|
],
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
)
|
)
|
||||||
@@ -80,7 +84,9 @@ class TestApplicationTLS(TestApplicationProto):
|
|||||||
[ myca_req_extensions ]
|
[ myca_req_extensions ]
|
||||||
subjectAltName = @alt_names
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
{a_names}""".format(a_names=a_names)
|
{a_names}""".format(
|
||||||
|
a_names=a_names
|
||||||
|
)
|
||||||
|
|
||||||
with open(conf_path, 'w') as f:
|
with open(conf_path, 'w') as f:
|
||||||
f.write(
|
f.write(
|
||||||
@@ -90,7 +96,9 @@ encrypt_key = no
|
|||||||
distinguished_name = req_distinguished_name
|
distinguished_name = req_distinguished_name
|
||||||
|
|
||||||
{a_sec}
|
{a_sec}
|
||||||
[ req_distinguished_name ]""".format(a_sec=a_sec if alt_names else "")
|
[ req_distinguished_name ]""".format(
|
||||||
|
a_sec=a_sec if alt_names else ""
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def load(self, script, name=None):
|
def load(self, script, name=None):
|
||||||
|
|||||||
@@ -43,11 +43,7 @@ class TestApplicationWebsocket(TestApplicationProto):
|
|||||||
'Sec-WebSocket-Version': 13,
|
'Sec-WebSocket-Version': 13,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, sock = self.get(
|
_, sock = self.get(headers=headers, no_recv=True, start=True,)
|
||||||
headers=headers,
|
|
||||||
no_recv=True,
|
|
||||||
start=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
resp = ''
|
resp = ''
|
||||||
while True:
|
while True:
|
||||||
@@ -57,7 +53,7 @@ class TestApplicationWebsocket(TestApplicationProto):
|
|||||||
|
|
||||||
resp += sock.recv(4096).decode()
|
resp += sock.recv(4096).decode()
|
||||||
|
|
||||||
if (resp.startswith('HTTP/') and '\r\n\r\n' in resp):
|
if resp.startswith('HTTP/') and '\r\n\r\n' in resp:
|
||||||
resp = self._resp_to_dict(resp)
|
resp = self._resp_to_dict(resp)
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -90,8 +86,8 @@ class TestApplicationWebsocket(TestApplicationProto):
|
|||||||
|
|
||||||
frame = {}
|
frame = {}
|
||||||
|
|
||||||
head1, = struct.unpack('!B', recv_bytes(sock, 1))
|
(head1,) = struct.unpack('!B', recv_bytes(sock, 1))
|
||||||
head2, = struct.unpack('!B', recv_bytes(sock, 1))
|
(head2,) = struct.unpack('!B', recv_bytes(sock, 1))
|
||||||
|
|
||||||
frame['fin'] = bool(head1 & 0b10000000)
|
frame['fin'] = bool(head1 & 0b10000000)
|
||||||
frame['rsv1'] = bool(head1 & 0b01000000)
|
frame['rsv1'] = bool(head1 & 0b01000000)
|
||||||
@@ -103,10 +99,10 @@ class TestApplicationWebsocket(TestApplicationProto):
|
|||||||
length = head2 & 0b01111111
|
length = head2 & 0b01111111
|
||||||
if length == 126:
|
if length == 126:
|
||||||
data = recv_bytes(sock, 2)
|
data = recv_bytes(sock, 2)
|
||||||
length, = struct.unpack('!H', data)
|
(length,) = struct.unpack('!H', data)
|
||||||
elif length == 127:
|
elif length == 127:
|
||||||
data = recv_bytes(sock, 8)
|
data = recv_bytes(sock, 8)
|
||||||
length, = struct.unpack('!Q', data)
|
(length,) = struct.unpack('!Q', data)
|
||||||
|
|
||||||
if frame['mask']:
|
if frame['mask']:
|
||||||
mask_bits = recv_bytes(sock, 4)
|
mask_bits = recv_bytes(sock, 4)
|
||||||
@@ -121,7 +117,7 @@ class TestApplicationWebsocket(TestApplicationProto):
|
|||||||
|
|
||||||
if frame['opcode'] == self.OP_CLOSE:
|
if frame['opcode'] == self.OP_CLOSE:
|
||||||
if length >= 2:
|
if length >= 2:
|
||||||
code, = struct.unpack('!H', data[:2])
|
(code,) = struct.unpack('!H', data[:2])
|
||||||
reason = data[2:].decode('utf-8')
|
reason = data[2:].decode('utf-8')
|
||||||
if not (code in self.CLOSE_CODES or 3000 <= code < 5000):
|
if not (code in self.CLOSE_CODES or 3000 <= code < 5000):
|
||||||
pytest.fail('Invalid status code')
|
pytest.fail('Invalid status code')
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from unit.utils import getns
|
|||||||
allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net']
|
allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net']
|
||||||
http = TestHTTP()
|
http = TestHTTP()
|
||||||
|
|
||||||
|
|
||||||
def check_isolation():
|
def check_isolation():
|
||||||
test_conf = {"namespaces": {"credential": True}}
|
test_conf = {"namespaces": {"credential": True}}
|
||||||
available = option.available
|
available = option.available
|
||||||
@@ -117,8 +118,7 @@ def check_isolation():
|
|||||||
"body_empty": {
|
"body_empty": {
|
||||||
"type": "perl",
|
"type": "perl",
|
||||||
"processes": {"spare": 0},
|
"processes": {"spare": 0},
|
||||||
"working_directory": option.test_dir
|
"working_directory": option.test_dir + "/perl/body_empty",
|
||||||
+ "/perl/body_empty",
|
|
||||||
"script": option.test_dir + "/perl/body_empty/psgi.pl",
|
"script": option.test_dir + "/perl/body_empty/psgi.pl",
|
||||||
"isolation": {"namespaces": {"credential": True}},
|
"isolation": {"namespaces": {"credential": True}},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,16 @@ import pytest
|
|||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|
||||||
class TestHTTP():
|
class TestHTTP:
|
||||||
def http(self, start_str, **kwargs):
|
def http(self, start_str, **kwargs):
|
||||||
sock_type = kwargs.get('sock_type', 'ipv4')
|
sock_type = kwargs.get('sock_type', 'ipv4')
|
||||||
port = kwargs.get('port', 7080)
|
port = kwargs.get('port', 7080)
|
||||||
url = kwargs.get('url', '/')
|
url = kwargs.get('url', '/')
|
||||||
http = 'HTTP/1.0' if 'http_10' in kwargs else 'HTTP/1.1'
|
http = 'HTTP/1.0' if 'http_10' in kwargs else 'HTTP/1.1'
|
||||||
|
|
||||||
headers = kwargs.get('headers',
|
headers = kwargs.get(
|
||||||
{'Host': 'localhost', 'Connection': 'close'})
|
'headers', {'Host': 'localhost', 'Connection': 'close'}
|
||||||
|
)
|
||||||
|
|
||||||
body = kwargs.get('body', b'')
|
body = kwargs.get('body', b'')
|
||||||
crlf = '\r\n'
|
crlf = '\r\n'
|
||||||
@@ -305,8 +306,9 @@ class TestHTTP():
|
|||||||
return body, content_type
|
return body, content_type
|
||||||
|
|
||||||
def form_url_encode(self, fields):
|
def form_url_encode(self, fields):
|
||||||
data = "&".join("%s=%s" % (name, value)
|
data = "&".join(
|
||||||
for name, value in fields.items()).encode()
|
"%s=%s" % (name, value) for name, value in fields.items()
|
||||||
|
).encode()
|
||||||
return data, 'application/x-www-form-urlencoded'
|
return data, 'application/x-www-form-urlencoded'
|
||||||
|
|
||||||
def multipart_encode(self, fields):
|
def multipart_encode(self, fields):
|
||||||
@@ -326,7 +328,9 @@ class TestHTTP():
|
|||||||
datatype = value['type']
|
datatype = value['type']
|
||||||
|
|
||||||
if not isinstance(value['data'], io.IOBase):
|
if not isinstance(value['data'], io.IOBase):
|
||||||
pytest.fail('multipart encoding of file requires a stream.')
|
pytest.fail(
|
||||||
|
'multipart encoding of file requires a stream.'
|
||||||
|
)
|
||||||
|
|
||||||
data = value['data'].read()
|
data = value['data'].read()
|
||||||
|
|
||||||
@@ -336,9 +340,10 @@ class TestHTTP():
|
|||||||
else:
|
else:
|
||||||
pytest.fail('multipart requires a string or stream data')
|
pytest.fail('multipart requires a string or stream data')
|
||||||
|
|
||||||
body += (
|
body += ("--%s\r\nContent-Disposition: form-data; name=\"%s\"") % (
|
||||||
"--%s\r\nContent-Disposition: form-data; name=\"%s\""
|
boundary,
|
||||||
) % (boundary, field)
|
field,
|
||||||
|
)
|
||||||
|
|
||||||
if filename != '':
|
if filename != '':
|
||||||
body += "; filename=\"%s\"" % filename
|
body += "; filename=\"%s\"" % filename
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
class Options():
|
class Options:
|
||||||
_options = {
|
_options = {
|
||||||
'skip_alerts': [],
|
'skip_alerts': [],
|
||||||
'skip_sanitizer': False,
|
'skip_sanitizer': False,
|
||||||
@@ -13,4 +13,5 @@ class Options():
|
|||||||
|
|
||||||
raise AttributeError
|
raise AttributeError
|
||||||
|
|
||||||
|
|
||||||
option = Options()
|
option = Options()
|
||||||
|
|||||||
Reference in New Issue
Block a user