From 863377441bdc70885d1bad80bbbd9c6a9a3646a7 Mon Sep 17 00:00:00 2001 From: Andrey Zelenkov Date: Tue, 21 Nov 2017 20:51:21 +0300 Subject: Tests: added basic infrastructure. --- test/unit.py | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 test/unit.py (limited to 'test/unit.py') diff --git a/test/unit.py b/test/unit.py new file mode 100644 index 00000000..224d026e --- /dev/null +++ b/test/unit.py @@ -0,0 +1,112 @@ +import os +import re +import sys +import json +import time +import shutil +import socket +import tempfile +import unittest +import subprocess + +class TestUnit(unittest.TestCase): + + def setUp(self): + self.testdir = tempfile.mkdtemp(prefix='unit-test-') + + os.mkdir(self.testdir + '/state') + + pardir = os.path.abspath(os.path.join(os.path.dirname(__file__), + os.pardir)) + + print() + + subprocess.call([pardir + '/build/unitd', + # TODO '--no-daemon', + '--modules', pardir + '/build', + '--state', self.testdir + '/state', + '--pid', self.testdir + '/unit.pid', + '--log', self.testdir + '/unit.log', + '--control', 'unix:' + self.testdir + '/control.unit.sock']) + + time_wait = 0 + while time_wait < 5 and not (os.path.exists(self.testdir + '/unit.pid') + and os.path.exists(self.testdir + '/unit.log') + and os.path.exists(self.testdir + '/control.unit.sock')): + time.sleep(0.1) + time_wait += 0.1 + + # TODO dependency check + + def tearDown(self): + with open(self.testdir + '/unit.pid', 'r') as f: + pid = f.read().rstrip() + + subprocess.call(['kill', pid]) + + time_wait = 0 + while time_wait < 5 and os.path.exists(self.testdir + '/unit.pid'): + time.sleep(0.1) + time_wait += 0.1 + + if '--log' in sys.argv: + with open(self.testdir + '/unit.log', 'r') as f: + print(f.read()) + + if '--leave' not in sys.argv: + shutil.rmtree(self.testdir) + +class TestUnitControl(TestUnit): + + # TODO socket reuse + # TODO http client + + def get(self, path='/'): + + with self._control_sock() as sock: + sock.sendall(('GET ' + path + + ' HTTP/1.1\r\nHost: localhost\r\n\r\n').encode()) + r = self._recvall(sock) + + return self._body_json(r) + + def delete(self, path='/'): + + with self._control_sock() as sock: + sock.sendall(('DELETE ' + path + + ' HTTP/1.1\r\nHost: localhost\r\n\r\n').encode()) + r = self._recvall(sock) + + return self._body_json(r) + + def put(self, path='/', data=''): + + if isinstance(data, str): + data = data.encode() + + with self._control_sock() as sock: + sock.sendall(('PUT ' + path + (' HTTP/1.1\nHost: localhost\n' + 'Content-Length: ') + str(len(data)) + '\r\n\r\n').encode() + + data) + r = self._recvall(sock) + + return self._body_json(r) + + def _control_sock(self): + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.connect(self.testdir + '/control.unit.sock') + return sock + + def _recvall(self, sock, buff_size=4096): + data = '' + while True: + part = sock.recv(buff_size).decode() + data += part + if len(part) < buff_size: + break + + return data + + def _body_json(self, resp): + m = re.search('.*?\x0d\x0a?\x0d\x0a?(.*)', resp, re.M | re.S) + return json.loads(m.group(1)) -- cgit