open-range / tests /test_registry.py
Aaron Brown
Add family registry, baseline solver suite, and hard manifest variants
b09903c
"""Tests for the family registry.
Covers:
- Loading registry from YAML
- Filtering by tag
- Filtering by difficulty range
- Looking up families by name (valid and invalid)
- Verifying all registered manifests exist and validate
"""
from __future__ import annotations
from pathlib import Path
import pytest
from open_range.registry import FamilyInfo, Registry
ROOT = Path(__file__).parent.parent
MANIFESTS_DIR = ROOT / "manifests"
REGISTRY_PATH = MANIFESTS_DIR / "registry.yaml"
# ===================================================================
# Loading
# ===================================================================
class TestRegistryLoading:
"""Registry loads correctly from YAML."""
def test_load_default_registry(self):
reg = Registry.load(REGISTRY_PATH)
assert len(reg) > 0
def test_load_returns_registry_instance(self):
reg = Registry.load(REGISTRY_PATH)
assert isinstance(reg, Registry)
def test_file_not_found_raises(self, tmp_path):
with pytest.raises(FileNotFoundError):
Registry.load(tmp_path / "nonexistent.yaml")
def test_malformed_yaml_raises(self, tmp_path):
bad = tmp_path / "bad.yaml"
bad.write_text("not_families: {}")
with pytest.raises(ValueError, match="families"):
Registry.load(bad)
def test_repr(self):
reg = Registry.load(REGISTRY_PATH)
r = repr(reg)
assert "Registry(" in r
assert "families" in r
# ===================================================================
# list_families
# ===================================================================
class TestListFamilies:
"""list_families returns all families sorted by difficulty."""
def test_returns_list(self):
reg = Registry.load(REGISTRY_PATH)
families = reg.list_families()
assert isinstance(families, list)
assert all(isinstance(f, FamilyInfo) for f in families)
def test_sorted_by_difficulty(self):
reg = Registry.load(REGISTRY_PATH)
families = reg.list_families()
difficulties = [f.difficulty for f in families]
assert difficulties == sorted(difficulties)
def test_all_families_have_required_fields(self):
reg = Registry.load(REGISTRY_PATH)
for fam in reg.list_families():
assert fam.name
assert fam.display_name
assert fam.manifest
assert fam.difficulty >= 1
# ===================================================================
# get_family
# ===================================================================
class TestGetFamily:
"""get_family looks up by registry key."""
def test_valid_name(self):
reg = Registry.load(REGISTRY_PATH)
fam = reg.get_family("tier1_basic_enterprise")
assert fam.name == "tier1_basic_enterprise"
assert fam.manifest == "tier1_basic.yaml"
def test_invalid_name_raises_key_error(self):
reg = Registry.load(REGISTRY_PATH)
with pytest.raises(KeyError, match="nonexistent"):
reg.get_family("nonexistent")
def test_contains_operator(self):
reg = Registry.load(REGISTRY_PATH)
assert "tier1_basic_enterprise" in reg
assert "nonexistent" not in reg
# ===================================================================
# filter_by_tag
# ===================================================================
class TestFilterByTag:
"""filter_by_tag returns families matching a tag."""
def test_healthcare_tag(self):
reg = Registry.load(REGISTRY_PATH)
results = reg.filter_by_tag("healthcare")
assert len(results) >= 1
for fam in results:
assert "healthcare" in [t.lower() for t in fam.tags]
def test_case_insensitive(self):
reg = Registry.load(REGISTRY_PATH)
lower = reg.filter_by_tag("healthcare")
upper = reg.filter_by_tag("Healthcare")
assert len(lower) == len(upper)
def test_nonexistent_tag_returns_empty(self):
reg = Registry.load(REGISTRY_PATH)
results = reg.filter_by_tag("zzz_nonexistent_tag")
assert results == []
def test_hard_tag(self):
reg = Registry.load(REGISTRY_PATH)
results = reg.filter_by_tag("hard")
assert len(results) >= 2
for fam in results:
assert "hard" in [t.lower() for t in fam.tags]
def test_tier_1_tag(self):
reg = Registry.load(REGISTRY_PATH)
results = reg.filter_by_tag("tier-1")
assert len(results) >= 1
# ===================================================================
# filter_by_difficulty
# ===================================================================
class TestFilterByDifficulty:
"""filter_by_difficulty returns families in a difficulty range."""
def test_difficulty_1(self):
reg = Registry.load(REGISTRY_PATH)
results = reg.filter_by_difficulty(1, 1)
assert len(results) >= 1
for fam in results:
assert fam.difficulty == 1
def test_difficulty_range(self):
reg = Registry.load(REGISTRY_PATH)
results = reg.filter_by_difficulty(1, 3)
assert len(results) >= 3 # at least tier1, tier2, tier3
for fam in results:
assert 1 <= fam.difficulty <= 3
def test_wide_range_returns_all(self):
reg = Registry.load(REGISTRY_PATH)
all_fam = reg.list_families()
wide = reg.filter_by_difficulty(1, 5)
assert len(wide) == len(all_fam)
def test_empty_range(self):
reg = Registry.load(REGISTRY_PATH)
results = reg.filter_by_difficulty(5, 5)
# May be empty if no difficulty-5 families exist
for fam in results:
assert fam.difficulty == 5
# ===================================================================
# Manifest existence and validation
# ===================================================================
class TestManifestIntegrity:
"""All registered manifests exist on disk and validate."""
def test_all_manifest_files_exist(self):
reg = Registry.load(REGISTRY_PATH)
for fam in reg.list_families():
manifest_path = MANIFESTS_DIR / fam.manifest
assert manifest_path.exists(), (
f"Family '{fam.name}' references '{fam.manifest}' "
f"but {manifest_path} does not exist"
)
def test_all_manifests_validate(self):
from manifests.schema import load_manifest
reg = Registry.load(REGISTRY_PATH)
for fam in reg.list_families():
manifest_path = MANIFESTS_DIR / fam.manifest
m = load_manifest(manifest_path)
assert m.name, f"Manifest {fam.manifest} loaded but has empty name"
assert m.tier >= 1
assert len(m.topology.hosts) >= 1
assert len(m.bug_families) >= 1
def test_learning_goals_non_empty(self):
reg = Registry.load(REGISTRY_PATH)
for fam in reg.list_families():
assert len(fam.learning_goals) >= 1, (
f"Family '{fam.name}' has no learning_goals"
)
def test_tags_non_empty(self):
reg = Registry.load(REGISTRY_PATH)
for fam in reg.list_families():
assert len(fam.tags) >= 1, (
f"Family '{fam.name}' has no tags"
)