mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
Check read every technical debt file and every changed file with its own git show, so each run started one process per file: 99 git processes for a typical pull request, 311 for a 118-file range, and the count grew with docs/dev/debt. Process start-up dominates on Windows. Read the blobs the checks use in one git cat-file --batch process, keyed by the object ids ls-tree already returns, and batch the files duplicates() inspects the same way. Paths that are not cached still go through git show, so failures are unchanged.
116 lines
4.0 KiB
Python
116 lines
4.0 KiB
Python
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from collections import Counter
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
import check_conventions
|
|
from check_conventions import Check
|
|
|
|
EXPORT = "core/libs/prx/libSceExample/Export.cpp"
|
|
UNLISTED = "core/libs/prx/libSceExample/Unlisted.cpp"
|
|
EXPECTED = [
|
|
("binary", "data.txt", 0, ""),
|
|
("comment", EXPORT, 3, ""),
|
|
("duplicate-export", EXPORT, 2, "sceShared is also in libSceOther"),
|
|
("silent-stub", UNLISTED, 1, "sceUnlisted"),
|
|
]
|
|
|
|
|
|
def repository(root, fillers):
|
|
def git(*args):
|
|
subprocess.run(["git", "-c", f"safe.directory={root}", "-c", "user.name=Conventions Test",
|
|
"-c", "[email protected]", "-c", "commit.gpgsign=false", *args],
|
|
cwd=root, capture_output=True, check=True)
|
|
|
|
def write(path, data):
|
|
target = root / path
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_bytes(data if isinstance(data, bytes) else data.encode("utf-8"))
|
|
|
|
git("init", "-q")
|
|
write("docs/dev/TechnicalDebt.md", "# Project technical debt\n")
|
|
for index in range(fillers):
|
|
write(f"docs/dev/debt/libSceFiller{index}.md", f"# libSceFiller{index} technical debt\n")
|
|
write("docs/dev/debt/libSceExample.md",
|
|
f"# libSceExample technical debt\n\n### Silent stubs\n\n- [Known](../../../{EXPORT}) - layout unknown.\n")
|
|
write("core/libs/prx/libSceOther/src/Other.cpp", "int APS5_VABI sceShared() { return now(); }\n")
|
|
write("removed.txt", "removed\n")
|
|
git("add", ".")
|
|
git("commit", "-qm", "docs: add base")
|
|
git("tag", "base")
|
|
write(EXPORT, "int APS5_VABI sceExample() { return 0; }\nint APS5_VABI sceShared() { return now(); }\nint value; // note\n")
|
|
write(UNLISTED, "int APS5_VABI sceUnlisted() { return 0; }\n")
|
|
write("data.txt", b"\xff\xfe not utf-8\n")
|
|
write("docs/user/Café.md", "# Café\n")
|
|
(root / "removed.txt").unlink()
|
|
git("add", "-A")
|
|
git("commit", "-qm", "feat: add example")
|
|
|
|
|
|
class BlobReadTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.directory = tempfile.TemporaryDirectory()
|
|
cls.roots = {}
|
|
for fillers in (2, 40):
|
|
root = Path(cls.directory.name) / str(fillers)
|
|
root.mkdir()
|
|
repository(root, fillers)
|
|
cls.roots[fillers] = root
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
cls.directory.cleanup()
|
|
|
|
def run_checks(self, root):
|
|
calls = Counter()
|
|
run = subprocess.run
|
|
|
|
def counting(args, *rest, **options):
|
|
command = [str(arg) for arg in args]
|
|
if command[0] == "git":
|
|
index = 1
|
|
while command[index] == "-c":
|
|
index += 2
|
|
calls[command[index]] += 1
|
|
return run(args, *rest, **options)
|
|
|
|
previous = os.getcwd()
|
|
os.chdir(root)
|
|
try:
|
|
with patch.object(check_conventions.subprocess, "run", counting):
|
|
check = Check("base", "HEAD")
|
|
check.code()
|
|
check.build()
|
|
check.repository()
|
|
check.docs()
|
|
check.workflows()
|
|
check.commits()
|
|
finally:
|
|
os.chdir(previous)
|
|
return sorted(check.findings), calls
|
|
|
|
def test_findings_come_from_the_batched_contents(self):
|
|
findings, _ = self.run_checks(self.roots[2])
|
|
self.assertEqual(findings, EXPECTED)
|
|
|
|
def test_contents_are_read_without_one_process_per_file(self):
|
|
_, calls = self.run_checks(self.roots[2])
|
|
self.assertEqual(calls["show"], 0, calls)
|
|
self.assertLessEqual(calls["cat-file"], 2, calls)
|
|
|
|
def test_process_count_does_not_grow_with_the_debt_files(self):
|
|
few_findings, few = self.run_checks(self.roots[2])
|
|
many_findings, many = self.run_checks(self.roots[40])
|
|
self.assertEqual(many_findings, few_findings)
|
|
self.assertEqual(many, few)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|