"""Tests for openjarvis.optimize.search_space module.""" from __future__ import annotations from openjarvis.learning.optimize.search_space import ( DEFAULT_SEARCH_SPACE, build_search_space, ) from openjarvis.learning.optimize.types import SearchSpace # --------------------------------------------------------------------------- # build_search_space # --------------------------------------------------------------------------- class TestBuildSearchSpace: """Tests for the build_search_space() factory function.""" def test_basic_build(self) -> None: config = { "optimize": { "search": [ { "name": "agent.type", "type": "categorical", "values": [ "orchestrator", "native_react", ], "description": "Agent architecture", }, ], "fixed": { "engine": "ollama", "model": "qwen3:8b", }, "constraints": { "rules": [ "SimpleAgent should only have max_turns = 1", ], }, }, } space = build_search_space(config) assert isinstance(space, SearchSpace) assert len(space.dimensions) == 1 dim = space.dimensions[0] assert dim.name == "agent.type" assert dim.dim_type == "categorical" assert dim.values == ["orchestrator", "native_react"] assert dim.description == "Agent architecture" assert dim.primitive == "agent" def test_fixed_params_preserved(self) -> None: config = { "optimize": { "search": [], "fixed": { "engine": "ollama", "model": "qwen3:8b", }, }, } space = build_search_space(config) assert space.fixed == { "engine": "ollama", "model": "qwen3:8b", } def test_constraints_parsed(self) -> None: config = { "optimize": { "search": [], "constraints": { "rules": [ "max_turns must be >= 1", "temperature should be <= 1.0", ], }, }, } space = build_search_space(config) assert len(space.constraints) == 2 assert "max_turns must be >= 1" in space.constraints assert "temperature should be <= 1.0" in space.constraints def test_continuous_dimension_build(self) -> None: config = { "optimize": { "search": [ { "name": "intelligence.temperature", "type": "continuous", "low": 0.0, "high": 1.0, "description": "Generation temperature", }, ], }, } space = build_search_space(config) dim = space.dimensions[0] assert dim.dim_type == "continuous" assert dim.low == 0.0 assert dim.high == 1.0 assert dim.primitive == "intelligence" def test_integer_dimension_build(self) -> None: config = { "optimize": { "search": [ { "name": "agent.max_turns", "type": "integer", "low": 1, "high": 30, }, ], }, } space = build_search_space(config) dim = space.dimensions[0] assert dim.dim_type == "integer" assert dim.low == 1 assert dim.high == 30 def test_subset_dimension_build(self) -> None: config = { "optimize": { "search": [ { "name": "tools.tool_set", "type": "subset", "values": [ "calculator", "think", "web_search", ], }, ], }, } space = build_search_space(config) dim = space.dimensions[0] assert dim.dim_type == "subset" assert dim.values == [ "calculator", "think", "web_search", ] assert dim.primitive == "tools" def test_text_dimension_build(self) -> None: config = { "optimize": { "search": [ { "name": "intelligence.system_prompt", "type": "text", "description": "System prompt", }, ], }, } space = build_search_space(config) dim = space.dimensions[0] assert dim.dim_type == "text" assert dim.values == [] assert dim.primitive == "intelligence" def test_multiple_dimensions(self) -> None: config = { "optimize": { "search": [ { "name": "agent.type", "type": "categorical", "values": ["simple"], }, { "name": "intelligence.temperature", "type": "continuous", "low": 0.0, "high": 1.0, }, { "name": "tools.tool_set", "type": "subset", "values": ["calculator"], }, ], }, } space = build_search_space(config) assert len(space.dimensions) == 3 def test_empty_config(self) -> None: space = build_search_space({}) assert space.dimensions == [] assert space.fixed == {} assert space.constraints == [] def test_empty_optimize_section(self) -> None: space = build_search_space({"optimize": {}}) assert space.dimensions == [] assert space.fixed == {} assert space.constraints == [] def test_primitive_inferred_from_name(self) -> None: config = { "optimize": { "search": [ { "name": "learning.routing_policy", "type": "categorical", "values": ["grpo"], }, { "name": "engine.backend", "type": "categorical", "values": ["ollama"], }, ], }, } space = build_search_space(config) assert space.dimensions[0].primitive == "learning" assert space.dimensions[1].primitive == "engine" def test_no_dot_in_name_gives_empty_primitive(self) -> None: config = { "optimize": { "search": [ { "name": "standalone", "type": "categorical", "values": ["a"], }, ], }, } space = build_search_space(config) assert space.dimensions[0].primitive == "" def test_missing_description_defaults_empty(self) -> None: config = { "optimize": { "search": [ { "name": "agent.type", "type": "categorical", "values": ["simple"], }, ], }, } space = build_search_space(config) assert space.dimensions[0].description == "" def test_missing_values_defaults_empty_list(self) -> None: config = { "optimize": { "search": [ { "name": "agent.type", "type": "categorical", }, ], }, } space = build_search_space(config) assert space.dimensions[0].values == [] def test_missing_constraints_section(self) -> None: config = { "optimize": { "search": [ { "name": "a.b", "type": "categorical", "values": ["x"], }, ], "fixed": {"k": "v"}, }, } space = build_search_space(config) assert space.constraints == [] # --------------------------------------------------------------------------- # DEFAULT_SEARCH_SPACE # --------------------------------------------------------------------------- _DIMS = DEFAULT_SEARCH_SPACE.dimensions def _find_dim(name: str): """Helper to find a dimension by name.""" return next(d for d in _DIMS if d.name == name) class TestDefaultSearchSpace: """Tests for the DEFAULT_SEARCH_SPACE module-level constant.""" def test_is_search_space(self) -> None: assert isinstance(DEFAULT_SEARCH_SPACE, SearchSpace) def test_has_all_five_primitives(self) -> None: primitives = {dim.primitive for dim in _DIMS} assert "intelligence" in primitives assert "engine" in primitives assert "agent" in primitives assert "tools" in primitives assert "learning" in primitives def test_intelligence_dimensions(self) -> None: intel_dims = [d for d in _DIMS if d.primitive == "intelligence"] intel_names = {d.name for d in intel_dims} assert "intelligence.model" in intel_names assert "intelligence.temperature" in intel_names assert "intelligence.max_tokens" in intel_names assert "intelligence.top_p" in intel_names assert "intelligence.system_prompt" in intel_names def test_intelligence_model_is_categorical(self) -> None: dim = _find_dim("intelligence.model") assert dim.dim_type == "categorical" assert len(dim.values) > 0 def test_intelligence_temperature_range(self) -> None: dim = _find_dim("intelligence.temperature") assert dim.dim_type == "continuous" assert dim.low == 0.0 assert dim.high == 1.0 def test_intelligence_max_tokens_range(self) -> None: dim = _find_dim("intelligence.max_tokens") assert dim.dim_type == "integer" assert dim.low == 256 assert dim.high == 8192 def test_intelligence_system_prompt_is_text(self) -> None: dim = _find_dim("intelligence.system_prompt") assert dim.dim_type == "text" def test_engine_backend_options(self) -> None: dim = _find_dim("engine.backend") assert dim.dim_type == "categorical" expected = { "ollama", "vllm", "sglang", "llamacpp", "mlx", "lmstudio", "exo", "nexa", "uzu", "apple_fm", } assert set(dim.values) == expected def test_agent_type_options(self) -> None: dim = _find_dim("agent.type") assert dim.dim_type == "categorical" expected = { "simple", "orchestrator", "native_react", "native_openhands", } assert set(dim.values) == expected def test_agent_max_turns_range(self) -> None: dim = _find_dim("agent.max_turns") assert dim.dim_type == "integer" assert dim.low == 1 assert dim.high == 30 def test_tools_tool_set_is_subset(self) -> None: dim = _find_dim("tools.tool_set") assert dim.dim_type == "subset" assert "calculator" in dim.values assert "think" in dim.values def test_learning_routing_policy(self) -> None: dim = _find_dim("learning.routing_policy") assert dim.dim_type == "categorical" expected = {"heuristic", "grpo", "bandit", "learned"} assert set(dim.values) == expected def test_has_constraints(self) -> None: assert len(DEFAULT_SEARCH_SPACE.constraints) > 0 def test_all_dimensions_have_descriptions(self) -> None: for dim in _DIMS: assert dim.description != "", f"Dimension {dim.name} has no description" def test_all_dimensions_have_primitives(self) -> None: for dim in _DIMS: assert dim.primitive != "", f"Dimension {dim.name} has no primitive" # --------------------------------------------------------------------------- # to_prompt_description rendering # --------------------------------------------------------------------------- class TestToPromptDescription: """Tests for SearchSpace.to_prompt_description().""" def test_default_space_renders(self) -> None: desc = DEFAULT_SEARCH_SPACE.to_prompt_description() assert isinstance(desc, str) assert len(desc) > 100 def test_all_dimensions_appear_in_description(self) -> None: desc = DEFAULT_SEARCH_SPACE.to_prompt_description() for dim in _DIMS: assert dim.name in desc, f"Dimension {dim.name} not in description" def test_all_primitive_headers_in_description(self) -> None: desc = DEFAULT_SEARCH_SPACE.to_prompt_description() for primitive in ( "Intelligence", "Engine", "Agent", "Tools", "Learning", ): assert f"## {primitive}" in desc, ( f"Primitive header {primitive} not in description" ) def test_constraints_in_description(self) -> None: desc = DEFAULT_SEARCH_SPACE.to_prompt_description() assert "## Constraints" in desc for constraint in DEFAULT_SEARCH_SPACE.constraints: assert constraint in desc def test_empty_space_renders(self) -> None: space = SearchSpace() desc = space.to_prompt_description() assert "# Search Space" in desc assert "## Fixed Parameters" not in desc assert "## Constraints" not in desc