tenseleyflow/sway / 9cb6226

Browse files

tests/integration: dlm public-surface compat regression (F06)

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
9cb6226f3ba424a651a062cb459c351744c04d3a
Parents
aecbf38
Tree
f62ca74

1 changed file

StatusFile+-
A tests/integration/test_dlm_api_compat.py 102 0
tests/integration/test_dlm_api_compat.pyadded
@@ -0,0 +1,102 @@
1
+"""Integration test: dlm public surface compatibility (F06).
2
+
3
+Asserts the contract sway's resolver depends on against a real
4
+installed ``dlm`` — every entry in dlm's built-in base-model registry
5
+must ``resolve()`` to an object carrying an ``hf_id`` attribute. Catches
6
+the ``.hf_id`` → ``.repo_id`` rename (or any equivalent) before a user
7
+hits it via ``sway autogen``.
8
+
9
+Runs under ``slow + online + dlm-extra``. Skipped cleanly when the
10
+``dlm`` extra isn't installed (so `pytest tests/integration` on a
11
+no-extras runner still works).
12
+"""
13
+
14
+from __future__ import annotations
15
+
16
+import pytest
17
+
18
+pytestmark = [pytest.mark.slow, pytest.mark.online]
19
+
20
+
21
+dlm_base_models = pytest.importorskip(
22
+    "dlm.base_models",
23
+    reason="dlm extra not installed (pip install 'dlm-sway[dlm]')",
24
+)
25
+
26
+
27
+def _iter_registry_keys() -> list[str]:
28
+    """Return every registry key dlm exposes.
29
+
30
+    dlm's API surface for enumerating the registry has moved around
31
+    (``list_bases``, ``registry.keys()``, ``iter_registered``). Try
32
+    the known shapes; if none work, yield the canonical keys hard-coded
33
+    in the sway CLAUDE.md so the test still runs against a stable
34
+    floor. Failure mode: zero keys → test is asserting nothing → fail
35
+    loudly in ``test_registry_nonempty``.
36
+    """
37
+    for accessor in ("list_bases", "registered_bases", "list_registered"):
38
+        fn = getattr(dlm_base_models, accessor, None)
39
+        if callable(fn):
40
+            return list(fn())
41
+    registry = getattr(dlm_base_models, "REGISTRY", None) or getattr(
42
+        dlm_base_models, "registry", None
43
+    )
44
+    if registry is not None and hasattr(registry, "keys"):
45
+        return list(registry.keys())
46
+    # Floor: keys the sway CLAUDE.md documents as shipped by dlm.
47
+    return [
48
+        "qwen2.5-0.5b",
49
+        "qwen2.5-1.5b",
50
+        "qwen2.5-3b",
51
+        "qwen2.5-coder-1.5b",
52
+        "llama-3.2-1b",
53
+        "llama-3.2-3b",
54
+        "smollm2-135m",
55
+        "smollm2-360m",
56
+        "smollm2-1.7b",
57
+        "phi-3.5-mini",
58
+    ]
59
+
60
+
61
+def test_registry_nonempty() -> None:
62
+    """At least one registry key exists — tests below are trivial
63
+    otherwise."""
64
+    keys = _iter_registry_keys()
65
+    assert keys, "dlm base-model registry appears empty; accessor changed?"
66
+
67
+
68
+@pytest.mark.parametrize("key", _iter_registry_keys())
69
+def test_base_resolves_with_hf_id(key: str) -> None:
70
+    """Every registry entry must resolve to an object with ``hf_id``.
71
+
72
+    sway's resolver (``integrations/dlm/resolver.py``) calls
73
+    ``dlm.base_models.resolve(key).hf_id``. A rename of that attribute
74
+    would break every autogen run; this test catches the drift at
75
+    sway's CI.
76
+    """
77
+    spec = dlm_base_models.resolve(key)
78
+    assert hasattr(spec, "hf_id"), (
79
+        f"dlm.base_models.resolve({key!r}) returned {type(spec).__name__} "
80
+        f"without .hf_id — public-surface drift. Visible attrs: "
81
+        f"{sorted(a for a in dir(spec) if not a.startswith('_'))[:8]!r}"
82
+    )
83
+    assert isinstance(spec.hf_id, str) and "/" in spec.hf_id, (
84
+        f"dlm.base_models.resolve({key!r}).hf_id = {spec.hf_id!r} — "
85
+        "not a plausible HuggingFace 'org/name' id."
86
+    )
87
+
88
+
89
+def test_sway_resolver_does_not_wrap_valid_response(monkeypatch: pytest.MonkeyPatch) -> None:
90
+    """A well-formed dlm spec passes through sway's resolver without
91
+    raising — guards against an accidentally over-strict hasattr check.
92
+    """
93
+    from dlm_sway.integrations.dlm.resolver import _resolve_base_model_to_hf_id
94
+
95
+    # Pick any key; use the smallest to keep the test fast.
96
+    keys = _iter_registry_keys()
97
+    # Prefer SmolLM 135M — it's the smallest known base and is the
98
+    # integration fixture sway already uses.
99
+    key = next((k for k in keys if "135m" in k), keys[0])
100
+
101
+    hf_id = _resolve_base_model_to_hf_id(key)
102
+    assert "/" in hf_id, f"{key!r} → {hf_id!r} (expected 'org/name')"