#!/usr/bin/env python3
"""Require the native acceptance matrix and report observed metadata work."""

import pathlib
import re
import sys


def report(path):
    """Read completed fixture records without accepting partial test output."""
    lines = path.read_text().splitlines()
    completed = set(lines)
    samples = {}
    waits = {}
    pending = None
    pending_wait = None
    invariants = False
    cycles_invariants = False
    cycles_pending = None
    cycles_wait = None
    for line in lines:
        if line == "smp final ownership and interval invariants passed":
            if invariants:
                raise ValueError("duplicate SMP invariant completion")
            invariants = True
        elif match := re.fullmatch(r"smp metadata instructions: 0x([0-9a-f]+)", line):
            pending = int(match[1], 16)
        elif match := re.fullmatch(r"smp acquisition instructions: 0x([0-9a-f]+)", line):
            pending_wait = int(match[1], 16)
        elif match := re.fullmatch(r"smp: ([128])-hart execution passed", line):
            if pending is None or pending <= 0:
                raise ValueError("SMP completion has no positive metadata measurement")
            if not invariants:
                raise ValueError("SMP completion has no final invariant check")
            invariants = False
            name = f"SMP {match[1]} harts"
            if name in samples:
                raise ValueError("duplicate SMP completion")
            samples[name] = pending
            waits[name] = pending_wait
            pending = None
            pending_wait = None
        elif line == "cycles final recovery and invariants passed":
            if cycles_invariants:
                raise ValueError("duplicate cycles invariant completion")
            cycles_invariants = True
        elif match := re.fullmatch(r"cycles metadata instructions: ([0-9a-f]+)", line):
            cycles_pending = int(match[1], 16)
        elif match := re.fullmatch(r"cycles acquisition instructions: ([0-9a-f]+)", line):
            cycles_wait = int(match[1], 16)
        elif match := re.fullmatch(r"cycles: ([128])-hart load, spawn, yield, fault, and recovery passed", line):
            if not cycles_invariants or cycles_pending is None or cycles_pending <= 0:
                raise ValueError("cycles completion has no final invariants or metadata measurement")
            name = f"cycles {match[1]} harts"
            if name in samples:
                raise ValueError("duplicate cycles completion")
            samples[name] = cycles_pending
            waits[name] = cycles_wait
            cycles_invariants = False
            cycles_pending = None
            cycles_wait = None
        elif match := re.fullmatch(r"runtime (admission )?metadata instructions: ([0-9a-f]+)", line):
            name = "runtime admission" if match[1] else "runtime completion"
            if name in samples:
                raise ValueError("duplicate runtime metadata measurement")
            samples[name] = int(match[2], 16)
        elif match := re.fullmatch(r"runtime (admission )?acquisition instructions: ([0-9a-f]+)", line):
            name = "runtime admission" if match[1] else "runtime completion"
            if name in waits:
                raise ValueError("duplicate runtime acquisition measurement")
            waits[name] = int(match[2], 16)
    names = {"SMP 1 harts", "SMP 2 harts", "SMP 8 harts", "runtime admission", "runtime completion"}
    names.update(f"cycles {harts} harts" for harts in (1, 2, 8))
    if samples.keys() != names or any(value <= 0 for value in samples.values()):
        raise ValueError("metadata measurements are incomplete")
    if waits.keys() != names or any(value is None or value <= 0 for value in waits.values()):
        raise ValueError("acquisition measurements are incomplete")
    required = {
        "dispatch: 1-hart execution passed",
        "termination: 1-hart execution passed",
        "runtime: scheduled cancellation, retry, and publication passed",
        "bootstrap: root exit preserves allocation and creation authority",
        "mmio: 1-hart execution passed",
    }
    for harts in (1, 2, 8):
        required.add(f"scheduling: {harts}-hart root handoff, four user-space yields, and checked shutdown passed")
    for profile, counts in (("dispatch", (1,)), ("smp", (1, 2, 8)), ("termination", (1,)),
                            ("runtime", (1,)), ("bootstrap", (1,)), ("mmio", (1,)),
                            ("scheduling", (1, 2, 8)), ("cycles", (1, 2, 8))):
        for harts in counts:
            required.add(f"replay: {profile} {harts}-hart output matched")
    if missing := required - completed:
        raise ValueError("native completions are missing: " + "; ".join(sorted(missing)))
    for name, value in sorted(samples.items()):
        print(f"{name}: {value} maximum metadata instructions")
        print(f"{name}: {waits[name]} maximum acquisition instructions")
    print(f"SMP/runtime/cycles maximum observed metadata work: {max(samples.values())} instructions")
    print(f"SMP/runtime/cycles maximum observed acquisition work: {max(waits.values())} instructions")


def main():
    """Report a log produced by the acceptance runner."""
    if len(sys.argv) != 2:
        raise ValueError("usage: metrics test-log")
    report(pathlib.Path(sys.argv[1]))


if __name__ == "__main__":
    try:
        main()
    except (OSError, ValueError) as error:
        print(f"kernel acceptance: {error}", file=sys.stderr)
        sys.exit(1)
