import argparse import copy import hashlib import json from pathlib import Path import pytest from ops import detect_vps_gcp_source_drift as detector def manifest(*, row_count: int = 3, rowset_md5: str = "1" * 32) -> dict: singleton = {kind: {"kind": kind, "items": []} for kind in detector.SINGLETON_KINDS if kind != "identity"} singleton["identity"] = { "kind": "identity", "database": "teleo", "transaction_read_only": "on", "server_version_num": 160000, "server_address": "10.0.0.1", "server_port": 5432, "ssl": True, "ssl_version": "TLSv1.3", } return { "singleton": singleton, "tables": { "public.claims": { "kind": "table", "schema": "public", "table": "claims", "row_count": row_count, "rowset_md5": rowset_md5, } }, "performance": {}, } def observation(label: str, value: dict | None = None) -> dict: selected = copy.deepcopy(value or manifest()) return { "schema": detector.OBSERVATION_SCHEMA, "label": label, "status": "observed_current", "observed_at_utc": "2026-07-15T20:00:00Z", "route": { "hostname": f"{label}-host", "service": f"{label}.service", "runtime_commit": "a" * 40, "expected_database": "teleo", }, "database_identity": selected["singleton"]["identity"], "fingerprint": detector.manifest_fingerprint(selected), "manifest": selected, "cleanup": {"remote_files_created": False, "local_temp_files_created": False}, } def test_identical_current_observations_pass() -> None: receipt = detector.evaluate_observations( observation("vps"), observation("gcp"), generated_at_utc="2026-07-15T20:01:00Z", ) assert receipt["status"] == "identical" assert receipt["comparison"]["state"] == "identical" assert receipt["fallback_used"] is False assert receipt["historical_receipt_substituted"] is False assert receipt["database_mutated"] is False assert "manifest" not in receipt["observations"]["vps"] def test_content_drift_fails_and_names_exact_table_mismatch() -> None: gcp_manifest = manifest(row_count=4, rowset_md5="2" * 32) receipt = detector.evaluate_observations(observation("vps"), observation("gcp", gcp_manifest)) assert receipt["status"] == "drift" assert receipt["comparison"]["content_identical"] is False assert "table_content_mismatches=1" in receipt["comparison"]["problems"] assert receipt["comparison"]["details"]["table_mismatches"] == [ { "table": "public.claims", "mismatch": { "row_count": {"source": 3, "target": 4}, "rowset_md5": {"source": "1" * 32, "target": "2" * 32}, }, } ] def test_unreachable_gcp_is_incomplete_without_vps_substitution() -> None: gcp = { "schema": detector.OBSERVATION_SCHEMA, "label": "gcp", "status": "unreachable", "failure_class": "probe_timeout", "error": "gcp probe exceeded 30s", "manifest": None, "route": None, } receipt = detector.evaluate_observations(observation("vps"), gcp) assert receipt["status"] == "incomplete" assert receipt["unavailable_targets"] == ["gcp"] assert receipt["comparison"] is None assert receipt["observations"]["gcp"]["route"] is None assert receipt["observations"]["gcp"] != receipt["observations"]["vps"] assert receipt["fallback_used"] is False assert receipt["historical_receipt_substituted"] is False def test_probe_timeout_preserves_exact_expected_target(monkeypatch: pytest.MonkeyPatch) -> None: expected = { "transport": "teleo-gcp-staging", "database_endpoint": "10.61.0.3:5432", "database": "teleo_canonical", } def timeout(*args, **kwargs): raise detector.subprocess.TimeoutExpired(args[0], kwargs["timeout"]) monkeypatch.setattr(detector.subprocess, "run", timeout) result = detector.collect_endpoint( label="gcp", command=["ssh", "teleo-gcp-staging", "--", "true"], manifest_sql=b"select 1", timeout=30, expected_target=expected, ) assert result["status"] == "unreachable" assert result["failure_class"] == "probe_timeout" assert result["expected_target"] == expected assert result["route"] is None def test_parser_rejects_non_readonly_or_wrong_database(monkeypatch: pytest.MonkeyPatch) -> None: selected = manifest() lines = [json.dumps(row) for row in selected["singleton"].values()] lines.extend(json.dumps(row) for row in selected["tables"].values()) route = { "runtime_commit": "a" * 40, "expected_database": "different", } stdout = (detector.ROUTE_PREFIX + json.dumps(route) + "\n" + "\n".join(lines)).encode() monkeypatch.setattr( detector.subprocess, "run", lambda *args, **kwargs: detector.subprocess.CompletedProcess(args[0], 0, stdout, b""), ) result = detector.collect_endpoint( label="gcp", command=["ssh", "target", "--", "true"], manifest_sql=b"select 1", timeout=30, expected_target={"database_endpoint": "10.61.0.3:5432", "database": "different"}, ) assert result["status"] == "invalid" assert result["failure_class"] == "invalid_probe_receipt" assert "does not match explicit target" in result["error"] def test_live_runs_both_independent_collectors_and_returns_incomplete(tmp_path: Path) -> None: manifest_path = tmp_path / "manifest.sql" manifest_bytes = b"reviewed manifest" manifest_path.write_bytes(manifest_bytes) key = tmp_path / "key" key.write_text("not-a-real-key") called = [] def fake_collector(**kwargs): called.append(kwargs["label"]) if kwargs["label"] == "vps": return observation("vps") return { "schema": detector.OBSERVATION_SCHEMA, "label": "gcp", "status": "unreachable", "failure_class": "transport_or_remote_probe_failed", "error": "target unavailable", "manifest": None, "route": None, } monkeypatch = pytest.MonkeyPatch() monkeypatch.setattr(detector, "REVIEWED_MANIFEST_SQL_SHA256", hashlib.sha256(manifest_bytes).hexdigest()) args = argparse.Namespace( output=tmp_path / "output.json", manifest=manifest_path, connect_timeout=3, probe_timeout=30, vps_ssh_target="root@127.0.0.1", vps_ssh_key=key, vps_container="teleo-pg", vps_database="teleo", vps_database_user="postgres", vps_service="leoclean-gateway.service", gcp_ssh_target="teleo-gcp-staging", gcp_host="10.61.0.3", gcp_database="teleo_restore", gcp_database_user="postgres", gcp_project="teleo-501523", gcp_secret="gcp-teleo-pgvector-standby-postgres-password", gcp_service="leoclean-gcp-prod-parallel.service", ) try: receipt, exit_code = detector.run_live(args, collector=fake_collector) finally: monkeypatch.undo() assert sorted(called) == ["gcp", "vps"] assert receipt["status"] == "incomplete" assert receipt["manifest_sql_sha256"] == hashlib.sha256(manifest_bytes).hexdigest() assert exit_code == 2 def test_sanitizer_redacts_connection_secrets() -> None: error = detector.sanitize_error( "fatal password=hunter2 postgresql://user:pw@db.internal/teleo", target="db.internal", ) assert "hunter2" not in error assert "user:pw" not in error assert "[REDACTED]" in error