Files
AnyPS5/tools/tests/test_check_conventions_env_reference.py
T
harisibrar1andClaude Opus 5.5 0c7d25c3d1 ci(conventions): check pull requests with the current base branch rules
The workflow checked out pull_request.base.sha, the base recorded when the
pull request was opened, and ran that revision's check_conventions.py. A rule
merged after a pull request was opened never ran on it: #7005 added
APS5_NO_WGI without an ENVIRONMENT.md row and passed with the checker of
07e741481, which had no env-reference rule.

Check out the current tip of the base branch and pass it as --base; the
checker already diffs from the merge base, so only the pull request's own
changes are checked. A name documented on the base branch after the branch
point now counts as documented unless the pull request removes its row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:50:41 -04:00

179 lines
7.6 KiB
Python

import os
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import check_conventions
from check_conventions import Check
DOC = "docs/dev/ENVIRONMENT.md"
SAMPLE = "core/libs/prx/libSceExample/Sample.cpp"
DOC_TEXT = "| `APS5_DOCUMENTED` | presence |\n| `APS5_GONE` | presence |\n"
def repository(root, base, head, target=None):
def git(*args):
subprocess.run(["git", "-c", f"safe.directory={root}", "-c", "user.name=Conventions Test",
"-c", "user.email=test@example.com", "-c", "commit.gpgsign=false", *args],
cwd=root, capture_output=True, check=True)
def apply(files):
for path, text in files.items():
target = root / path
if text is None:
target.unlink()
continue
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(text, encoding="utf-8")
git("init", "-q")
apply(base)
git("add", ".")
git("commit", "-qm", "docs: add base")
git("tag", "base")
if target is not None:
git("branch", "pull")
apply(target)
git("add", "-A")
git("commit", "-qm", "docs: advance the target")
git("tag", "target")
git("checkout", "-q", "pull")
apply(head)
git("add", "-A")
git("commit", "-qm", "feat: read a new name")
def findings_of(root, base, head, ref="base"):
previous = os.getcwd()
os.chdir(root)
try:
check = Check(ref, "HEAD")
check.env_reference()
return check.findings
finally:
os.chdir(previous)
class EnvReferenceDiffTests(unittest.TestCase):
def run_case(self, base, head, target=None):
directory = tempfile.TemporaryDirectory()
self.addCleanup(directory.cleanup)
root = Path(directory.name)
repository(root, base, head, target)
return findings_of(root, base, head, "base" if target is None else "target")
def test_only_a_name_the_pull_request_adds_is_reported_at_its_line(self):
base = {
DOC: DOC_TEXT,
SAMPLE: 'static bool a = std::getenv("APS5_DOCUMENTED") != nullptr;\n'
'static bool b = std::getenv("APS5_OLD_UNDOCUMENTED") != nullptr;\n',
}
added = 'static bool c = std::getenv("APS5_NEW_READ") != nullptr;\n'
head = {SAMPLE: base[SAMPLE] + added}
findings = self.run_case(base, head)
self.assertEqual(findings, [("env-reference", SAMPLE, 3,
f"APS5_NEW_READ is read here but has no row in {DOC}")])
def test_a_branch_without_the_document_still_reports_its_new_reads(self):
base = {SAMPLE: "int unrelated;\n"}
head = {SAMPLE: 'static bool a = std::getenv("APS5_NEW_READ") != nullptr;\n'}
findings = self.run_case(base, head)
self.assertEqual([(rule, detail) for rule, _, _, detail in findings],
[("env-reference", f"APS5_NEW_READ is read here but has no row in {DOC}")])
def test_a_row_is_reported_when_the_pull_request_removes_its_last_read(self):
base = {
DOC: DOC_TEXT,
SAMPLE: 'static bool a = std::getenv("APS5_DOCUMENTED") != nullptr;\n'
'static bool b = std::getenv("APS5_GONE") != nullptr;\n',
}
head = {SAMPLE: 'static bool a = std::getenv("APS5_DOCUMENTED") != nullptr;\n'}
findings = self.run_case(base, head)
self.assertEqual(findings, [("env-reference", DOC, 0,
"APS5_GONE has a row but the code no longer reads it")])
def test_removing_one_of_two_reads_keeps_the_row(self):
other = "core/libs/prx/libSceExample/Other.cpp"
base = {
DOC: DOC_TEXT,
SAMPLE: 'static bool a = std::getenv("APS5_DOCUMENTED") != nullptr;\n',
other: 'static bool b = std::getenv("APS5_DOCUMENTED") != nullptr;\n',
}
head = {other: None}
self.assertEqual(self.run_case(base, head), [])
def test_a_name_the_pull_request_does_not_touch_is_not_reported(self):
base = {
DOC: DOC_TEXT,
SAMPLE: 'static bool b = std::getenv("APS5_OLD_UNDOCUMENTED") != nullptr;\n',
}
head = {SAMPLE: base[SAMPLE] + "int unrelated;\n"}
self.assertEqual(self.run_case(base, head), [])
def test_a_row_the_pull_request_removes_is_reported_while_the_code_still_reads_it(self):
base = {
DOC: DOC_TEXT,
SAMPLE: 'static bool a = std::getenv("APS5_DOCUMENTED") != nullptr;\n',
}
head = {DOC: "| `APS5_GONE` | presence |\n"}
self.assertEqual(self.run_case(base, head), [("env-reference", DOC, 0,
"APS5_DOCUMENTED is still read by the code but this pull request removes its row")])
def test_a_removed_row_is_kept_quiet_when_the_code_stops_reading_it_too(self):
base = {
DOC: DOC_TEXT,
SAMPLE: 'static bool a = std::getenv("APS5_DOCUMENTED") != nullptr;\n'
'static bool b = std::getenv("APS5_GONE") != nullptr;\n',
}
head = {
DOC: "| `APS5_DOCUMENTED` | presence |\n",
SAMPLE: 'static bool a = std::getenv("APS5_DOCUMENTED") != nullptr;\n',
}
self.assertEqual(self.run_case(base, head), [])
def test_an_added_line_starting_with_plus_does_not_shift_the_reported_line(self):
base = {DOC: DOC_TEXT, SAMPLE: "int a;\n"}
head = {SAMPLE: "int a;\n+++x;\n" 'static bool b = std::getenv("APS5_NEW_READ") != nullptr;\n'}
findings = self.run_case(base, head)
self.assertEqual(findings, [("env-reference", SAMPLE, 3,
f"APS5_NEW_READ is read here but has no row in {DOC}")])
def test_a_removed_line_starting_with_minus_still_counts_as_a_removed_read(self):
base = {
DOC: DOC_TEXT,
SAMPLE: '--x; std::getenv("APS5_GONE") != nullptr;\n',
}
head = {SAMPLE: "int unrelated;\n"}
self.assertEqual(self.run_case(base, head), [("env-reference", DOC, 0,
"APS5_GONE has a row but the code no longer reads it")])
def test_a_row_the_target_added_after_the_branch_point_documents_the_read(self):
base = {SAMPLE: "int unrelated;\n"}
target = {DOC: "| `APS5_NEW_READ` | presence |\n"}
head = {SAMPLE: 'static bool a = std::getenv("APS5_NEW_READ") != nullptr;\n'}
self.assertEqual(self.run_case(base, head, target), [])
def test_a_read_the_target_does_not_document_is_still_reported(self):
base = {SAMPLE: "int unrelated;\n"}
target = {DOC: DOC_TEXT}
head = {SAMPLE: 'static bool a = std::getenv("APS5_NEW_READ") != nullptr;\n'}
self.assertEqual(self.run_case(base, head, target), [("env-reference", SAMPLE, 1,
f"APS5_NEW_READ is read here but has no row in {DOC}")])
def test_a_row_the_pull_request_removes_is_reported_although_the_target_keeps_it(self):
base = {
DOC: DOC_TEXT,
SAMPLE: 'static bool a = std::getenv("APS5_DOCUMENTED") != nullptr;\n',
}
target = {"core/libs/prx/libSceExample/Other.cpp": "int other;\n"}
head = {DOC: "| `APS5_GONE` | presence |\n"}
self.assertEqual(self.run_case(base, head, target), [("env-reference", DOC, 0,
"APS5_DOCUMENTED is still read by the code but this pull request removes its row")])
if __name__ == "__main__":
unittest.main()