From 00d195c6ef736741dcdda7b7016dcc545ae6e606 Mon Sep 17 00:00:00 2001 From: Elias Date: Mon, 3 Aug 2026 11:00:51 +0300 Subject: [PATCH 1/2] test(config): add configuration loader unit coverage --- Autotests/run_mandatory | 1 + Autotests/unit/test_config.py | 135 ++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 Autotests/unit/test_config.py diff --git a/Autotests/run_mandatory b/Autotests/run_mandatory index 7e14c84e..4539926a 100644 --- a/Autotests/run_mandatory +++ b/Autotests/run_mandatory @@ -38,3 +38,4 @@ test_openai_runtime_embeddings.py test_prompt_grounding.py test_websearch_smoke.py unit/test_fileio_verified_writes.py +unit/test_config.py diff --git a/Autotests/unit/test_config.py b/Autotests/unit/test_config.py new file mode 100644 index 00000000..69093e7e --- /dev/null +++ b/Autotests/unit/test_config.py @@ -0,0 +1,135 @@ +"""In-process unit tests for src/config.py. + +The configuration resolver checks command-line arguments, OMEGACLAW_ +environment variables, the YAML configuration file, and finally the supplied +default. Resolved values are cached until configuration is initialized again. + +No container, no network, no token — same pattern as +unit/test_fileio_verified_writes.py: the module is loaded by file path. +""" +import importlib.util +import os + +import pytest + +_REPO_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), "..", "..")) +_CONFIG_PATH = os.path.join(_REPO_ROOT, "src", "config.py") + + +def _load_config(): + spec = importlib.util.spec_from_file_location("config_under_test", _CONFIG_PATH) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +@pytest.fixture +def config(): + return _load_config() + + +def test_config_module_exposes_public_api(config): + assert hasattr(config, "config_get_by_key") + assert hasattr(config, "command_line_to_dict") + assert hasattr(config, "init_config") + + +def test_command_line_key_value_pairs(config): + result = config.command_line_to_dict(["provider=OpenRouter", "model=free"]) + + assert result == {"provider": "OpenRouter", "model": "free"} + + +def test_command_line_bare_argument_becomes_true(config): + assert config.command_line_to_dict(["verbose"]) == {"verbose": True} + + +def test_command_line_splits_on_first_equals_only(config): + result = config.command_line_to_dict(["url=http://host/?a=b"]) + + assert result == {"url": "http://host/?a=b"} + + +def test_command_line_empty_value_is_empty_string(config): + assert config.command_line_to_dict(["key="]) == {"key": ""} + + +def test_command_line_empty_list(config): + assert config.command_line_to_dict([]) == {} + + +def test_default_used_when_nothing_configured(config): + assert config.config_get_by_key("MISSING", "fallback") == "fallback" + + +def test_default_is_none_when_unspecified(config): + assert config.config_get_by_key("MISSING") is None + + +def test_reads_from_command_line(config): + config._COMMAND_LINE = {"provider": "OpenRouter"} + + assert config.config_get_by_key("provider", "Anthropic") == "OpenRouter" + + +def test_reads_from_environment_with_omegaclaw_prefix(config, monkeypatch): + monkeypatch.setenv("OMEGACLAW_provider", "OpenRouter") + + assert config.config_get_by_key("provider", "Anthropic") == "OpenRouter" + + +def test_environment_key_without_prefix_is_ignored(config, monkeypatch): + # Only OMEGACLAW_ is consulted, never the bare key. + monkeypatch.setenv("provider", "OpenRouter") + monkeypatch.delenv("OMEGACLAW_provider", raising=False) + + assert config.config_get_by_key("provider", "Anthropic") == "Anthropic" + + +def test_reads_from_config_file(config): + config._CONFIG_FILE = {"provider": "OpenRouter"} + + assert config.config_get_by_key("provider", "Anthropic") == "OpenRouter" + + +def test_command_line_beats_environment_and_file(config, monkeypatch): + config._COMMAND_LINE = {"provider": "OpenRouter"} + monkeypatch.setenv("OMEGACLAW_provider", "OpenAI") + config._CONFIG_FILE = {"provider": "Anthropic"} + + assert config.config_get_by_key("provider") == "OpenRouter" + + +def test_environment_beats_config_file(config, monkeypatch): + monkeypatch.setenv("OMEGACLAW_provider", "OpenRouter") + config._CONFIG_FILE = {"provider": "Anthropic"} + + assert config.config_get_by_key("provider", "DefaultProvider") == "OpenRouter" + + +def test_config_file_beats_default(config, monkeypatch): + monkeypatch.delenv("OMEGACLAW_provider", raising=False) + config._CONFIG_FILE = {"provider": "OpenRouter"} + + assert config.config_get_by_key("provider", "Anthropic") == "OpenRouter" + + +def test_resolved_value_is_cached(config): + config._COMMAND_LINE = {"provider": "OpenRouter"} + first_result = config.config_get_by_key("provider") + + config._COMMAND_LINE["provider"] = "Anthropic" + second_result = config.config_get_by_key("provider") + + assert first_result == "OpenRouter" + assert second_result == "OpenRouter" + + +def test_init_config_resets_old_cache(config, tmp_path): + config._CONFIG["provider"] = "OldProvider" + config_file = tmp_path / "config.yaml" + config_file.write_text("provider: Anthropic\n", encoding="utf-8") + + config.init_config([f"config={config_file}", "provider=OpenRouter"]) + + assert config.config_get_by_key("provider") == "OpenRouter" From e5c74d3a10a4b15c463fc55d2b38be233b478f26 Mon Sep 17 00:00:00 2001 From: Totski Vjatseslav Date: Wed, 12 Aug 2026 15:46:56 +0300 Subject: [PATCH 2/2] [OMEGA-332] Cover the real YAML read in configuration loader tests --- Autotests/unit/test_config.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Autotests/unit/test_config.py b/Autotests/unit/test_config.py index 69093e7e..acb5bec5 100644 --- a/Autotests/unit/test_config.py +++ b/Autotests/unit/test_config.py @@ -86,12 +86,24 @@ def test_environment_key_without_prefix_is_ignored(config, monkeypatch): assert config.config_get_by_key("provider", "Anthropic") == "Anthropic" -def test_reads_from_config_file(config): +def test_reads_from_config_file(config, monkeypatch): + monkeypatch.delenv("OMEGACLAW_provider", raising=False) config._CONFIG_FILE = {"provider": "OpenRouter"} assert config.config_get_by_key("provider", "Anthropic") == "OpenRouter" +def test_init_config_reads_yaml_file(config, monkeypatch, tmp_path): + # Goes through the real open() and yaml.safe_load(), not an injected dict. + monkeypatch.delenv("OMEGACLAW_provider", raising=False) + config_file = tmp_path / "config.yaml" + config_file.write_text("provider: Anthropic\n", encoding="utf-8") + + config.init_config([f"config={config_file}"]) + + assert config.config_get_by_key("provider", "Fallback") == "Anthropic" + + def test_command_line_beats_environment_and_file(config, monkeypatch): config._COMMAND_LINE = {"provider": "OpenRouter"} monkeypatch.setenv("OMEGACLAW_provider", "OpenAI") @@ -125,11 +137,13 @@ def test_resolved_value_is_cached(config): assert second_result == "OpenRouter" -def test_init_config_resets_old_cache(config, tmp_path): +def test_init_config_resets_old_cache(config, monkeypatch, tmp_path): + monkeypatch.delenv("OMEGACLAW_model", raising=False) config._CONFIG["provider"] = "OldProvider" config_file = tmp_path / "config.yaml" - config_file.write_text("provider: Anthropic\n", encoding="utf-8") + config_file.write_text("provider: Anthropic\nmodel: free\n", encoding="utf-8") config.init_config([f"config={config_file}", "provider=OpenRouter"]) assert config.config_get_by_key("provider") == "OpenRouter" + assert config.config_get_by_key("model") == "free"