aetherscale

[unmaintained] code for a cloud provider tutorial
Log | Files | Refs | README | LICENSE

commit c0999d7b52d2c44c4dce70f65fff912fdf501a37
parent 57a97efaa00b03312acd388f105b9d882e7a70f0
Author: Stefan Koch <programming@stefan-koch.name>
Date:   Tue,  8 Dec 2020 20:57:33 +0100

create unit tests

Diffstat:
M.gitignore | 1+
MREADME.md | 8++++++++
Maetherscale/__main__.py | 2+-
Maetherscale/qemu.py | 6+++---
Atests/test_interfaces.py | 8++++++++
Atests/test_qemu.py | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atox.ini | 6++++++
7 files changed, 98 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -2,6 +2,7 @@ base_images user_images .idea +.tox build dist env diff --git a/README.md b/README.md @@ -63,6 +63,14 @@ For example, to list all running VMs run the following client command: aetherscale-cli list-vms ``` +## Run Tests + +You can run tests with `tox`: + +```bash +tox +``` + ## Overview diff --git a/aetherscale/__main__.py b/aetherscale/__main__.py @@ -1,4 +1,4 @@ -from .minikloud import main +from .server import main if __name__ == '__main__': main() diff --git a/aetherscale/qemu.py b/aetherscale/qemu.py @@ -5,9 +5,9 @@ from typing import Any class QemuMonitor: + # TODO: Improve QMP communication, spec is here: + # https://github.com/qemu/qemu/blob/master/docs/interop/qmp-spec.txt def __init__(self, socket_file: Path): - # TODO: It's not really nice that we use the file object - # to read lines and the socket to write self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.connect(str(socket_file)) self.f = self.sock.makefile('rw') @@ -16,7 +16,7 @@ class QemuMonitor: self._initialize() def execute(self, command: str) -> Any: - json_line = json.dumps({'execute': command}) + '\n' + json_line = json.dumps({'execute': command}) + '\r\n' self.sock.sendall(json_line.encode('utf-8')) return json.loads(self.f.readline()) diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py @@ -0,0 +1,8 @@ +from aetherscale.interfaces import create_mac_address + + +def test_mac_address_is_random(): + mac_a = create_mac_address() + mac_b = create_mac_address() + + assert mac_a != mac_b diff --git a/tests/test_qemu.py b/tests/test_qemu.py @@ -0,0 +1,71 @@ +import contextlib +import json +from pathlib import Path +import socket +import tempfile +import threading +import uuid + +from aetherscale.qemu import QemuMonitor + + +class MockQemuServer: + init_msg = {"QMP": {"version": {"qemu": { + "micro": 0, "minor": 6, "major": 1 + }, "package": ""}, "capabilities": []}} + mock_ok_response = {'return': {}} + + def __init__(self, socket_file: str): + self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self._socket_file = socket_file + self.received_executes = [] + + def __enter__(self): + self._sock.bind(self._socket_file) + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self._sock.close() + + def listen(self): + self._sock.listen() + + conn, addr = self._sock.accept() + filelike = conn.makefile('rb') + + self._send_message(self.init_msg, conn) + + try: + while True: + msg = self._recv_message(filelike) + self.received_executes.append(msg['execute']) + + # for now always return with OK status + self._send_message(self.mock_ok_response, conn) + except json.JSONDecodeError as e: + conn.close() + + def _send_message(self, message, conn): + msg_with_newline = json.dumps(message) + '\r\n' + conn.send(msg_with_newline.encode('ascii')) + + def _recv_message(self, filelike): + line = filelike.readline() + return json.loads(line.decode('utf-8')) + + +@contextlib.contextmanager +def run_mock_qemu_server(socket_file: str) -> MockQemuServer: + with MockQemuServer(socket_file) as mock_server: + t = threading.Thread(target=mock_server.listen) + t.daemon = True + t.start() + yield mock_server + + +def test_initializes_with_capabilities_acceptance(): + socket_file = Path(tempfile.gettempdir()) / str(uuid.uuid4()) + + with run_mock_qemu_server(str(socket_file)) as mock_server: + QemuMonitor(socket_file) + assert 'qmp_capabilities' in mock_server.received_executes diff --git a/tox.ini b/tox.ini @@ -0,0 +1,6 @@ +[tox] +envlist = py3 + +[testenv] +deps = pytest +commands = pytest {posargs}