From 5b524b0b3d7a9b4ba527322f64d664cf16dfb7da Mon Sep 17 00:00:00 2001 From: moritzsommer Date: Wed, 29 May 2024 05:13:10 +0200 Subject: [PATCH] Add test cases --- .github/workflows/ci.yml | 29 +++++++ .gitignore | 1 + config.ini.default | 2 +- requirements.txt | 2 + semantic_id_resolver/resolver.py | 9 ++- semantic_id_resolver/service.py | 5 +- test/__init__.py | 0 test/test_resolving_service.py | 117 ++++++++++++++++++++++++++++ test_resources/config.ini | 9 +++ test_resources/debug_endpoints.json | 4 + 10 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 test/__init__.py create mode 100644 test/test_resolving_service.py create mode 100644 test_resources/config.ini create mode 100644 test_resources/debug_endpoints.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..757a553 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: test + +on: + push: + branches: + - wip/testing + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + architecture: x64 + + - name: Install Python dependencies + run: pip install -r requirements.txt + + - name: Run Python Tests + run: python -m unittest discover \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9c92902..e7af935 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ # Typical virtualenv dir /venv/ +/.venv/ # IDE settings /.idea/ diff --git a/config.ini.default b/config.ini.default index 1d957d6..87f96bf 100644 --- a/config.ini.default +++ b/config.ini.default @@ -6,4 +6,4 @@ port=8125 fallback_semantic_matching_service=https://example.org/semantic_matching_service eclass_semantic_matching_service=https://example.org/semantic_matching_service cdd_semantic_matching_service=https://example.org/semantic_matching_service -debug_semantic_matching_service_endpoints=../debug_endpoints.json \ No newline at end of file +debug_semantic_matching_service_endpoints=../debug_endpoints.json diff --git a/requirements.txt b/requirements.txt index 33bfc16..aa9f52e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,5 @@ fastapi>=0.95.0 pydantic>=1.10 uvicorn>=0.21.1 dnspython>=2.4.2 +requests>=2.32.2 +setuptools>=68.2.0 \ No newline at end of file diff --git a/semantic_id_resolver/resolver.py b/semantic_id_resolver/resolver.py index cac45f5..b0fc090 100644 --- a/semantic_id_resolver/resolver.py +++ b/semantic_id_resolver/resolver.py @@ -39,8 +39,8 @@ def is_iri_not_irdi(semantic_id: str) -> Optional[bool]: # Check if the scheme is present, which indicates it's a URI if parsed_url.scheme: return True - # Check if there is a colon in the netloc, which could indicate an IRI - elif ':' in parsed_url.netloc: + # TODO IRDI parser + elif "#" in parsed_url.fragment: return False # If neither condition is met, return None else: @@ -103,9 +103,10 @@ def find_semantic_matching_service(self, semantic_id: str) -> Optional[str]: return debug_endpoint # Check for IRI and IRDI - if is_iri_not_irdi(semantic_id) is True: + is_iri = is_iri_not_irdi(semantic_id) + if is_iri is True: return _iri_find_semantic_matching_service(semantic_id) - elif is_iri_not_irdi(semantic_id) is False: + elif is_iri is False: return self._irdi_find_semantic_matching_service(semantic_id) else: return None diff --git a/semantic_id_resolver/service.py b/semantic_id_resolver/service.py index 0b57130..16289d4 100644 --- a/semantic_id_resolver/service.py +++ b/semantic_id_resolver/service.py @@ -57,7 +57,7 @@ def get_semantic_matching_service( endpoint = found_endpoint return SMSResponse( semantic_matching_service_endpoint=endpoint, - meta_information={} # Todo + meta_information={} # TODO metainformation ) @@ -82,7 +82,7 @@ def get_semantic_matching_service( DEBUG_ENDPOINTS = resolver.DebugSemanticMatchingServiceEndpoints.from_file( config["RESOLVER"]["debug_semantic_matching_service_endpoints"] ) - print(f"USING DEBUG ENDPOINTS FROM {config["RESOLVER"]["debug_semantic_matching_service_endpoints"]}") + print(f"USING DEBUG ENDPOINTS FROM {config['RESOLVER']['debug_semantic_matching_service_endpoints']}") except FileNotFoundError: DEBUG_ENDPOINTS = resolver.DebugSemanticMatchingServiceEndpoints(debug_endpoints={}) @@ -97,4 +97,5 @@ def get_semantic_matching_service( APP.include_router( SEMANTIC_ID_RESOLVING_SERVICE.router ) + # TODO read host from config uvicorn.run(APP, host="127.0.0.1", port=int(config["SERVICE"]["PORT"])) diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/test_resolving_service.py b/test/test_resolving_service.py new file mode 100644 index 0000000..ae19fd5 --- /dev/null +++ b/test/test_resolving_service.py @@ -0,0 +1,117 @@ +import os +import configparser +from typing import Dict +import multiprocessing +import requests +import unittest + +from fastapi import FastAPI +import uvicorn + +from semantic_id_resolver import resolver +from semantic_id_resolver.service import SemanticIdResolvingService, SMSRequest + + +def run_server(): + # Load test configuration + config = configparser.ConfigParser() + config.read([ + os.path.abspath(os.path.join(os.path.dirname(__file__), "../test_resources/config.ini")), + ]) + + # Define test configuration + IRDI_MATCHER_DICT: Dict[resolver.IRDISources, str] = { + resolver.IRDISources.ECLASS: config["RESOLVER"]["eclass_semantic_matching_service"], + resolver.IRDISources.IEC_CDD: config["RESOLVER"]["cdd_semantic_matching_service"] + } + + try: + DEBUG_ENDPOINTS = resolver.DebugSemanticMatchingServiceEndpoints.from_file( + config["RESOLVER"]["debug_semantic_matching_service_endpoints"] + ) + print(f"USING DEBUG ENDPOINTS FROM {config['RESOLVER']['debug_semantic_matching_service_endpoints']}") + except FileNotFoundError: + DEBUG_ENDPOINTS = resolver.DebugSemanticMatchingServiceEndpoints(debug_endpoints={}) + + # Mock SemanticIdResolvingService for testing + mock_resolver = resolver.SemanticIdResolver(IRDI_MATCHER_DICT, DEBUG_ENDPOINTS) + semantic_id_resolver_service = SemanticIdResolvingService( + endpoint=config["SERVICE"]["endpoint"], + fallback_semantic_matching_service_endpoint=config["RESOLVER"]["fallback_semantic_matching_service"], + semantic_id_resolver=mock_resolver + ) + + app = FastAPI() + app.include_router(semantic_id_resolver_service.router) + uvicorn.run(app, host=str(config["SERVICE"]["ENDPOINT"]), port=int(config["SERVICE"]["PORT"]), log_level="error") + + +class TestSemanticMatchingService(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.server_process = multiprocessing.Process(target=run_server) + cls.server_process.start() + + @classmethod + def tearDownClass(cls): + cls.server_process.terminate() + cls.server_process.join() + + def test_semantic_matching_service_iri(self): + # TODO deposit DNS record + sms_request = SMSRequest( + semantic_id="foo://example.org:1234/over/there?name=bar#page=3", + ) + response = requests.get( + "http://127.0.0.1:8125/get_semantic_matching_service", + data=sms_request.model_dump_json() + ) + self.assertEqual( + "https://example.org/fallback_semantic_matching_service", + response.json()["semantic_matching_service_endpoint"] + ) + + def test_semantic_matching_service_irdi_eclass(self): + sms_request = SMSRequest( + semantic_id="0173-1#01-ACK323#017", + ) + response = requests.get( + "http://127.0.0.1:8125/get_semantic_matching_service", + data=sms_request.model_dump_json() + ) + self.assertEqual( + "https://example.org/eclass_semantic_matching_service", + response.json()["semantic_matching_service_endpoint"] + ) + + def test_semantic_matching_service_irdi_cdd(self): + sms_request = SMSRequest( + semantic_id="0112-1#01-ACK323#017", + ) + response = requests.get( + "http://127.0.0.1:8125/get_semantic_matching_service", + data=sms_request.model_dump_json() + ) + self.assertEqual( + "https://example.org/cdd_semantic_matching_service", + response.json()["semantic_matching_service_endpoint"] + ) + + def test_semantic_matching_service_fallback(self): + sms_request = SMSRequest( + semantic_id="nothing", + ) + response = requests.get( + "http://127.0.0.1:8125/get_semantic_matching_service", + data=sms_request.model_dump_json() + ) + self.assertEqual( + "https://example.org/fallback_semantic_matching_service", + response.json()["semantic_matching_service_endpoint"] + ) + + # TODO check debug endpoints + + +if __name__ == '__main__': + unittest.main() diff --git a/test_resources/config.ini b/test_resources/config.ini new file mode 100644 index 0000000..ee3edbd --- /dev/null +++ b/test_resources/config.ini @@ -0,0 +1,9 @@ +[SERVICE] +endpoint=127.0.0.1 +port=8125 + +[RESOLVER] +fallback_semantic_matching_service=https://example.org/fallback_semantic_matching_service +eclass_semantic_matching_service=https://example.org/eclass_semantic_matching_service +cdd_semantic_matching_service=https://example.org/cdd_semantic_matching_service +debug_semantic_matching_service_endpoints=../debug_endpoints.json diff --git a/test_resources/debug_endpoints.json b/test_resources/debug_endpoints.json new file mode 100644 index 0000000..c5395a9 --- /dev/null +++ b/test_resources/debug_endpoints.json @@ -0,0 +1,4 @@ +{ + "https://example.org/semanticIDone": "http://localhost:1234/semantic_matching_service", + "https://example.org/semanticIDtwo": "http://localhost:1234/semantic_matching_service" +}