Add API integration test
Test the HTTP API directly from outside the VM by forwarding /run/weldr/api.socket to a TCP port on the host. This is only a start to test that the API always returns JSON (see previous commit).
This commit is contained in:
parent
8ed910b29a
commit
b50f1967c6
69
test/check-api
Executable file
69
test/check-api
Executable file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import composertest
|
||||
import requests
|
||||
import subprocess
|
||||
|
||||
|
||||
class TestApi(composertest.ComposerTestCase):
|
||||
"""Test Composer HTTP API"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
# Forward /run/weldr/api.socket to a port on the host
|
||||
# Set ExitOnForwardFailure so that ssh blocks until the forward is set
|
||||
# up before going to the background (-f), which it closes stdout. We
|
||||
# wait for that by calling read() on it.
|
||||
self.composer_port = self.network._lock(8080)
|
||||
forwarder_command = [*self.ssh_command, "-fNT",
|
||||
"-o", "ExitOnForwardFailure=yes",
|
||||
"-L", f"localhost:{self.composer_port}:/run/weldr/api.socket"]
|
||||
self.forwarder_proc = subprocess.Popen(forwarder_command, stdout=subprocess.PIPE)
|
||||
self.forwarder_proc.stdout.read()
|
||||
|
||||
def tearDown(self):
|
||||
self.forwarder_proc.terminate()
|
||||
try:
|
||||
self.forwarder_proc.wait(timeout=1)
|
||||
except TimeoutError:
|
||||
self.forwarder_proc.kill()
|
||||
super().tearDown()
|
||||
|
||||
def request(self, method, path, check=True):
|
||||
self.assertEqual(path[0], "/")
|
||||
r = requests.request(method, f"http://localhost:{self.composer_port}{path}", timeout=30)
|
||||
if check:
|
||||
r.raise_for_status()
|
||||
return r
|
||||
|
||||
def test_basic(self):
|
||||
"""Basic checks for the API"""
|
||||
|
||||
#
|
||||
# API status without depsolve errors
|
||||
#
|
||||
status = self.request("GET", "/api/status").json()
|
||||
self.assertEqual(status.keys(), { "build", "api", "db_version", "schema_version", "db_supported", "backend", "msgs" })
|
||||
self.assertEqual(status["msgs"], [])
|
||||
|
||||
#
|
||||
# HTTP errors should return json responses
|
||||
#
|
||||
r = self.request("GET", "/marmalade", check=False)
|
||||
self.assertEqual(r.status_code, 404)
|
||||
self.assertEqual(r.json(), {
|
||||
"status": False,
|
||||
"errors": [{ "id": "HTTPError", "code": 404, "msg": "Not Found" }]
|
||||
})
|
||||
|
||||
r = self.request("POST", "/api/status", check=False)
|
||||
self.assertEqual(r.status_code, 405)
|
||||
self.assertEqual(r.json(), {
|
||||
"status": False,
|
||||
"errors": [{ "id": "HTTPError", "code": 405, "msg": "Method Not Allowed" }]
|
||||
})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
composertest.main()
|
@ -28,8 +28,8 @@ class ComposerTestCase(unittest.TestCase):
|
||||
sit = False
|
||||
|
||||
def setUp(self):
|
||||
network = testvm.VirtNetwork(0)
|
||||
self.machine = testvm.VirtMachine(self.image, networking=network.host(), memory_mb=2048)
|
||||
self.network = testvm.VirtNetwork(0)
|
||||
self.machine = testvm.VirtMachine(self.image, networking=self.network.host(), memory_mb=2048)
|
||||
|
||||
print(f"Starting virtual machine '{self.image}'")
|
||||
self.machine.start()
|
||||
@ -58,7 +58,6 @@ class ComposerTestCase(unittest.TestCase):
|
||||
# Peek into internal data structure, because there's no way to get the
|
||||
# TestResult at this point. `errors` is a list of tuples (method, error)
|
||||
errors = filter(None, [ e[1] for e in self._outcome.errors ])
|
||||
|
||||
if errors and self.sit:
|
||||
for e in errors:
|
||||
print_exception(*e)
|
||||
|
Loading…
Reference in New Issue
Block a user