mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-01 00:27:20 -05:00
refactor: one proof line per claim
Records that back the same field or issue claim share one line. Each line says what the runs showed: the BIOS the core ran, the file strace saw opened, or what a maintainer watched in an issue's run (tests/campaign/observations.yml). A run with nothing to state stays off the page.
This commit is contained in:
1 parent
3806f60c8e
commit
9c07dabfae
7 files changed
+272
-62
No files matched your search
@@ -73,8 +73,8 @@ on:
|
||||
- "release.json"
|
||||
- "derivable.json"
|
||||
- "measurements/**"
|
||||
# The coverage table and the region results read the test game list.
|
||||
- "tests/campaign/content.yml"
|
||||
# The Proof lines of the emulator pages read what an issue's runs showed.
|
||||
- "tests/campaign/observations.yml"
|
||||
# The Starlight project: config, components, styles, lockfile. Its
|
||||
# generated folders are gitignored and never trigger anything.
|
||||
- "website/**"
|
||||
|
||||
+143
-32
@@ -48,6 +48,10 @@ SQLITE_SCHEMA_VERSION = "3"
|
||||
# Observables the variants table leaves out: one value per sampled frame.
|
||||
BULKY_OBSERVABLES = ("frame_hashes",)
|
||||
INDEX_SCHEMA_VERSION = 1
|
||||
# What a maintainer saw in an issue's runs, by record subject.
|
||||
OBSERVATIONS = Path("tests") / "campaign" / "observations.yml"
|
||||
# A Proof line lists this many record links at most, else one link to the file.
|
||||
MAX_RECORD_LINKS = 8
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
@@ -86,7 +90,8 @@ def verdicts_of(record: dict) -> list[dict]:
|
||||
"""Each variant's boot verdict, from record version 4 on, and the BIOS
|
||||
it ran from version 5 on."""
|
||||
return [{"variant": v["label"], "verdict": shown_verdict(v), "bios_used": v.get("bios_used", "unknown"),
|
||||
"detail": (v.get("verdict_evidence") or {}).get("detail", "")}
|
||||
"detail": (v.get("verdict_evidence") or {}).get("detail", ""),
|
||||
"staged": sorted(name for name, sha1 in (v.get("system_files") or {}).items() if sha1)}
|
||||
for v in record["variants"] if "verdict" in v]
|
||||
|
||||
|
||||
@@ -115,8 +120,50 @@ def result_of(record: dict) -> tuple[str, str]:
|
||||
return result.get("status") or "ran", result.get("statement") or ""
|
||||
|
||||
|
||||
def opened(record: dict) -> str | None:
|
||||
"""The staged name a check varied, when strace saw the core open it in
|
||||
every repetition of a variant that staged it."""
|
||||
name = (record.get("check") or {}).get("variable")
|
||||
if not isinstance(name, str):
|
||||
return None
|
||||
for variant in record["variants"]:
|
||||
reps = variant.get("repetitions") or []
|
||||
if (variant.get("system_files") or {}).get(name) and reps and all(
|
||||
any(f.get("path") == name for f in rep.get("files_opened") or ()) for rep in reps):
|
||||
return name
|
||||
return None
|
||||
|
||||
|
||||
def load_observations(path: Path) -> dict[str, dict]:
|
||||
"""Each record id or subject an observation covers, with its issue
|
||||
number and words."""
|
||||
import yaml # noqa: PLC0415
|
||||
|
||||
if not path.is_file():
|
||||
return {}
|
||||
out = {}
|
||||
for issue, entries in (yaml.safe_load(path.read_text(encoding="utf-8")) or {}).items():
|
||||
number = ISSUE_SUBJECT.match(f"{issue}-")["number"]
|
||||
for entry in entries:
|
||||
for key in [*entry.get("records", ()), *entry.get("subjects", ())]:
|
||||
out[key] = {"issue": number, "said": entry["said"]}
|
||||
return out
|
||||
|
||||
|
||||
def shown_of(record: dict) -> list | None:
|
||||
"""What a record showed that a page can state: ["text", words] from
|
||||
its boot verdicts, ["opened", name] for a staged name strace saw the
|
||||
core open, or None."""
|
||||
verdicts = verdicts_of(record)
|
||||
if verdicts:
|
||||
return ["text", proof_result(verdicts)]
|
||||
name = opened(record)
|
||||
return ["opened", name] if name else None
|
||||
|
||||
|
||||
def index_item(entry: mr.Stored, runs: int, source: dict, profiles: dict,
|
||||
system_names: dict[str, str], ancestry: set[str] | None = None) -> dict:
|
||||
system_names: dict[str, str], ancestry: set[str] | None = None,
|
||||
records: list[dict] | None = None) -> dict:
|
||||
record = entry.record
|
||||
profile = profiles.get(entry.emulator) or {}
|
||||
check = record.get("check") or {}
|
||||
@@ -152,13 +199,15 @@ def index_item(entry: mr.Stored, runs: int, source: dict, profiles: dict,
|
||||
"id": record["id"],
|
||||
"runs": runs,
|
||||
"record_url": permalink(source["repo"], source["commit"], mr.records_path(entry.emulator), entry.line),
|
||||
"records": records if records is not None else [],
|
||||
"sqlite": f"downloads/measurements/{entry.emulator}.sqlite",
|
||||
"proves": proves(ancestry or {record["id"]}, profile),
|
||||
}
|
||||
|
||||
|
||||
def build_index(stored: list[mr.Stored], source: dict | None, profiles: dict,
|
||||
system_names: dict[str, str] | None = None) -> dict:
|
||||
system_names: dict[str, str] | None = None,
|
||||
observations: dict[str, dict] | None = None) -> dict:
|
||||
"""One item per (emulator, subject): its latest record not superseded."""
|
||||
by_subject: dict[tuple[str, str], list[mr.Stored]] = {}
|
||||
live_ids = {r["id"] for r in mr.live(s.record for s in stored)}
|
||||
@@ -171,8 +220,15 @@ def build_index(stored: list[mr.Stored], source: dict | None, profiles: dict,
|
||||
for key in sorted(by_subject):
|
||||
entries = by_subject[key]
|
||||
latest = max(entries, key=lambda s: (s.record["recorded_at"], s.line))
|
||||
profile = profiles.get(key[0]) or {}
|
||||
records = [{"url": permalink((source or {}).get("repo"), (source or {}).get("commit"),
|
||||
mr.records_path(s.emulator), s.line),
|
||||
"proves": proves(ancestors.get(s.record["id"]) or {s.record["id"]}, profile),
|
||||
"shown": shown_of(s.record),
|
||||
"observed": (observations or {}).get(s.record["id"]) or (observations or {}).get(key[1])}
|
||||
for s in sorted(entries, key=lambda s: s.line)]
|
||||
items.append(index_item(latest, len(entries), source or {}, profiles, system_names or {},
|
||||
ancestors.get(latest.record["id"])))
|
||||
ancestors.get(latest.record["id"]), records))
|
||||
items.sort(key=lambda item: (item["emulator"], item["date"], item["subject"]))
|
||||
return {
|
||||
"schema_version": INDEX_SCHEMA_VERSION,
|
||||
@@ -185,10 +241,6 @@ def build_index(stored: list[mr.Stored], source: dict | None, profiles: dict,
|
||||
}
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Coverage and region results
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# SQLite
|
||||
# --------------------------------------------------------------------------
|
||||
@@ -410,7 +462,7 @@ def build(public: Path, root: Path = ROOT, emulators_dir: Path = ROOT / "emulato
|
||||
stored = mr.read_records(root)
|
||||
source = {"repo": repo, "commit": commit or (records_commit(root) if stored else None)}
|
||||
profiles = load_profiles(emulators_dir)
|
||||
index = build_index(stored, source, profiles, system_names)
|
||||
index = build_index(stored, source, profiles, system_names, load_observations(root / OBSERVATIONS))
|
||||
paths = [public / INDEX_PATH]
|
||||
(public / INDEX_PATH).parent.mkdir(parents=True, exist_ok=True)
|
||||
write_if_changed(str(public / INDEX_PATH),
|
||||
@@ -441,47 +493,106 @@ def by_emulator(index: dict) -> dict[str, list[dict]]:
|
||||
ISSUE_SUBJECT = re.compile(r"^issue(?P<number>\d+)-")
|
||||
|
||||
|
||||
def proof_result(item: dict) -> str:
|
||||
VERDICT_WORDS = {"boots": "boots", "bios_error": "shows a BIOS error", "crash": "crashes",
|
||||
"hang": "hangs", "unknown": "gives no verdict"}
|
||||
|
||||
|
||||
def proof_result(verdicts: list[dict]) -> str:
|
||||
"""What a record showed, in words, naming the BIOS each boot ran: a
|
||||
boot on the core's built-in BIOS is never the staged file's."""
|
||||
boot on the core's built-in BIOS is never the staged file's. A single
|
||||
run says what was staged, a check names each variant."""
|
||||
def said(verdict: dict) -> str:
|
||||
used = verdict.get("bios_used") or "unknown"
|
||||
if verdict["verdict"] == BOOTS_BUILTIN:
|
||||
return "boots on the core's built-in BIOS"
|
||||
if verdict["verdict"] == "boots" and used.startswith("staged:"):
|
||||
return f"boots on {used.removeprefix('staged:')}"
|
||||
return verdict["verdict"].replace("_", " ")
|
||||
verdicts = item.get("verdicts") or []
|
||||
return VERDICT_WORDS.get(verdict["verdict"], verdict["verdict"].replace("_", " "))
|
||||
if len(verdicts) == 1:
|
||||
return said(verdicts[0])
|
||||
if verdicts:
|
||||
return ". ".join(f"{v['variant']}: {said(v)}" for v in verdicts)
|
||||
claim = item.get("claim") or f"a run of {item.get('content') or item['subject']}"
|
||||
return f"{claim.rstrip('.')}, recorded before the boot oracle"
|
||||
staged = verdicts[0].get("staged") or []
|
||||
given = " and ".join(staged) if len(staged) < 3 else f"{', '.join(staged[:-1])} and {staged[-1]}"
|
||||
return f"with {given or 'no BIOS'}, it {said(verdicts[0])}"
|
||||
return ". ".join(f"{v['variant']}: {said(v)}" for v in verdicts)
|
||||
|
||||
|
||||
def proof_line(item: dict) -> str | None:
|
||||
"""One line for a record a page relies on, or None: a profile field its
|
||||
`evidence:` names the record for, or an issue the record answers."""
|
||||
def proof_claims(item: dict, record: dict) -> tuple[list[str], list | None]:
|
||||
"""The claims one record of an item backs on its emulator's page, and
|
||||
what it showed. An issue observation is the claim and needs no more.
|
||||
No claim when the record shows nothing a page can state."""
|
||||
observed = record.get("observed")
|
||||
if observed:
|
||||
return [f"issue {observed['issue']}: {observed['said']}"], None
|
||||
shown = record.get("shown")
|
||||
if shown is None:
|
||||
return [], None
|
||||
if record.get("proves"):
|
||||
return record["proves"], shown
|
||||
issue = ISSUE_SUBJECT.match(item["subject"])
|
||||
if not item.get("proves") and not issue:
|
||||
return None
|
||||
what = ", ".join(item.get("proves") or ()) or f"issue {issue['number']}"
|
||||
text = f"{_cell(what)}: {_cell(proof_result(item))}".translate(_MARKDOWN)
|
||||
target = _href(item.get("record_url"))
|
||||
return f"- {text}" + (f" ([record]({target}))" if target else "") + "."
|
||||
if issue and shown[0] == "text":
|
||||
return [f"issue {issue['number']}"], shown
|
||||
return [], None
|
||||
|
||||
|
||||
def _md(value: object) -> str:
|
||||
"""Record text placed in a Markdown line: no span, link or tag out of it."""
|
||||
return _cell(value).translate(_MARKDOWN)
|
||||
|
||||
|
||||
def _records(urls: list[str]) -> str:
|
||||
"""The record links of one statement, escaped and safe targets only."""
|
||||
def place(url: str) -> tuple[str, int]:
|
||||
path, _, line = url.partition("#L")
|
||||
return path, int(line) if line.isdigit() else 0
|
||||
targets = sorted(dict.fromkeys(t for u in urls if (t := _href(u))), key=place)
|
||||
if not targets:
|
||||
return ""
|
||||
if len(targets) == 1:
|
||||
return f" ([record]({targets[0]}))"
|
||||
files = {t.split("#", 1)[0] for t in targets}
|
||||
if len(targets) > MAX_RECORD_LINKS and len(files) == 1:
|
||||
return f" ([{len(targets)} records]({files.pop()}))"
|
||||
return " (records " + ", ".join(f"[{n}]({t})" for n, t in enumerate(targets, 1)) + ")"
|
||||
|
||||
|
||||
def proof_line(claim: str, shown: list[tuple[list | None, list[str]]]) -> str:
|
||||
"""One line per claim, its records collapsed: the files strace saw
|
||||
opened in one list, each distinct result once with its records."""
|
||||
names: dict[str, list[str]] = {}
|
||||
texts: dict[str, list[str]] = {}
|
||||
bare: list[str] = []
|
||||
for what, urls in shown:
|
||||
if what is None:
|
||||
bare.extend(urls)
|
||||
elif what[0] == "opened":
|
||||
names.setdefault(what[1], []).extend(urls)
|
||||
else:
|
||||
texts.setdefault(what[1], []).extend(urls)
|
||||
parts = []
|
||||
if names:
|
||||
parts.append("the core opened " + ", ".join(_md(n) for n in names)
|
||||
+ _records([u for urls in names.values() for u in urls]))
|
||||
parts.extend(_md(text) + _records(urls) for text, urls in texts.items())
|
||||
if not parts:
|
||||
return f"- {_md(claim)}{_records(bare)}."
|
||||
return f"- {_md(claim)}: " + ". ".join(part[:1].upper() + part[1:] if n else part
|
||||
for n, part in enumerate(parts)) + "."
|
||||
|
||||
|
||||
def proof_section(items: list[dict]) -> list[str]:
|
||||
"""The Proof lines of an emulator page: only the runs a claim of the
|
||||
page rests on, one line each. Every other record stays on the
|
||||
"""The Proof lines of an emulator page: only the claims of the page a
|
||||
run backs, one line per claim. Every other record stays on the
|
||||
Measurements page."""
|
||||
lines = sorted({line for item in items if (line := proof_line(item))})
|
||||
if not lines:
|
||||
by_claim: dict[str, list] = {}
|
||||
for item in sorted(items, key=lambda i: i["subject"]):
|
||||
for record in item.get("records") or ():
|
||||
claims, what = proof_claims(item, record)
|
||||
for claim in claims:
|
||||
by_claim.setdefault(claim, []).append((what, [record["url"]]))
|
||||
if not by_claim:
|
||||
return []
|
||||
return ["## Proof", "",
|
||||
f"Real runs that back this page ([how they are made](../../{METHOD_PAGE.removesuffix('.md')}/)):",
|
||||
"", *lines, ""]
|
||||
"", *(proof_line(claim, by_claim[claim]) for claim in sorted(by_claim)), ""]
|
||||
|
||||
|
||||
def _text(value: object) -> str:
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# What a maintainer saw in the runs an issue points at. The records keep
|
||||
# frame and audio hashes, which say a run is the same as another, never what
|
||||
# it showed: the sentence comes from watching the run. An entry names the
|
||||
# records it was seen in (`records:`), or every record of a subject when the
|
||||
# sentence is about all of them (`subjects:`). A run of an issue with no
|
||||
# entry here and no boot verdict reaches no page.
|
||||
# Read by scripts/sitemeasurements.py for the Proof lines of emulator pages.
|
||||
issue85:
|
||||
- said: the Lunar opening movie plays with sound
|
||||
records: [2026-10-27-f17b2280e1af]
|
||||
- said: Video CD play, pause, stop and play again work
|
||||
records: [2026-10-27-a84574cf24a1, 2026-10-27-119c8e80edb5]
|
||||
- said: next and previous track work on a three-track Video CD
|
||||
records: [2026-10-27-51a78500620f]
|
||||
- said: the 704x480 menu still of Super Gamer No. 5 shows
|
||||
records: [2026-10-27-a9557cfd13d7]
|
||||
# tests/test_measurements.py checks this one against the records: video
|
||||
# and audio hashes equal across both core commits, card off and on.
|
||||
- said: video and audio identical with and without the patch, card off and on, on 20 discs
|
||||
subjects: [issue85-regression-card-off, issue85-regression-card-on]
|
||||
+100
-23
@@ -221,7 +221,7 @@ class ReadAndIndex(Workspace):
|
||||
keys = {"emulator", "emulator_name", "profiled", "systems", "system_names", "subject", "kind",
|
||||
"claim", "method", "observable", "variable", "status", "statement", "content",
|
||||
"variants", "repetitions", "flags", "date", "host", "core", "frontend_commit", "id",
|
||||
"runs", "record_url", "sqlite", "verdicts", "proves"}
|
||||
"runs", "record_url", "sqlite", "verdicts", "proves", "records"}
|
||||
for item in index["items"]:
|
||||
self.assertEqual(set(item), keys)
|
||||
alpha = {i["subject"]: i for i in index["items"] if i["emulator"] == "alpha"}
|
||||
@@ -267,10 +267,10 @@ class ReadAndIndex(Workspace):
|
||||
self.assertEqual(status, sm.BOOTS_BUILTIN)
|
||||
self.assertIn("built-in BIOS", statement)
|
||||
# The proof line a profile field rests on names the BIOS the core ran.
|
||||
item = {**SitePages.ITEM, "kind": "run", "status": status, "statement": statement,
|
||||
"verdicts": sm.verdicts_of(record), "proves": ["required of scph5501.bin"]}
|
||||
line = sm.proof_line(item)
|
||||
self.assertIn("required of scph5501.bin: boots on the core's built-in BIOS", line)
|
||||
record["variants"][0]["system_files"] = {}
|
||||
line = sm.proof_line("required of scph5501.bin", [(sm.shown_of(record), ["../r.jsonl#L1"])])
|
||||
self.assertEqual(html.unescape(line), "- required of scph5501.bin: with no BIOS, it boots on the "
|
||||
"core's built-in BIOS ([record](../r.jsonl#L1)).")
|
||||
self.assertNotIn("other region", line)
|
||||
|
||||
def test_links_name_the_last_commit_that_touched_the_records(self) -> None:
|
||||
@@ -462,24 +462,101 @@ class SitePages(unittest.TestCase):
|
||||
"file": "x.so", "sha256": SHA256, "repo": None, "build": "make"},
|
||||
"frontend_commit": None, "id": "2026-10-27-43527b763ace", "runs": 2,
|
||||
"record_url": f"{REPO_URL}/blob/{'e' * 40}/measurements/beetle_saturn.jsonl#L4",
|
||||
"sqlite": "downloads/measurements/beetle_saturn.sqlite",
|
||||
"sqlite": "downloads/measurements/beetle_saturn.sqlite", "records": [],
|
||||
}
|
||||
|
||||
def item(self, **values: object) -> dict:
|
||||
return {**self.ITEM, **values}
|
||||
|
||||
def test_only_the_runs_a_page_rests_on_get_a_proof_line(self) -> None:
|
||||
self.assertIsNone(sm.proof_line(self.item(proves=[])))
|
||||
self.assertEqual(sm.proof_section([self.item(proves=[])]), [])
|
||||
line = sm.proof_line(self.item(proves=["hle_fallback of mpeg_card.bin"], verdicts=[
|
||||
{"variant": "default", "verdict": "boots", "bios_used": "staged:mpeg_card.bin", "detail": "d"}]))
|
||||
self.assertEqual(html.unescape(line), f"- hle_fallback of mpeg_card.bin: boots on mpeg_card.bin "
|
||||
f"([record]({self.ITEM['record_url']})).")
|
||||
issue = sm.proof_line(self.item(subject="issue85-lunar-opening-movie", proves=[], verdicts=[],
|
||||
claim=None, content="Lunar"))
|
||||
self.assertTrue(issue.startswith("- issue 85: a run of Lunar, recorded before the boot oracle"))
|
||||
section = sm.proof_section([self.item(proves=["required of a.bin"], verdicts=[])])
|
||||
self.assertEqual(section[0], "## Proof")
|
||||
URL = f"{REPO_URL}/blob/{'e' * 40}/measurements/beetle_psx.jsonl"
|
||||
|
||||
def record(self, line: int, proves=(), shown=None, observed=None) -> dict:
|
||||
return {"url": f"{self.URL}#L{line}", "proves": list(proves), "shown": shown, "observed": observed}
|
||||
|
||||
def lines(self, *items: dict) -> list[str]:
|
||||
return [html.unescape(line) for line in sm.proof_section(list(items)) if line.startswith("- ")]
|
||||
|
||||
def test_one_line_per_claim(self) -> None:
|
||||
"""Records that back the same claim collapse into one line: every
|
||||
name strace saw opened in one list, each result once."""
|
||||
alias = "aliases of scph5501.bin"
|
||||
builtin = ["text", sm.proof_result([{"variant": "default", "verdict": sm.BOOTS_BUILTIN,
|
||||
"bios_used": "builtin", "detail": "", "staged": []}])]
|
||||
lines = self.lines(
|
||||
self.item(subject="alias-b", records=[self.record(5, [alias], ["opened", "SCPH5501.BIN"])]),
|
||||
self.item(subject="alias-a", records=[self.record(3, [alias], ["opened", "SCPH-5501.BIN"])]),
|
||||
self.item(subject="none", records=[self.record(9, ["hle_fallback of scph5501.bin"], builtin),
|
||||
self.record(7, ["hle_fallback of scph5501.bin"], builtin)]))
|
||||
self.assertEqual(lines, [
|
||||
f"- aliases of scph5501.bin: the core opened SCPH-5501.BIN, SCPH5501.BIN "
|
||||
f"(records [1]({self.URL}#L3), [2]({self.URL}#L5)).",
|
||||
f"- hle_fallback of scph5501.bin: with no BIOS, it boots on the core's built-in BIOS "
|
||||
f"(records [1]({self.URL}#L7), [2]({self.URL}#L9)).",
|
||||
])
|
||||
many = self.lines(self.item(subject="s", records=[
|
||||
self.record(n, ["required of a.bin"], ["text", "with no BIOS, it hangs"]) for n in range(1, 11)]))
|
||||
self.assertEqual(many, [f"- required of a.bin: with no BIOS, it hangs ([10 records]({self.URL}))."])
|
||||
# Two results for one claim stay on its one line, each with its records.
|
||||
mixed = self.lines(self.item(subject="s", records=[
|
||||
self.record(1, ["validation of a.bin"], ["text", "a.bin: boots. zeros: hangs"]),
|
||||
self.record(2, ["validation of a.bin"], ["text", "with no BIOS, it boots"])]))
|
||||
self.assertEqual(mixed, [f"- validation of a.bin: a.bin: boots. zeros: hangs ([record]({self.URL}#L1)). "
|
||||
f"With no BIOS, it boots ([record]({self.URL}#L2))."])
|
||||
|
||||
def test_a_line_says_what_was_observed_or_is_left_out(self) -> None:
|
||||
said = {"issue": "85", "said": "the Lunar opening movie plays with sound"}
|
||||
lines = self.lines(
|
||||
# A pre-oracle record with no opened file and no observation: nothing to state.
|
||||
self.item(subject="alias-x", records=[self.record(1, ["aliases of a.bin"], None)]),
|
||||
self.item(subject="issue85-vcd-player-boot", records=[self.record(2)]),
|
||||
self.item(subject="issue85-lunar-opening-movie",
|
||||
records=[self.record(3, observed=said), self.record(4)]))
|
||||
self.assertEqual(lines, [f"- issue 85: the Lunar opening movie plays with sound ([record]({self.URL}#L3))."])
|
||||
self.assertEqual(sm.proof_section([self.item(records=[self.record(1)])]), [])
|
||||
|
||||
def test_no_page_says_before_the_boot_oracle(self) -> None:
|
||||
stored = mr.read_records(REPO_ROOT)
|
||||
index = sm.build_index(stored, {"repo": REPO_URL, "commit": "e" * 40}, sm.load_profiles(REPO_ROOT / "emulators"),
|
||||
None, sm.load_observations(REPO_ROOT / sm.OBSERVATIONS))
|
||||
for emulator, items in sm.by_emulator(index).items():
|
||||
text = "\n".join(sm.proof_section(items))
|
||||
self.assertNotIn("boot oracle", text, emulator)
|
||||
# One line per profile field: its records never spread over two lines.
|
||||
fields = [line.split(":")[0] for line in text.splitlines()
|
||||
if line.startswith("- ") and not line.startswith("- issue ")]
|
||||
self.assertEqual(len(fields), len(set(fields)), emulator)
|
||||
lines = [html.unescape(line) for line in sm.proof_section(sm.by_emulator(index).get("beetle_psx", []))
|
||||
if line.startswith("- aliases of")]
|
||||
self.assertEqual(len(lines), 1)
|
||||
self.assertIn("the core opened ", lines[0])
|
||||
|
||||
def test_every_observation_names_records_that_exist(self) -> None:
|
||||
observations = sm.load_observations(REPO_ROOT / sm.OBSERVATIONS)
|
||||
stored = mr.read_records(REPO_ROOT)
|
||||
known = {s.record["id"] for s in stored} | {s.record["subject"] for s in stored}
|
||||
self.assertTrue(observations)
|
||||
self.assertLessEqual(set(observations), known, set(observations) - known)
|
||||
|
||||
def test_the_issue_85_comparison_holds_in_the_records(self) -> None:
|
||||
"""Video and audio equal on each disc across both core commits, card
|
||||
off and on: the sentence the Proof line gives."""
|
||||
said = sm.load_observations(REPO_ROOT / sm.OBSERVATIONS)["issue85-regression-card-on"]["said"]
|
||||
self.assertIn("20 discs", said)
|
||||
runs: dict[str, list[dict]] = {}
|
||||
for entry in mr.read_records(REPO_ROOT):
|
||||
if entry.record["subject"] in ("issue85-regression-card-off", "issue85-regression-card-on"):
|
||||
runs.setdefault(entry.record["inputs"]["content"]["label"], []).append(entry.record)
|
||||
if not runs:
|
||||
self.skipTest("no issue 85 record")
|
||||
self.assertEqual(len(runs), 20)
|
||||
for disc, records in runs.items():
|
||||
with self.subTest(disc=disc):
|
||||
self.assertEqual(len({r["core"]["commit"] for r in records}), 2)
|
||||
self.assertEqual({r["subject"] for r in records},
|
||||
{"issue85-regression-card-off", "issue85-regression-card-on"})
|
||||
seen = {(rep["observables"]["video_sha1"], rep["observables"]["audio_sha1"])
|
||||
for r in records for v in r["variants"] for rep in v["repetitions"]}
|
||||
self.assertEqual(len(seen), 1)
|
||||
|
||||
def test_the_removed_blocks_are_gone(self) -> None:
|
||||
for name in ("tested_section", "region_section", "core_region_line", "campaign_section",
|
||||
@@ -498,14 +575,14 @@ class SitePages(unittest.TestCase):
|
||||
|
||||
def test_run_output_is_text_never_markup(self) -> None:
|
||||
nasty = "`code` {expr} <script>alert(1)</script> [x](javascript:alert(1)) \"q\" 'q' **b**"
|
||||
line = sm.proof_line(self.item(proves=[nasty], verdicts=[
|
||||
{"variant": nasty, "verdict": nasty, "bios_used": f"staged:{nasty}", "detail": nasty},
|
||||
{"variant": nasty, "verdict": "boots", "bios_used": "builtin", "detail": nasty}],
|
||||
record_url="javascript:alert(1)"))
|
||||
verdicts = [{"variant": nasty, "verdict": nasty, "bios_used": f"staged:{nasty}", "detail": nasty},
|
||||
{"variant": nasty, "verdict": "boots", "bios_used": "builtin", "detail": nasty}]
|
||||
line = sm.proof_line(nasty, [(["text", sm.proof_result(verdicts)], ["javascript:alert(1)"]),
|
||||
(["opened", nasty], ["javascript:alert(1)"])])
|
||||
self.assertNotIn("<script", line)
|
||||
self.assertNotIn("(javascript:", line)
|
||||
self.assertNotRegex(line, r"[{}`*]")
|
||||
self.assertNotRegex(line, r"\[(?!record\])")
|
||||
self.assertNotRegex(line, r"\[")
|
||||
self.assertNotIn("](", line)
|
||||
self.assertIn("<script>", line)
|
||||
|
||||
|
||||
@@ -246,18 +246,20 @@ class SitePages(unittest.TestCase):
|
||||
import sitemeasurements as sm
|
||||
|
||||
stored = mr.read_records(ROOT)
|
||||
index = sm.build_index(stored, {"repo": sm.REPO, "commit": "0" * 40}, sm.load_profiles(ROOT / "emulators"))
|
||||
index = sm.build_index(stored, {"repo": sm.REPO, "commit": "0" * 40}, sm.load_profiles(ROOT / "emulators"),
|
||||
None, sm.load_observations(ROOT / sm.OBSERVATIONS))
|
||||
items = sm.by_emulator(index).get("beetle_psx") or []
|
||||
if not items:
|
||||
self.skipTest("no beetle_psx record")
|
||||
text = "\n".join(sm.proof_section(items))
|
||||
self.assertNotIn("Region check", text)
|
||||
lines = [line for line in text.splitlines() if line.startswith("- ")]
|
||||
self.assertEqual(len(lines), sum(1 for i in items if i["proves"]))
|
||||
required = [line for line in lines if line.startswith("- required of scph55")]
|
||||
self.assertEqual(len(required), 3)
|
||||
for line in required:
|
||||
self.assertIn("boots on the core's built-in BIOS", line)
|
||||
# The run staged only the other regions' files and booted OpenBIOS.
|
||||
self.assertIn("it boots on the core's built-in BIOS", line)
|
||||
self.assertIn(", it boots", line)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -155,7 +155,7 @@ class ThePullRequestBuildsTheSite(unittest.TestCase):
|
||||
}
|
||||
self.assertIn("wiki/**", inputs)
|
||||
# A path the deploy names inside a folder validate.yml watches
|
||||
# whole (tests/campaign/content.yml under tests/**) is watched.
|
||||
# whole (tests/campaign/observations.yml under tests/**) is watched.
|
||||
unwatched = [path for path in inputs - watched
|
||||
if not any(fnmatch.fnmatch(path, pattern) for pattern in watched)]
|
||||
self.assertEqual(sorted(unwatched), [])
|
||||
|
||||
+1
-1
@@ -848,7 +848,7 @@ Runs a libretro core with no window, no sound and no input device, and
|
||||
reports what it did. It is the test in real conditions behind a claim about
|
||||
a core: which files it opens, what it shows, which BIOS it ran.
|
||||
|
||||
These probes run on demand only, for three cases: to settle a dispute or an issue, to back a correction sent to a platform, and to check the packs before a release. They are never run as a campaign over every emulator, and the site keeps no showcase of their runs: an emulator page shows a run only when a profile's `evidence:` names it or it answers an issue (`issue<N>-` subjects), as one **Proof** line naming the BIOS the core ran. Every record stays in `measurements/` and on the Measurements page. Benchmarks (`bench`) stay in the records and the SQLite files and
|
||||
These probes run on demand only, for three cases: to settle a dispute or an issue, to back a correction sent to a platform, and to check the packs before a release. They are never run as a campaign over every emulator, and the site keeps no showcase of their runs: an emulator page shows a run only when a profile's `evidence:` names it or it answers an issue (`issue<N>-` subjects). Its **Proof** section has one line per claim, every record of that claim linked on it, and says what the runs showed: the BIOS the core ran, or the file strace saw it open. What an issue's run showed comes from `tests/campaign/observations.yml`, written by whoever watched it, and a run with nothing to state stays off the page. Every record stays in `measurements/` and on the Measurements page. Benchmarks (`bench`) stay in the records and the SQLite files and
|
||||
only choose between variants: no page shows a time per frame.
|
||||
|
||||
```bash
|
||||
|
||||
Reference in new issue
Block a user