| """ |
| Tests for the dataset_get_integration_plan MCP tool (ADR-0001 T4). |
| |
| The tool is a thin agent-side wrapper over biodata_registry.get_integration_plan, |
| re-exposed through src/datasets/registry.py. These tests confirm it is registered |
| on dataset_mcp, delegates unchanged to the registry, returns the full plan |
| contract, forwards the optional contrast args to the confound gate, and degrades |
| to an error dict on unknown ids. Pure metadata — no network, no data loading. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import asyncio |
| import sys |
| from pathlib import Path |
|
|
| sys.path.insert(0, str(Path(__file__).parent.parent)) |
|
|
| import biodata_registry as bdr |
|
|
| from src.datasets.registry import get_integration_plan |
| from src.tools import dataset_tools |
| from src.tools.dataset_tools import dataset_get_integration_plan |
|
|
| PLAN_KEYS = { |
| "mode", |
| "reason", |
| "shared_feature_space", |
| "requires_ortholog_mapping", |
| "requires_probe_collapse", |
| "batch_key", |
| "poolable_data_level", |
| "per_dataset", |
| "refusal_rules_triggered", |
| } |
|
|
|
|
| def test_tool_registered_on_dataset_mcp(): |
| """The wrapper is discoverable as an MCP tool, like the other dataset tools.""" |
| tools = asyncio.run(dataset_tools.dataset_mcp.list_tools()) |
| names = {t.name for t in tools} |
| assert "dataset_get_integration_plan" in names |
|
|
|
|
| def test_known_raw_counts_pair_is_early(): |
| """Two raw_counts RNA-seq cohorts pool early; the full contract is returned.""" |
| plan = dataset_get_integration_plan(["paca_au_rnaseq", "tcga_paad"]) |
| assert set(plan) >= PLAN_KEYS |
| assert plan["mode"] == "early" |
| assert plan["poolable_data_level"] == "raw_counts" |
| assert plan["batch_key"] == "dataset_id" |
| assert plan["reason"] |
| assert plan["refusal_rules_triggered"] == [] |
|
|
|
|
| def test_mixed_levels_fall_back_to_late(): |
| """Microarray (log_expression) + RNA-seq (raw_counts) must NOT pool -> late.""" |
| plan = dataset_get_integration_plan(["gse71729_moffitt", "tcga_paad"]) |
| assert plan["mode"] == "late" |
| assert plan["reason"] |
|
|
|
|
| def test_single_dataset_refuses_not_multi(): |
| plan = dataset_get_integration_plan(["tcga_paad"]) |
| assert plan["mode"] == "refuse" |
| assert "NOT_MULTI" in plan["refusal_rules_triggered"] |
|
|
|
|
| def test_unknown_dataset_returns_error_dict(): |
| """Unknown ids degrade to an error dict (mirrors dataset_describe), not a raise.""" |
| plan = dataset_get_integration_plan(["tcga_paad", "nope_not_real"]) |
| assert "error" in plan |
| assert "available_datasets" in plan |
| assert "nope_not_real" in plan["error"] |
|
|
|
|
| def test_contrast_args_reach_confound_gate(): |
| """A contrast no cohort can express forwards to Gate 6 -> CONFOUNDED_DESIGN.""" |
| plan = dataset_get_integration_plan( |
| ["paca_au_rnaseq", "tcga_paad"], |
| design_factor="tumor_subtype", |
| test_group="a", |
| control_group="b", |
| ) |
| assert plan["mode"] == "refuse" |
| assert "CONFOUNDED_DESIGN" in plan["refusal_rules_triggered"] |
|
|
|
|
| def test_registry_passthrough_is_thin(): |
| """src.datasets.registry.get_integration_plan delegates unchanged to the package.""" |
| pair = ["paca_au_rnaseq", "tcga_paad"] |
| assert get_integration_plan(pair) == bdr.get_integration_plan(pair) |
|
|