diff options
Diffstat (limited to 'test/unit')
-rw-r--r-- | test/unit/applications/lang/go.py | 7 | ||||
-rw-r--r-- | test/unit/applications/lang/java.py | 5 | ||||
-rw-r--r-- | test/unit/applications/lang/node.py | 11 | ||||
-rw-r--r-- | test/unit/applications/lang/perl.py | 5 | ||||
-rw-r--r-- | test/unit/applications/lang/php.py | 5 | ||||
-rw-r--r-- | test/unit/applications/lang/python.py | 5 | ||||
-rw-r--r-- | test/unit/applications/lang/ruby.py | 5 | ||||
-rw-r--r-- | test/unit/applications/proto.py | 14 | ||||
-rw-r--r-- | test/unit/feature/isolation.py | 3 | ||||
-rw-r--r-- | test/unit/http.py | 82 | ||||
-rw-r--r-- | test/unit/main.py | 21 |
11 files changed, 135 insertions, 28 deletions
diff --git a/test/unit/applications/lang/go.py b/test/unit/applications/lang/go.py index 18345828..7212a95c 100644 --- a/test/unit/applications/lang/go.py +++ b/test/unit/applications/lang/go.py @@ -23,7 +23,7 @@ class TestApplicationGo(TestApplicationProto): os.mkdir(self.testdir + '/go') env = os.environ.copy() - env['GOPATH'] = self.pardir + '/go' + env['GOPATH'] = self.pardir + '/build/go' try: process = Popen( @@ -44,7 +44,7 @@ class TestApplicationGo(TestApplicationProto): return process - def load(self, script, name='app'): + def load(self, script, name='app', **kwargs): self.prepare_env(script, name) self._load_conf( @@ -60,5 +60,6 @@ class TestApplicationGo(TestApplicationProto): "executable": self.testdir + "/go/" + name, } }, - } + }, + **kwargs ) diff --git a/test/unit/applications/lang/java.py b/test/unit/applications/lang/java.py index bcf87f59..a370d96b 100644 --- a/test/unit/applications/lang/java.py +++ b/test/unit/applications/lang/java.py @@ -6,7 +6,7 @@ from unit.applications.proto import TestApplicationProto class TestApplicationJava(TestApplicationProto): - def load(self, script, name='app'): + def load(self, script, name='app', **kwargs): app_path = self.testdir + '/java' web_inf_path = app_path + '/WEB-INF/' classes_path = web_inf_path + 'classes/' @@ -82,5 +82,6 @@ class TestApplicationJava(TestApplicationProto): "webapp": app_path, } }, - } + }, + **kwargs ) diff --git a/test/unit/applications/lang/node.py b/test/unit/applications/lang/node.py index 3cc72669..d818298f 100644 --- a/test/unit/applications/lang/node.py +++ b/test/unit/applications/lang/node.py @@ -15,20 +15,22 @@ class TestApplicationNode(TestApplicationProto): return unit if not complete_check else unit.complete() - def load(self, script, name='app.js'): + def load(self, script, name='app.js', **kwargs): # copy application shutil.copytree( self.current_dir + '/node/' + script, self.testdir + '/node' ) - # link modules + # copy modules - os.symlink( + shutil.copytree( self.pardir + '/node/node_modules', self.testdir + '/node/node_modules', ) + self.public_dir(self.testdir + '/node') + self._load_conf( { "listeners": {"*:7080": {"pass": "applications/" + script}}, @@ -40,5 +42,6 @@ class TestApplicationNode(TestApplicationProto): "executable": name, } }, - } + }, + **kwargs ) diff --git a/test/unit/applications/lang/perl.py b/test/unit/applications/lang/perl.py index 79df2cfa..d32aca33 100644 --- a/test/unit/applications/lang/perl.py +++ b/test/unit/applications/lang/perl.py @@ -4,7 +4,7 @@ from unit.applications.proto import TestApplicationProto class TestApplicationPerl(TestApplicationProto): application_type = "perl" - def load(self, script, name='psgi.pl'): + def load(self, script, name='psgi.pl', **kwargs): script_path = self.current_dir + '/perl/' + script self._load_conf( @@ -18,5 +18,6 @@ class TestApplicationPerl(TestApplicationProto): "script": script_path + '/' + name, } }, - } + }, + **kwargs ) diff --git a/test/unit/applications/lang/php.py b/test/unit/applications/lang/php.py index 9c54368d..6b1677e6 100644 --- a/test/unit/applications/lang/php.py +++ b/test/unit/applications/lang/php.py @@ -4,7 +4,7 @@ from unit.applications.proto import TestApplicationProto class TestApplicationPHP(TestApplicationProto): application_type = "php" - def load(self, script, name='index.php'): + def load(self, script, name='index.php', **kwargs): script_path = self.current_dir + '/php/' + script self._load_conf( @@ -19,5 +19,6 @@ class TestApplicationPHP(TestApplicationProto): "index": name, } }, - } + }, + **kwargs ) diff --git a/test/unit/applications/lang/python.py b/test/unit/applications/lang/python.py index ded76cb6..fdda024a 100644 --- a/test/unit/applications/lang/python.py +++ b/test/unit/applications/lang/python.py @@ -4,7 +4,7 @@ from unit.applications.proto import TestApplicationProto class TestApplicationPython(TestApplicationProto): application_type = "python" - def load(self, script, name=None): + def load(self, script, name=None, **kwargs): if name is None: name = script @@ -22,5 +22,6 @@ class TestApplicationPython(TestApplicationProto): "module": "wsgi", } }, - } + }, + **kwargs ) diff --git a/test/unit/applications/lang/ruby.py b/test/unit/applications/lang/ruby.py index d30735ad..8c8acecc 100644 --- a/test/unit/applications/lang/ruby.py +++ b/test/unit/applications/lang/ruby.py @@ -4,7 +4,7 @@ from unit.applications.proto import TestApplicationProto class TestApplicationRuby(TestApplicationProto): application_type = "ruby" - def load(self, script, name='config.ru'): + def load(self, script, name='config.ru', **kwargs): script_path = self.current_dir + '/ruby/' + script self._load_conf( @@ -18,5 +18,6 @@ class TestApplicationRuby(TestApplicationProto): "script": script_path + '/' + name, } }, - } + }, + **kwargs ) diff --git a/test/unit/applications/proto.py b/test/unit/applications/proto.py index 4105473f..ae1af354 100644 --- a/test/unit/applications/proto.py +++ b/test/unit/applications/proto.py @@ -25,7 +25,19 @@ class TestApplicationProto(TestControl): return found - def _load_conf(self, conf): + def _load_conf(self, conf, **kwargs): + if 'applications' in conf: + for app in conf['applications'].keys(): + app_conf = conf['applications'][app] + if 'user' in kwargs: + app_conf['user'] = kwargs['user'] + + if 'group' in kwargs: + app_conf['group'] = kwargs['group'] + + if 'isolation' in kwargs: + app_conf['isolation'] = kwargs['isolation'] + self.assertIn( 'success', self.conf(conf), 'load application configuration' ) diff --git a/test/unit/feature/isolation.py b/test/unit/feature/isolation.py index 9b06ab3c..3f474993 100644 --- a/test/unit/feature/isolation.py +++ b/test/unit/feature/isolation.py @@ -82,6 +82,3 @@ class TestFeatureIsolation(TestApplicationProto): data = int(os.readlink(nspath)[len(nstype) + 2 : -1]) return data - - def parsejson(self, data): - return json.loads(data.split('\n')[1]) diff --git a/test/unit/http.py b/test/unit/http.py index c7e3e36d..839e91a2 100644 --- a/test/unit/http.py +++ b/test/unit/http.py @@ -1,5 +1,6 @@ import re import time +import json import socket import select from unit.main import TestUnit @@ -86,23 +87,24 @@ class TestHTTP(TestUnit): sock.sendall(req) + encoding = 'utf-8' if 'encoding' not in kwargs else kwargs['encoding'] + if TestUnit.detailed: print('>>>') try: - print(req.decode('utf-8', 'ignore')) + print(req.decode(encoding, 'ignore')) except UnicodeEncodeError: print(req) resp = '' if 'no_recv' not in kwargs: - enc = 'utf-8' if 'encoding' not in kwargs else kwargs['encoding'] read_timeout = ( 30 if 'read_timeout' not in kwargs else kwargs['read_timeout'] ) resp = self.recvall( sock, read_timeout=read_timeout, buff_size=read_buffer_size - ).decode(enc) + ).decode(encoding) if TestUnit.detailed: print('<<<') @@ -114,6 +116,15 @@ class TestHTTP(TestUnit): if 'raw_resp' not in kwargs: resp = self._resp_to_dict(resp) + headers = resp.get('headers') + if headers and headers.get('Transfer-Encoding') == 'chunked': + resp['body'] = self._parse_chunked_body(resp['body']).decode( + encoding + ) + + if 'json' in kwargs: + resp = self._parse_json(resp) + if 'start' not in kwargs: sock.close() return resp @@ -151,7 +162,7 @@ class TestHTTP(TestUnit): return data def _resp_to_dict(self, resp): - m = re.search('(.*?\x0d\x0a?)\x0d\x0a?(.*)', resp, re.M | re.S) + m = re.search(r'(.*?\x0d\x0a?)\x0d\x0a?(.*)', resp, re.M | re.S) if not m: return {} @@ -162,12 +173,12 @@ class TestHTTP(TestUnit): headers_lines = p.findall(headers_text) status = re.search( - '^HTTP\/\d\.\d\s(\d+)|$', headers_lines.pop(0) + r'^HTTP\/\d\.\d\s(\d+)|$', headers_lines.pop(0) ).group(1) headers = {} for line in headers_lines: - m = re.search('(.*)\:\s(.*)', line) + m = re.search(r'(.*)\:\s(.*)', line) if m.group(1) not in headers: headers[m.group(1)] = m.group(2) @@ -180,6 +191,65 @@ class TestHTTP(TestUnit): return {'status': int(status), 'headers': headers, 'body': body} + def _parse_chunked_body(self, raw_body): + if isinstance(raw_body, str): + raw_body = bytes(raw_body.encode()) + + crlf = b'\r\n' + chunks = raw_body.split(crlf) + + if len(chunks) < 3: + self.fail('Invalid chunked body') + + if chunks.pop() != b'': + self.fail('No CRLF at the end of the body') + + try: + last_size = int(chunks[-2], 16) + except: + self.fail('Invalid zero size chunk') + + if last_size != 0 or chunks[-1] != b'': + self.fail('Incomplete body') + + body = b'' + while len(chunks) >= 2: + try: + size = int(chunks.pop(0), 16) + except: + self.fail('Invalid chunk size %s' % str(size)) + + if size == 0: + self.assertEqual(len(chunks), 1, 'last zero size') + break + + temp_body = crlf.join(chunks) + + body += temp_body[:size] + + temp_body = temp_body[size + len(crlf) :] + + chunks = temp_body.split(crlf) + + return body + + def _parse_json(self, resp): + headers = resp['headers'] + + self.assertIn('Content-Type', headers, 'Content-Type header set') + self.assertEqual( + headers['Content-Type'], + 'application/json', + 'Content-Type header is application/json', + ) + + resp['body'] = json.loads(resp['body']) + + return resp + + def getjson(self, **kwargs): + return self.get(json=True, **kwargs) + def waitforsocket(self, port): ret = False diff --git a/test/unit/main.py b/test/unit/main.py index 094fdb0e..ea6afd7f 100644 --- a/test/unit/main.py +++ b/test/unit/main.py @@ -1,6 +1,7 @@ import os import re import sys +import stat import time import fcntl import shutil @@ -20,6 +21,9 @@ class TestUnit(unittest.TestCase): pardir = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir, os.pardir) ) + is_su = os.geteuid() == 0 + uid = os.geteuid() + gid = os.getegid() architecture = platform.architecture()[0] system = platform.system() maxDiff = None @@ -188,13 +192,19 @@ class TestUnit(unittest.TestCase): self.stop_processes() def _run(self): - self.unitd = self.pardir + '/build/unitd' + build_dir = self.pardir + '/build' + self.unitd = build_dir + '/unitd' if not os.path.isfile(self.unitd): exit("Could not find unit") self.testdir = tempfile.mkdtemp(prefix='unit-test-') + self.public_dir(self.testdir) + + if oct(stat.S_IMODE(os.stat(build_dir).st_mode)) != '0o777': + self.public_dir(build_dir) + os.mkdir(self.testdir + '/state') print() @@ -328,6 +338,15 @@ class TestUnit(unittest.TestCase): return ret + def public_dir(self, path): + os.chmod(path, 0o777) + + for root, dirs, files in os.walk(path): + for d in dirs: + os.chmod(os.path.join(root, d), 0o777) + for f in files: + os.chmod(os.path.join(root, f), 0o777) + @staticmethod def _parse_args(): parser = argparse.ArgumentParser(add_help=False) |