Skip to main content
Glama
test_catalog_service_offline.py6.7 kB
"""Offline tests that exercise catalog services and tools using fixtures.""" from __future__ import annotations import json from pathlib import Path from types import SimpleNamespace import pytest from igloo_mcp.catalog.catalog_service import CatalogService from igloo_mcp.config import Config, SnowflakeConfig from igloo_mcp.mcp.tools.build_catalog import BuildCatalogTool from igloo_mcp.mcp.tools.get_catalog_summary import GetCatalogSummaryTool from igloo_mcp.snow_cli import SnowCLIError from tests.helpers.fixture_snow_cli import FixtureSnowCLI FIXTURE_DIR = Path(__file__).parent / "fixtures" / "snowflake_cli" def _catalog_service_with_fixture_cli( *, raise_on: dict[str, Exception] | None = None, ) -> CatalogService: service = CatalogService(context=None) service.cli = FixtureSnowCLI(FIXTURE_DIR, raise_on=raise_on) return service def test_catalog_service_build_with_fixtures(tmp_path: Path) -> None: service = _catalog_service_with_fixture_cli() output_dir = tmp_path / "catalog" result = service.build(output_dir=str(output_dir), database="ANALYTICS") assert result.success is True assert result.output_dir == str(output_dir) assert result.totals.databases == 1 assert result.totals.schemas == 2 assert result.totals.tables == 3 assert result.totals.views == 1 assert result.totals.materialized_views == 0 assert result.totals.dynamic_tables == 0 assert result.totals.tasks == 1 assert result.totals.functions == 2 assert result.totals.procedures == 1 assert result.totals.columns == 3 catalog_file = output_dir / "catalog.json" summary_file = output_dir / "catalog_summary.json" assert catalog_file.exists() assert summary_file.exists() summary = json.loads(summary_file.read_text(encoding="utf-8")) assert summary["totals"]["tables"] == 3 assert summary["format"] == "json" def test_catalog_service_build_handles_cli_error(tmp_path: Path) -> None: service = _catalog_service_with_fixture_cli( raise_on={"SHOW TABLES": SnowCLIError("simulated failure")} ) output_dir = tmp_path / "catalog" result = service.build(output_dir=str(output_dir)) # Failures inside _build_real_catalog are logged and produce empty totals. assert result.success is True assert result.totals.tables == 0 summary_file = output_dir / "catalog_summary.json" assert summary_file.exists() summary = json.loads(summary_file.read_text(encoding="utf-8")) assert summary["totals"]["tables"] == 0 def test_catalog_service_build_account_scope_jsonl(tmp_path: Path) -> None: service = CatalogService(context=None) class StubCLI: def __init__(self): self.calls: list[str] = [] def run_query(self, query: str, output_format: str | None = None): self.calls.append(query.strip()) if "DATABASES" in query: rows = [{"name": "DB1"}, {"name": "DB2"}] elif "SCHEMAS" in query: rows = [{"schema": "PUBLIC"}] elif "TABLES" in query: rows = [{"table": "T1"}, {"table": "T2"}, {"table": "T3"}] elif "FUNCTIONS" in query: rows = [{"function_name": "F1"}] elif "COLUMNS" in query: rows = [{"column_name": "C1"}] else: rows = [{"value": query.strip()}] return SimpleNamespace(rows=rows) stub_cli = StubCLI() service.cli = stub_cli # type: ignore[assignment] output_dir = tmp_path / "acct" result = service.build( output_dir=str(output_dir), account_scope=True, output_format="jsonl", ) assert result.success is True assert result.totals.databases == 2 assert result.totals.tables == 3 assert output_dir.joinpath("catalog.jsonl").exists() assert "SHOW DATABASES" in stub_cli.calls[0] assert any("FUNCTIONS" in call for call in stub_cli.calls) def test_catalog_service_build_handles_write_failure( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: service = _catalog_service_with_fixture_cli() output_dir = tmp_path / "catalog" original_open = open def fail_open(path, *args, **kwargs): if getattr(path, "name", str(path)).endswith("catalog_summary.json"): raise OSError("disk full") return original_open(path, *args, **kwargs) monkeypatch.setattr("builtins.open", fail_open, raising=False) result = service.build(output_dir=str(output_dir)) assert result.success is False assert result.error == "disk full" @pytest.mark.anyio async def test_build_catalog_tool_execute_with_fixtures(tmp_path: Path) -> None: service = _catalog_service_with_fixture_cli() config = Config(snowflake=SnowflakeConfig(profile="TEST")) tool = BuildCatalogTool(config=config, catalog_service=service) output_dir = tmp_path / "tool_catalog" result = await tool.execute( output_dir=str(output_dir), database="ANALYTICS", account=False, output_format="json", ) assert result["status"] == "success" assert result["output_dir"] == str(output_dir) assert result["totals"]["tables"] == 3 assert output_dir.joinpath("catalog_summary.json").exists() @pytest.mark.anyio async def test_get_catalog_summary_tool_success(tmp_path: Path) -> None: service = _catalog_service_with_fixture_cli() output_dir = tmp_path / "catalog" service.build(output_dir=str(output_dir), database="ANALYTICS") tool = GetCatalogSummaryTool(catalog_service=service) result = await tool.execute(catalog_dir=str(output_dir)) assert result["status"] == "success" assert result["summary"]["totals"]["tables"] == 3 assert result["summary"]["format"] == "json" @pytest.mark.anyio async def test_get_catalog_summary_tool_missing_directory(tmp_path: Path) -> None: service = _catalog_service_with_fixture_cli() tool = GetCatalogSummaryTool(catalog_service=service) missing_dir = tmp_path / "missing" result = await tool.execute(catalog_dir=str(missing_dir)) assert result["status"] == "error" assert "No catalog found" in result["error"] def test_load_summary_missing_directory(tmp_path: Path) -> None: service = CatalogService(context=None) with pytest.raises(FileNotFoundError): service.load_summary(str(tmp_path / "missing")) def test_load_summary_missing_file(tmp_path: Path) -> None: service = CatalogService(context=None) catalog_dir = tmp_path / "catalog" catalog_dir.mkdir() with pytest.raises(FileNotFoundError): service.load_summary(str(catalog_dir))

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Evan-Kim2028/igloo-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server