mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-11-13 09:48:18 +00:00
129 lines
3.7 KiB
Python
129 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
|