Tests: style.

This commit is contained in:
Andrey Zelenkov
2019-03-26 23:38:30 +03:00
parent 3d7a47c9ac
commit 281899fcef
18 changed files with 4091 additions and 2312 deletions

View File

@@ -5,8 +5,8 @@ from subprocess import call
import unittest
import unit
class TestUnitAccessLog(unit.TestUnitApplicationPython):
class TestUnitAccessLog(unit.TestUnitApplicationPython):
def setUpClass():
unit.TestUnit().check_modules('python')
@@ -22,34 +22,45 @@ class TestUnitAccessLog(unit.TestUnitApplicationPython):
def test_access_log_keepalive(self):
self.load('mirror')
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='01234')
'Content-Type': 'text/html',
},
start=True,
body='01234',
)
time.sleep(0.2)
self.assertIsNotNone(
self.search_in_log(r'"POST / HTTP/1.1" 200 5'), 'keepalive 1')
self.search_in_log(r'"POST / HTTP/1.1" 200 5'), 'keepalive 1'
)
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=sock, body='0123456789')
'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
)
time.sleep(0.2)
self.stop()
self.assertIsNotNone(
self.search_in_log(r'"POST / HTTP/1.1" 200 10'), 'keepalive 2')
self.search_in_log(r'"POST / HTTP/1.1" 200 10'), 'keepalive 2'
)
def test_access_log_pipeline(self):
self.load('empty')
self.http(b"""GET / HTTP/1.1
self.http(
b"""GET / HTTP/1.1
Host: localhost
Referer: Referer-1
@@ -62,7 +73,10 @@ Host: localhost
Referer: Referer-3
Connection: close
""", raw_resp=True, raw=True)
""",
raw_resp=True,
raw=True,
)
time.sleep(0.2)
@@ -70,22 +84,21 @@ Connection: close
self.assertIsNotNone(
self.search_in_log(r'"GET / HTTP/1.1" 200 0 "Referer-1" "-"'),
'pipeline 1')
'pipeline 1',
)
self.assertIsNotNone(
self.search_in_log(r'"GET / HTTP/1.1" 200 0 "Referer-2" "-"'),
'pipeline 2')
'pipeline 2',
)
self.assertIsNotNone(
self.search_in_log(r'"GET / HTTP/1.1" 200 0 "Referer-3" "-"'),
'pipeline 3')
'pipeline 3',
)
def test_access_log_ipv6(self):
self.load('empty')
self.conf({
"[::1]:7080": {
"application": "empty"
}
}, 'listeners')
self.conf({"[::1]:7080": {"application": "empty"}}, 'listeners')
self.get(sock_type='ipv6')
@@ -95,18 +108,17 @@ Connection: close
self.assertIsNotNone(
self.search_in_log(
r'::1 - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"'), 'ipv6')
r'::1 - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"'
),
'ipv6',
)
def test_access_log_unix(self):
self.load('empty')
addr = self.testdir + '/sock'
self.conf({
"unix:" + addr: {
"application": "empty"
}
}, 'listeners')
self.conf({"unix:" + addr: {"application": "empty"}}, 'listeners')
self.get(sock_type='unix', addr=addr)
@@ -114,17 +126,23 @@ Connection: close
self.stop()
self.assertIsNotNone(self.search_in_log(
r'unix: - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"'), 'unix')
self.assertIsNotNone(
self.search_in_log(
r'unix: - - \[.+\] "GET / HTTP/1.1" 200 0 "-" "-"'
),
'unix',
)
def test_access_log_referer(self):
self.load('empty')
self.get(headers={
self.get(
headers={
'Host': 'localhost',
'Referer': 'referer-value',
'Connection': 'close'
})
'Connection': 'close',
}
)
time.sleep(0.2)
@@ -132,16 +150,19 @@ Connection: close
self.assertIsNotNone(
self.search_in_log(r'"GET / HTTP/1.1" 200 0 "referer-value" "-"'),
'referer')
'referer',
)
def test_access_log_user_agent(self):
self.load('empty')
self.get(headers={
self.get(
headers={
'Host': 'localhost',
'User-Agent': 'user-agent-value',
'Connection': 'close'
})
'Connection': 'close',
}
)
time.sleep(0.2)
@@ -149,7 +170,10 @@ Connection: close
self.assertIsNotNone(
self.search_in_log(
r'"GET / HTTP/1.1" 200 0 "-" "user-agent-value"'), 'user agent')
r'"GET / HTTP/1.1" 200 0 "-" "user-agent-value"'
),
'user agent',
)
def test_access_log_http10(self):
self.load('empty')
@@ -161,8 +185,8 @@ Connection: close
self.stop()
self.assertIsNotNone(
self.search_in_log(
r'"GET / HTTP/1.0" 200 0 "-" "-"'), 'http 1.0')
self.search_in_log(r'"GET / HTTP/1.0" 200 0 "-" "-"'), 'http 1.0'
)
def test_access_log_partial(self):
self.load('empty')
@@ -174,7 +198,8 @@ Connection: close
self.stop()
self.assertIsNotNone(
self.search_in_log(r'"GE" 400 0 "-" "-"'), 'partial')
self.search_in_log(r'"GE" 400 0 "-" "-"'), 'partial'
)
def test_access_log_partial_2(self):
self.load('empty')
@@ -186,7 +211,8 @@ Connection: close
self.stop()
self.assertIsNotNone(
self.search_in_log(r'"GET /" 400 \d+ "-" "-"'), 'partial 2')
self.search_in_log(r'"GET /" 400 \d+ "-" "-"'), 'partial 2'
)
def test_access_log_partial_3(self):
self.load('empty')
@@ -198,7 +224,8 @@ Connection: close
self.stop()
self.assertIsNotNone(
self.search_in_log(r'"GET /" 400 0 "-" "-"'), 'partial 3')
self.search_in_log(r'"GET /" 400 0 "-" "-"'), 'partial 3'
)
def test_access_log_partial_4(self):
self.load('empty')
@@ -210,8 +237,8 @@ Connection: close
self.stop()
self.assertIsNotNone(
self.search_in_log(r'"GET / HTTP/1.1" 400 0 "-" "-"'),
'partial 4')
self.search_in_log(r'"GET / HTTP/1.1" 400 0 "-" "-"'), 'partial 4'
)
def test_access_log_partial_5(self):
self.load('empty')
@@ -221,7 +248,8 @@ Connection: close
self.stop()
self.assertIsNotNone(
self.search_in_log(r'"GET / HTTP/1.1" 200 0 "-" "-"'), 'partial 5')
self.search_in_log(r'"GET / HTTP/1.1" 200 0 "-" "-"'), 'partial 5'
)
def test_access_log_get_parameters(self):
self.load('empty')
@@ -234,8 +262,10 @@ Connection: close
self.assertIsNotNone(
self.search_in_log(
r'"GET /\?blah&var=val HTTP/1.1" 200 0 "-" "-"'),
'get parameters')
r'"GET /\?blah&var=val HTTP/1.1" 200 0 "-" "-"'
),
'get parameters',
)
def test_access_log_delete(self):
self.load('empty')
@@ -265,7 +295,8 @@ Connection: close
self.assertIsNotNone(
self.search_in_log(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log'),
'change')
'change',
)
def test_access_log_reopen(self):
self.load('empty')
@@ -284,7 +315,8 @@ Connection: close
self.assertIsNotNone(
self.search_in_log(r'"GET / HTTP/1.1" 200 0 "-" "-"', 'new.log'),
'rename new')
'rename new',
)
self.assertFalse(os.path.isfile(log_path), 'rename old')
with open(self.testdir + '/unit.pid', 'r') as f:
@@ -299,10 +331,13 @@ Connection: close
time.sleep(0.2)
self.assertIsNone(
self.search_in_log(r'/usr1', 'new.log'), 'rename new 2')
self.search_in_log(r'/usr1', 'new.log'), 'rename new 2'
)
self.assertIsNotNone(
self.search_in_log(r'"GET /usr1 HTTP/1.1" 200 0 "-" "-"'),
'reopen 2')
'reopen 2',
)
if __name__ == '__main__':
TestUnitAccessLog.main()

View File

@@ -1,8 +1,8 @@
import unittest
import unit
class TestUnitConfiguration(unit.TestUnitControl):
class TestUnitConfiguration(unit.TestUnitControl):
def setUpClass():
unit.TestUnit().check_modules('python')
@@ -13,7 +13,10 @@ class TestUnitConfiguration(unit.TestUnitControl):
self.assertIn('error', self.conf('00'), 'leading zero')
def test_json_unicode(self):
self.assertIn('success', self.conf(b"""
self.assertIn(
'success',
self.conf(
b"""
{
"ap\u0070": {
"type": "\u0070ython",
@@ -22,32 +25,51 @@ class TestUnitConfiguration(unit.TestUnitControl):
"module": "wsgi"
}
}
""", 'applications'), 'unicode')
""",
'applications',
),
'unicode',
)
self.assertDictEqual(self.conf_get('applications'), {
self.assertDictEqual(
self.conf_get('applications'),
{
"app": {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
}, 'unicode get')
},
'unicode get',
)
def test_json_unicode_2(self):
self.assertIn('success', self.conf({
self.assertIn(
'success',
self.conf(
{
"приложение": {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
}, 'applications'), 'unicode 2')
},
'applications',
),
'unicode 2',
)
self.assertIn('приложение', self.conf_get('applications'),
'unicode 2 get')
self.assertIn(
'приложение', self.conf_get('applications'), 'unicode 2 get'
)
def test_json_unicode_number(self):
self.assertIn('error', self.conf(b"""
self.assertIn(
'error',
self.conf(
b"""
{
"app": {
"type": "python",
@@ -56,7 +78,11 @@ class TestUnitConfiguration(unit.TestUnitControl):
"module": "wsgi"
}
}
""", 'applications'), 'unicode number')
""",
'applications',
),
'unicode number',
)
def test_applications_open_brace(self):
self.assertIn('error', self.conf('{', 'applications'), 'open brace')
@@ -65,20 +91,25 @@ class TestUnitConfiguration(unit.TestUnitControl):
self.assertIn('error', self.conf('"{}"', 'applications'), 'string')
def test_applications_type_only(self):
self.skip_alerts.extend([
self.skip_alerts.extend(
[
r'python module is empty',
r'failed to apply new conf',
r'process \d+ exited on signal'
])
r'process \d+ exited on signal',
]
)
self.assertIn('error', self.conf({
"app": {
"type": "python"
}
}, 'applications'), 'type only')
self.assertIn(
'error',
self.conf({"app": {"type": "python"}}, 'applications'),
'type only',
)
def test_applications_miss_quote(self):
self.assertIn('error', self.conf("""
self.assertIn(
'error',
self.conf(
"""
{
app": {
"type": "python",
@@ -87,10 +118,17 @@ class TestUnitConfiguration(unit.TestUnitControl):
"module": "wsgi"
}
}
""", 'applications'), 'miss quote')
""",
'applications',
),
'miss quote',
)
def test_applications_miss_colon(self):
self.assertIn('error', self.conf("""
self.assertIn(
'error',
self.conf(
"""
{
"app" {
"type": "python",
@@ -99,10 +137,17 @@ class TestUnitConfiguration(unit.TestUnitControl):
"module": "wsgi"
}
}
""", 'applications'), 'miss colon')
""",
'applications',
),
'miss colon',
)
def test_applications_miss_comma(self):
self.assertIn('error', self.conf("""
self.assertIn(
'error',
self.conf(
"""
{
"app": {
"type": "python"
@@ -111,181 +156,206 @@ class TestUnitConfiguration(unit.TestUnitControl):
"module": "wsgi"
}
}
""", 'applications'), 'miss comma')
""",
'applications',
),
'miss comma',
)
def test_applications_skip_spaces(self):
self.assertIn('success', self.conf(b'{ \n\r\t}', 'applications'),
'skip spaces')
self.assertIn(
'success', self.conf(b'{ \n\r\t}', 'applications'), 'skip spaces'
)
def test_applications_relative_path(self):
self.assertIn('success', self.conf({
self.assertIn(
'success',
self.conf(
{
"app": {
"type": "python",
"processes": {"spare": 0},
"path": "../app",
"module": "wsgi"
"module": "wsgi",
}
}, 'applications'), 'relative path')
},
'applications',
),
'relative path',
)
@unittest.expectedFailure
def test_listeners_empty(self):
self.skip_sanitizer = True
self.skip_alerts.extend([
self.skip_alerts.extend(
[
r'failed to apply previous configuration',
r'process \d+ exited on signal'
])
r'process \d+ exited on signal',
]
)
self.assertIn('error', self.conf({"*:7080":{}}, 'listeners'),
'listener empty')
self.assertIn(
'error', self.conf({"*:7080": {}}, 'listeners'), 'listener empty'
)
def test_listeners_no_app(self):
self.assertIn('error', self.conf({"*:7080":{"application":"app"}},
'listeners'), 'listeners no app')
self.assertIn(
'error',
self.conf({"*:7080": {"application": "app"}}, 'listeners'),
'listeners no app',
)
def test_listeners_wildcard(self):
self.assertIn('success', self.conf({
"listeners": {
"*:7080": {
"application":"app"
}
},
self.assertIn(
'success',
self.conf(
{
"listeners": {"*:7080": {"application": "app"}},
"applications": {
"app": {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
},
}
}), 'listeners wildcard')
),
'listeners wildcard',
)
def test_listeners_explicit(self):
self.assertIn('success', self.conf({
"listeners": {
"127.0.0.1:7080": {
"application":"app"
}
},
self.assertIn(
'success',
self.conf(
{
"listeners": {"127.0.0.1:7080": {"application": "app"}},
"applications": {
"app": {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
},
}
}), 'explicit')
),
'explicit',
)
def test_listeners_explicit_ipv6(self):
self.assertIn('success', self.conf({
"listeners": {
"[::1]:7080": {
"application":"app"
}
},
self.assertIn(
'success',
self.conf(
{
"listeners": {"[::1]:7080": {"application": "app"}},
"applications": {
"app": {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
},
}
}), 'explicit ipv6')
),
'explicit ipv6',
)
def test_listeners_no_port(self):
self.skip_alerts.extend([
self.skip_alerts.extend(
[
r'invalid listener "127\.0\.0\.1"',
r'failed to apply new conf',
r'process \d+ exited on signal'
])
r'process \d+ exited on signal',
]
)
self.assertIn('error', self.conf({
"listeners": {
"127.0.0.1": {
"application":"app"
}
},
self.assertIn(
'error',
self.conf(
{
"listeners": {"127.0.0.1": {"application": "app"}},
"applications": {
"app": {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
},
}
}), 'no port')
),
'no port',
)
def test_json_application_name_large(self):
name = "X" * 1024 * 1024
self.assertIn('success', self.conf({
"listeners": {
"*:7080": {
"application": name
}
},
self.assertIn(
'success',
self.conf(
{
"listeners": {"*:7080": {"application": name}},
"applications": {
name: {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
},
}
}))
),
)
@unittest.expectedFailure
def test_json_application_many(self):
self.skip_alerts.extend([
r'eventfd.+failed',
r'epoll.+failed',
r'failed to apply'
])
self.skip_alerts.extend(
[r'eventfd.+failed', r'epoll.+failed', r'failed to apply']
)
apps = 999
conf = {
"applications":
{"app-" + str(a): {
"applications": {
"app-"
+ str(a): {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
} for a in range(apps)
"module": "wsgi",
}
for a in range(apps)
},
"listeners": {
"*:" + str(7000 + a): {
"application": "app-" + str(a)
} for a in range(apps)
}
"*:" + str(7000 + a): {"application": "app-" + str(a)}
for a in range(apps)
},
}
self.assertIn('success', self.conf(conf))
def test_json_application_many2(self):
self.skip_alerts.extend([
r'eventfd.+failed',
r'epoll.+failed',
r'failed to apply'
])
self.skip_alerts.extend(
[r'eventfd.+failed', r'epoll.+failed', r'failed to apply']
)
conf = {
"applications":
{"app-" + str(a): {
"applications": {
"app-"
+ str(a): {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
} for a in range(999)
"module": "wsgi",
}
for a in range(999)
},
"listeners": {
"*:7001": {
"application": "app-1"
}
}
"listeners": {"*:7001": {"application": "app-1"}},
}
self.assertIn('success', self.conf(conf))
if __name__ == '__main__':
TestUnitConfiguration.main()

View File

@@ -1,8 +1,8 @@
import unittest
import unit
class TestUnitGoApplication(unit.TestUnitApplicationGo):
class TestUnitGoApplication(unit.TestUnitApplicationGo):
def setUpClass():
unit.TestUnit().check_modules('go')
@@ -11,12 +11,15 @@ class TestUnitGoApplication(unit.TestUnitApplicationGo):
body = 'Test body string.'
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Custom-Header': 'blah',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['status'], 200, 'status')
headers = resp['headers']
@@ -25,10 +28,15 @@ class TestUnitGoApplication(unit.TestUnitApplicationGo):
date = headers.pop('Date')
self.assertEqual(date[-4:], ' GMT', 'date header timezone')
self.assertLess(abs(self.date_to_sec_epoch(date) - self.sec_epoch()), 5,
'date header')
self.assertLess(
abs(self.date_to_sec_epoch(date) - self.sec_epoch()),
5,
'date header',
)
self.assertDictEqual(headers, {
self.assertDictEqual(
headers,
{
'Content-Length': str(len(body)),
'Content-Type': 'text/html',
'Request-Method': 'POST',
@@ -38,8 +46,10 @@ class TestUnitGoApplication(unit.TestUnitApplicationGo):
'Server-Protocol-Major': '1',
'Server-Protocol-Minor': '1',
'Custom-Header': 'blah',
'Connection': 'close'
}, 'headers')
'Connection': 'close',
},
'headers',
)
self.assertEqual(resp['body'], body, 'body')
def test_go_application_get_variables(self):
@@ -53,11 +63,14 @@ class TestUnitGoApplication(unit.TestUnitApplicationGo):
def test_go_application_post_variables(self):
self.load('post_variables')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Content-Type': 'application/x-www-form-urlencoded',
'Connection': 'close'
}, body='var1=val1&var2=&var3')
'Connection': 'close',
},
body='var1=val1&var2=&var3',
)
self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'POST variables')
self.assertEqual(resp['headers']['X-Var-2'], '', 'POST variables 2')
@@ -69,36 +82,47 @@ class TestUnitGoApplication(unit.TestUnitApplicationGo):
resp = self.get()
self.assertEqual(resp['status'], 404, '404 status')
self.assertRegex(resp['body'], r'<title>404 Not Found</title>',
'404 body')
self.assertRegex(
resp['body'], r'<title>404 Not Found</title>', '404 body'
)
def test_go_keepalive_body(self):
self.load('mirror')
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='0123456789' * 500)
'Content-Type': 'text/html',
},
start=True,
body='0123456789' * 500,
)
self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Connection': 'close'
}, sock=sock, body='0123456789')
'Connection': 'close',
},
sock=sock,
body='0123456789',
)
self.assertEqual(resp['body'], '0123456789', 'keep-alive 2')
def test_go_application_cookies(self):
self.load('cookies')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Cookie': 'var1=val1; var2=val2',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['headers']['X-Cookie-1'], 'val1', 'cookie 1')
self.assertEqual(resp['headers']['X-Cookie-2'], 'val2', 'cookie 2')
@@ -106,15 +130,22 @@ class TestUnitGoApplication(unit.TestUnitApplicationGo):
def test_go_application_command_line_arguments_type(self):
self.load('command_line_arguments')
self.assertIn('error', self.conf(''"a b c",
'applications/command_line_arguments/arguments'), 'arguments type')
self.assertIn(
'error',
self.conf(
'' "a b c", 'applications/command_line_arguments/arguments'
),
'arguments type',
)
def test_go_application_command_line_arguments_0(self):
self.load('command_line_arguments')
self.assertEqual(self.get()['headers']['X-Arg-0'],
self.assertEqual(
self.get()['headers']['X-Arg-0'],
self.conf_get('applications/command_line_arguments/executable'),
'argument 0')
'argument 0',
)
def test_go_application_command_line_arguments(self):
self.load('command_line_arguments')
@@ -123,11 +154,14 @@ class TestUnitGoApplication(unit.TestUnitApplicationGo):
arg2 = '--cc-opt=\'-O0 -DNXT_DEBUG_MEMORY=1 -fsanitize=address\''
arg3 = '--debug'
self.conf('["' + arg1 + '", "' + arg2 + '", "' + arg3 + '"]',
'applications/command_line_arguments/arguments')
self.conf(
'["' + arg1 + '", "' + arg2 + '", "' + arg3 + '"]',
'applications/command_line_arguments/arguments',
)
self.assertEqual(self.get()['body'], arg1 + ',' + arg2 + ',' + arg3,
'arguments')
self.assertEqual(
self.get()['body'], arg1 + ',' + arg2 + ',' + arg3, 'arguments'
)
def test_go_application_command_line_arguments_change(self):
self.load('command_line_arguments')
@@ -144,8 +178,10 @@ class TestUnitGoApplication(unit.TestUnitApplicationGo):
self.conf('[]', args_path)
self.assertEqual(self.get()['headers']['Content-Length'], '0',
'arguments empty')
self.assertEqual(
self.get()['headers']['Content-Length'], '0', 'arguments empty'
)
if __name__ == '__main__':
TestUnitGoApplication.main()

View File

@@ -1,216 +1,302 @@
import unittest
import unit
class TestUnitHTTPHeader(unit.TestUnitApplicationPython):
class TestUnitHTTPHeader(unit.TestUnitApplicationPython):
def setUpClass():
unit.TestUnit().check_modules('python')
def test_http_header_value_leading_sp(self):
self.load('custom_header')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header': ' ,',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 200, 'value leading sp status')
self.assertEqual(resp['headers']['Custom-Header'], ',',
'value leading sp custom header')
self.assertEqual(
resp['headers']['Custom-Header'],
',',
'value leading sp custom header',
)
def test_http_header_value_leading_htab(self):
self.load('custom_header')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header': '\t,',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 200, 'value leading htab status')
self.assertEqual(resp['headers']['Custom-Header'], ',',
'value leading htab custom header')
self.assertEqual(
resp['headers']['Custom-Header'],
',',
'value leading htab custom header',
)
def test_http_header_value_trailing_sp(self):
self.load('custom_header')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header': ', ',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 200, 'value trailing sp status')
self.assertEqual(resp['headers']['Custom-Header'], ',',
'value trailing sp custom header')
self.assertEqual(
resp['headers']['Custom-Header'],
',',
'value trailing sp custom header',
)
def test_http_header_value_trailing_htab(self):
self.load('custom_header')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header': ',\t',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 200, 'value trailing htab status')
self.assertEqual(resp['headers']['Custom-Header'], ',',
'value trailing htab custom header')
self.assertEqual(
resp['headers']['Custom-Header'],
',',
'value trailing htab custom header',
)
def test_http_header_value_both_sp(self):
self.load('custom_header')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header': ' , ',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 200, 'value both sp status')
self.assertEqual(resp['headers']['Custom-Header'], ',',
'value both sp custom header')
self.assertEqual(
resp['headers']['Custom-Header'],
',',
'value both sp custom header',
)
def test_http_header_value_both_htab(self):
self.load('custom_header')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header': '\t,\t',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 200, 'value both htab status')
self.assertEqual(resp['headers']['Custom-Header'], ',',
'value both htab custom header')
self.assertEqual(
resp['headers']['Custom-Header'],
',',
'value both htab custom header',
)
def test_http_header_value_chars(self):
self.load('custom_header')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header': '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 200, 'value chars status')
self.assertEqual(resp['headers']['Custom-Header'],
'(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~', 'value chars custom header')
self.assertEqual(
resp['headers']['Custom-Header'],
'(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~',
'value chars custom header',
)
def test_http_header_value_chars_edge(self):
self.load('custom_header')
resp = self.http(b"""GET / HTTP/1.1
resp = self.http(
b"""GET / HTTP/1.1
Host: localhost
Custom-Header: \x20\xFF
Connection: close
""", raw=True, encoding='latin1')
""",
raw=True,
encoding='latin1',
)
self.assertEqual(resp['status'], 200, 'value chars edge status')
self.assertEqual(resp['headers']['Custom-Header'], '\xFF',
'value chars edge')
self.assertEqual(
resp['headers']['Custom-Header'], '\xFF', 'value chars edge'
)
def test_http_header_value_chars_below(self):
self.load('custom_header')
resp = self.http(b"""GET / HTTP/1.1
resp = self.http(
b"""GET / HTTP/1.1
Host: localhost
Custom-Header: \x1F
Connection: close
""", raw=True)
""",
raw=True,
)
self.assertEqual(resp['status'], 400, 'value chars below')
def test_http_header_field_leading_sp(self):
self.load('empty')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
' Custom-Header': 'blah',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 400, 'field leading sp')
def test_http_header_field_leading_htab(self):
self.load('empty')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'\tCustom-Header': 'blah',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 400, 'field leading htab')
def test_http_header_field_trailing_sp(self):
self.load('empty')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header ': 'blah',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 400, 'field trailing sp')
def test_http_header_field_trailing_htab(self):
self.load('empty')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'Custom-Header\t': 'blah',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['status'], 400, 'field trailing htab')
def test_http_header_content_length_big(self):
self.load('empty')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Length': str(2 ** 64),
'Connection': 'close'
}, body='X' * 1000)['status'], 400, 'Content-Length big')
'Connection': 'close',
},
body='X' * 1000,
)['status'],
400,
'Content-Length big',
)
def test_http_header_content_length_negative(self):
self.load('empty')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Length': '-100',
'Connection': 'close'
}, body='X' * 1000)['status'], 400, 'Content-Length negative')
'Connection': 'close',
},
body='X' * 1000,
)['status'],
400,
'Content-Length negative',
)
def test_http_header_content_length_text(self):
self.load('empty')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Length': 'blah',
'Connection': 'close'
}, body='X' * 1000)['status'], 400, 'Content-Length text')
'Connection': 'close',
},
body='X' * 1000,
)['status'],
400,
'Content-Length text',
)
def test_http_header_content_length_multiple_values(self):
self.load('empty')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Length': '41, 42',
'Connection': 'close'
}, body='X' * 1000)['status'], 400, 'Content-Length multiple value')
'Connection': 'close',
},
body='X' * 1000,
)['status'],
400,
'Content-Length multiple value',
)
def test_http_header_content_length_multiple_fields(self):
self.load('empty')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Length': ['41', '42'],
'Connection': 'close'
}, body='X' * 1000)['status'], 400, 'Content-Length multiple fields')
'Connection': 'close',
},
body='X' * 1000,
)['status'],
400,
'Content-Length multiple fields',
)
def test_http_header_host_absent(self):
self.load('host')
@@ -218,146 +304,182 @@ Connection: close
resp = self.get(headers={'Connection': 'close'})
self.assertEqual(resp['status'], 200, 'Host absent status')
self.assertNotEqual(resp['headers']['X-Server-Name'], '',
'Host absent SERVER_NAME')
self.assertNotEqual(
resp['headers']['X-Server-Name'], '', 'Host absent SERVER_NAME'
)
def test_http_header_host_empty(self):
self.load('host')
resp = self.get(headers={
'Host': '',
'Connection': 'close'
})
resp = self.get(headers={'Host': '', 'Connection': 'close'})
self.assertEqual(resp['status'], 200, 'Host empty status')
self.assertNotEqual(resp['headers']['X-Server-Name'], '',
'Host empty SERVER_NAME')
self.assertNotEqual(
resp['headers']['X-Server-Name'], '', 'Host empty SERVER_NAME'
)
def test_http_header_host_big(self):
self.load('empty')
self.assertEqual(self.get(headers={
'Host': 'X' * 10000,
'Connection': 'close'
})['status'], 431, 'Host big')
self.assertEqual(
self.get(headers={'Host': 'X' * 10000, 'Connection': 'close'})[
'status'
],
431,
'Host big',
)
def test_http_header_host_port(self):
self.load('host')
resp = self.get(headers={
'Host': 'exmaple.com:7080',
'Connection': 'close'
})
resp = self.get(
headers={'Host': 'exmaple.com:7080', 'Connection': 'close'}
)
self.assertEqual(resp['status'], 200, 'Host port status')
self.assertEqual(resp['headers']['X-Server-Name'], 'exmaple.com',
'Host port SERVER_NAME')
self.assertEqual(resp['headers']['X-Http-Host'], 'exmaple.com:7080',
'Host port HTTP_HOST')
self.assertEqual(
resp['headers']['X-Server-Name'],
'exmaple.com',
'Host port SERVER_NAME',
)
self.assertEqual(
resp['headers']['X-Http-Host'],
'exmaple.com:7080',
'Host port HTTP_HOST',
)
def test_http_header_host_port_empty(self):
self.load('host')
resp = self.get(headers={
'Host': 'exmaple.com:',
'Connection': 'close'
})
resp = self.get(
headers={'Host': 'exmaple.com:', 'Connection': 'close'}
)
self.assertEqual(resp['status'], 200, 'Host port empty status')
self.assertEqual(resp['headers']['X-Server-Name'], 'exmaple.com',
'Host port empty SERVER_NAME')
self.assertEqual(resp['headers']['X-Http-Host'], 'exmaple.com:',
'Host port empty HTTP_HOST')
self.assertEqual(
resp['headers']['X-Server-Name'],
'exmaple.com',
'Host port empty SERVER_NAME',
)
self.assertEqual(
resp['headers']['X-Http-Host'],
'exmaple.com:',
'Host port empty HTTP_HOST',
)
def test_http_header_host_literal(self):
self.load('host')
resp = self.get(headers={
'Host': '127.0.0.1',
'Connection': 'close'
})
resp = self.get(headers={'Host': '127.0.0.1', 'Connection': 'close'})
self.assertEqual(resp['status'], 200, 'Host literal status')
self.assertEqual(resp['headers']['X-Server-Name'], '127.0.0.1',
'Host literal SERVER_NAME')
self.assertEqual(
resp['headers']['X-Server-Name'],
'127.0.0.1',
'Host literal SERVER_NAME',
)
def test_http_header_host_literal_ipv6(self):
self.load('host')
resp = self.get(headers={
'Host': '[::1]:7080',
'Connection': 'close'
})
resp = self.get(headers={'Host': '[::1]:7080', 'Connection': 'close'})
self.assertEqual(resp['status'], 200, 'Host literal ipv6 status')
self.assertEqual(resp['headers']['X-Server-Name'], '[::1]',
'Host literal ipv6 SERVER_NAME')
self.assertEqual(resp['headers']['X-Http-Host'], '[::1]:7080',
'Host literal ipv6 HTTP_HOST')
self.assertEqual(
resp['headers']['X-Server-Name'],
'[::1]',
'Host literal ipv6 SERVER_NAME',
)
self.assertEqual(
resp['headers']['X-Http-Host'],
'[::1]:7080',
'Host literal ipv6 HTTP_HOST',
)
def test_http_header_host_trailing_period(self):
self.load('host')
resp = self.get(headers={
'Host': '127.0.0.1.',
'Connection': 'close'
})
resp = self.get(headers={'Host': '127.0.0.1.', 'Connection': 'close'})
self.assertEqual(resp['status'], 200, 'Host trailing period status')
self.assertEqual(resp['headers']['X-Server-Name'], '127.0.0.1',
'Host trailing period SERVER_NAME')
self.assertEqual(resp['headers']['X-Http-Host'], '127.0.0.1.',
'Host trailing period HTTP_HOST')
self.assertEqual(
resp['headers']['X-Server-Name'],
'127.0.0.1',
'Host trailing period SERVER_NAME',
)
self.assertEqual(
resp['headers']['X-Http-Host'],
'127.0.0.1.',
'Host trailing period HTTP_HOST',
)
def test_http_header_host_trailing_period_2(self):
self.load('host')
resp = self.get(headers={
'Host': 'EXAMPLE.COM.',
'Connection': 'close'
})
resp = self.get(
headers={'Host': 'EXAMPLE.COM.', 'Connection': 'close'}
)
self.assertEqual(resp['status'], 200, 'Host trailing period 2 status')
self.assertEqual(resp['headers']['X-Server-Name'], 'example.com',
'Host trailing period 2 SERVER_NAME')
self.assertEqual(resp['headers']['X-Http-Host'], 'EXAMPLE.COM.',
'Host trailing period 2 HTTP_HOST')
self.assertEqual(
resp['headers']['X-Server-Name'],
'example.com',
'Host trailing period 2 SERVER_NAME',
)
self.assertEqual(
resp['headers']['X-Http-Host'],
'EXAMPLE.COM.',
'Host trailing period 2 HTTP_HOST',
)
def test_http_header_host_case_insensitive(self):
self.load('host')
resp = self.get(headers={
'Host': 'EXAMPLE.COM',
'Connection': 'close'
})
resp = self.get(headers={'Host': 'EXAMPLE.COM', 'Connection': 'close'})
self.assertEqual(resp['status'], 200, 'Host case insensitive')
self.assertEqual(resp['headers']['X-Server-Name'], 'example.com',
'Host case insensitive SERVER_NAME')
self.assertEqual(
resp['headers']['X-Server-Name'],
'example.com',
'Host case insensitive SERVER_NAME',
)
def test_http_header_host_double_dot(self):
self.load('empty')
self.assertEqual(self.get(headers={
'Host': '127.0.0..1',
'Connection': 'close'
})['status'], 400, 'Host double dot')
self.assertEqual(
self.get(headers={'Host': '127.0.0..1', 'Connection': 'close'})[
'status'
],
400,
'Host double dot',
)
def test_http_header_host_slash(self):
self.load('empty')
self.assertEqual(self.get(headers={
'Host': '/localhost',
'Connection': 'close'
})['status'], 400, 'Host slash')
self.assertEqual(
self.get(headers={'Host': '/localhost', 'Connection': 'close'})[
'status'
],
400,
'Host slash',
)
def test_http_header_host_multiple_fields(self):
self.load('empty')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': ['localhost', 'example.com'],
'Connection': 'close'
})['status'], 400, 'Host multiple fields')
'Connection': 'close',
}
)['status'],
400,
'Host multiple fields',
)
if __name__ == '__main__':
TestUnitHTTPHeader.main()

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
import unittest
import unit
class TestUnitNodeApplication(unit.TestUnitApplicationNode):
class TestUnitNodeApplication(unit.TestUnitApplicationNode):
def setUpClass():
u = unit.TestUnit().check_modules('node')
@@ -10,8 +10,9 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
self.load('basic')
resp = self.get()
self.assertEqual(resp['headers']['Content-Type'], 'text/plain',
'basic header')
self.assertEqual(
resp['headers']['Content-Type'], 'text/plain', 'basic header'
)
self.assertEqual(resp['body'], 'Hello World\n', 'basic body')
def test_node_application_seq(self):
@@ -25,12 +26,15 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
body = 'Test body string.'
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Custom-Header': 'blah',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['status'], 200, 'status')
headers = resp['headers']
@@ -39,15 +43,24 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
date = headers.pop('Date')
self.assertEqual(date[-4:], ' GMT', 'date header timezone')
self.assertLess(abs(self.date_to_sec_epoch(date) - self.sec_epoch()), 5,
'date header')
self.assertLess(
abs(self.date_to_sec_epoch(date) - self.sec_epoch()),
5,
'date header',
)
raw_headers = headers.pop('Request-Raw-Headers')
self.assertRegex(raw_headers, r'^(?:Host|localhost|Content-Type|' \
'text\/html|Custom-Header|blah|Content-Length|17|Connection|' \
'close|,)+$', 'raw headers')
self.assertRegex(
raw_headers,
r'^(?:Host|localhost|Content-Type|'
'text\/html|Custom-Header|blah|Content-Length|17|Connection|'
'close|,)+$',
'raw headers',
)
self.assertDictEqual(headers, {
self.assertDictEqual(
headers,
{
'Connection': 'close',
'Content-Length': str(len(body)),
'Content-Type': 'text/html',
@@ -55,8 +68,10 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
'Request-Uri': '/',
'Http-Host': 'localhost',
'Server-Protocol': 'HTTP/1.1',
'Custom-Header': 'blah'
}, 'headers')
'Custom-Header': 'blah',
},
'headers',
)
self.assertEqual(resp['body'], body, 'body')
def test_node_application_get_variables(self):
@@ -70,11 +85,14 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
def test_node_application_post_variables(self):
self.load('post_variables')
resp = self.post(headers={
resp = self.post(
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Host': 'localhost',
'Connection': 'close'
}, body='var1=val1&var2=&var3')
'Connection': 'close',
},
body='var1=val1&var2=&var3',
)
self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'POST variables')
self.assertEqual(resp['headers']['X-Var-2'], '', 'POST variables 2')
@@ -86,41 +104,56 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
resp = self.get()
self.assertEqual(resp['status'], 404, '404 status')
self.assertRegex(resp['body'], r'<title>404 Not Found</title>',
'404 body')
self.assertRegex(
resp['body'], r'<title>404 Not Found</title>', '404 body'
)
def test_node_keepalive_body(self):
self.load('mirror')
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='0123456789' * 500)
'Content-Type': 'text/html',
},
start=True,
body='0123456789' * 500,
)
self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=sock, body='0123456789')
'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
)
self.assertEqual(resp['body'], '0123456789', 'keep-alive 2')
def test_node_application_write_buffer(self):
self.load('write_buffer')
self.assertEqual(self.get()['body'], '6\r\nbuffer\r\n0\r\n\r\n',
'write buffer')
self.assertEqual(
self.get()['body'], '6\r\nbuffer\r\n0\r\n\r\n', 'write buffer'
)
def test_node_application_write_callback(self):
self.load('write_callback')
self.assertEqual(self.get()['body'],
'5\r\nhello\r\n5\r\nworld\r\n0\r\n\r\n', 'write callback order')
self.assertTrue(self.waitforfiles(self.testdir + '/node/callback'),
'write callback')
self.assertEqual(
self.get()['body'],
'5\r\nhello\r\n5\r\nworld\r\n0\r\n\r\n',
'write callback order',
)
self.assertTrue(
self.waitforfiles(self.testdir + '/node/callback'),
'write callback',
)
def test_node_application_write_before_write_head(self):
self.load('write_before_write_head')
@@ -136,17 +169,22 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
def test_node_application_write_return(self):
self.load('write_return')
self.assertEqual(self.get()['body'],
'4\r\nbody\r\n4\r\ntrue\r\n0\r\n\r\n', 'write return')
self.assertEqual(
self.get()['body'],
'4\r\nbody\r\n4\r\ntrue\r\n0\r\n\r\n',
'write return',
)
def test_node_application_remove_header(self):
self.load('remove_header')
resp = self.get(headers={
resp = self.get(
headers={
'Host': 'localhost',
'X-Remove': 'X-Header',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['headers']['Was-Header'], 'true', 'was header')
self.assertEqual(resp['headers']['Has-Header'], 'false', 'has header')
self.assertFalse('X-Header' in resp['headers'], 'remove header')
@@ -154,35 +192,48 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
def test_node_application_remove_header_nonexisting(self):
self.load('remove_header')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Remove': 'blah',
'Connection': 'close'
})['headers']['Has-Header'], 'true', 'remove header nonexisting')
'Connection': 'close',
}
)['headers']['Has-Header'],
'true',
'remove header nonexisting',
)
def test_node_application_update_header(self):
self.load('update_header')
self.assertEqual(self.get()['headers']['X-Header'], 'new',
'update header')
self.assertEqual(
self.get()['headers']['X-Header'], 'new', 'update header'
)
def test_node_application_set_header_array(self):
self.load('set_header_array')
self.assertListEqual(self.get()['headers']['Set-Cookie'],
['tc=one,two,three', 'tc=four,five,six'], 'set header array')
self.assertListEqual(
self.get()['headers']['Set-Cookie'],
['tc=one,two,three', 'tc=four,five,six'],
'set header array',
)
@unittest.expectedFailure
def test_node_application_status_message(self):
self.load('status_message')
self.assertRegex(self.get(raw_resp=True), r'200 blah', 'status message')
self.assertRegex(
self.get(raw_resp=True), r'200 blah', 'status message'
)
def test_node_application_get_header_type(self):
self.load('get_header_type')
self.assertEqual(self.get()['headers']['X-Type'], 'number',
'get header type')
self.assertEqual(
self.get()['headers']['X-Type'], 'number', 'get header type'
)
def test_node_application_header_name_case(self):
self.load('header_name_case')
@@ -196,56 +247,89 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
def test_node_application_promise_handler(self):
self.load('promise_handler')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Connection': 'close'
}, body='callback')['status'], 200, 'promise handler request')
self.assertTrue(self.waitforfiles(self.testdir + '/node/callback'),
'promise handler')
'Connection': 'close',
},
body='callback',
)['status'],
200,
'promise handler request',
)
self.assertTrue(
self.waitforfiles(self.testdir + '/node/callback'),
'promise handler',
)
def test_node_application_promise_handler_write_after_end(self):
self.load('promise_handler')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'X-Write-Call': '1',
'Connection': 'close'
}, body='callback')['status'], 200,
'promise handler request write after end')
'Connection': 'close',
},
body='callback',
)['status'],
200,
'promise handler request write after end',
)
def test_node_application_promise_end(self):
self.load('promise_end')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Connection': 'close'
}, body='end')['status'], 200, 'promise end request')
self.assertTrue(self.waitforfiles(self.testdir + '/node/callback'),
'promise end')
'Connection': 'close',
},
body='end',
)['status'],
200,
'promise end request',
)
self.assertTrue(
self.waitforfiles(self.testdir + '/node/callback'), 'promise end'
)
def test_node_application_promise_multiple_calls(self):
self.load('promise_handler')
self.post(headers={
self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Connection': 'close'
}, body='callback1')
'Connection': 'close',
},
body='callback1',
)
self.assertTrue(self.waitforfiles(self.testdir + '/node/callback1'),
'promise first call')
self.assertTrue(
self.waitforfiles(self.testdir + '/node/callback1'),
'promise first call',
)
self.post(headers={
self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Connection': 'close'
}, body='callback2')
'Connection': 'close',
},
body='callback2',
)
self.assertTrue(self.waitforfiles(self.testdir + '/node/callback2'),
'promise second call')
self.assertTrue(
self.waitforfiles(self.testdir + '/node/callback2'),
'promise second call',
)
@unittest.expectedFailure
def test_node_application_header_name_valid(self):
@@ -261,28 +345,46 @@ class TestUnitNodeApplication(unit.TestUnitApplicationNode):
def test_node_application_get_header_names(self):
self.load('get_header_names')
self.assertListEqual(self.get()['headers']['X-Names'],
['date', 'x-header'], 'get header names')
self.assertListEqual(
self.get()['headers']['X-Names'],
['date', 'x-header'],
'get header names',
)
def test_node_application_has_header(self):
self.load('has_header')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Header': 'length',
'Connection': 'close'
})['headers']['X-Has-Header'], 'false', 'has header length')
'Connection': 'close',
}
)['headers']['X-Has-Header'],
'false',
'has header length',
)
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Header': 'Date',
'Connection': 'close'
})['headers']['X-Has-Header'], 'false', 'has header date')
'Connection': 'close',
}
)['headers']['X-Has-Header'],
'false',
'has header date',
)
def test_node_application_write_multiple(self):
self.load('write_multiple')
self.assertEqual(self.get()['body'], 'writewrite2end', 'write multiple')
self.assertEqual(
self.get()['body'], 'writewrite2end', 'write multiple'
)
if __name__ == '__main__':
TestUnitNodeApplication.main()

View File

@@ -1,8 +1,8 @@
import unittest
import unit
class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
def setUpClass():
unit.TestUnit().check_modules('perl')
@@ -11,26 +11,37 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
body = 'Test body string.'
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Custom-Header': 'blah',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['status'], 200, 'status')
headers = resp['headers']
header_server = headers.pop('Server')
self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header')
self.assertEqual(headers.pop('Server-Software'), header_server,
'server software header')
self.assertEqual(
headers.pop('Server-Software'),
header_server,
'server software header',
)
date = headers.pop('Date')
self.assertEqual(date[-4:], ' GMT', 'date header timezone')
self.assertLess(abs(self.date_to_sec_epoch(date) - self.sec_epoch()), 5,
'date header')
self.assertLess(
abs(self.date_to_sec_epoch(date) - self.sec_epoch()),
5,
'date header',
)
self.assertDictEqual(headers, {
self.assertDictEqual(
headers,
{
'Connection': 'close',
'Content-Length': str(len(body)),
'Content-Type': 'text/html',
@@ -45,8 +56,10 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
'Psgi-Multiprocess': '1',
'Psgi-Run-Once': '',
'Psgi-Nonblocking': '',
'Psgi-Streaming': '1'
}, 'headers')
'Psgi-Streaming': '1',
},
'headers',
)
self.assertEqual(resp['body'], body, 'body')
def test_perl_application_query_string(self):
@@ -54,8 +67,11 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
resp = self.get(url='/?var1=val1&var2=val2')
self.assertEqual(resp['headers']['Query-String'], 'var1=val1&var2=val2',
'Query-String header')
self.assertEqual(
resp['headers']['Query-String'],
'var1=val1&var2=val2',
'Query-String header',
)
def test_perl_application_query_string_empty(self):
self.load('query_string')
@@ -63,8 +79,9 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
resp = self.get(url='/?')
self.assertEqual(resp['status'], 200, 'query string empty status')
self.assertEqual(resp['headers']['Query-String'], '',
'query string empty')
self.assertEqual(
resp['headers']['Query-String'], '', 'query string empty'
)
@unittest.expectedFailure
def test_perl_application_query_string_absent(self):
@@ -73,15 +90,17 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
resp = self.get()
self.assertEqual(resp['status'], 200, 'query string absent status')
self.assertEqual(resp['headers']['Query-String'], '',
'query string absent')
self.assertEqual(
resp['headers']['Query-String'], '', 'query string absent'
)
@unittest.expectedFailure
def test_perl_application_server_port(self):
self.load('server_port')
self.assertEqual(self.get()['headers']['Server-Port'], '7080',
'Server-Port header')
self.assertEqual(
self.get()['headers']['Server-Port'], '7080', 'Server-Port header'
)
def test_perl_application_input_read_empty(self):
self.load('input_read_empty')
@@ -91,15 +110,19 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
def test_perl_application_input_read_parts(self):
self.load('input_read_parts')
self.assertEqual(self.post(body='0123456789')['body'], '0123456789',
'input read parts')
self.assertEqual(
self.post(body='0123456789')['body'],
'0123456789',
'input read parts',
)
@unittest.expectedFailure
def test_perl_application_input_read_offset(self):
self.load('input_read_offset')
self.assertEqual(self.post(body='0123456789')['body'], '4567',
'read offset')
self.assertEqual(
self.post(body='0123456789')['body'], '4567', 'read offset'
)
def test_perl_application_input_copy(self):
self.load('input_copy')
@@ -116,13 +139,17 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
self.assertIsNotNone(
self.search_in_log(r'\[error\].+Error in application'),
'errors print')
'errors print',
)
def test_perl_application_header_equal_names(self):
self.load('header_equal_names')
self.assertListEqual(self.get()['headers']['Set-Cookie'],
['tc=one,two,three', 'tc=four,five,six'], 'header equal names')
self.assertListEqual(
self.get()['headers']['Set-Cookie'],
['tc=one,two,three', 'tc=four,five,six'],
'header equal names',
)
def test_perl_application_header_pairs(self):
self.load('header_pairs')
@@ -160,10 +187,9 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
@unittest.expectedFailure
def test_perl_application_syntax_error(self):
self.skip_alerts.extend([
r'PSGI: Failed to parse script',
r'process \d+ exited on signal'
])
self.skip_alerts.extend(
[r'PSGI: Failed to parse script', r'process \d+ exited on signal']
)
self.load('syntax_error')
self.assertEqual(self.get()['status'], 500, 'syntax error')
@@ -171,19 +197,27 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
def test_perl_keepalive_body(self):
self.load('variables')
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='0123456789' * 500)
'Content-Type': 'text/html',
},
start=True,
body='0123456789' * 500,
)
self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=sock, body='0123456789')
'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
)
self.assertEqual(resp['body'], '0123456789', 'keep-alive 2')
@@ -194,11 +228,13 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
self.assertIsNotNone(
self.search_in_log(r'\[error\].+IOFake getline\(\) \$\/ is \d+'),
'body io fake $/ value')
'body io fake $/ value',
)
self.assertIsNotNone(
self.search_in_log(r'\[error\].+IOFake close\(\) called'),
'body io fake close')
'body io fake close',
)
def test_perl_delayed_response(self):
self.load('delayed_response')
@@ -216,5 +252,6 @@ class TestUnitPerlApplication(unit.TestUnitApplicationPerl):
self.assertEqual(resp['status'], 200, 'status')
self.assertEqual(resp['body'], 'Hello World!', 'body')
if __name__ == '__main__':
TestUnitPerlApplication.main()

View File

@@ -2,8 +2,8 @@ import unittest
import unit
import re
class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
def setUpClass():
unit.TestUnit().check_modules('php')
@@ -18,38 +18,51 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
body = 'Test body string.'
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Custom-Header': 'blah',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['status'], 200, 'status')
headers = resp['headers']
header_server = headers.pop('Server')
self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header')
self.assertEqual(headers.pop('Server-Software'), header_server,
'server software header')
self.assertEqual(
headers.pop('Server-Software'),
header_server,
'server software header',
)
date = headers.pop('Date')
self.assertEqual(date[-4:], ' GMT', 'date header timezone')
self.assertLess(abs(self.date_to_sec_epoch(date) - self.sec_epoch()), 5,
'date header')
self.assertLess(
abs(self.date_to_sec_epoch(date) - self.sec_epoch()),
5,
'date header',
)
if 'X-Powered-By' in headers:
headers.pop('X-Powered-By')
headers.pop('Content-type')
self.assertDictEqual(headers, {
self.assertDictEqual(
headers,
{
'Connection': 'close',
'Content-Length': str(len(body)),
'Request-Method': 'POST',
'Request-Uri': '/',
'Http-Host': 'localhost',
'Server-Protocol': 'HTTP/1.1',
'Custom-Header': 'blah'
}, 'headers')
'Custom-Header': 'blah',
},
'headers',
)
self.assertEqual(resp['body'], body, 'body')
def test_php_application_query_string(self):
@@ -57,8 +70,11 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
resp = self.get(url='/?var1=val1&var2=val2')
self.assertEqual(resp['headers']['Query-String'], 'var1=val1&var2=val2',
'query string')
self.assertEqual(
resp['headers']['Query-String'],
'var1=val1&var2=val2',
'query string',
)
def test_php_application_query_string_empty(self):
self.load('query_string')
@@ -66,8 +82,9 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
resp = self.get(url='/?')
self.assertEqual(resp['status'], 200, 'query string empty status')
self.assertEqual(resp['headers']['Query-String'], '',
'query string empty')
self.assertEqual(
resp['headers']['Query-String'], '', 'query string empty'
)
@unittest.expectedFailure
def test_php_application_query_string_absent(self):
@@ -76,8 +93,9 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
resp = self.get()
self.assertEqual(resp['status'], 200, 'query string absent status')
self.assertEqual(resp['headers']['Query-String'], '',
'query string absent')
self.assertEqual(
resp['headers']['Query-String'], '', 'query string absent'
)
def test_php_application_phpinfo(self):
self.load('phpinfo')
@@ -93,25 +111,34 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
resp = self.get()
self.assertEqual(resp['status'], 404, '404 status')
self.assertRegex(resp['body'], r'<title>404 Not Found</title>',
'404 body')
self.assertRegex(
resp['body'], r'<title>404 Not Found</title>', '404 body'
)
def test_php_application_keepalive_body(self):
self.load('mirror')
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='0123456789' * 500)
'Content-Type': 'text/html',
},
start=True,
body='0123456789' * 500,
)
self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=sock, body='0123456789')
'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
)
self.assertEqual(resp['body'], '0123456789', 'keep-alive 2')
@@ -133,11 +160,14 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
def test_php_application_post_variables(self):
self.load('post_variables')
resp = self.post(headers={
resp = self.post(
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Host': 'localhost',
'Connection': 'close'
}, body='var1=val1&var2=')
'Connection': 'close',
},
body='var1=val1&var2=',
)
self.assertEqual(resp['headers']['X-Var-1'], 'val1', 'POST variables')
self.assertEqual(resp['headers']['X-Var-2'], '1', 'POST variables 2')
self.assertEqual(resp['headers']['X-Var-3'], '', 'POST variables 3')
@@ -145,11 +175,13 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
def test_php_application_cookies(self):
self.load('cookies')
resp = self.get(headers={
resp = self.get(
headers={
'Cookie': 'var=val; var2=val2',
'Host': 'localhost',
'Connection': 'close'
})
'Connection': 'close',
}
)
self.assertEqual(resp['headers']['X-Cookie-1'], 'val', 'cookie')
self.assertEqual(resp['headers']['X-Cookie-2'], 'val2', 'cookie')
@@ -157,96 +189,129 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
def test_php_application_ini_precision(self):
self.load('ini_precision')
self.assertNotEqual(self.get()['headers']['X-Precision'], '4',
'ini value default')
self.assertNotEqual(
self.get()['headers']['X-Precision'], '4', 'ini value default'
)
self.conf({"file": "ini/php.ini"}, 'applications/ini_precision/options')
self.conf(
{"file": "ini/php.ini"}, 'applications/ini_precision/options'
)
self.assertEqual(self.get()['headers']['X-File'],
self.current_dir + '/php/ini_precision/ini/php.ini', 'ini file')
self.assertEqual(self.get()['headers']['X-Precision'], '4', 'ini value')
self.assertEqual(
self.get()['headers']['X-File'],
self.current_dir + '/php/ini_precision/ini/php.ini',
'ini file',
)
self.assertEqual(
self.get()['headers']['X-Precision'], '4', 'ini value'
)
@unittest.expectedFailure
def test_php_application_ini_admin_user(self):
self.load('ini_precision')
self.assertIn('error', self.conf({
"user": { "precision": "4" },
"admin": { "precision": "5" }
}, 'applications/ini_precision/options'), 'ini admin user')
self.assertIn(
'error',
self.conf(
{"user": {"precision": "4"}, "admin": {"precision": "5"}},
'applications/ini_precision/options',
),
'ini admin user',
)
def test_php_application_ini_admin(self):
self.load('ini_precision')
self.conf({
"file": "php.ini",
"admin": { "precision": "5" }
}, 'applications/ini_precision/options')
self.conf(
{"file": "php.ini", "admin": {"precision": "5"}},
'applications/ini_precision/options',
)
self.assertEqual(self.get()['headers']['X-Precision'], '5',
'ini value admin')
self.assertEqual(
self.get()['headers']['X-Precision'], '5', 'ini value admin'
)
def test_php_application_ini_user(self):
self.load('ini_precision')
self.conf({
"file": "php.ini",
"user": { "precision": "5" }
}, 'applications/ini_precision/options')
self.conf(
{"file": "php.ini", "user": {"precision": "5"}},
'applications/ini_precision/options',
)
self.assertEqual(self.get()['headers']['X-Precision'], '5',
'ini value user')
self.assertEqual(
self.get()['headers']['X-Precision'], '5', 'ini value user'
)
def test_php_application_ini_user_2(self):
self.load('ini_precision')
self.conf({"file": "ini/php.ini"}, 'applications/ini_precision/options')
self.conf(
{"file": "ini/php.ini"}, 'applications/ini_precision/options'
)
self.assertEqual(self.get()['headers']['X-Precision'], '4',
'ini user file')
self.assertEqual(
self.get()['headers']['X-Precision'], '4', 'ini user file'
)
self.conf({ "precision": "5" },
'applications/ini_precision/options/user')
self.conf(
{"precision": "5"}, 'applications/ini_precision/options/user'
)
self.assertEqual(self.get()['headers']['X-Precision'], '5',
'ini value user')
self.assertEqual(
self.get()['headers']['X-Precision'], '5', 'ini value user'
)
def test_php_application_ini_set_admin(self):
self.load('ini_precision')
self.conf({"admin": { "precision": "5" }},
'applications/ini_precision/options')
self.conf(
{"admin": {"precision": "5"}}, 'applications/ini_precision/options'
)
self.assertEqual(self.get(url='/?precision=6')['headers']['X-Precision'],
'5', 'ini set admin')
self.assertEqual(
self.get(url='/?precision=6')['headers']['X-Precision'],
'5',
'ini set admin',
)
def test_php_application_ini_set_user(self):
self.load('ini_precision')
self.conf({"user": { "precision": "5" }},
'applications/ini_precision/options')
self.conf(
{"user": {"precision": "5"}}, 'applications/ini_precision/options'
)
self.assertEqual(self.get(url='/?precision=6')['headers']['X-Precision'],
'6', 'ini set user')
self.assertEqual(
self.get(url='/?precision=6')['headers']['X-Precision'],
'6',
'ini set user',
)
def test_php_application_ini_repeat(self):
self.load('ini_precision')
self.conf({"user": { "precision": "5" }},
'applications/ini_precision/options')
self.conf(
{"user": {"precision": "5"}}, 'applications/ini_precision/options'
)
self.assertEqual(self.get()['headers']['X-Precision'], '5', 'ini value')
self.assertEqual(
self.get()['headers']['X-Precision'], '5', 'ini value'
)
self.assertEqual(self.get()['headers']['X-Precision'], '5',
'ini value repeat')
self.assertEqual(
self.get()['headers']['X-Precision'], '5', 'ini value repeat'
)
def test_php_application_disable_functions_exec(self):
self.load('time_exec')
self.before_disable_functions()
self.conf({"admin": { "disable_functions": "exec" }},
'applications/time_exec/options')
self.conf(
{"admin": {"disable_functions": "exec"}},
'applications/time_exec/options',
)
body = self.get()['body']
@@ -258,80 +323,103 @@ class TestUnitPHPApplication(unit.TestUnitApplicationPHP):
self.before_disable_functions()
self.conf({"admin": { "disable_functions": "exec,time" }},
'applications/time_exec/options')
self.conf(
{"admin": {"disable_functions": "exec,time"}},
'applications/time_exec/options',
)
body = self.get()['body']
self.assertNotRegex(body, r'time: \d+', 'disable_functions comma time')
self.assertNotRegex(body, r'exec: \/\w+',
'disable_functions comma exec')
self.assertNotRegex(
body, r'exec: \/\w+', 'disable_functions comma exec'
)
def test_php_application_disable_functions_space(self):
self.load('time_exec')
self.before_disable_functions()
self.conf({"admin": { "disable_functions": "exec time" }},
'applications/time_exec/options')
self.conf(
{"admin": {"disable_functions": "exec time"}},
'applications/time_exec/options',
)
body = self.get()['body']
self.assertNotRegex(body, r'time: \d+', 'disable_functions space time')
self.assertNotRegex(body, r'exec: \/\w+',
'disable_functions space exec')
self.assertNotRegex(
body, r'exec: \/\w+', 'disable_functions space exec'
)
def test_php_application_disable_functions_user(self):
self.load('time_exec')
self.before_disable_functions()
self.conf({"user": { "disable_functions": "exec" }},
'applications/time_exec/options')
self.conf(
{"user": {"disable_functions": "exec"}},
'applications/time_exec/options',
)
body = self.get()['body']
self.assertRegex(body, r'time: \d+', 'disable_functions user time')
self.assertNotRegex(body, r'exec: \/\w+', 'disable_functions user exec')
self.assertNotRegex(
body, r'exec: \/\w+', 'disable_functions user exec'
)
def test_php_application_disable_functions_nonexistent(self):
self.load('time_exec')
self.before_disable_functions()
self.conf({"admin": { "disable_functions": "blah" }},
'applications/time_exec/options')
self.conf(
{"admin": {"disable_functions": "blah"}},
'applications/time_exec/options',
)
body = self.get()['body']
self.assertRegex(body, r'time: \d+',
'disable_functions nonexistent time')
self.assertRegex(body, r'exec: \/\w+',
'disable_functions nonexistent exec')
self.assertRegex(
body, r'time: \d+', 'disable_functions nonexistent time'
)
self.assertRegex(
body, r'exec: \/\w+', 'disable_functions nonexistent exec'
)
def test_php_application_disable_classes(self):
self.load('date_time')
self.assertRegex(self.get()['body'], r'012345',
'disable_classes before')
self.assertRegex(
self.get()['body'], r'012345', 'disable_classes before'
)
self.conf({"admin": { "disable_classes": "DateTime" }},
'applications/date_time/options')
self.conf(
{"admin": {"disable_classes": "DateTime"}},
'applications/date_time/options',
)
self.assertNotRegex(self.get()['body'], r'012345',
'disable_classes before')
self.assertNotRegex(
self.get()['body'], r'012345', 'disable_classes before'
)
def test_php_application_disable_classes_user(self):
self.load('date_time')
self.assertRegex(self.get()['body'], r'012345',
'disable_classes before')
self.assertRegex(
self.get()['body'], r'012345', 'disable_classes before'
)
self.conf({"user": { "disable_classes": "DateTime" }},
'applications/date_time/options')
self.conf(
{"user": {"disable_classes": "DateTime"}},
'applications/date_time/options',
)
self.assertNotRegex(
self.get()['body'], r'012345', 'disable_classes before'
)
self.assertNotRegex(self.get()['body'], r'012345',
'disable_classes before')
if __name__ == '__main__':
TestUnitPHPApplication.main()

View File

@@ -1,8 +1,8 @@
import unittest
import unit
class TestUnitPHPBasic(unit.TestUnitControl):
class TestUnitPHPBasic(unit.TestUnitControl):
def setUpClass():
unit.TestUnit().check_modules('php')
@@ -11,17 +11,13 @@ class TestUnitPHPBasic(unit.TestUnitControl):
"type": "php",
"processes": {"spare": 0},
"root": "/app",
"index": "index.php"
"index": "index.php",
}
}
conf_basic = {
"listeners": {
"*:7080": {
"application": "app"
}
},
"applications": conf_app
"listeners": {"*:7080": {"application": "app"}},
"applications": conf_app,
}
def test_php_get_applications(self):
@@ -30,113 +26,146 @@ class TestUnitPHPBasic(unit.TestUnitControl):
conf = self.conf_get()
self.assertEqual(conf['listeners'], {}, 'listeners')
self.assertEqual(conf['applications'],
self.assertEqual(
conf['applications'],
{
"app": {
"type": "php",
"processes": {"spare": 0},
"root": "/app",
"index": "index.php"
"index": "index.php",
}
},
'applications')
'applications',
)
def test_php_get_applications_prefix(self):
self.conf(self.conf_app, 'applications')
self.assertEqual(self.conf_get('applications'),
self.assertEqual(
self.conf_get('applications'),
{
"app": {
"type": "php",
"processes": {"spare": 0},
"root": "/app",
"index": "index.php"
"index": "index.php",
}
},
'applications prefix')
'applications prefix',
)
def test_php_get_applications_prefix_2(self):
self.conf(self.conf_app, 'applications')
self.assertEqual(self.conf_get('applications/app'),
self.assertEqual(
self.conf_get('applications/app'),
{
"type": "php",
"processes": {"spare": 0},
"root": "/app",
"index": "index.php"
"index": "index.php",
},
'applications prefix 2')
'applications prefix 2',
)
def test_php_get_applications_prefix_3(self):
self.conf(self.conf_app, 'applications')
self.assertEqual(self.conf_get('applications/app/type'), 'php',
'type')
self.assertEqual(self.conf_get('applications/app/processes/spare'), 0,
'spare processes')
self.assertEqual(self.conf_get('applications/app/type'), 'php', 'type')
self.assertEqual(
self.conf_get('applications/app/processes/spare'),
0,
'spare processes',
)
def test_php_get_listeners(self):
self.conf(self.conf_basic)
self.assertEqual(self.conf_get()['listeners'],
{"*:7080":{"application":"app"}}, 'listeners')
self.assertEqual(
self.conf_get()['listeners'],
{"*:7080": {"application": "app"}},
'listeners',
)
def test_php_get_listeners_prefix(self):
self.conf(self.conf_basic)
self.assertEqual(self.conf_get('listeners'),
{"*:7080":{"application":"app"}}, 'listeners prefix')
self.assertEqual(
self.conf_get('listeners'),
{"*:7080": {"application": "app"}},
'listeners prefix',
)
def test_php_get_listeners_prefix_2(self):
self.conf(self.conf_basic)
self.assertEqual(self.conf_get('listeners/*:7080'),
{"application":"app"}, 'listeners prefix 2')
self.assertEqual(
self.conf_get('listeners/*:7080'),
{"application": "app"},
'listeners prefix 2',
)
def test_php_change_listener(self):
self.conf(self.conf_basic)
self.conf({"*:7081": {"application": "app"}}, 'listeners')
self.assertEqual(self.conf_get('listeners'),
{"*:7081": {"application":"app"}}, 'change listener')
self.assertEqual(
self.conf_get('listeners'),
{"*:7081": {"application": "app"}},
'change listener',
)
def test_php_add_listener(self):
self.conf(self.conf_basic)
self.conf({"application": "app"}, 'listeners/*:7082')
self.assertEqual(self.conf_get('listeners'),
self.assertEqual(
self.conf_get('listeners'),
{
"*:7080": {
"application": "app"
"*:7080": {"application": "app"},
"*:7082": {"application": "app"},
},
"*:7082": {
"application": "app"
}
},
'add listener')
'add listener',
)
def test_php_change_application(self):
self.conf(self.conf_basic)
self.conf('30', 'applications/app/processes/max')
self.assertEqual(self.conf_get('applications/app/processes/max'), 30,
'change application max')
self.assertEqual(
self.conf_get('applications/app/processes/max'),
30,
'change application max',
)
self.conf('"/www"', 'applications/app/root')
self.assertEqual(self.conf_get('applications/app/root'), '/www',
'change application root')
self.assertEqual(
self.conf_get('applications/app/root'),
'/www',
'change application root',
)
def test_php_delete(self):
self.conf(self.conf_basic)
self.assertIn('error', self.conf_delete('applications/app'),
'delete app before listener')
self.assertIn('success', self.conf_delete('listeners/*:7080'),
'delete listener')
self.assertIn('success', self.conf_delete('applications/app'),
'delete app after listener')
self.assertIn('error', self.conf_delete('applications/app'),
'delete app again')
self.assertIn(
'error',
self.conf_delete('applications/app'),
'delete app before listener',
)
self.assertIn(
'success', self.conf_delete('listeners/*:7080'), 'delete listener'
)
self.assertIn(
'success',
self.conf_delete('applications/app'),
'delete app after listener',
)
self.assertIn(
'error', self.conf_delete('applications/app'), 'delete app again'
)
if __name__ == '__main__':
TestUnitPHPBasic.main()

View File

@@ -2,8 +2,8 @@ import time
import unittest
import unit
class TestUnitPythonApplication(unit.TestUnitApplicationPython):
class TestUnitPythonApplication(unit.TestUnitApplicationPython):
def setUpClass():
unit.TestUnit().check_modules('python')
@@ -12,26 +12,37 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython):
body = 'Test body string.'
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Custom-Header': 'blah',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['status'], 200, 'status')
headers = resp['headers']
header_server = headers.pop('Server')
self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header')
self.assertEqual(headers.pop('Server-Software'), header_server,
'server software header')
self.assertEqual(
headers.pop('Server-Software'),
header_server,
'server software header',
)
date = headers.pop('Date')
self.assertEqual(date[-4:], ' GMT', 'date header timezone')
self.assertLess(abs(self.date_to_sec_epoch(date) - self.sec_epoch()), 5,
'date header')
self.assertLess(
abs(self.date_to_sec_epoch(date) - self.sec_epoch()),
5,
'date header',
)
self.assertDictEqual(headers, {
self.assertDictEqual(
headers,
{
'Connection': 'close',
'Content-Length': str(len(body)),
'Content-Type': 'text/html',
@@ -44,8 +55,10 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython):
'Wsgi-Url-Scheme': 'http',
'Wsgi-Multithread': 'False',
'Wsgi-Multiprocess': 'True',
'Wsgi-Run-Once': 'False'
}, 'headers')
'Wsgi-Run-Once': 'False',
},
'headers',
)
self.assertEqual(resp['body'], body, 'body')
def test_python_application_query_string(self):
@@ -53,8 +66,11 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython):
resp = self.get(url='/?var1=val1&var2=val2')
self.assertEqual(resp['headers']['Query-String'], 'var1=val1&var2=val2',
'Query-String header')
self.assertEqual(
resp['headers']['Query-String'],
'var1=val1&var2=val2',
'Query-String header',
)
def test_python_application_query_string_empty(self):
self.load('query_string')
@@ -62,8 +78,9 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython):
resp = self.get(url='/?')
self.assertEqual(resp['status'], 200, 'query string empty status')
self.assertEqual(resp['headers']['Query-String'], '',
'query string empty')
self.assertEqual(
resp['headers']['Query-String'], '', 'query string empty'
)
def test_python_application_query_string_absent(self):
self.load('query_string')
@@ -71,71 +88,87 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython):
resp = self.get()
self.assertEqual(resp['status'], 200, 'query string absent status')
self.assertEqual(resp['headers']['Query-String'], '',
'query string absent')
self.assertEqual(
resp['headers']['Query-String'], '', 'query string absent'
)
@unittest.expectedFailure
def test_python_application_server_port(self):
self.load('server_port')
self.assertEqual(self.get()['headers']['Server-Port'], '7080',
'Server-Port header')
self.assertEqual(
self.get()['headers']['Server-Port'], '7080', 'Server-Port header'
)
def test_python_application_204_transfer_encoding(self):
self.load('204_no_content')
self.assertNotIn('Transfer-Encoding', self.get()['headers'],
'204 header transfer encoding')
self.assertNotIn(
'Transfer-Encoding',
self.get()['headers'],
'204 header transfer encoding',
)
def test_python_application_ctx_iter_atexit(self):
self.load('ctx_iter_atexit')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, body='0123456789')
'Content-Type': 'text/html',
},
body='0123456789',
)
self.assertEqual(resp['status'], 200, 'ctx iter status')
self.assertEqual(resp['body'], '0123456789', 'ctx iter body')
self.conf({
"listeners": {},
"applications": {}
})
self.conf({"listeners": {}, "applications": {}})
self.stop()
time.sleep(0.2)
self.assertIsNotNone(self.search_in_log(r'RuntimeError'),
'ctx iter atexit')
self.assertIsNotNone(
self.search_in_log(r'RuntimeError'), 'ctx iter atexit'
)
def test_python_keepalive_body(self):
self.load('mirror')
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='0123456789' * 500)
'Content-Type': 'text/html',
},
start=True,
body='0123456789' * 500,
)
self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=sock, body='0123456789')
'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
)
self.assertEqual(resp['body'], '0123456789', 'keep-alive 2')
def test_python_keepalive_reconfigure(self):
self.skip_alerts.extend([
self.skip_alerts.extend(
[
r'pthread_mutex.+failed',
r'failed to apply',
r'process \d+ exited on signal'
])
r'process \d+ exited on signal',
]
)
self.load('mirror')
body = '0123456789'
@@ -143,74 +176,109 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython):
socks = []
for i in range(conns):
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body=body)
'Content-Type': 'text/html',
},
start=True,
body=body,
)
self.assertEqual(resp['body'], body, 'keep-alive open')
self.assertIn('success', self.conf({
"spare": i % 4,
"max": (i % 4) + 1
}, 'applications/mirror/processes'), 'reconfigure')
self.assertIn(
'success',
self.conf(
str(i + 1),
'applications/mirror/processes',
),
'reconfigure',
)
socks.append(sock)
for i in range(conns):
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, sock=socks[i], body=body)
'Content-Type': 'text/html',
},
start=True,
sock=socks[i],
body=body,
)
self.assertEqual(resp['body'], body, 'keep-alive request')
self.assertIn('success', self.conf({
"spare": i % 4,
"max": (i % 4) + 1
}, 'applications/mirror/processes'), 'reconfigure 2')
self.assertIn(
'success',
self.conf(
str(i + 1),
'applications/mirror/processes',
),
'reconfigure 2',
)
for i in range(conns):
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=socks[i], body=body)
'Content-Type': 'text/html',
},
sock=socks[i],
body=body,
)
self.assertEqual(resp['body'], body, 'keep-alive close')
self.assertIn('success', self.conf({
"spare": i % 4,
"max": (i % 4) + 1
}, 'applications/mirror/processes'), 'reconfigure 3')
self.assertIn(
'success',
self.conf(
str(i + 1),
'applications/mirror/processes',
),
'reconfigure 3',
)
def test_python_keepalive_reconfigure_2(self):
self.load('mirror')
body = '0123456789'
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body=body)
'Content-Type': 'text/html',
},
start=True,
body=body,
)
self.assertEqual(resp['body'], body, 'reconfigure 2 keep-alive 1')
self.load('empty')
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, start=True, sock=sock, body=body)
'Content-Type': 'text/html',
},
start=True,
sock=sock,
body=body,
)
self.assertEqual(resp['status'], 200, 'reconfigure 2 keep-alive 2')
self.assertEqual(resp['body'], '', 'reconfigure 2 keep-alive 2 body')
self.assertIn('success', self.conf({
"listeners": {},
"applications": {}
}), 'reconfigure 2 clear configuration')
self.assertIn(
'success',
self.conf({"listeners": {}, "applications": {}}),
'reconfigure 2 clear configuration',
)
resp = self.get(sock=sock)
@@ -219,18 +287,27 @@ class TestUnitPythonApplication(unit.TestUnitApplicationPython):
def test_python_keepalive_reconfigure_3(self):
self.load('empty')
(resp, sock) = self.http(b"""GET / HTTP/1.1
""", start=True, raw=True)
(resp, sock) = self.http(
b"""GET / HTTP/1.1
""",
start=True,
raw=True,
)
self.assertIn('success', self.conf({
"listeners": {},
"applications": {}
}), 'reconfigure 3 clear configuration')
self.assertIn(
'success',
self.conf({"listeners": {}, "applications": {}}),
'reconfigure 3 clear configuration',
)
resp = self.http(b"""Host: localhost
resp = self.http(
b"""Host: localhost
Connection: close
""", sock=sock, raw=True)
""",
sock=sock,
raw=True,
)
self.assertEqual(resp['status'], 200, 'reconfigure 3')
@@ -239,10 +316,7 @@ Connection: close
self.get()
self.conf({
"listeners": {},
"applications": {}
})
self.conf({"listeners": {}, "applications": {}})
self.stop()
@@ -267,35 +341,47 @@ Connection: close
body = '0123456789'
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Input-Length': '5',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['body'], body[:5], 'input read length lt body')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Input-Length': '15',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['body'], body, 'input read length gt body')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Input-Length': '0',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['body'], '', 'input read length zero')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Input-Length': '-1',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['body'], body, 'input read length negative')
@@ -309,7 +395,8 @@ Connection: close
self.assertIsNotNone(
self.search_in_log(r'\[error\].+Error in application\.'),
'errors write')
'errors write',
)
def test_python_application_body_array(self):
self.load('body_array')
@@ -349,8 +436,9 @@ Connection: close
self.stop()
self.assertIsNotNone(self.search_in_log(r'Close called\.'),
'close error')
self.assertIsNotNone(
self.search_in_log(r'Close called\.'), 'close error'
)
def test_python_application_not_iterable(self):
self.load('not_iterable')
@@ -359,14 +447,18 @@ Connection: close
self.stop()
self.assertIsNotNone(self.search_in_log(
r'\[error\].+the application returned not an iterable object'),
'not iterable')
self.assertIsNotNone(
self.search_in_log(
r'\[error\].+the application returned not an iterable object'
),
'not iterable',
)
def test_python_application_write(self):
self.load('write')
self.assertEqual(self.get()['body'], '0123456789', 'write')
if __name__ == '__main__':
TestUnitPythonApplication.main()

View File

@@ -1,8 +1,8 @@
import unittest
import unit
class TestUnitPythonBasic(unit.TestUnitControl):
class TestUnitPythonBasic(unit.TestUnitControl):
def setUpClass():
unit.TestUnit().check_modules('python')
@@ -11,28 +11,27 @@ class TestUnitPythonBasic(unit.TestUnitControl):
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
}
conf_basic = {
"listeners": {
"*:7080": {
"application": "app"
}
},
"applications": conf_app
"listeners": {"*:7080": {"application": "app"}},
"applications": conf_app,
}
def test_python_get_empty(self):
self.assertEqual(self.conf_get(),
{'listeners': {}, 'applications': {}}, 'empty')
self.assertEqual(
self.conf_get(), {'listeners': {}, 'applications': {}}, 'empty'
)
def test_python_get_prefix_listeners(self):
self.assertEqual(self.conf_get('listeners'), {}, 'listeners prefix')
def test_python_get_prefix_applications(self):
self.assertEqual(self.conf_get('applications'), {}, 'applications prefix')
self.assertEqual(
self.conf_get('applications'), {}, 'applications prefix'
)
def test_python_get_applications(self):
self.conf(self.conf_app, 'applications')
@@ -40,113 +39,146 @@ class TestUnitPythonBasic(unit.TestUnitControl):
conf = self.conf_get()
self.assertEqual(conf['listeners'], {}, 'listeners')
self.assertEqual(conf['applications'],
self.assertEqual(
conf['applications'],
{
"app": {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
}
},
'applications')
'applications',
)
def test_python_get_applications_prefix(self):
self.conf(self.conf_app, 'applications')
self.assertEqual(self.conf_get('applications'),
self.assertEqual(
self.conf_get('applications'),
{
"app": {
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module":"wsgi"
"module": "wsgi",
}
},
'applications prefix')
'applications prefix',
)
def test_python_get_applications_prefix_2(self):
self.conf(self.conf_app, 'applications')
self.assertEqual(self.conf_get('applications/app'),
self.assertEqual(
self.conf_get('applications/app'),
{
"type": "python",
"processes": {"spare": 0},
"path": "/app",
"module": "wsgi"
"module": "wsgi",
},
'applications prefix 2')
'applications prefix 2',
)
def test_python_get_applications_prefix_3(self):
self.conf(self.conf_app, 'applications')
self.assertEqual(self.conf_get('applications/app/type'), 'python',
'type')
self.assertEqual(self.conf_get('applications/app/processes/spare'), 0,
'spare')
self.assertEqual(
self.conf_get('applications/app/type'), 'python', 'type'
)
self.assertEqual(
self.conf_get('applications/app/processes/spare'), 0, 'spare'
)
def test_python_get_listeners(self):
self.conf(self.conf_basic)
self.assertEqual(self.conf_get()['listeners'],
{"*:7080":{"application":"app"}}, 'listeners')
self.assertEqual(
self.conf_get()['listeners'],
{"*:7080": {"application": "app"}},
'listeners',
)
def test_python_get_listeners_prefix(self):
self.conf(self.conf_basic)
self.assertEqual(self.conf_get('listeners'),
{"*:7080":{"application":"app"}}, 'listeners prefix')
self.assertEqual(
self.conf_get('listeners'),
{"*:7080": {"application": "app"}},
'listeners prefix',
)
def test_python_get_listeners_prefix_2(self):
self.conf(self.conf_basic)
self.assertEqual(self.conf_get('listeners/*:7080'),
{"application":"app"}, 'listeners prefix 2')
self.assertEqual(
self.conf_get('listeners/*:7080'),
{"application": "app"},
'listeners prefix 2',
)
def test_python_change_listener(self):
self.conf(self.conf_basic)
self.conf({"*:7081": {"application": "app"}}, 'listeners')
self.assertEqual(self.conf_get('listeners'),
{"*:7081": {"application":"app"}}, 'change listener')
self.assertEqual(
self.conf_get('listeners'),
{"*:7081": {"application": "app"}},
'change listener',
)
def test_python_add_listener(self):
self.conf(self.conf_basic)
self.conf({"application": "app"}, 'listeners/*:7082')
self.assertEqual(self.conf_get('listeners'),
self.assertEqual(
self.conf_get('listeners'),
{
"*:7080": {
"application": "app"
"*:7080": {"application": "app"},
"*:7082": {"application": "app"},
},
"*:7082": {
"application": "app"
}
},
'add listener')
'add listener',
)
def test_python_change_application(self):
self.conf(self.conf_basic)
self.conf('30', 'applications/app/processes/max')
self.assertEqual(self.conf_get('applications/app/processes/max'), 30,
'change application max')
self.assertEqual(
self.conf_get('applications/app/processes/max'),
30,
'change application max',
)
self.conf('"/www"', 'applications/app/path')
self.assertEqual(self.conf_get('applications/app/path'), '/www',
'change application path')
self.assertEqual(
self.conf_get('applications/app/path'),
'/www',
'change application path',
)
def test_python_delete(self):
self.conf(self.conf_basic)
self.assertIn('error', self.conf_delete('applications/app'),
'delete app before listener')
self.assertIn('success', self.conf_delete('listeners/*:7080'),
'delete listener')
self.assertIn('success', self.conf_delete('applications/app'),
'delete app after listener')
self.assertIn('error', self.conf_delete('applications/app'),
'delete app again')
self.assertIn(
'error',
self.conf_delete('applications/app'),
'delete app before listener',
)
self.assertIn(
'success', self.conf_delete('listeners/*:7080'), 'delete listener'
)
self.assertIn(
'success',
self.conf_delete('applications/app'),
'delete app after listener',
)
self.assertIn(
'error', self.conf_delete('applications/app'), 'delete app again'
)
if __name__ == '__main__':
TestUnitPythonBasic.main()

View File

@@ -1,128 +1,181 @@
import unittest
import unit
class TestUnitPythonEnvironment(unit.TestUnitApplicationPython):
class TestUnitPythonEnvironment(unit.TestUnitApplicationPython):
def setUpClass():
unit.TestUnit().check_modules('python')
def test_python_environment_name_null(self):
self.load('environment')
self.assertIn('error', self.conf({
"va\0r": "val1"
}, 'applications/environment/environment'), 'name null')
self.assertIn(
'error',
self.conf(
{"va\0r": "val1"}, 'applications/environment/environment'
),
'name null',
)
def test_python_environment_name_equals(self):
self.load('environment')
self.assertIn('error', self.conf({
"var=": "val1"
}, 'applications/environment/environment'), 'name equals')
self.assertIn(
'error',
self.conf(
{"var=": "val1"}, 'applications/environment/environment'
),
'name equals',
)
def test_python_environment_value_null(self):
self.load('environment')
self.assertIn('error', self.conf({
"var": "\0val"
}, 'applications/environment/environment'), 'value null')
self.assertIn(
'error',
self.conf(
{"var": "\0val"}, 'applications/environment/environment'
),
'value null',
)
def test_python_environment_update(self):
self.load('environment')
self.conf({
"var": "val1"
}, 'applications/environment/environment')
self.conf({"var": "val1"}, 'applications/environment/environment')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Variables': 'var',
'Connection': 'close'
})['body'], 'val1,', 'set')
'Connection': 'close',
}
)['body'],
'val1,',
'set',
)
self.conf({
"var": "val2"
}, 'applications/environment/environment')
self.conf({"var": "val2"}, 'applications/environment/environment')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Variables': 'var',
'Connection': 'close'
})['body'], 'val2,', 'update')
'Connection': 'close',
}
)['body'],
'val2,',
'update',
)
def test_python_environment_replace(self):
self.load('environment')
self.conf({
"var1": "val1"
}, 'applications/environment/environment')
self.conf({"var1": "val1"}, 'applications/environment/environment')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Variables': 'var1',
'Connection': 'close'
})['body'], 'val1,', 'set')
'Connection': 'close',
}
)['body'],
'val1,',
'set',
)
self.conf({
"var2": "val2"
}, 'applications/environment/environment')
self.conf({"var2": "val2"}, 'applications/environment/environment')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Variables': 'var1,var2',
'Connection': 'close'
})['body'], 'val2,', 'replace')
'Connection': 'close',
}
)['body'],
'val2,',
'replace',
)
def test_python_environment_clear(self):
self.load('environment')
self.conf({
"var1": "val1",
"var2": "val2"
}, 'applications/environment/environment')
self.conf(
{"var1": "val1", "var2": "val2"},
'applications/environment/environment',
)
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Variables': 'var1,var2',
'Connection': 'close'
})['body'], 'val1,val2,', 'set')
'Connection': 'close',
}
)['body'],
'val1,val2,',
'set',
)
self.conf({}, 'applications/environment/environment')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Variables': 'var1,var2',
'Connection': 'close'
})['body'], '', 'clear')
'Connection': 'close',
}
)['body'],
'',
'clear',
)
def test_python_environment_replace_default(self):
self.load('environment')
pwd_default = self.get(headers={
pwd_default = self.get(
headers={
'Host': 'localhost',
'X-Variables': 'PWD',
'Connection': 'close'
})['body']
'Connection': 'close',
}
)['body']
self.assertGreater(len(pwd_default), 1, 'get default')
self.conf({
"PWD": "new/pwd"
}, 'applications/environment/environment')
self.conf({"PWD": "new/pwd"}, 'applications/environment/environment')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Variables': 'PWD',
'Connection': 'close'
})['body'], 'new/pwd,', 'replace default')
'Connection': 'close',
}
)['body'],
'new/pwd,',
'replace default',
)
self.conf({}, 'applications/environment/environment')
self.assertEqual(self.get(headers={
self.assertEqual(
self.get(
headers={
'Host': 'localhost',
'X-Variables': 'PWD',
'Connection': 'close'
})['body'], pwd_default, 'restore default')
'Connection': 'close',
}
)['body'],
pwd_default,
'restore default',
)
if __name__ == '__main__':
TestUnitPythonEnvironment.main()

View File

@@ -4,8 +4,8 @@ import subprocess
import unittest
import unit
class TestUnitPythonProcman(unit.TestUnitApplicationPython):
class TestUnitPythonProcman(unit.TestUnitApplicationPython):
def setUpClass():
unit.TestUnit().check_modules('python')
@@ -29,55 +29,88 @@ class TestUnitPythonProcman(unit.TestUnitApplicationPython):
def test_python_processes_access(self):
self.conf('1', 'applications/' + self.app_name + '/processes')
self.assertIn('error', self.conf_get('/applications/' + self.app_name +
'/processes/max'), 'max no access')
self.assertIn('error', self.conf_get('/applications/' + self.app_name +
'/processes/spare'), 'spare no access')
self.assertIn('error', self.conf_get('/applications/' + self.app_name +
'/processes/idle_timeout'), 'idle_timeout no access')
self.assertIn(
'error',
self.conf_get('/applications/' + self.app_name + '/processes/max'),
'max no access',
)
self.assertIn(
'error',
self.conf_get(
'/applications/' + self.app_name + '/processes/spare'
),
'spare no access',
)
self.assertIn(
'error',
self.conf_get(
'/applications/' + self.app_name + '/processes/idle_timeout'
),
'idle_timeout no access',
)
def test_python_processes_spare_negative(self):
self.assertIn('error', self.conf({
"spare": -1
}, 'applications/' + self.app_name + '/processes'), 'negative spare')
self.assertIn(
'error',
self.conf(
{"spare": -1}, 'applications/' + self.app_name + '/processes'
),
'negative spare',
)
def test_python_processes_max_negative(self):
self.assertIn('error', self.conf({
"max": -1
}, 'applications/' + self.app_name + '/processes'), 'negative max')
self.assertIn(
'error',
self.conf(
{"max": -1}, 'applications/' + self.app_name + '/processes'
),
'negative max',
)
def test_python_processes_idle_timeout_negative(self):
self.assertIn('error', self.conf({
"idle_timeout": -1
}, 'applications/' + self.app_name + '/processes'),
'negative idle_timeout')
self.assertIn(
'error',
self.conf(
{"idle_timeout": -1},
'applications/' + self.app_name + '/processes',
),
'negative idle_timeout',
)
def test_python_processes_spare_gt_max_default(self):
self.assertIn('error', self.conf({"spare": 2},
'applications/' + self.app_name + '/processes'),
'spare greater than max default')
self.assertIn(
'error',
self.conf(
{"spare": 2}, 'applications/' + self.app_name + '/processes'
),
'spare greater than max default',
)
def test_python_processes_spare_gt_max(self):
self.assertIn('error', self.conf({
"spare": 2,
"max": 1,
"idle_timeout": 1
}, '/applications/' + self.app_name + '/processes'),
'spare greater than max')
self.assertIn(
'error',
self.conf(
{"spare": 2, "max": 1, "idle_timeout": 1},
'/applications/' + self.app_name + '/processes',
),
'spare greater than max',
)
def test_python_processes_max_zero(self):
self.assertIn('error', self.conf({
"spare": 0,
"max": 0,
"idle_timeout": 1
}, 'applications/' + self.app_name + '/processes'), 'max 0')
self.assertIn(
'error',
self.conf(
{"spare": 0, "max": 0, "idle_timeout": 1},
'applications/' + self.app_name + '/processes',
),
'max 0',
)
def test_python_processes_idle_timeout_zero(self):
self.conf({
"spare": 0,
"max": 2,
"idle_timeout": 0
}, 'applications/' + self.app_name + '/processes')
self.conf(
{"spare": 0, "max": 2, "idle_timeout": 0},
'applications/' + self.app_name + '/processes',
)
self.get()
self.assertEqual(len(self.pids_for_process()), 0, 'idle timeout 0')
@@ -114,11 +147,10 @@ class TestUnitPythonProcman(unit.TestUnitApplicationPython):
self.assertTrue(pids.issubset(pids_new), 'prefork same processes')
def test_python_ondemand(self):
self.conf({
"spare": 0,
"max": 8,
"idle_timeout": 1
}, 'applications/' + self.app_name + '/processes')
self.conf(
{"spare": 0, "max": 8, "idle_timeout": 1},
'applications/' + self.app_name + '/processes',
)
self.assertEqual(len(self.pids_for_process()), 0, 'on-demand 0')
@@ -131,16 +163,17 @@ class TestUnitPythonProcman(unit.TestUnitApplicationPython):
time.sleep(1)
self.assertEqual(len(self.pids_for_process()), 0, 'on-demand stop idle')
self.assertEqual(
len(self.pids_for_process()), 0, 'on-demand stop idle'
)
self.stop_all()
def test_python_scale_updown(self):
self.conf({
"spare": 2,
"max": 8,
"idle_timeout": 1
}, 'applications/' + self.app_name + '/processes')
self.conf(
{"spare": 2, "max": 8, "idle_timeout": 1},
'applications/' + self.app_name + '/processes',
)
pids = self.pids_for_process()
self.assertEqual(len(pids), 2, 'updown 2')
@@ -151,7 +184,9 @@ class TestUnitPythonProcman(unit.TestUnitApplicationPython):
self.assertTrue(pids.issubset(pids_new), 'updown 3 only 1 new')
self.get()
self.assertSetEqual(self.pids_for_process(), pids_new, 'updown still 3')
self.assertSetEqual(
self.pids_for_process(), pids_new, 'updown still 3'
)
time.sleep(1)
@@ -166,11 +201,10 @@ class TestUnitPythonProcman(unit.TestUnitApplicationPython):
self.stop_all()
def test_python_reconfigure(self):
self.conf({
"spare": 2,
"max": 6,
"idle_timeout": 1
}, 'applications/' + self.app_name + '/processes')
self.conf(
{"spare": 2, "max": 6, "idle_timeout": 1},
'applications/' + self.app_name + '/processes',
)
pids = self.pids_for_process()
self.assertEqual(len(pids), 2, 'reconf 2')
@@ -191,11 +225,10 @@ class TestUnitPythonProcman(unit.TestUnitApplicationPython):
self.stop_all()
def test_python_idle_timeout(self):
self.conf({
"spare": 0,
"max": 6,
"idle_timeout": 2
}, 'applications/' + self.app_name + '/processes')
self.conf(
{"spare": 0, "max": 6, "idle_timeout": 2},
'applications/' + self.app_name + '/processes',
)
self.get()
pids = self.pids_for_process()
@@ -209,40 +242,42 @@ class TestUnitPythonProcman(unit.TestUnitApplicationPython):
pids_new = self.pids_for_process()
self.assertEqual(len(pids_new), 1, 'idle timeout still 1')
self.assertSetEqual(self.pids_for_process(), pids,
'idle timeout still 1 same pid')
self.assertSetEqual(
self.pids_for_process(), pids, 'idle timeout still 1 same pid'
)
time.sleep(1)
self.assertEqual(len(self.pids_for_process()), 0, 'idle timed out')
def test_python_processes_connection_keepalive(self):
self.conf({
"spare": 0,
"max": 6,
"idle_timeout": 2
}, 'applications/' + self.app_name + '/processes')
self.conf(
{"spare": 0, "max": 6, "idle_timeout": 2},
'applications/' + self.app_name + '/processes',
)
(resp, sock) = self.get(headers={
'Host': 'localhost',
'Connection': 'keep-alive'
}, start=True, read_timeout=1)
self.assertEqual(len(self.pids_for_process()), 1,
'keepalive connection 1')
(resp, sock) = self.get(
headers={'Host': 'localhost', 'Connection': 'keep-alive'},
start=True,
read_timeout=1,
)
self.assertEqual(
len(self.pids_for_process()), 1, 'keepalive connection 1'
)
time.sleep(2)
self.assertEqual(len(self.pids_for_process()), 0, 'keepalive connection 0')
self.assertEqual(
len(self.pids_for_process()), 0, 'keepalive connection 0'
)
sock.close()
def stop_all(self):
self.conf({
"listeners": {},
"applications": {}
})
self.conf({"listeners": {}, "applications": {}})
self.assertEqual(len(self.pids_for_process()), 0, 'stop all')
if __name__ == '__main__':
TestUnitPythonProcman.main()

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
import unittest
import unit
class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
def setUpClass():
unit.TestUnit().check_modules('ruby')
@@ -11,26 +11,37 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
body = 'Test body string.'
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Custom-Header': 'blah',
'Connection': 'close'
}, body=body)
'Connection': 'close',
},
body=body,
)
self.assertEqual(resp['status'], 200, 'status')
headers = resp['headers']
header_server = headers.pop('Server')
self.assertRegex(header_server, r'Unit/[\d\.]+', 'server header')
self.assertEqual(headers.pop('Server-Software'), header_server,
'server software header')
self.assertEqual(
headers.pop('Server-Software'),
header_server,
'server software header',
)
date = headers.pop('Date')
self.assertEqual(date[-4:], ' GMT', 'date header timezone')
self.assertLess(abs(self.date_to_sec_epoch(date) - self.sec_epoch()), 5,
'date header')
self.assertLess(
abs(self.date_to_sec_epoch(date) - self.sec_epoch()),
5,
'date header',
)
self.assertDictEqual(headers, {
self.assertDictEqual(
headers,
{
'Connection': 'close',
'Content-Length': str(len(body)),
'Content-Type': 'text/html',
@@ -46,8 +57,10 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
'Rack-Run-Once': 'false',
'Rack-Hijack-Q': 'false',
'Rack-Hijack': '',
'Rack-Hijack-IO': ''
}, 'headers')
'Rack-Hijack-IO': '',
},
'headers',
)
self.assertEqual(resp['body'], body, 'body')
def test_ruby_application_query_string(self):
@@ -55,8 +68,11 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
resp = self.get(url='/?var1=val1&var2=val2')
self.assertEqual(resp['headers']['Query-String'], 'var1=val1&var2=val2',
'Query-String header')
self.assertEqual(
resp['headers']['Query-String'],
'var1=val1&var2=val2',
'Query-String header',
)
def test_ruby_application_query_string_empty(self):
self.load('query_string')
@@ -64,8 +80,9 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
resp = self.get(url='/?')
self.assertEqual(resp['status'], 200, 'query string empty status')
self.assertEqual(resp['headers']['Query-String'], '',
'query string empty')
self.assertEqual(
resp['headers']['Query-String'], '', 'query string empty'
)
@unittest.expectedFailure
def test_ruby_application_query_string_absent(self):
@@ -74,15 +91,17 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
resp = self.get()
self.assertEqual(resp['status'], 200, 'query string absent status')
self.assertEqual(resp['headers']['Query-String'], '',
'query string absent')
self.assertEqual(
resp['headers']['Query-String'], '', 'query string absent'
)
@unittest.expectedFailure
def test_ruby_application_server_port(self):
self.load('server_port')
self.assertEqual(self.get()['headers']['Server-Port'], '7080',
'Server-Port header')
self.assertEqual(
self.get()['headers']['Server-Port'], '7080', 'Server-Port header'
)
def test_ruby_application_status_int(self):
self.load('status_int')
@@ -97,20 +116,29 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
def test_ruby_application_input_read_parts(self):
self.load('input_read_parts')
self.assertEqual(self.post(body='0123456789')['body'], '012345678',
'input read parts')
self.assertEqual(
self.post(body='0123456789')['body'],
'012345678',
'input read parts',
)
def test_ruby_application_input_read_buffer(self):
self.load('input_read_buffer')
self.assertEqual(self.post(body='0123456789')['body'], '0123456789',
'input read buffer')
self.assertEqual(
self.post(body='0123456789')['body'],
'0123456789',
'input read buffer',
)
def test_ruby_application_input_read_buffer_not_empty(self):
self.load('input_read_buffer_not_empty')
self.assertEqual(self.post(body='0123456789')['body'], '0123456789',
'input read buffer not empty')
self.assertEqual(
self.post(body='0123456789')['body'],
'0123456789',
'input read buffer not empty',
)
def test_ruby_application_input_gets(self):
self.load('input_gets')
@@ -122,8 +150,9 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
def test_ruby_application_input_gets_2(self):
self.load('input_gets')
self.assertEqual(self.post(body='01234\n56789\n')['body'], '01234\n',
'input gets 2')
self.assertEqual(
self.post(body='01234\n56789\n')['body'], '01234\n', 'input gets 2'
)
def test_ruby_application_input_gets_all(self):
self.load('input_gets_all')
@@ -149,12 +178,14 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
@unittest.expectedFailure
def test_ruby_application_syntax_error(self):
self.skip_alerts.extend([
self.skip_alerts.extend(
[
r'Failed to parse rack script',
r'syntax error',
r'new_from_string',
r'parse_file'
])
r'parse_file',
]
)
self.load('syntax_error')
self.assertEqual(self.get()['status'], 500, 'syntax error')
@@ -168,7 +199,8 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
self.assertIsNotNone(
self.search_in_log(r'\[error\].+Error in application'),
'errors puts')
'errors puts',
)
def test_ruby_application_errors_puts_int(self):
self.load('errors_puts_int')
@@ -178,8 +210,8 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
self.stop()
self.assertIsNotNone(
self.search_in_log(r'\[error\].+1234567890'),
'errors puts int')
self.search_in_log(r'\[error\].+1234567890'), 'errors puts int'
)
def test_ruby_application_errors_write(self):
self.load('errors_write')
@@ -190,13 +222,13 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
self.assertIsNotNone(
self.search_in_log(r'\[error\].+Error in application'),
'errors write')
'errors write',
)
def test_ruby_application_errors_write_to_s_custom(self):
self.load('errors_write_to_s_custom')
self.assertEqual(self.get()['status'], 200,
'errors write to_s custom')
self.assertEqual(self.get()['status'], 200, 'errors write to_s custom')
def test_ruby_application_errors_write_int(self):
self.load('errors_write_int')
@@ -206,38 +238,40 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
self.stop()
self.assertIsNotNone(
self.search_in_log(r'\[error\].+1234567890'),
'errors write int')
self.search_in_log(r'\[error\].+1234567890'), 'errors write int'
)
def test_ruby_application_at_exit(self):
self.load('at_exit')
self.get()
self.conf({
"listeners": {},
"applications": {}
})
self.conf({"listeners": {}, "applications": {}})
self.stop()
self.assertIsNotNone(
self.search_in_log(r'\[error\].+At exit called\.'), 'at exit')
self.search_in_log(r'\[error\].+At exit called\.'), 'at exit'
)
def test_ruby_application_header_custom(self):
self.load('header_custom')
resp = self.post(body="\ntc=one,two\ntc=three,four,\n\n")
self.assertEqual(resp['headers']['Custom-Header'],
['', 'tc=one,two', 'tc=three,four,', '', ''], 'header custom')
self.assertEqual(
resp['headers']['Custom-Header'],
['', 'tc=one,two', 'tc=three,four,', '', ''],
'header custom',
)
@unittest.expectedFailure
def test_ruby_application_header_custom_non_printable(self):
self.load('header_custom')
self.assertEqual(self.post(body='\b')['status'], 500,
'header custom non printable')
self.assertEqual(
self.post(body='\b')['status'], 500, 'header custom non printable'
)
def test_ruby_application_header_status(self):
self.load('header_status')
@@ -277,7 +311,8 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
self.assertIsNotNone(
self.search_in_log(r'\[error\].+Failed to run ruby script'),
'body each error')
'body each error',
)
def test_ruby_application_body_file(self):
self.load('body_file')
@@ -287,21 +322,30 @@ class TestUnitRubyApplication(unit.TestUnitApplicationRuby):
def test_ruby_keepalive_body(self):
self.load('mirror')
(resp, sock) = self.post(headers={
(resp, sock) = self.post(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='0123456789' * 500)
'Content-Type': 'text/html',
},
start=True,
body='0123456789' * 500,
)
self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1')
resp = self.post(headers={
resp = self.post(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=sock, body='0123456789')
'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
)
self.assertEqual(resp['body'], '0123456789', 'keep-alive 2')
if __name__ == '__main__':
TestUnitRubyApplication.main()

View File

@@ -3,8 +3,8 @@ import socket
import unittest
import unit
class TestUnitSettings(unit.TestUnitApplicationPython):
class TestUnitSettings(unit.TestUnitApplicationPython):
def setUpClass():
unit.TestUnit().check_modules('python')
@@ -13,15 +13,24 @@ class TestUnitSettings(unit.TestUnitApplicationPython):
self.conf({'http': {'header_read_timeout': 2}}, 'settings')
(resp, sock) = self.http(b"""GET / HTTP/1.1
""", start=True, read_timeout=1, raw=True)
(resp, sock) = self.http(
b"""GET / HTTP/1.1
""",
start=True,
read_timeout=1,
raw=True,
)
time.sleep(3)
resp = self.http(b"""Host: localhost
resp = self.http(
b"""Host: localhost
Connection: close
""", sock=sock, raw=True)
""",
sock=sock,
raw=True,
)
self.assertEqual(resp['status'], 408, 'status header read timeout')
@@ -30,18 +39,37 @@ Connection: close
self.conf({'http': {'header_read_timeout': 4}}, 'settings')
(resp, sock) = self.http(b"""GET / HTTP/1.1
""", start=True, read_timeout=1, raw=True, no_recv=True)
(resp, sock) = self.http(
b"""GET / HTTP/1.1
""",
start=True,
read_timeout=1,
raw=True,
no_recv=True,
)
time.sleep(2)
(resp, sock) = self.http(b"""Host: localhost
""", start=True, sock=sock, read_timeout=1, raw=True, no_recv=True)
(resp, sock) = self.http(
b"""Host: localhost
""",
start=True,
sock=sock,
read_timeout=1,
raw=True,
no_recv=True,
)
time.sleep(2)
(resp, sock) = self.http(b"""X-Blah: blah
""", start=True, sock=sock, read_timeout=1, raw=True)
(resp, sock) = self.http(
b"""X-Blah: blah
""",
start=True,
sock=sock,
read_timeout=1,
raw=True,
)
if len(resp) != 0:
sock.close()
@@ -49,24 +77,35 @@ Connection: close
else:
time.sleep(2)
resp = self.http(b"""Connection: close
resp = self.http(
b"""Connection: close
""", sock=sock, raw=True)
""",
sock=sock,
raw=True,
)
self.assertEqual(resp['status'], 408,
'status header read timeout update')
self.assertEqual(
resp['status'], 408, 'status header read timeout update'
)
def test_settings_body_read_timeout(self):
self.load('empty')
self.conf({'http': {'body_read_timeout': 2}}, 'settings')
(resp, sock) = self.http(b"""POST / HTTP/1.1
(resp, sock) = self.http(
b"""POST / HTTP/1.1
Host: localhost
Content-Length: 10
Connection: close
""", start=True, raw_resp=True, read_timeout=1, raw=True)
""",
start=True,
raw_resp=True,
read_timeout=1,
raw=True,
)
time.sleep(3)
@@ -79,28 +118,37 @@ Connection: close
self.conf({'http': {'body_read_timeout': 4}}, 'settings')
(resp, sock) = self.http(b"""POST / HTTP/1.1
(resp, sock) = self.http(
b"""POST / HTTP/1.1
Host: localhost
Content-Length: 10
Connection: close
""", start=True, read_timeout=1, raw=True)
""",
start=True,
read_timeout=1,
raw=True,
)
time.sleep(2)
(resp, sock) = self.http(b"""012""", start=True, sock=sock,
read_timeout=1, raw=True)
(resp, sock) = self.http(
b"""012""", start=True, sock=sock, read_timeout=1, raw=True
)
time.sleep(2)
(resp, sock) = self.http(b"""345""", start=True, sock=sock,
read_timeout=1, raw=True)
(resp, sock) = self.http(
b"""345""", start=True, sock=sock, read_timeout=1, raw=True
)
time.sleep(2)
resp = self.http(b"""6789""", sock=sock, raw=True)
self.assertEqual(resp['status'], 200, 'status body read timeout update')
self.assertEqual(
resp['status'], 200, 'status body read timeout update'
)
def test_settings_send_timeout(self):
self.load('mirror')
@@ -122,7 +170,9 @@ Content-Type: text/html
Content-Length: %d
Connection: close
""" % data_len + ('X' * data_len)
""" % data_len + (
'X' * data_len
)
sock.sendall(req.encode())
@@ -142,17 +192,17 @@ Connection: close
self.conf({'http': {'idle_timeout': 2}}, 'settings')
(resp, sock) = self.get(headers={
'Host': 'localhost',
'Connection': 'keep-alive'
}, start=True, read_timeout=1)
(resp, sock) = self.get(
headers={'Host': 'localhost', 'Connection': 'keep-alive'},
start=True,
read_timeout=1,
)
time.sleep(3)
resp = self.get(headers={
'Host': 'localhost',
'Connection': 'close'
}, sock=sock)
resp = self.get(
headers={'Host': 'localhost', 'Connection': 'close'}, sock=sock
)
self.assertEqual(resp['status'], 408, 'status idle timeout')
@@ -162,13 +212,18 @@ Connection: close
self.conf({'http': {'max_body_size': 5}}, 'settings')
self.assertEqual(self.post(body='01234')['status'], 200, 'status size')
self.assertEqual(self.post(body='012345')['status'], 413,
'status size max')
self.assertEqual(
self.post(body='012345')['status'], 413, 'status size max'
)
@unittest.expectedFailure
def test_settings_negative_value(self):
self.assertIn('error', self.conf({'http': { 'max_body_size': -1 }},
'settings'), 'settings negative value')
self.assertIn(
'error',
self.conf({'http': {'max_body_size': -1}}, 'settings'),
'settings negative value',
)
if __name__ == '__main__':
TestUnitSettings.main()

View File

@@ -5,8 +5,8 @@ import subprocess
import unittest
import unit
class TestUnitTLS(unit.TestUnitApplicationTLS):
class TestUnitTLS(unit.TestUnitApplicationTLS):
def setUpClass():
unit.TestUnit().check_modules('python', 'openssl')
@@ -26,17 +26,13 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
return self.date_to_sec_epoch(date, '%b %d %H:%M:%S %Y %Z')
def add_tls(self, application='empty', cert='default', port=7080):
self.conf({
"application": application,
"tls": {
"certificate": cert
}
}, 'listeners/*:' + str(port))
self.conf(
{"application": application, "tls": {"certificate": cert}},
'listeners/*:' + str(port),
)
def remove_tls(self, application='empty', port=7080):
self.conf({
"application": application
}, 'listeners/*:' + str(port))
self.conf({"application": application}, 'listeners/*:' + str(port))
def test_tls_listener_option_add(self):
self.load('empty')
@@ -65,8 +61,11 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
self.certificate()
self.assertIn('success', self.conf_delete('/certificates/default'),
'remove certificate')
self.assertIn(
'success',
self.conf_delete('/certificates/default'),
'remove certificate',
)
def test_tls_certificate_remove_used(self):
self.load('empty')
@@ -75,8 +74,11 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
self.add_tls()
self.assertIn('error', self.conf_delete('/certificates/default'),
'remove certificate')
self.assertIn(
'error',
self.conf_delete('/certificates/default'),
'remove certificate',
)
def test_tls_certificate_remove_nonexisting(self):
self.load('empty')
@@ -85,8 +87,11 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
self.add_tls()
self.assertIn('error', self.conf_delete('/certificates/blah'),
'remove nonexistings certificate')
self.assertIn(
'error',
self.conf_delete('/certificates/blah'),
'remove nonexistings certificate',
)
@unittest.expectedFailure
def test_tls_certificate_update(self):
@@ -100,8 +105,9 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
self.certificate()
self.assertNotEqual(cert_old, self.get_server_certificate(),
'update certificate')
self.assertNotEqual(
cert_old, self.get_server_certificate(), 'update certificate'
)
@unittest.expectedFailure
def test_tls_certificate_key_incorrect(self):
@@ -110,8 +116,9 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
self.certificate('first', False)
self.certificate('second', False)
self.assertIn('error', self.certificate_load('first', 'second'),
'key incorrect')
self.assertIn(
'error', self.certificate_load('first', 'second'), 'key incorrect'
)
def test_tls_certificate_change(self):
self.load('empty')
@@ -125,33 +132,53 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
self.add_tls(cert='new')
self.assertNotEqual(cert_old, self.get_server_certificate(),
'change certificate')
self.assertNotEqual(
cert_old, self.get_server_certificate(), 'change certificate'
)
def test_tls_certificate_key_rsa(self):
self.load('empty')
self.certificate()
self.assertEqual(self.conf_get('/certificates/default/key'),
'RSA (1024 bits)', 'certificate key rsa')
self.assertEqual(
self.conf_get('/certificates/default/key'),
'RSA (1024 bits)',
'certificate key rsa',
)
def test_tls_certificate_key_ec(self):
self.load('empty')
subprocess.call(['openssl', 'ecparam', '-noout', '-genkey',
subprocess.call(
[
'openssl',
'ecparam',
'-noout',
'-genkey',
'-out', self.testdir + '/ec.key',
'-name', 'prime256v1'])
'-name', 'prime256v1',
]
)
subprocess.call(['openssl', 'req', '-x509', '-new',
subprocess.call(
[
'openssl',
'req',
'-x509',
'-new',
'-subj', '/CN=ec/',
'-config', self.testdir + '/openssl.conf',
'-key', self.testdir + '/ec.key', '-subj', '/CN=ec/',
'-out', self.testdir + '/ec.crt'])
'-key', self.testdir + '/ec.key',
'-out', self.testdir + '/ec.crt',
]
)
self.certificate_load('ec')
self.assertEqual(self.conf_get('/certificates/ec/key'), 'ECDH',
'certificate key ec')
self.assertEqual(
self.conf_get('/certificates/ec/key'), 'ECDH', 'certificate key ec'
)
def test_tls_certificate_chain_options(self):
self.load('empty')
@@ -164,36 +191,64 @@ class TestUnitTLS(unit.TestUnitApplicationTLS):
cert = chain[0]
self.assertEqual(cert['subject']['common_name'], 'default',
'certificate subject common name')
self.assertEqual(cert['issuer']['common_name'], 'default',
'certificate issuer common name')
self.assertLess(abs(self.sec_epoch() -
self.openssl_date_to_sec_epoch(cert['validity']['since'])), 5,
'certificate validity since')
self.assertEqual(
self.openssl_date_to_sec_epoch(cert['validity']['until']) -
self.openssl_date_to_sec_epoch(cert['validity']['since']), 2592000,
'certificate validity until')
cert['subject']['common_name'],
'default',
'certificate subject common name',
)
self.assertEqual(
cert['issuer']['common_name'],
'default',
'certificate issuer common name',
)
self.assertLess(
abs(
self.sec_epoch()
- self.openssl_date_to_sec_epoch(cert['validity']['since'])
),
5,
'certificate validity since',
)
self.assertEqual(
self.openssl_date_to_sec_epoch(cert['validity']['until'])
- self.openssl_date_to_sec_epoch(cert['validity']['since']),
2592000,
'certificate validity until',
)
def test_tls_certificate_chain(self):
self.load('empty')
self.certificate('root', False)
subprocess.call(['openssl', 'req', '-new', '-config',
self.testdir + '/openssl.conf', '-subj', '/CN=int/',
subprocess.call(
[
'openssl',
'req',
'-new',
'-subj', '/CN=int/',
'-config', self.testdir + '/openssl.conf',
'-out', self.testdir + '/int.csr',
'-keyout', self.testdir + '/int.key'])
'-keyout', self.testdir + '/int.key',
]
)
subprocess.call(['openssl', 'req', '-new', '-config',
self.testdir + '/openssl.conf', '-subj', '/CN=end/',
subprocess.call(
[
'openssl',
'req',
'-new',
'-subj', '/CN=end/',
'-config', self.testdir + '/openssl.conf',
'-out', self.testdir + '/end.csr',
'-keyout', self.testdir + '/end.key'])
'-keyout', self.testdir + '/end.key',
]
)
with open(self.testdir + '/ca.conf', 'w') as f:
f.write("""[ ca ]
f.write(
"""[ ca ]
default_ca = myca
[ myca ]
@@ -209,11 +264,13 @@ x509_extensions = myca_extensions
commonName = supplied
[ myca_extensions ]
basicConstraints = critical,CA:TRUE""" % {
basicConstraints = critical,CA:TRUE"""
% {
'dir': self.testdir,
'database': self.testdir + '/certindex',
'certserial': self.testdir + '/certserial'
})
'certserial': self.testdir + '/certserial',
}
)
with open(self.testdir + '/certserial', 'w') as f:
f.write('1000')
@@ -221,25 +278,41 @@ basicConstraints = critical,CA:TRUE""" % {
with open(self.testdir + '/certindex', 'w') as f:
f.write('')
subprocess.call(['openssl', 'ca', '-batch',
subprocess.call(
[
'openssl',
'ca',
'-batch',
'-subj', '/CN=int/',
'-config', self.testdir + '/ca.conf',
'-keyfile', self.testdir + '/root.key',
'-cert', self.testdir + '/root.crt',
'-subj', '/CN=int/',
'-in', self.testdir + '/int.csr',
'-out', self.testdir + '/int.crt'])
'-out', self.testdir + '/int.crt',
]
)
subprocess.call(['openssl', 'ca', '-batch',
subprocess.call(
[
'openssl',
'ca',
'-batch',
'-subj', '/CN=end/',
'-config', self.testdir + '/ca.conf',
'-keyfile', self.testdir + '/int.key',
'-cert', self.testdir + '/int.crt',
'-subj', '/CN=end/',
'-in', self.testdir + '/end.csr',
'-out', self.testdir + '/end.crt'])
'-out', self.testdir + '/end.crt',
]
)
with open(self.testdir + '/end-int.crt', 'wb') as crt, \
open(self.testdir + '/end.crt', 'rb') as end, \
open(self.testdir + '/int.crt', 'rb') as int:
crt_path = self.testdir + '/end-int.crt'
end_path = self.testdir + '/end.crt'
int_path = self.testdir + '/int.crt'
with open(crt_path, 'wb') as crt, \
open(end_path, 'rb') as end, \
open(int_path, 'rb') as int:
crt.write(end.read() + int.read())
self.context = ssl.create_default_context()
@@ -249,15 +322,24 @@ basicConstraints = critical,CA:TRUE""" % {
# incomplete chain
self.assertIn('success', self.certificate_load('end', 'end'),
'certificate chain end upload')
self.assertIn(
'success',
self.certificate_load('end', 'end'),
'certificate chain end upload',
)
chain = self.conf_get('/certificates/end/chain')
self.assertEqual(len(chain), 1, 'certificate chain end length')
self.assertEqual(chain[0]['subject']['common_name'], 'end',
'certificate chain end subject common name')
self.assertEqual(chain[0]['issuer']['common_name'], 'int',
'certificate chain end issuer common name')
self.assertEqual(
chain[0]['subject']['common_name'],
'end',
'certificate chain end subject common name',
)
self.assertEqual(
chain[0]['issuer']['common_name'],
'int',
'certificate chain end issuer common name',
)
self.add_tls(cert='end')
@@ -270,41 +352,69 @@ basicConstraints = critical,CA:TRUE""" % {
# intermediate
self.assertIn('success', self.certificate_load('int', 'int'),
'certificate chain int upload')
self.assertIn(
'success',
self.certificate_load('int', 'int'),
'certificate chain int upload',
)
chain = self.conf_get('/certificates/int/chain')
self.assertEqual(len(chain), 1, 'certificate chain int length')
self.assertEqual(chain[0]['subject']['common_name'], 'int',
'certificate chain int subject common name')
self.assertEqual(chain[0]['issuer']['common_name'], 'root',
'certificate chain int issuer common name')
self.assertEqual(
chain[0]['subject']['common_name'],
'int',
'certificate chain int subject common name',
)
self.assertEqual(
chain[0]['issuer']['common_name'],
'root',
'certificate chain int issuer common name',
)
self.add_tls(cert='int')
self.assertEqual(self.get_ssl()['status'], 200,
'certificate chain intermediate')
self.assertEqual(
self.get_ssl()['status'], 200, 'certificate chain intermediate'
)
# intermediate server
self.assertIn('success', self.certificate_load('end-int', 'end'),
'certificate chain end-int upload')
self.assertIn(
'success',
self.certificate_load('end-int', 'end'),
'certificate chain end-int upload',
)
chain = self.conf_get('/certificates/end-int/chain')
self.assertEqual(len(chain), 2, 'certificate chain end-int length')
self.assertEqual(chain[0]['subject']['common_name'], 'end',
'certificate chain end-int int subject common name')
self.assertEqual(chain[0]['issuer']['common_name'], 'int',
'certificate chain end-int int issuer common name')
self.assertEqual(chain[1]['subject']['common_name'], 'int',
'certificate chain end-int end subject common name')
self.assertEqual(chain[1]['issuer']['common_name'], 'root',
'certificate chain end-int end issuer common name')
self.assertEqual(
chain[0]['subject']['common_name'],
'end',
'certificate chain end-int int subject common name',
)
self.assertEqual(
chain[0]['issuer']['common_name'],
'int',
'certificate chain end-int int issuer common name',
)
self.assertEqual(
chain[1]['subject']['common_name'],
'int',
'certificate chain end-int end subject common name',
)
self.assertEqual(
chain[1]['issuer']['common_name'],
'root',
'certificate chain end-int end issuer common name',
)
self.add_tls(cert='end-int')
self.assertEqual(self.get_ssl()['status'], 200,
'certificate chain intermediate server')
self.assertEqual(
self.get_ssl()['status'],
200,
'certificate chain intermediate server',
)
@unittest.expectedFailure
def test_tls_reconfigure(self):
@@ -312,19 +422,21 @@ basicConstraints = critical,CA:TRUE""" % {
self.certificate()
(resp, sock) = self.get(headers={
'Host': 'localhost',
'Connection': 'keep-alive'
}, start=True)
(resp, sock) = self.get(
headers={'Host': 'localhost', 'Connection': 'keep-alive'},
start=True,
)
self.assertEqual(resp['status'], 200, 'initial status')
self.add_tls()
self.assertEqual(self.get(sock=sock)['status'], 200,
'reconfigure status')
self.assertEqual(self.get_ssl()['status'], 200,
'reconfigure tls status')
self.assertEqual(
self.get(sock=sock)['status'], 200, 'reconfigure status'
)
self.assertEqual(
self.get_ssl()['status'], 200, 'reconfigure tls status'
)
def test_tls_keepalive(self):
self.load('mirror')
@@ -333,19 +445,27 @@ basicConstraints = critical,CA:TRUE""" % {
self.add_tls(application='mirror')
(resp, sock) = self.post_ssl(headers={
(resp, sock) = self.post_ssl(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='0123456789')
'Content-Type': 'text/html',
},
start=True,
body='0123456789',
)
self.assertEqual(resp['body'], '0123456789', 'keepalive 1')
resp = self.post_ssl(headers={
resp = self.post_ssl(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=sock, body='0123456789')
'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
)
self.assertEqual(resp['body'], '0123456789', 'keepalive 2')
@@ -357,21 +477,18 @@ basicConstraints = critical,CA:TRUE""" % {
self.add_tls()
(resp, sock) = self.get_ssl(headers={
'Host': 'localhost',
'Connection': 'keep-alive'
}, start=True)
(resp, sock) = self.get_ssl(
headers={'Host': 'localhost', 'Connection': 'keep-alive'},
start=True,
)
self.conf({
"application": "empty"
}, 'listeners/*:7080')
self.conf({"application": "empty"}, 'listeners/*:7080')
self.conf_delete('/certificates/default')
try:
resp = self.get_ssl(headers={
'Host': 'localhost',
'Connection': 'close'
}, sock=sock)
resp = self.get_ssl(
headers={'Host': 'localhost', 'Connection': 'close'}, sock=sock
)
except:
resp = None
@@ -383,8 +500,11 @@ basicConstraints = critical,CA:TRUE""" % {
self.certificate()
self.assertIn('success', self.conf_delete('/certificates'),
'remove all certificates')
self.assertIn(
'success',
self.conf_delete('/certificates'),
'remove all certificates',
)
def test_tls_application_respawn(self):
self.skip_alerts.append(r'process \d+ exited on signal 9')
@@ -396,48 +516,73 @@ basicConstraints = critical,CA:TRUE""" % {
self.add_tls(application='mirror')
(resp, sock) = self.post_ssl(headers={
(resp, sock) = self.post_ssl(
headers={
'Host': 'localhost',
'Connection': 'keep-alive',
'Content-Type': 'text/html'
}, start=True, body='0123456789')
'Content-Type': 'text/html',
},
start=True,
body='0123456789',
)
app_id = self.findall(r'(\d+)#\d+ "mirror" application started')[0]
subprocess.call(['kill', '-9', app_id])
self.wait_for_record(re.compile(' (?!' + app_id +
'#)(\d+)#\d+ "mirror" application started'))
self.wait_for_record(
re.compile(
' (?!' + app_id + '#)(\d+)#\d+ "mirror" application started'
)
)
resp = self.post_ssl(headers={
resp = self.post_ssl(
headers={
'Host': 'localhost',
'Connection': 'close',
'Content-Type': 'text/html'
}, sock=sock, body='0123456789')
'Content-Type': 'text/html',
},
sock=sock,
body='0123456789',
)
self.assertEqual(resp['status'], 200, 'application respawn status')
self.assertEqual(resp['body'], '0123456789', 'application respawn body')
self.assertEqual(
resp['body'], '0123456789', 'application respawn body'
)
def test_tls_url_scheme(self):
self.load('variables')
self.assertEqual(self.post(headers={
self.assertEqual(
self.post(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Custom-Header': '',
'Connection': 'close'
})['headers']['Wsgi-Url-Scheme'], 'http', 'url scheme http')
'Connection': 'close',
}
)['headers']['Wsgi-Url-Scheme'],
'http',
'url scheme http',
)
self.certificate()
self.add_tls(application='variables')
self.assertEqual(self.post_ssl(headers={
self.assertEqual(
self.post_ssl(
headers={
'Host': 'localhost',
'Content-Type': 'text/html',
'Custom-Header': '',
'Connection': 'close'
})['headers']['Wsgi-Url-Scheme'], 'https', 'url scheme https')
'Connection': 'close',
}
)['headers']['Wsgi-Url-Scheme'],
'https',
'url scheme https',
)
if __name__ == '__main__':
TestUnitTLS.main()

View File

@@ -14,9 +14,12 @@ import unittest
import subprocess
from multiprocessing import Process
class TestUnit(unittest.TestCase):
pardir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
pardir = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir)
)
architecture = platform.architecture()[0]
maxDiff = None
@@ -61,16 +64,19 @@ class TestUnit(unittest.TestCase):
result = self.defaultTestResult()
self._feedErrorsToResult(result, self._outcome.errors)
else:
result = getattr(self, '_outcomeForDoCleanups',
self._resultForDoCleanups)
result = getattr(
self, '_outcomeForDoCleanups', self._resultForDoCleanups
)
success = not list2reason(result.errors) \
and not list2reason(result.failures)
success = not list2reason(result.errors) and not list2reason(
result.failures
)
# check unit.log for alerts
with open(self.testdir + '/unit.log', 'r', encoding='utf-8',
errors='ignore') as f:
unit_log = self.testdir + '/unit.log'
with open(unit_log, 'r', encoding='utf-8', errors='ignore') as f:
self._check_alerts(f.read())
# remove unit.log
@@ -107,9 +113,16 @@ class TestUnit(unittest.TestCase):
env['GOPATH'] = self.pardir + '/go'
try:
process = subprocess.Popen(['go', 'build', '-o',
process = subprocess.Popen(
[
'go',
'build',
'-o',
self.testdir + '/go/check_module',
current_dir + '/go/empty/app.go'], env=env)
current_dir + '/go/empty/app.go',
],
env=env,
)
process.communicate()
m = module if process.returncode == 0 else None
@@ -127,9 +140,10 @@ class TestUnit(unittest.TestCase):
try:
subprocess.check_output(['which', 'openssl'])
output = subprocess.check_output([
self.pardir + '/build/unitd', '--version'],
stderr=subprocess.STDOUT)
output = subprocess.check_output(
[self.pardir + '/build/unitd', '--version'],
stderr=subprocess.STDOUT,
)
m = re.search('--openssl', output.decode())
@@ -162,25 +176,35 @@ class TestUnit(unittest.TestCase):
print()
def _run_unit():
subprocess.call([self.pardir + '/build/unitd',
subprocess.call(
[
self.pardir + '/build/unitd',
'--no-daemon',
'--modules', self.pardir + '/build',
'--state', self.testdir + '/state',
'--pid', self.testdir + '/unit.pid',
'--log', self.testdir + '/unit.log',
'--control', 'unix:' + self.testdir + '/control.unit.sock'])
'--control', 'unix:' + self.testdir + '/control.unit.sock',
]
)
self._p = Process(target=_run_unit)
self._p.start()
if not self.waitforfiles(self.testdir + '/unit.pid',
self.testdir + '/unit.log', self.testdir + '/control.unit.sock'):
if not self.waitforfiles(
self.testdir + '/unit.pid',
self.testdir + '/unit.log',
self.testdir + '/control.unit.sock',
):
exit("Could not start unit")
self._started = True
self.skip_alerts = [r'read signalfd\(4\) failed', r'sendmsg.+failed',
r'recvmsg.+failed']
self.skip_alerts = [
r'read signalfd\(4\) failed',
r'sendmsg.+failed',
r'recvmsg.+failed',
]
self.skip_sanitizer = False
def _stop(self):
@@ -264,10 +288,20 @@ class TestUnit(unittest.TestCase):
def _parse_args():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-d', '--detailed', dest='detailed',
action='store_true', help='Detailed output for tests')
parser.add_argument('-l', '--log', dest='save_log',
action='store_true', help='Save unit.log after the test execution')
parser.add_argument(
'-d',
'--detailed',
dest='detailed',
action='store_true',
help='Detailed output for tests',
)
parser.add_argument(
'-l',
'--log',
dest='save_log',
action='store_true',
help='Save unit.log after the test execution',
)
return parser.parse_known_args()
@@ -279,18 +313,21 @@ class TestUnit(unittest.TestCase):
def _print_path_to_log(self):
print('Path to unit.log:\n' + self.testdir + '/unit.log')
class TestUnitHTTP(TestUnit):
class TestUnitHTTP(TestUnit):
def http(self, start_str, **kwargs):
sock_type = 'ipv4' if 'sock_type' not in kwargs else kwargs['sock_type']
sock_type = (
'ipv4' if 'sock_type' not in kwargs else kwargs['sock_type']
)
port = 7080 if 'port' not in kwargs else kwargs['port']
url = '/' if 'url' not in kwargs else kwargs['url']
http = 'HTTP/1.0' if 'http_10' in kwargs else 'HTTP/1.1'
headers = ({
'Host': 'localhost',
'Connection': 'close'
} if 'headers' not in kwargs else kwargs['headers'])
headers = (
{'Host': 'localhost', 'Connection': 'close'}
if 'headers' not in kwargs
else kwargs['headers']
)
body = b'' if 'body' not in kwargs else kwargs['body']
crlf = '\r\n'
@@ -303,13 +340,16 @@ class TestUnitHTTP(TestUnit):
sock_types = {
'ipv4': socket.AF_INET,
'ipv6': socket.AF_INET6,
'unix': socket.AF_UNIX
'unix': socket.AF_UNIX,
}
if 'sock' not in kwargs:
sock = socket.socket(sock_types[sock_type], socket.SOCK_STREAM)
if sock_type == sock_types['ipv4'] or sock_type == sock_types['ipv6']:
if (
sock_type == sock_types['ipv4']
or sock_type == sock_types['ipv6']
):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
if 'wrapper' in kwargs:
@@ -357,7 +397,9 @@ class TestUnitHTTP(TestUnit):
if 'no_recv' not in kwargs:
enc = 'utf-8' if 'encoding' not in kwargs else kwargs['encoding']
read_timeout = 5 if 'read_timeout' not in kwargs else kwargs['read_timeout']
read_timeout = (
5 if 'read_timeout' not in kwargs else kwargs['read_timeout']
)
resp = self.recvall(sock, read_timeout=read_timeout).decode(enc)
if TestUnit.detailed:
@@ -410,7 +452,9 @@ class TestUnitHTTP(TestUnit):
p = re.compile('(.*?)\x0d\x0a?', re.M | re.S)
headers_lines = p.findall(headers_text)
status = re.search('^HTTP\/\d\.\d\s(\d+)|$', headers_lines.pop(0)).group(1)
status = re.search(
'^HTTP\/\d\.\d\s(\d+)|$', headers_lines.pop(0)
).group(1)
headers = {}
for line in headers_lines:
@@ -418,16 +462,15 @@ class TestUnitHTTP(TestUnit):
if m.group(1) not in headers:
headers[m.group(1)] = m.group(2)
elif isinstance(headers[m.group(1)], list):
headers[m.group(1)].append(m.group(2))
else:
headers[m.group(1)] = [headers[m.group(1)], m.group(2)]
return {
'status': int(status),
'headers': headers,
'body': body
}
return {'status': int(status), 'headers': headers, 'body': body}
class TestUnitControl(TestUnitHTTP):
@@ -441,32 +484,39 @@ class TestUnitControl(TestUnitHTTP):
if path[:1] != '/':
path = '/config/' + path
return json.loads(self.put(
return json.loads(
self.put(
url=path,
body=conf,
sock_type='unix',
addr=self.testdir + '/control.unit.sock'
)['body'])
addr=self.testdir + '/control.unit.sock',
)['body']
)
def conf_get(self, path='/config'):
if path[:1] != '/':
path = '/config/' + path
return json.loads(self.get(
return json.loads(
self.get(
url=path,
sock_type='unix',
addr=self.testdir + '/control.unit.sock'
)['body'])
addr=self.testdir + '/control.unit.sock',
)['body']
)
def conf_delete(self, path='/config'):
if path[:1] != '/':
path = '/config/' + path
return json.loads(self.delete(
return json.loads(
self.delete(
url=path,
sock_type='unix',
addr=self.testdir + '/control.unit.sock'
)['body'])
addr=self.testdir + '/control.unit.sock',
)['body']
)
class TestUnitApplicationProto(TestUnitControl):
@@ -482,64 +532,68 @@ class TestUnitApplicationProto(TestUnitControl):
with open(self.testdir + '/unit.log', 'r', errors='ignore') as f:
return re.search(pattern, f.read())
class TestUnitApplicationPython(TestUnitApplicationProto):
def load(self, script, name=None):
if name is None:
name = script
self.conf({
"listeners": {
"*:7080": {
"application": name
}
},
script_path = self.current_dir + '/python/' + script
self.conf(
{
"listeners": {"*:7080": {"application": name}},
"applications": {
name: {
"type": "python",
"processes": {"spare": 0},
"path": self.current_dir + '/python/' + script,
"working_directory": self.current_dir + '/python/' + script,
"module": "wsgi"
"path": script_path,
"working_directory": script_path,
"module": "wsgi",
}
},
}
})
)
class TestUnitApplicationRuby(TestUnitApplicationProto):
def load(self, script, name='config.ru'):
self.conf({
"listeners": {
"*:7080": {
"application": script
}
},
script_path = self.current_dir + '/ruby/' + script
self.conf(
{
"listeners": {"*:7080": {"application": script}},
"applications": {
script: {
"type": "ruby",
"processes": {"spare": 0},
"working_directory": self.current_dir + '/ruby/' + script,
"script": self.current_dir + '/ruby/' + script + '/' + name
"working_directory": script_path,
"script": script_path + '/' + name,
}
},
}
})
)
class TestUnitApplicationPHP(TestUnitApplicationProto):
def load(self, script, name='index.php'):
self.conf({
"listeners": {
"*:7080": {
"application": script
}
},
script_path = self.current_dir + '/php/' + script
self.conf(
{
"listeners": {"*:7080": {"application": script}},
"applications": {
script: {
"type": "php",
"processes": {"spare": 0},
"root": self.current_dir + '/php/' + script,
"working_directory": self.current_dir + '/php/' + script,
"index": name
"root": script_path,
"working_directory": script_path,
"index": name,
}
},
}
})
)
class TestUnitApplicationGo(TestUnitApplicationProto):
def load(self, script, name='app'):
@@ -547,58 +601,67 @@ class TestUnitApplicationGo(TestUnitApplicationProto):
if not os.path.isdir(self.testdir + '/go'):
os.mkdir(self.testdir + '/go')
go_app_path = self.current_dir + '/go/'
env = os.environ.copy()
env['GOPATH'] = self.pardir + '/go'
process = subprocess.Popen(['go', 'build', '-o',
process = subprocess.Popen(
[
'go',
'build',
'-o',
self.testdir + '/go/' + name,
self.current_dir + '/go/' + script + '/' + name + '.go'],
env=env)
go_app_path + script + '/' + name + '.go',
],
env=env,
)
process.communicate()
self.conf({
"listeners": {
"*:7080": {
"application": script
}
},
self.conf(
{
"listeners": {"*:7080": {"application": script}},
"applications": {
script: {
"type": "external",
"processes": {"spare": 0},
"working_directory": self.current_dir + '/go/' + script,
"executable": self.testdir + '/go/' + name
"working_directory": go_app_path + script,
"executable": self.testdir + '/go/' + name,
}
},
}
})
)
class TestUnitApplicationNode(TestUnitApplicationProto):
def load(self, script, name='app.js'):
# copy application
shutil.copytree(self.current_dir + '/node/' + script,
self.testdir + '/node')
shutil.copytree(
self.current_dir + '/node/' + script, self.testdir + '/node'
)
# link modules
os.symlink(self.pardir + '/node/node_modules',
self.testdir + '/node/node_modules')
os.symlink(
self.pardir + '/node/node_modules',
self.testdir + '/node/node_modules',
)
self.conf({
"listeners": {
"*:7080": {
"application": script
}
},
self.conf(
{
"listeners": {"*:7080": {"application": script}},
"applications": {
script: {
"type": "external",
"processes": {"spare": 0},
"working_directory": self.testdir + '/node',
"executable": name
"executable": name,
}
},
}
})
)
class TestUnitApplicationJava(TestUnitApplicationProto):
def load(self, script, name='app'):
@@ -641,48 +704,53 @@ class TestUnitApplicationJava(TestUnitApplicationProto):
if not os.path.isdir(classes_path):
os.makedirs(classes_path)
javac = ['javac', '-encoding', 'utf-8', '-d', classes_path,
'-classpath',
self.pardir + '/build/tomcat-servlet-api-9.0.13.jar']
tomcat_jar = self.pardir + '/build/tomcat-servlet-api-9.0.13.jar'
javac = [
'javac',
'-encoding', 'utf-8',
'-d', classes_path,
'-classpath', tomcat_jar,
]
javac.extend(src)
process = subprocess.Popen(javac)
process.communicate()
self.conf({
"listeners": {
"*:7080": {
"application": script
}
},
self.conf(
{
"listeners": {"*:7080": {"application": script}},
"applications": {
script: {
"unit_jars": self.pardir + '/build',
"type": "java",
"processes": {"spare": 0},
"working_directory": script_path,
"webapp": app_path
"webapp": app_path,
}
},
}
})
)
class TestUnitApplicationPerl(TestUnitApplicationProto):
def load(self, script, name='psgi.pl'):
self.conf({
"listeners": {
"*:7080": {
"application": script
}
},
script_path = self.current_dir + '/perl/' + script
self.conf(
{
"listeners": {"*:7080": {"application": script}},
"applications": {
script: {
"type": "perl",
"processes": {"spare": 0},
"working_directory": self.current_dir + '/perl/' + script,
"script": self.current_dir + '/perl/' + script + '/' + name
"working_directory": script_path,
"script": script_path + '/' + name,
}
},
}
})
)
class TestUnitApplicationTLS(TestUnitApplicationProto):
def __init__(self, test):
@@ -693,10 +761,18 @@ class TestUnitApplicationTLS(TestUnitApplicationProto):
self.context.verify_mode = ssl.CERT_NONE
def certificate(self, name='default', load=True):
subprocess.call(['openssl', 'req', '-x509', '-new', '-config',
self.testdir + '/openssl.conf', '-subj', '/CN=' + name + '/',
subprocess.call(
[
'openssl',
'req',
'-x509',
'-new',
'-subj', '/CN=' + name + '/',
'-config', self.testdir + '/openssl.conf',
'-out', self.testdir + '/' + name + '.crt',
'-keyout', self.testdir + '/' + name + '.key'])
'-keyout', self.testdir + '/' + name + '.key',
]
)
if load:
self.certificate_load(name)
@@ -705,17 +781,17 @@ class TestUnitApplicationTLS(TestUnitApplicationProto):
if key is None:
key = crt
with open(self.testdir + '/' + key + '.key', 'rb') as k, \
open(self.testdir + '/' + crt + '.crt', 'rb') as c:
key_path = self.testdir + '/' + key + '.key'
crt_path = self.testdir + '/' + crt + '.crt'
with open(key_path, 'rb') as k, open(crt_path, 'rb') as c:
return self.conf(k.read() + c.read(), '/certificates/' + crt)
def get_ssl(self, **kwargs):
return self.get(wrapper=self.context.wrap_socket,
**kwargs)
return self.get(wrapper=self.context.wrap_socket, **kwargs)
def post_ssl(self, **kwargs):
return self.post(wrapper=self.context.wrap_socket,
**kwargs)
return self.post(wrapper=self.context.wrap_socket, **kwargs)
def get_server_certificate(self, addr=('127.0.0.1', 7080)):
@@ -739,25 +815,27 @@ class TestUnitApplicationTLS(TestUnitApplicationProto):
# create default openssl configuration
with open(self.testdir + '/openssl.conf', 'w') as f:
f.write("""[ req ]
f.write(
"""[ req ]
default_bits = 1024
encrypt_key = no
distinguished_name = req_distinguished_name
[ req_distinguished_name ]""")
[ req_distinguished_name ]"""
)
self.conf({
"listeners": {
"*:7080": {
"application": name
}
},
script_path = self.current_dir + '/python/' + script
self.conf(
{
"listeners": {"*:7080": {"application": name}},
"applications": {
name: {
"type": "python",
"processes": {"spare": 0},
"path": self.current_dir + '/python/' + script,
"working_directory": self.current_dir + '/python/' + script,
"module": "wsgi"
"path": script_path,
"working_directory": script_path,
"module": "wsgi",
}
},
}
})
)