chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
"""Tests for the language resolver registry (graphify.resolver_registry).
|
||||
|
||||
The registry formalizes the previously hand-wired, suffix-gated cross-file
|
||||
resolution passes. These tests pin its contract so future languages can be
|
||||
registered with confidence: gating by suffix, in-order execution, in-place
|
||||
mutation, and fault isolation (a failing pass logs and is skipped, never
|
||||
aborting the build or blocking later passes).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from graphify.resolver_registry import (
|
||||
LanguageResolver,
|
||||
registered_resolvers,
|
||||
run_language_resolvers,
|
||||
)
|
||||
|
||||
|
||||
def _make_resolver(name: str, suffix: str, log: list[str]) -> LanguageResolver:
|
||||
def _resolve(per_file, all_nodes, all_edges):
|
||||
log.append(name)
|
||||
return LanguageResolver(name, frozenset({suffix}), _resolve)
|
||||
|
||||
|
||||
def test_default_registry_contains_swift_then_python() -> None:
|
||||
# Importing extract registers its resolvers into the shared registry. Order
|
||||
# matters: it preserves the prior inlined wiring (Swift before Python).
|
||||
import graphify.extract # noqa: F401 (registers resolvers on import)
|
||||
|
||||
names = [r.name for r in registered_resolvers()]
|
||||
assert "swift_member_calls" in names
|
||||
assert "python_member_calls" in names
|
||||
assert names.index("swift_member_calls") < names.index("python_member_calls")
|
||||
|
||||
|
||||
def test_resolver_runs_only_when_suffix_present() -> None:
|
||||
log: list[str] = []
|
||||
resolvers = [_make_resolver("ruby", ".rb", log), _make_resolver("go", ".go", log)]
|
||||
run_language_resolvers([Path("a.rb")], [], [], [], resolvers=resolvers)
|
||||
assert log == ["ruby"] # go skipped: no .go file present
|
||||
|
||||
|
||||
def test_resolvers_run_in_given_order() -> None:
|
||||
log: list[str] = []
|
||||
resolvers = [_make_resolver("first", ".rb", log), _make_resolver("second", ".rb", log)]
|
||||
run_language_resolvers([Path("a.rb")], [], [], [], resolvers=resolvers)
|
||||
assert log == ["first", "second"]
|
||||
|
||||
|
||||
def test_failing_resolver_is_isolated() -> None:
|
||||
log: list[str] = []
|
||||
|
||||
def _boom(per_file, all_nodes, all_edges):
|
||||
raise RuntimeError("resolver blew up")
|
||||
|
||||
resolvers = [
|
||||
LanguageResolver("boom", frozenset({".rb"}), _boom),
|
||||
_make_resolver("after", ".rb", log),
|
||||
]
|
||||
# Must not raise, and the later resolver still runs.
|
||||
run_language_resolvers([Path("a.rb")], [], [], [], resolvers=resolvers)
|
||||
assert log == ["after"]
|
||||
|
||||
|
||||
def test_resolver_mutates_edges_in_place() -> None:
|
||||
def _add_edge(per_file, all_nodes, all_edges):
|
||||
all_edges.append({"source": "x", "target": "y", "relation": "calls"})
|
||||
|
||||
resolvers = [LanguageResolver("adder", frozenset({".rb"}), _add_edge)]
|
||||
edges: list[dict] = []
|
||||
run_language_resolvers([Path("a.rb")], [], [], edges, resolvers=resolvers)
|
||||
assert edges == [{"source": "x", "target": "y", "relation": "calls"}]
|
||||
Reference in New Issue
Block a user