from pathlib import Path from genesis.config import Settings FIXTURES = Path(__file__).parent / "fixtures" def test_from_dir_maps_yaml_fields(): s = Settings.from_dir(FIXTURES) assert s.app.server.max_upload_mb == 10 assert s.app.session["sqlite_path"] == "C:/tmp/genesis.db" assert s.app.task_queue["timeout_sec"] == 300 assert s.inference.models.primary.name == "deepseek-chat" assert s.inference.llm_calls.max_context_tokens == 16000 assert s.inference.structured_output.max_parse_retry == 3 assert s.rag.embedding.model == "BAAI/bge-small-zh-v1.5" assert s.rag.retrieval.rrf_k == 42 def test_defaults_when_dir_empty(tmp_path): s = Settings.from_dir(tmp_path) assert s.app.name == "genesis" assert s.app.server.max_upload_mb == 100 assert s.app.task_queue["backend"] == "memory" assert s.inference.models.primary.name == "deepseek-chat" assert s.rag.embedding.model == "BAAI/bge-small-zh-v1.5" assert s.rag.retrieval.rrf_k == 60 def test_env_override_yaml(monkeypatch): monkeypatch.setenv("GENESIS_APP__SERVER__MAX_UPLOAD_MB", "25") s = Settings.from_dir(FIXTURES) assert s.app.server.max_upload_mb == 25 def test_env_create_missing_key(monkeypatch): monkeypatch.setenv("GENESIS_RAG__RETRIEVAL__DEFAULT_TOP_K", "7") s = Settings.from_dir(FIXTURES) assert s.rag.retrieval.default_top_k == 7 def test_env_placeholder_expansion(monkeypatch): monkeypatch.setenv("QDRANT_API_KEY", "sk-test-xyz") s = Settings.from_dir(FIXTURES) assert s.rag.vector_store.qdrant.api_key == "sk-test-xyz" def test_redacted_hides_secrets(): s = Settings.from_dir(FIXTURES) red = s.get_redacted() assert red["rag"]["vector_store"]["qdrant"]["api_key"] == "***" def test_expand_env_list_branch(monkeypatch): # _expand_env 的 list 分支(L134):列表项递归展开环境占位 from genesis.config import _expand_env monkeypatch.setenv("QDRANT_API_KEY", "sk-list-xyz") data = {"models": [{"name": "a", "key": "${QDRANT_API_KEY}"}, "plain"]} out = _expand_env(data) assert out["models"][0]["key"] == "sk-list-xyz" assert out["models"][1] == "plain"