/
pickling
/
mcp-sourcecontrol-python
Обзор
Документация
Войти
/
pickling
/
mcp-sourcecontrol-python
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/test_config.py
140 строк
6 KB
pickling-21
Python-порт mcp-sourcecontrol: 20 инструментов, stdio и Streamable HTTP
29 июл 2026, 02:18
29 июл 2026, 02:18
bc8bde4
Код
Авторство
О чём код?
"""Порт tests/config.test.ts + конфигурационной части tests/server.test.ts.""" from __future__ import annotations import pytest from mcp_sourcecontrol.config import ( DEFAULT_TENANT_ID, build_api_url, resolve_config, resolve_session_config, resolve_tenant_id, ) from tests.conftest import TEST_CONFIG TEST_TENANTS = [ {"name": "ci", "uuid": "uuid-ci", "instance": "api.sc-ci.sber.ru", "context": "/sc"}, {"name": "cd", "uuid": "uuid-cd", "instance": "api.sc-cd.sber.ru", "context": "/sccd"}, {"name": "gs", "uuid": "uuid-gs", "instance": "api.sc-ci-gs.sberbank.ru", "context": "/scgs"}, ] class TestBuildApiUrl: def test_returns_unchanged_if_already_api_format(self, no_tenants): assert build_api_url("https://api.sc-ci.sber.ru/sc/api/v3") == "https://api.sc-ci.sber.ru/sc/api/v3" assert build_api_url("https://api.sc-cd.sber.ru/sccd/api/v3") == "https://api.sc-cd.sber.ru/sccd/api/v3" def test_builds_ci_url_from_tenants_array_format(self, tenants_file): tenants_file(TEST_TENANTS) assert build_api_url("https://sc-ci.sber.ru") == "https://api.sc-ci.sber.ru/sc/api/v3" def test_builds_cd_url_from_tenants_array_format(self, tenants_file): tenants_file(TEST_TENANTS) assert build_api_url("https://sc-cd.sber.ru") == "https://api.sc-cd.sber.ru/sccd/api/v3" def test_builds_cd_url_from_tenants_object_format(self, tenants_file): tenants_file({"tenants": TEST_TENANTS}) assert build_api_url("https://sc-cd.sber.ru") == "https://api.sc-cd.sber.ru/sccd/api/v3" def test_falls_back_to_prefix_based_url_without_tenants(self, no_tenants): assert build_api_url("https://sc-ci.sber.ru") == "https://api.sc-ci.sber.ru/sc/api/v3" assert build_api_url("https://sc-cd.sber.ru") == "https://api.sc-cd.sber.ru/sccd/api/v3" def test_fallback_handles_domain_already_prefixed_with_api(self, no_tenants): # Исправление краевого случая TS-версии: без tenants.json домен api.* не должен удваиваться assert build_api_url("https://api.sc-cd.sber.ru") == "https://api.sc-cd.sber.ru/sccd/api/v3" def test_fallback_gs_context(self, no_tenants): assert build_api_url("https://sc-ci-gs.sberbank.ru") == "https://api.sc-ci-gs.sberbank.ru/scgs/api/v3" class TestResolveTenantId: def test_hardcoded_fallback_without_tenants(self, no_tenants): assert resolve_tenant_id("https://sc-ci.sber.ru") == DEFAULT_TENANT_ID def test_resolves_ci_tenant_array_format(self, tenants_file): tenants_file(TEST_TENANTS) assert resolve_tenant_id("https://sc-ci.sber.ru") == "uuid-ci" def test_resolves_cd_tenant_array_format(self, tenants_file): tenants_file(TEST_TENANTS) assert resolve_tenant_id("https://sc-cd.sber.ru") == "uuid-cd" def test_resolves_tenant_object_format(self, tenants_file): tenants_file({"tenants": TEST_TENANTS}) assert resolve_tenant_id("https://sc-cd.sber.ru") == "uuid-cd" def test_resolves_tenant_by_full_api_url(self, tenants_file): tenants_file(TEST_TENANTS) assert resolve_tenant_id("https://api.sc-ci.sber.ru/sc/api/v3") == "uuid-ci" def test_falls_back_to_first_tenant_for_unknown_domain(self, tenants_file): tenants_file(TEST_TENANTS) assert resolve_tenant_id("https://unknown.example.com") == "uuid-ci" def test_hardcoded_fallback_on_malformed_tenants(self, tenants_file): tenants_file("{broken json") assert resolve_tenant_id("https://sc-ci.sber.ru") == DEFAULT_TENANT_ID class TestResolveSessionConfig: def test_returns_default_without_headers(self, no_tenants): assert resolve_session_config({}, TEST_CONFIG) is TEST_CONFIG def test_overrides_url_from_header(self, tenants_file): tenants_file(TEST_TENANTS) config = resolve_session_config({"x-sc-url": "https://sc-cd.sber.ru"}, TEST_CONFIG) assert config.api_url == "https://api.sc-cd.sber.ru/sccd/api/v3" assert config.tenant_id == "uuid-cd" assert config.token == TEST_CONFIG.token # токен сохраняется def test_overrides_token_from_header(self, no_tenants): config = resolve_session_config({"x-sc-token": "header-token"}, TEST_CONFIG) assert config.token == "header-token" assert config.api_url == TEST_CONFIG.api_url def test_headers_are_case_insensitive(self, no_tenants): config = resolve_session_config({"X-SC-Token": "header-token"}, TEST_CONFIG) assert config.token == "header-token" def test_overrides_both(self, tenants_file): tenants_file(TEST_TENANTS) headers = {"x-sc-url": "https://sc-cd.sber.ru", "x-sc-token": "cd-token"} config = resolve_session_config(headers, TEST_CONFIG) assert config.api_url == "https://api.sc-cd.sber.ru/sccd/api/v3" assert config.token == "cd-token" class TestResolveConfig: def test_reads_env(self, no_tenants, monkeypatch): monkeypatch.setenv("SC_API_URL", "https://sc-ci.sber.ru") monkeypatch.setenv("SC_TOKEN", "my-token") monkeypatch.setenv("SC_LOG_LEVEL", "debug") config = resolve_config() assert config.api_url == "https://api.sc-ci.sber.ru/sc/api/v3" assert config.token == "my-token" assert config.log_level == "debug" def test_falls_back_to_bitbucket_token(self, no_tenants, monkeypatch): monkeypatch.delenv("SC_TOKEN", raising=False) monkeypatch.setenv("BITBUCKET_TOKEN", "bb-token") assert resolve_config().token == "bb-token" def test_invalid_log_level_falls_back_to_info(self, no_tenants, monkeypatch): monkeypatch.setenv("SC_LOG_LEVEL", "verbose") assert resolve_config().log_level == "info" @pytest.mark.parametrize(("raw", "expected"), [("false", False), ("true", True), ("1", True)]) def test_tls_flag(self, no_tenants, monkeypatch, raw, expected): monkeypatch.setenv("SC_TLS_REJECT_UNAUTHORIZED", raw) assert resolve_config().tls_reject_unauthorized is expected def test_defaults(self, no_tenants, monkeypatch): for var in ("SC_API_URL", "SC_TOKEN", "BITBUCKET_TOKEN", "SC_LOG_LEVEL", "SC_TLS_REJECT_UNAUTHORIZED"): monkeypatch.delenv(var, raising=False) config = resolve_config() assert config.api_url == "https://api.sc-ci.sber.ru/sc/api/v3" assert config.token is None assert config.log_level == "info" assert config.tls_reject_unauthorized is False