Files
Open_Ultra_SAST/tests/test_registration_sites.py
T

127 lines
3.7 KiB
Python

"""Registration-site strategy tests (task 11.2).
The generic call-site registration adapter resolves handlers registered at
call sites through the same-file stable symbols and reports unresolved
registrations as coverage. Vocabulary is data supplied to the strategy; the
module itself names no target.
"""
from __future__ import annotations
import inspect
from openultrasast.mapping.registration_sites import RegistrationSiteStrategy
from openultrasast.mapping.registry import register, registry_entries
from openultrasast.preprocess import FileTarget
PATH = "src/Main.java"
JAVA_EXACT = """class Handler {
void handle() {
}
void respond() {
}
}
class Registry {
void install() {
addHandler(new Handler());
}
}
"""
JAVA_UNRESOLVED = """class Registry {
void install() {
addHandler(new Elsewhere());
}
}
"""
def _target(path: str = PATH, text: str = JAVA_EXACT) -> FileTarget:
return FileTarget(
path=path,
absolute_path=f"/repo/{path}",
language="java",
loc=max(len(text.splitlines()), 1),
tags=[],
has_fuzz_entry_point=False,
)
def _strategy(vocabulary: tuple[str, ...] = ("addHandler",)) -> RegistrationSiteStrategy:
return RegistrationSiteStrategy(
identifier="test-registration",
languages=("java",),
vocabulary=vocabulary,
)
def test_registered_handler_methods_become_entries() -> None:
entries = _strategy().recognize(_target(), JAVA_EXACT)
by_function = {entry.function_name: entry for entry in entries}
assert set(by_function) == {"handle", "respond"}
entry = by_function["handle"]
assert entry.path == PATH
assert entry.kind == "route"
assert entry.function_name == "handle"
assert entry.access_level == "unknown"
assert entry.access_evidence == [
f"registration site {PATH}:11",
"registered handler Handler",
]
assert entry.registered_by == "addHandler"
def test_unresolved_registration_produces_no_entry_but_coverage() -> None:
strategy = _strategy()
assert strategy.recognize(_target(text=JAVA_UNRESOLVED), JAVA_UNRESOLVED) == []
assert strategy.registration_coverage(_target(text=JAVA_UNRESOLVED), JAVA_UNRESOLVED) == {"registration_unresolved": 1}
def test_exact_registration_reports_zero_unresolved() -> None:
assert _strategy().registration_coverage(_target(), JAVA_EXACT) == {}
def test_empty_vocabulary_matches_nothing() -> None:
strategy = _strategy(vocabulary=())
assert strategy.recognize(_target(), JAVA_EXACT) == []
assert strategy.registration_coverage(_target(), JAVA_EXACT) == {}
def test_multiple_entries_are_deterministic() -> None:
strategy = _strategy()
first = strategy.recognize(_target(), JAVA_EXACT)
second = strategy.recognize(_target(), JAVA_EXACT)
assert first == second
assert [entry.function_name for entry in first] == sorted(entry.function_name or "" for entry in first)
def test_registry_dispatch_stamps_strategy_provenance() -> None:
strategy = _strategy()
register(strategy)
stamped = registry_entries(_target(), JAVA_EXACT)
fixture_entries = [entry for entry in stamped if entry.provenance == "strategy:test-registration"]
assert {entry.function_name for entry in fixture_entries} == {"handle", "respond"}
def test_module_names_no_targets() -> None:
from openultrasast.mapping import registration_sites
source = inspect.getsource(registration_sites).lower()
for name in (
"symfony",
"laravel",
"tornado",
"wordpress",
"stapler",
"jetty",
"django",
"flask",
"rails",
"spring",
"express",
):
assert name not in source