mirror of
https://github.com/NaC-L/Mergen.git
synced 2026-05-12 09:40:34 +00:00
fix: stabilize full-handler oracle fixtures
This commit is contained in:
@@ -57,6 +57,7 @@ Use `run_microtests.cmd --check-flags <filter>` to enforce oracle flag compariso
|
||||
Use `run_microtests.cmd --build <filter>` to force rebuilding `rewrite_microtests.exe`, or `run_microtests.cmd --no-build <filter>` to skip any build step.
|
||||
Set `SKIP_ORACLE_GENERATION=1` to reuse a pre-generated oracle file. Set `MERGEN_TEST_VECTORS=<path>` to point tests at a custom oracle JSON file.
|
||||
Use `run_all_handlers.cmd` to exercise full handler coverage smoke tests. It writes `lifter/test_vectors/oracle_vectors_full_handlers.json` and then runs microtests against it through `run_microtests.cmd` (which now builds lazily).
|
||||
Oracle vector JSON fixtures are deterministic by design; regenerating them should only change tracked files when the underlying cases change, not because of wall-clock metadata.
|
||||
Full-handler vectors are expected to execute end-to-end (no default `skip: true` crash exclusions).
|
||||
Use `run_flagstress.cmd` (or `python test.py flags`) for broad strict-flag validation across all handlers that explicitly write flags.
|
||||
Use `python test.py semantic` to run runtime semantic regression for all samples (accepts `--filter` to narrow scope and `--input-ir` to override the IR file for a single sample).
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"schema": "mergen-oracle-v1",
|
||||
"generated_at_utc": "2026-03-23T01:08:54.375218+00:00",
|
||||
"source_seed_schema": "mergen-oracle-seed-v1",
|
||||
"providers": [
|
||||
"unicorn"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"schema": "mergen-oracle-v1",
|
||||
"generated_at_utc": "2026-03-23T02:39:45.593139+00:00",
|
||||
"source_seed_schema": "mergen-oracle-seed-v1",
|
||||
"providers": [
|
||||
"unicorn"
|
||||
@@ -4493,6 +4492,40 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "smoke_scasx_scasq",
|
||||
"handler": "scasx",
|
||||
"oracle_mode": "none",
|
||||
"instruction_bytes": [
|
||||
73,
|
||||
175
|
||||
],
|
||||
"initial": {
|
||||
"registers": {
|
||||
"RAX": "0x1122334455667788",
|
||||
"RBX": "0x8877665544332211",
|
||||
"RCX": "0x10",
|
||||
"RDX": "0x2"
|
||||
},
|
||||
"flags": {
|
||||
"FLAG_CF": 0,
|
||||
"FLAG_PF": 0,
|
||||
"FLAG_AF": 0,
|
||||
"FLAG_ZF": 0,
|
||||
"FLAG_SF": 0,
|
||||
"FLAG_OF": 0,
|
||||
"FLAG_DF": 0,
|
||||
"FLAG_IF": 1
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"registers": {},
|
||||
"flags": {}
|
||||
},
|
||||
"oracle_observations": {},
|
||||
"skip": true,
|
||||
"skip_reason": "memory operand in 'scasq rax, qword ptr [rdi]'; needs mapped memory for emulation"
|
||||
},
|
||||
{
|
||||
"name": "smoke_setb_setb",
|
||||
"handler": "setb",
|
||||
|
||||
@@ -4,7 +4,6 @@ import importlib
|
||||
import json
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
@@ -176,6 +175,12 @@ def load_seed(path: Path) -> dict:
|
||||
return payload
|
||||
|
||||
|
||||
def _format_register_hex(reg_name: str, value: int) -> str:
|
||||
if reg_name.upper().startswith("XMM"):
|
||||
return f"0x{value:032x}"
|
||||
return f"0x{value:x}"
|
||||
|
||||
|
||||
def normalize_expected(case: dict, oracle_result: OracleResult) -> dict:
|
||||
expected = case.get("expected", {})
|
||||
out = {
|
||||
@@ -184,7 +189,9 @@ def normalize_expected(case: dict, oracle_result: OracleResult) -> dict:
|
||||
}
|
||||
|
||||
for reg_name in expected.get("registers", {}).keys():
|
||||
out["registers"][reg_name] = f"0x{oracle_result.registers[reg_name]:x}"
|
||||
out["registers"][reg_name] = _format_register_hex(
|
||||
reg_name, oracle_result.registers[reg_name]
|
||||
)
|
||||
|
||||
for flag_name in expected.get("flags", {}).keys():
|
||||
out["flags"][flag_name] = int(oracle_result.flags[flag_name])
|
||||
@@ -218,9 +225,10 @@ def compare_results(results: Dict[str, OracleResult], case_name: str, *, strict:
|
||||
|
||||
|
||||
def build_output(seed_payload: dict, provider_names: List[str], output_cases: List[dict]) -> dict:
|
||||
# These oracle fixtures are checked into the repo, so wall-clock metadata
|
||||
# would create meaningless diffs on every regeneration.
|
||||
return {
|
||||
"schema": "mergen-oracle-v1",
|
||||
"generated_at_utc": datetime.now(timezone.utc).isoformat(),
|
||||
"source_seed_schema": seed_payload["schema"],
|
||||
"providers": provider_names,
|
||||
"cases": output_cases,
|
||||
@@ -371,7 +379,7 @@ def main():
|
||||
"oracle_observations": {
|
||||
provider_name: {
|
||||
"registers": {
|
||||
reg: f"0x{value:x}"
|
||||
reg: _format_register_hex(reg, value)
|
||||
for reg, value in result.registers.items()
|
||||
},
|
||||
"flags": result.flags,
|
||||
|
||||
@@ -3412,6 +3412,38 @@
|
||||
"oracle": "none",
|
||||
"source": "capstone-auto-discovery"
|
||||
},
|
||||
{
|
||||
"name": "smoke_scasx_scasq",
|
||||
"handler": "scasx",
|
||||
"instruction_bytes": [
|
||||
73,
|
||||
175
|
||||
],
|
||||
"initial": {
|
||||
"registers": {
|
||||
"RAX": "0x1122334455667788",
|
||||
"RBX": "0x8877665544332211",
|
||||
"RCX": "0x10",
|
||||
"RDX": "0x2"
|
||||
},
|
||||
"flags": {
|
||||
"FLAG_CF": 0,
|
||||
"FLAG_PF": 0,
|
||||
"FLAG_AF": 0,
|
||||
"FLAG_ZF": 0,
|
||||
"FLAG_SF": 0,
|
||||
"FLAG_OF": 0,
|
||||
"FLAG_DF": 0,
|
||||
"FLAG_IF": 1
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"registers": {},
|
||||
"flags": {}
|
||||
},
|
||||
"oracle": "none",
|
||||
"source": "capstone-auto-discovery"
|
||||
},
|
||||
{
|
||||
"name": "smoke_setb_setb",
|
||||
"handler": "setb",
|
||||
|
||||
@@ -3786,6 +3786,40 @@
|
||||
"oracle": "unicorn",
|
||||
"source": "capstone-auto-discovery"
|
||||
},
|
||||
{
|
||||
"name": "smoke_scasx_scasq",
|
||||
"handler": "scasx",
|
||||
"instruction_bytes": [
|
||||
73,
|
||||
175
|
||||
],
|
||||
"initial": {
|
||||
"registers": {
|
||||
"RAX": "0x1122334455667788",
|
||||
"RBX": "0x8877665544332211",
|
||||
"RCX": "0x10",
|
||||
"RDX": "0x2"
|
||||
},
|
||||
"flags": {
|
||||
"FLAG_CF": 0,
|
||||
"FLAG_PF": 0,
|
||||
"FLAG_AF": 0,
|
||||
"FLAG_ZF": 0,
|
||||
"FLAG_SF": 0,
|
||||
"FLAG_OF": 0,
|
||||
"FLAG_DF": 0,
|
||||
"FLAG_IF": 1
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"registers": {},
|
||||
"flags": {}
|
||||
},
|
||||
"oracle": "none",
|
||||
"source": "capstone-auto-discovery",
|
||||
"skip": true,
|
||||
"skip_reason": "memory operand in 'scasq rax, qword ptr [rdi]'; needs mapped memory for emulation"
|
||||
},
|
||||
{
|
||||
"name": "smoke_setb_setb",
|
||||
"handler": "setb",
|
||||
|
||||
Reference in New Issue
Block a user