Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 104 additions & 1 deletion tools/tests/test_runtime_lifecycle_invariants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,101 @@
ROOT = Path(__file__).resolve().parents[2]


def strip_comments(text: str) -> str:
"""Remove // line comments and /* */ block comments from C++ source text.

A regex over raw source cannot distinguish "the call is here" from "the
call used to be here and is now commented out" — both contain the same
substring. Strip comments first so a commented-out call site (with or
without a decoy real statement nearby) is invisible to the regex, the
same way the compiler would see it. String/char literals are tracked so
a literal containing "//" or "/*" is not treated as a comment start.
Newlines are preserved so line numbers in any future diagnostics stay
roughly aligned; comment bodies are dropped, not blanked to the same width.
"""
result = []
i = 0
n = len(text)
in_line_comment = False
in_block_comment = False
in_string = False
in_char = False
while i < n:
c = text[i]
two = text[i : i + 2]
if in_line_comment:
if c == "\n":
in_line_comment = False
result.append(c)
i += 1
continue
if in_block_comment:
if two == "*/":
in_block_comment = False
i += 2
# The compiler treats a block comment as whitespace, so a
# closed block comment must leave a separator behind it —
# otherwise "return/**/Unregister();" collapses into
# "returnUnregister();" and \bUnregister can no longer match
# a real call that a comment merely interrupts.
result.append(" ")
else:
if c == "\n":
result.append("\n")
i += 1
continue
if in_string:
result.append(c)
if c == "\\" and i + 1 < n:
result.append(text[i + 1])
i += 2
continue
if c == '"':
in_string = False
i += 1
continue
if in_char:
result.append(c)
if c == "\\" and i + 1 < n:
result.append(text[i + 1])
i += 2
continue
if c == "'":
in_char = False
i += 1
continue
if two == "//":
in_line_comment = True
i += 2
continue
if two == "/*":
in_block_comment = True
i += 2
continue
if c == '"':
in_string = True
result.append(c)
i += 1
continue
if c == "'":
in_char = True
result.append(c)
i += 1
continue
result.append(c)
i += 1
return "".join(result)


def extract_braced_function(source: str, signature: str) -> str:
"""Extract a function body by brace-matching, with comments stripped.

Every sensor in this file matches against the returned text with regex
or substring checks, none of which can tell real code from a comment
describing it. Stripping here, once, means every sensor gets the same
comment-transparency the compiler has — not just the ones a reviewer
happened to wrap by hand (#123).
"""
start = source.index(signature)
opening = source.index("{", start)
depth = 0
Expand All @@ -16,7 +110,7 @@ def extract_braced_function(source: str, signature: str) -> str:
elif source[index] == "}":
depth -= 1
if depth == 0:
return source[opening : index + 1]
return strip_comments(source[opening : index + 1])
raise AssertionError(f"unterminated function body: {signature}")


Expand Down Expand Up @@ -108,6 +202,11 @@ def test_shutdown_thread_never_touches_the_callback_registry(self):
# no lock (echovr.exe 0x140f8df20). The shutdown thread now hands that work to Update()
# through MainThreadHandoff; its own fallback must skip the registry.
source = (ROOT / "src/runtime/server/gameserver.cpp").read_text()
# Comment-stripped (#123): extract_braced_function strips comments for
# every caller, so a commented-out call site with a decoy real
# statement nearby can't satisfy these regexes — a raw substring
# match can't tell "the call is here" from "the call is described in
# a comment above the decoy".
shutdown = extract_braced_function(source, "void GameServerLib::BeginGracefulShutdown(")

for forbidden in (r"\bUnregister\s*\(\s*\)", r"\bUnregisterAllCallbacks\s*\(",
Expand Down Expand Up @@ -139,6 +238,10 @@ def test_broadcaster_callbacks_record_their_owner_before_listening(self):
# the owner null every unregister silently skipped the game and only cleared the struct. No
# C++ test links gameserver.cpp, so the wiring is pinned here.
source = (ROOT / "src/runtime/server/gameserver.cpp").read_text()
# Comment-stripped (#123): same reasoning as the #44 sensor above — a
# commented-out RecordBroadcasterOwner call with a `owner = nullptr;`
# decoy nearby can't satisfy the substring these regexes look for,
# because extract_braced_function strips comments before returning.
register = extract_braced_function(source, "void GameServerLib::RegisterBroadcasterCallbacks(")
record = re.search(r"\bGameServer::RecordBroadcasterOwner\s*\(\s*\*m_context\s*\)", register)
self.assertIsNotNone(record, "RegisterBroadcasterCallbacks no longer records the callback owner")
Expand Down
Loading