From 800a4b3a2225eec8525fbd00b13e42c0472d4d4b Mon Sep 17 00:00:00 2001 From: Dennis Wittich Date: Mon, 12 Feb 2024 11:26:16 +0100 Subject: [PATCH] adds test for /about endpoint, fixes some bugs, code cleanups and refactoring --- learning_loop_node/data_classes/general.py | 4 ++++ learning_loop_node/detector/detector_logic.py | 2 -- learning_loop_node/detector/detector_node.py | 2 +- learning_loop_node/detector/rest/about.py | 2 +- learning_loop_node/detector/tests/conftest.py | 4 ++++ .../detector/tests/test_client_communication.py | 16 ++++++++++++++++ .../detector/tests/testing_detector.py | 2 +- 7 files changed, 27 insertions(+), 5 deletions(-) diff --git a/learning_loop_node/data_classes/general.py b/learning_loop_node/data_classes/general.py index 92f021d2..8404ab22 100644 --- a/learning_loop_node/data_classes/general.py +++ b/learning_loop_node/data_classes/general.py @@ -90,6 +90,10 @@ def save(self): del self_as_dict['model_root_path'] f.write(json.dumps(self_as_dict)) + @staticmethod + def from_dict(data: Dict) -> 'ModelInformation': + return from_dict(ModelInformation, data=data) + @dataclass(**KWONLY_SLOTS) class ErrorConfiguration(): diff --git a/learning_loop_node/detector/detector_logic.py b/learning_loop_node/detector/detector_logic.py index 899f7285..2bc4aa12 100644 --- a/learning_loop_node/detector/detector_logic.py +++ b/learning_loop_node/detector/detector_logic.py @@ -13,11 +13,9 @@ class DetectorLogic(): def __init__(self, model_format: str) -> None: self.model_format: str = model_format self._model_info: Optional[ModelInformation] = None - self.target_model: Optional[str] = None async def soft_reload(self): self._model_info = None - self.target_model = None @property def model_info(self) -> ModelInformation: diff --git a/learning_loop_node/detector/detector_node.py b/learning_loop_node/detector/detector_node.py index 9bca1306..785a10fe 100644 --- a/learning_loop_node/detector/detector_node.py +++ b/learning_loop_node/detector/detector_node.py @@ -50,7 +50,7 @@ def __init__(self, name: str, detector: DetectorLogic, uuid: Optional[str] = Non self.loop_communicator) self.relevance_filter: RelevanceFilter = RelevanceFilter(self.outbox) - self.target_model = None + self.target_model: Optional[str] = None self.include_router(rest_detect.router, tags=["detect"]) self.include_router(rest_upload.router, prefix="") diff --git a/learning_loop_node/detector/rest/about.py b/learning_loop_node/detector/rest/about.py index aa72cd9f..c464b999 100644 --- a/learning_loop_node/detector/rest/about.py +++ b/learning_loop_node/detector/rest/about.py @@ -20,5 +20,5 @@ async def get_about(request: Request): 'operation_mode': app.operation_mode.value, 'state': app.status.state, 'model_info': app.detector_logic._model_info, # pylint: disable=protected-access - 'target_model': app.detector_logic.target_model, # pylint: disable=protected-access + 'target_model': app.target_model, # pylint: disable=protected-access } diff --git a/learning_loop_node/detector/tests/conftest.py b/learning_loop_node/detector/tests/conftest.py index 59735589..ad183fe2 100644 --- a/learning_loop_node/detector/tests/conftest.py +++ b/learning_loop_node/detector/tests/conftest.py @@ -37,6 +37,8 @@ def should_have_segmentations(request) -> bool: @pytest.fixture() async def test_detector_node(): + """Initializes and runs a detector testnode. Note that the running instance and the one the function returns are not the same instances!""" + os.environ['ORGANIZATION'] = 'zauberzeug' os.environ['PROJECT'] = 'demo' @@ -46,6 +48,8 @@ async def test_detector_node(): multiprocessing.set_start_method('fork', force=True) assert multiprocessing.get_start_method() == 'fork' + # print('\n\n',multiprocessing.get_start_method()) + proc = Process(target=uvicorn.run, args=(node,), kwargs={ diff --git a/learning_loop_node/detector/tests/test_client_communication.py b/learning_loop_node/detector/tests/test_client_communication.py index cfaaf3e9..be3d2d4b 100644 --- a/learning_loop_node/detector/tests/test_client_communication.py +++ b/learning_loop_node/detector/tests/test_client_communication.py @@ -1,9 +1,11 @@ import asyncio +import json import pytest import requests from learning_loop_node import DetectorNode +from learning_loop_node.data_classes import Category, ModelInformation from learning_loop_node.detector.tests.conftest import get_outbox_files from learning_loop_node.globals import GLOBALS @@ -84,3 +86,17 @@ async def test_sio_upload(test_detector_node: DetectorNode, sio_client): result = await sio_client.call('upload', {'image': image_bytes}) assert result is None assert len(get_outbox_files(test_detector_node.outbox)) == 2, 'There should be one image and one .json file.' + + +async def test_about_endpoint(test_detector_node: DetectorNode): + await asyncio.sleep(1) + response = requests.get(f'http://localhost:{GLOBALS.detector_port}/about', timeout=30) + + assert response.status_code == 200 + response_dict = json.loads(response.content) + model_information = ModelInformation.from_dict(response_dict['model_info']) + + assert response_dict['operation_mode'] == 'idle' + assert response_dict['state'] == 'online' + assert response_dict['target_model'] == '1.1' + assert any([c.name == 'purple point' for c in model_information.categories]) diff --git a/learning_loop_node/detector/tests/testing_detector.py b/learning_loop_node/detector/tests/testing_detector.py index 8eecf48d..ed710824 100644 --- a/learning_loop_node/detector/tests/testing_detector.py +++ b/learning_loop_node/detector/tests/testing_detector.py @@ -4,7 +4,7 @@ from learning_loop_node import DetectorLogic from learning_loop_node.conftest import get_dummy_detections -from learning_loop_node.data_classes import Detections +from learning_loop_node.data_classes import Category, Detections, ModelInformation class TestingDetectorLogic(DetectorLogic):