fix(conventions): restrict silent stub exemptions to their section
This commit is contained in:
parent
2bb78d2c7a
commit
271e31a5a3
|
|
@ -83,7 +83,7 @@ class Check:
|
|||
return git("show", f"{self.head}:{path}")
|
||||
|
||||
def code(self):
|
||||
debt = [(text, links("docs/dev/TechnicalDebt.md", text)) for text in self.show("docs/dev/TechnicalDebt.md").splitlines()] if "docs/dev/TechnicalDebt.md" in self.tree else []
|
||||
debt = silent_stub_debt(self.show("docs/dev/TechnicalDebt.md")) if "docs/dev/TechnicalDebt.md" in self.tree else []
|
||||
exports = {}
|
||||
for path, lines in self.files(lambda p: p.suffix in CPP):
|
||||
core = path.startswith("core/") and "tests" not in PurePosixPath(path).parts
|
||||
|
|
@ -193,6 +193,22 @@ def links(path, text):
|
|||
return result
|
||||
|
||||
|
||||
def silent_stub_debt(text):
|
||||
debt = []
|
||||
section_level = 0
|
||||
for line in text.splitlines():
|
||||
heading = re.match(r"^(#{1,6})\s+(.+?)\s*$", line)
|
||||
if heading:
|
||||
level = len(heading[1])
|
||||
if heading[2] == "Silent stubs":
|
||||
section_level = level
|
||||
elif level <= section_level:
|
||||
section_level = 0
|
||||
if section_level:
|
||||
debt.append((line, links("docs/dev/TechnicalDebt.md", line)))
|
||||
return debt
|
||||
|
||||
|
||||
def listed(debt, name, path):
|
||||
own = PurePosixPath(path).parts[:4]
|
||||
for text, targets in debt:
|
||||
|
|
|
|||
|
|
@ -92,5 +92,84 @@ class SilentStubTests(unittest.TestCase):
|
|||
self.assertNotIn("[comment]", result.stdout)
|
||||
|
||||
|
||||
class SilentStubSectionTests(unittest.TestCase):
|
||||
path = "core/libs/prx/libSceExample/Export.cpp"
|
||||
entry = f"- [Existing limitation](../../{path}) - console layout is unknown.\n"
|
||||
|
||||
def check_stub(self, debt_text):
|
||||
checker = Path(__file__).resolve().parents[1] / "check_conventions.py"
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
|
||||
def git(*args):
|
||||
return 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, text=True, check=True,
|
||||
)
|
||||
|
||||
git("init", "-q")
|
||||
debt = root / "docs/dev/TechnicalDebt.md"
|
||||
debt.parent.mkdir(parents=True)
|
||||
debt.write_text("# Project technical debt\n", encoding="utf-8")
|
||||
for library in ("libSceExample", "libSceOther"):
|
||||
reference = root / "core/libs/prx" / library / "Reference.hpp"
|
||||
reference.parent.mkdir(parents=True)
|
||||
reference.write_text("", encoding="utf-8")
|
||||
git("add", ".")
|
||||
git("commit", "-qm", "docs: record technical debt")
|
||||
source = root / self.path
|
||||
source.write_text("int APS5_VABI sceExample() { return 0; }\n", encoding="utf-8")
|
||||
debt.write_text(debt_text, encoding="utf-8")
|
||||
git("add", ".")
|
||||
git("commit", "-qm", "feat: add example export")
|
||||
env = {key: value for key, value in os.environ.items()
|
||||
if key not in ("GITHUB_EVENT_PATH", "GITHUB_STEP_SUMMARY", "GITHUB_ACTIONS")}
|
||||
env.update(GIT_CONFIG_COUNT="1", GIT_CONFIG_KEY_0="safe.directory", GIT_CONFIG_VALUE_0=str(root))
|
||||
return subprocess.run(
|
||||
[sys.executable, str(checker), "--base", "HEAD~1"],
|
||||
cwd=root, capture_output=True, text=True, env=env, timeout=10,
|
||||
)
|
||||
|
||||
def require_rejected(self, debt):
|
||||
result = self.check_stub(debt)
|
||||
self.assertEqual(result.returncode, 1, result.stdout + result.stderr)
|
||||
self.assertIn("[silent-stub]", result.stdout)
|
||||
self.assertNotIn("[doc-link]", result.stdout)
|
||||
|
||||
def require_accepted(self, debt):
|
||||
result = self.check_stub(debt)
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
self.assertIn("All conventions checks passed", result.stdout)
|
||||
|
||||
def test_debt_outside_silent_stubs_does_not_exempt_export(self):
|
||||
for section in ("Build", "Unknown function info", "Functional"):
|
||||
with self.subTest(section=section):
|
||||
self.require_rejected(f"# Project technical debt\n\n### {section}\n\n{self.entry}")
|
||||
|
||||
def test_entries_after_silent_stubs_do_not_exempt_export(self):
|
||||
for heading in ("# Other debt", "## Other debt", "### Functional"):
|
||||
with self.subTest(heading=heading):
|
||||
self.require_rejected(f"# Project technical debt\n\n### Silent stubs\n\n{heading}\n\n{self.entry}")
|
||||
|
||||
def test_file_entry_in_silent_stubs_exempts_export(self):
|
||||
self.require_accepted(f"# Project technical debt\n\n### Silent stubs\n\n{self.entry}")
|
||||
|
||||
def test_named_entry_in_same_library_exempts_export(self):
|
||||
entry = "- sceExample: [reference](../../core/libs/prx/libSceExample/Reference.hpp)\n"
|
||||
self.require_accepted(f"# Project technical debt\n\n### Silent stubs\n\n{entry}")
|
||||
|
||||
def test_named_entry_in_another_library_does_not_exempt_export(self):
|
||||
entry = "- sceExample: [reference](../../core/libs/prx/libSceOther/Reference.hpp)\n"
|
||||
self.require_rejected(f"# Project technical debt\n\n### Silent stubs\n\n{entry}")
|
||||
|
||||
def test_different_function_in_same_library_does_not_exempt_export(self):
|
||||
entry = "- sceExampleOther: [reference](../../core/libs/prx/libSceExample/Reference.hpp)\n"
|
||||
self.require_rejected(f"# Project technical debt\n\n### Silent stubs\n\n{entry}")
|
||||
|
||||
def test_subsection_in_silent_stubs_keeps_exemption(self):
|
||||
self.require_accepted(f"# Project technical debt\n\n### Silent stubs\n\n#### Dialogs\n\n{self.entry}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Reference in New Issue