commit c0999d7b52d2c44c4dce70f65fff912fdf501a37
parent 57a97efaa00b03312acd388f105b9d882e7a70f0
Author: Stefan Koch <programming@stefan-koch.name>
Date: Tue, 8 Dec 2020 20:57:33 +0100
create unit tests
Diffstat:
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}