From 06d9313a7cdb9a836c3538b7c461ac4d8e3d8cdd Mon Sep 17 00:00:00 2001 From: Taddeus Date: Mon, 3 Nov 2025 14:44:15 +0200 Subject: [PATCH] Adds unit tests for LightRAG input/output processors and package exports Introduces comprehensive async unit tests to verify input processing merges extra values correctly and output generation returns expected URLs and ports. Adds a basic test to confirm package exports remain intact. Cleans up the .gitignore by removing redundant test file ignores to allow test discovery. Improves code quality and test coverage for the LightRAG app integration. Relates to MLO-469 --- .apolo/tests/unit/test_inputs_processor.py | 78 +++++++++++++++++++++ .apolo/tests/unit/test_outputs_processor.py | 68 ++++++++++++++++++ .apolo/tests/unit/test_package.py | 13 ++++ .gitignore | 2 - 4 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 .apolo/tests/unit/test_inputs_processor.py create mode 100644 .apolo/tests/unit/test_outputs_processor.py create mode 100644 .apolo/tests/unit/test_package.py diff --git a/.apolo/tests/unit/test_inputs_processor.py b/.apolo/tests/unit/test_inputs_processor.py new file mode 100644 index 00000000..166b42e2 --- /dev/null +++ b/.apolo/tests/unit/test_inputs_processor.py @@ -0,0 +1,78 @@ +from __future__ import annotations + +from typing import Any + +import pytest + +from apolo_app_types.app_types import AppType +from apolo_app_types.protocols.common import IngressHttp, Preset +from apolo_app_types.protocols.postgres import CrunchyPostgresUserCredentials + +from apolo_apps_lightrag.inputs_processor import LightRAGInputsProcessor +from apolo_apps_lightrag.types import ( + LightRAGAppInputs, + LightRAGPersistence, + OpenAIEmbeddingProvider, + OpenAILLMProvider, +) + + +@pytest.mark.asyncio +async def test_gen_extra_values_merges_sources(monkeypatch: pytest.MonkeyPatch) -> None: + client_stub = object() + processor = LightRAGInputsProcessor(client_stub) # type: ignore[arg-type] + + captured: dict[str, Any] = {} + + async def fake_gen_extra_values(**kwargs: Any) -> dict[str, Any]: + captured.update(kwargs) + return {"platform": {"ingress": True}} + + monkeypatch.setattr( + "apolo_apps_lightrag.inputs_processor.gen_extra_values", + fake_gen_extra_values, + ) + + app_inputs = LightRAGAppInputs( + preset=Preset(name="medium"), + ingress_http=IngressHttp(), + pgvector_user=CrunchyPostgresUserCredentials( + user="rag", + password="secret", + host="postgres.internal", + port=5432, + pgbouncer_host="pgbouncer.internal", + pgbouncer_port=6432, + dbname="lightrag", + ), + persistence=LightRAGPersistence( + rag_storage_size=20, + inputs_storage_size=15, + ), + llm_config=OpenAILLMProvider(api_key="llm-key", model="gpt-4o-mini"), + embedding_config=OpenAIEmbeddingProvider(api_key="embed-key"), + ) + + values = await processor.gen_extra_values( + app_inputs, + app_name="lightrag-app", + namespace="apps", + app_id="instance-123", + app_secrets_name="lightrag-secrets", + ) + + assert values["replicaCount"] == 1 + assert values["fullnameOverride"] == "lightrag-app" + assert values["env"]["POSTGRES_HOST"] == "pgbouncer.internal" + assert values["env"]["LLM_BINDING"] == "openai" + assert values["persistence"]["ragStorage"]["size"] == "20Gi" + assert values["persistence"]["inputs"]["size"] == "15Gi" + assert values["platform"] == {"ingress": True} + + assert captured["apolo_client"] is client_stub + assert captured["preset_type"] == app_inputs.preset + assert captured["ingress_http"] == app_inputs.ingress_http + assert captured["ingress_grpc"] is None + assert captured["namespace"] == "apps" + assert captured["app_id"] == "instance-123" + assert captured["app_type"] == AppType.LightRAG diff --git a/.apolo/tests/unit/test_outputs_processor.py b/.apolo/tests/unit/test_outputs_processor.py new file mode 100644 index 00000000..dcefd339 --- /dev/null +++ b/.apolo/tests/unit/test_outputs_processor.py @@ -0,0 +1,68 @@ +from __future__ import annotations + +import pytest + +from apolo_app_types.outputs.common import INSTANCE_LABEL +from apolo_app_types.protocols.common.networking import WebApp + +from apolo_apps_lightrag.outputs_processor import LightRAGOutputsProcessor + + +@pytest.mark.asyncio +async def test_generate_outputs(monkeypatch: pytest.MonkeyPatch) -> None: + processor = LightRAGOutputsProcessor() + internal_web = WebApp( + host="internal.local", + port=9621, + base_path="/", + protocol="http", + ) + external_web = WebApp( + host="external.example.com", + port=443, + base_path="/", + protocol="https", + ) + + async def fake_get_internal_external_web_urls(labels: dict[str, str]): + assert labels == { + "app.kubernetes.io/name": "lightrag", + INSTANCE_LABEL: "instance-123", + } + return internal_web, external_web + + async def fake_get_service_host_port(match_labels: dict[str, str]): + assert match_labels == { + "app.kubernetes.io/name": "lightrag", + INSTANCE_LABEL: "instance-123", + } + return "service.local", 9621 + + async def fake_get_ingress_host_port(match_labels: dict[str, str]): + assert match_labels == { + "app.kubernetes.io/name": "lightrag", + INSTANCE_LABEL: "instance-123", + } + return "service.example.com", 443 + + monkeypatch.setattr( + "apolo_apps_lightrag.outputs_processor.get_internal_external_web_urls", + fake_get_internal_external_web_urls, + ) + monkeypatch.setattr( + "apolo_apps_lightrag.outputs_processor.get_service_host_port", + fake_get_service_host_port, + ) + monkeypatch.setattr( + "apolo_apps_lightrag.outputs_processor.get_ingress_host_port", + fake_get_ingress_host_port, + ) + + outputs = await processor.generate_outputs({}, "instance-123") + + assert outputs["app_url"]["internal_url"]["host"] == internal_web.host + assert outputs["app_url"]["external_url"]["host"] == external_web.host + assert outputs["server_url"]["internal_url"]["host"] == "service.local" + assert outputs["server_url"]["internal_url"]["port"] == 9621 + assert outputs["server_url"]["external_url"]["host"] == "service.example.com" + assert outputs["server_url"]["external_url"]["port"] == 443 diff --git a/.apolo/tests/unit/test_package.py b/.apolo/tests/unit/test_package.py new file mode 100644 index 00000000..3b522cdf --- /dev/null +++ b/.apolo/tests/unit/test_package.py @@ -0,0 +1,13 @@ +from apolo_apps_lightrag import ( + LightRAGAppInputs, + LightRAGAppOutputs, + LightRAGInputsProcessor, + LightRAGOutputsProcessor, +) + + +def test_package_exports() -> None: + assert LightRAGAppInputs.__name__ == "LightRAGAppInputs" + assert LightRAGAppOutputs.__name__ == "LightRAGAppOutputs" + assert LightRAGInputsProcessor.__name__ == "LightRAGInputsProcessor" + assert LightRAGOutputsProcessor.__name__ == "LightRAGOutputsProcessor" diff --git a/.gitignore b/.gitignore index e96b5a11..2d66281f 100644 --- a/.gitignore +++ b/.gitignore @@ -70,8 +70,6 @@ download_models_hf.py lightrag-dev/ gui/ -# unit-test files -test_* # Cline files memory-bank/