Files
RustNotMC/tools/test_collision_parity.py
SashegDev 874b6f20c2 Клиент: начальный импорт кодовой базы
Основа — Horizon (MIT). История апстрима не переносится: этот репозиторий ведёт свою.
2026-10-29 22:04:28 +03:00

88 lines
5.6 KiB
Python

#!/usr/bin/env python3
"""Validate registry-backed cached collisions against the pinned vanilla binaries."""
import argparse
import json
import os
from pathlib import Path
import platform
import shutil
import subprocess
import tempfile
try:
from . import lab, test_rust_parity
except ImportError:
import lab
import test_rust_parity
def counts(output):
marker = "HORIZON_COLLISION_RESULT "
found = [json.loads(line.split(marker, 1)[1]) for line in output.splitlines() if marker in line]
if len(found) != 1:
raise AssertionError(f"Missing collision counts: {found}")
result = found[0]
if result["registry_states"] != 35723 or result["cached_states"] + result["uncached_states"] != result["registry_states"] or result["queries"] != result["cached_states"] * 6 or result["unique_shapes"] <= 0:
raise AssertionError(f"Incomplete collision coverage: {result}")
return result
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--prepare", action="store_true")
args = parser.parse_args()
directory = lab.LOCAL / "rust-collision-parity"
directory.mkdir(parents=True, exist_ok=True)
report_path = directory / "report.json"
report_path.unlink(missing_ok=True)
if args.prepare:
lab.prepare()
lock, jars, libraries = test_rust_parity.verify_artifacts()
for earlier in directory.glob("run-*"): # one run per run used to stay behind: 5 GB here after a few weeks
shutil.rmtree(earlier, ignore_errors=True)
base = Path(tempfile.mkdtemp(prefix="run-", dir=directory))
oracle = lab.ROOT / "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionOracle.java"
sources = [oracle, Path(__file__).resolve(), lab.ROOT / "tools/test_rust_parity.py", lab.ROOT / "Cargo.toml", lab.ROOT / "Cargo.lock", lab.ROOT / "crates/horizon-core/Cargo.toml", lab.ROOT / "crates/horizon-world/Cargo.toml", *sorted((lab.ROOT / "crates/horizon-core/src").rglob("*.rs")), *sorted((lab.ROOT / "crates/horizon-world/src").rglob("*.rs")), lab.ROOT / "crates/horizon-world/examples/probe/collision_fixture.rs"]
tested_sources = test_rust_parity.source_hashes(sources)
classes = base / "classes"
classes.mkdir()
dependency_path = os.pathsep.join(map(str, libraries))
test_rust_parity.run(["javac", "--release", "25", "-proc:none", "-cp", os.pathsep.join([str(jars["server"]), dependency_path]), "-d", str(classes), str(oracle)])
def java(side, mode):
result = subprocess.run(["java", "-Xmx1G", "-cp", os.pathsep.join([str(classes), str(jars[side]), dependency_path]), "dev.horizonlab.parity.VanillaCollisionOracle", mode, str(base)], cwd=lab.ROOT, capture_output=True, text=True, timeout=300)
(base / f"{side}-{mode}.log").write_text(result.stdout + result.stderr, encoding="utf-8")
result.check_returncode()
return result.stdout
expected = counts(java("server", "generate"))
test_rust_parity.run(["cargo", "build", "--release", "-p", "horizon-world", "--example", "world_probe"])
metadata = json.loads(subprocess.check_output(["cargo", "metadata", "--no-deps", "--format-version", "1"], cwd=lab.ROOT, text=True))
binary = Path(metadata["target_directory"]) / "release/examples" / ("world_probe.exe" if os.name=="nt" else "world_probe")
actual = counts(subprocess.check_output([str(binary), "collision_fixture", str(base)], cwd=lab.ROOT, text=True))
if actual != expected:
raise AssertionError(f"Collision coverage differs: vanilla={expected}, Rust={actual}")
canonical = {"empty_states":0,"block_states":0,"other_cached_states":0}
for line in (base / "rust.txt").read_text().splitlines():
if line == 'canonical true false': canonical['empty_states'] += 1
elif line == 'canonical false true': canonical['block_states'] += 1
elif line == 'canonical false false': canonical['other_cached_states'] += 1
if sum(canonical.values()) != expected['cached_states']: raise AssertionError('incomplete canonical identity comparison')
references = []
for side, jar in jars.items():
java(side, side)
reference = base / f"vanilla-{side}.txt"
matched = test_rust_parity.compare(reference, base / "rust.txt")
references.append({"side": side, "jar_sha256": lab.digest(jar, "sha256"), "output_sha256": lab.digest(reference, "sha256"), "matched_output_lines": matched, **expected})
print(f"{side}: {matched:,} cached collision output lines match", flush=True)
test_rust_parity.ensure_sources_unchanged(sources, tested_sources)
report = {"schema": 1, "minecraft": lock["minecraft"]["version"], "manifest_sha1": lock["minecraft"]["manifest_sha1"], "platform": platform.platform(),
"java": subprocess.check_output(["java", "--version"], text=True).splitlines()[0], "rustc": subprocess.check_output(["rustc", "--version"], text=True).strip(),
"inputs_sha256": lab.digest(base / "inputs.txt", "sha256"), "rust_output_sha256": lab.digest(base / "rust.txt", "sha256"), "sources_sha256": tested_sources, "references": references, "canonical_identities":canonical,
"scope": "Pinned no-context cached collision branch only. Registry identity validation, resident section lookup, grids, native canonical empty/block identities distinct from equal geometry, discrete extrema including empty shapes, greedy boxes, bounds, translated collide, ray hits, closest points and moved cell lookup. Uncached and entity-context behavior have separate comparison suites."}
lab.write_json(report_path, report)
lab.write_json(base / "report.json", report)
print(f"Cached collision comparison passed: {report_path}")
if __name__ == "__main__":
main()