mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-25 06:33:13 +08:00
Preserve the current selector, frozen-input inventory, result codec, coverage collection, runner filtering, and isolated Windows venue work. Component-level regression proofs are recorded in the PR handover. The live classified provider, public execution integration, artifact admission, fresh oracle/shadow evidence, and full platform gates remain incomplete. This checkpoint does not enable or claim verified narrowing. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
505 lines
23 KiB
Python
505 lines
23 KiB
Python
#!/usr/bin/env python3
|
|
"""Six genuine canonical-runner child-coverage cases; one oracle in every phase."""
|
|
import argparse
|
|
import errno
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import re
|
|
import signal
|
|
import stat
|
|
import subprocess
|
|
import sys
|
|
import threading
|
|
import time
|
|
|
|
DEADLINE = 60
|
|
GRACE = 5
|
|
LOG_CAP = 1024 * 1024
|
|
ANSI = re.compile(r"\x1b\[[0-9;]*m")
|
|
COUNT_PREFIX = "cbm_cov_child_count_"
|
|
PROCESS_RECORDS = []
|
|
MATRIX = (
|
|
("explicit_success", "coverage_children", ["coverage_explicit_success"], ["lower", "upper"]),
|
|
("explicit_write_failure", "coverage_children", ["coverage_explicit_write_failure"], ["lower", "upper"]),
|
|
("normal_exit", "coverage_children", ["coverage_normal_exit"], ["normal_ok", "normal_bad"]),
|
|
("exec_wrappers", "coverage_children", ["coverage_exec_wrappers"],
|
|
["execve", "execv", "execvp", "execl", "failed_exec"]),
|
|
("setup_success", "coverage_setup_success", ["coverage_setup_first", "coverage_setup_second"], ["setup_ok"]),
|
|
("setup_uncertain", "coverage_setup_uncertain", ["coverage_setup_first", "coverage_setup_second"], ["setup_killed"]),
|
|
)
|
|
|
|
|
|
class Infrastructure(Exception):
|
|
pass
|
|
|
|
|
|
def save(path, value):
|
|
with path.open("x", encoding="utf-8") as stream:
|
|
json.dump(value, stream, indent=2, sort_keys=True)
|
|
stream.write("\n")
|
|
|
|
|
|
def identity(path, executable=False):
|
|
path = Path(path).resolve(strict=True)
|
|
info = path.stat()
|
|
if not stat.S_ISREG(info.st_mode) or (executable and not os.access(str(path), os.X_OK)):
|
|
raise Infrastructure("invalid input file: " + str(path))
|
|
digest = hashlib.sha256()
|
|
with path.open("rb") as stream:
|
|
for data in iter(lambda: stream.read(1024 * 1024), b""):
|
|
digest.update(data)
|
|
return {"path": str(path), "bytes": info.st_size, "sha256": digest.hexdigest()}
|
|
|
|
|
|
def drain(pipe, destination, state, stop):
|
|
try:
|
|
with destination.open("xb", buffering=0) as stream:
|
|
while True:
|
|
data = pipe.read(4096)
|
|
if not data:
|
|
break
|
|
state["seen"] += len(data)
|
|
part = memoryview(data)[:max(0, LOG_CAP - state["saved"])]
|
|
while part:
|
|
size = stream.write(part)
|
|
if not size:
|
|
raise OSError("short evidence write")
|
|
state["saved"] += size
|
|
part = part[size:]
|
|
if state["seen"] > LOG_CAP:
|
|
state["overflow"] = True
|
|
stop.set()
|
|
except (OSError, ValueError) as exc:
|
|
state["error"] = str(exc)
|
|
stop.set()
|
|
finally:
|
|
pipe.close()
|
|
|
|
|
|
def group_exists(pid):
|
|
try:
|
|
os.killpg(pid, 0)
|
|
return True
|
|
except ProcessLookupError:
|
|
return False
|
|
|
|
|
|
def signal_group(pid, sig):
|
|
try:
|
|
os.killpg(pid, sig)
|
|
except ProcessLookupError:
|
|
pass
|
|
|
|
|
|
def quiesce(proc):
|
|
# Every spawned process is the leader of its own new session/group. Nested
|
|
# reducer tools inherit that group. C fixtures separately prove native reaps.
|
|
notes = []
|
|
for sig in (signal.SIGTERM, signal.SIGKILL):
|
|
if proc.poll() is not None and not group_exists(proc.pid):
|
|
return True, notes
|
|
signal_group(proc.pid, sig)
|
|
notes.append("sent " + signal.Signals(sig).name)
|
|
until = time.monotonic() + GRACE
|
|
while time.monotonic() < until:
|
|
if proc.poll() is not None and not group_exists(proc.pid):
|
|
return True, notes
|
|
time.sleep(min(0.05, max(0, until - time.monotonic())))
|
|
return proc.poll() is not None and not group_exists(proc.pid), notes
|
|
|
|
|
|
def run_process(directory, label, argv, environment):
|
|
record = {"argv": argv, "deadline_seconds": DEADLINE, "returncode": None,
|
|
"failure": None, "quiescent": False,
|
|
"stdout": label + ".stdout.log", "stderr": label + ".stderr.log"}
|
|
start = time.monotonic()
|
|
proc = None
|
|
threads, started_pipes, states = [], [], {}
|
|
stop = threading.Event()
|
|
try:
|
|
proc = subprocess.Popen(argv, env=environment, stdin=subprocess.DEVNULL,
|
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
bufsize=0, start_new_session=True)
|
|
record["pid"] = proc.pid
|
|
for kind, pipe in (("stdout", proc.stdout), ("stderr", proc.stderr)):
|
|
state = {"seen": 0, "saved": 0, "overflow": False, "error": None}
|
|
thread = threading.Thread(target=drain,
|
|
args=(pipe, directory / record[kind], state, stop), daemon=True)
|
|
thread.start()
|
|
threads.append(thread)
|
|
started_pipes.append(pipe)
|
|
states[kind] = state
|
|
while proc.poll() is None:
|
|
left = DEADLINE - (time.monotonic() - start)
|
|
if stop.is_set() or left <= 0:
|
|
record["failure"] = "capture limit/error" if stop.is_set() else "timeout"
|
|
break
|
|
try:
|
|
proc.wait(timeout=min(left, 0.1))
|
|
except subprocess.TimeoutExpired:
|
|
pass
|
|
except (OSError, RuntimeError, KeyboardInterrupt) as exc:
|
|
record["failure"] = type(exc).__name__ + ": " + str(exc)
|
|
finally:
|
|
if proc is not None:
|
|
try:
|
|
record["quiescent"], record["cleanup"] = quiesce(proc)
|
|
if record["cleanup"] and record["failure"] is None:
|
|
record["failure"] = "unexpected processes remained after leader exit"
|
|
except (OSError, KeyboardInterrupt) as exc:
|
|
record["cleanup_error"] = str(exc)
|
|
if not record["quiescent"]:
|
|
record["failure"] = record["failure"] or "owned process group did not quiesce"
|
|
for pipe in (proc.stdout, proc.stderr):
|
|
if pipe not in started_pipes:
|
|
pipe.close()
|
|
until = time.monotonic() + GRACE
|
|
for thread in threads:
|
|
thread.join(timeout=max(0, until - time.monotonic()))
|
|
if any(thread.is_alive() for thread in threads):
|
|
record["failure"] = record["failure"] or "pipe readers did not quiesce"
|
|
record["returncode"] = proc.poll()
|
|
if any(state["overflow"] or state["error"] for state in states.values()):
|
|
record["failure"] = record["failure"] or "bounded capture failed"
|
|
record["streams"] = states
|
|
record["elapsed_seconds"] = round(time.monotonic() - start, 3)
|
|
PROCESS_RECORDS.append(record)
|
|
save(directory / (label + ".process.json"), record)
|
|
return record
|
|
|
|
|
|
def require_process(record):
|
|
if record["failure"] or not record["quiescent"] or record["returncode"] != 0:
|
|
raise Infrastructure("process failed: " + json.dumps(record))
|
|
|
|
|
|
def regular_nonempty(path):
|
|
try:
|
|
value = path.lstat()
|
|
return stat.S_ISREG(value.st_mode) and value.st_size > 0
|
|
except OSError:
|
|
return False
|
|
|
|
|
|
def read_log(directory, record, kind):
|
|
return (directory / record[kind]).read_text(encoding="utf-8", errors="replace")
|
|
|
|
|
|
def validate_test_output(stdout, tests):
|
|
clean = ANSI.sub("", stdout)
|
|
rows = re.findall(r"(?m)^ ([A-Za-z_][A-Za-z0-9_]*)[ \t]+(PASS|FAIL|SKIP)\b", clean)
|
|
starts = re.findall(r"(?m)^ (coverage_[A-Za-z0-9_]+)\b", clean)
|
|
summaries = re.findall(r"(?m)^[ \t]*(\d+) passed(?:, (\d+) failed)?(?:, (\d+) skipped)?"
|
|
r"(?:, (\d+) deselected)?[ \t]*$", clean)
|
|
if rows != [(name, "PASS") for name in tests] or starts != tests or len(summaries) != 1:
|
|
raise Infrastructure("selected native tests did not run exactly once and pass")
|
|
if [int(value or 0) for value in summaries[0]][:3] != [len(tests), 0, 0]:
|
|
raise Infrastructure("native suite summary failed")
|
|
|
|
|
|
def parse_events(stderr, ids):
|
|
events = {name: [] for name in ids}
|
|
for line in stderr.splitlines():
|
|
if not line.startswith("COV_CHILD "):
|
|
continue
|
|
try:
|
|
item = json.loads(line[len("COV_CHILD "):])
|
|
except ValueError as exc:
|
|
raise Infrastructure("invalid fixture event") from exc
|
|
if (not isinstance(item, dict) or set(item) != {"id", "pid", "stage", "marker", "code"}
|
|
or not isinstance(item["id"], str) or item["id"] not in events
|
|
or type(item["pid"]) is not int or item["pid"] <= 0
|
|
or type(item["marker"]) is not int or item["marker"] not in (-1, 0, 1)
|
|
or type(item["code"]) is not int or not isinstance(item["stage"], str)):
|
|
raise Infrastructure("invalid fixture event fields")
|
|
events[item["id"]].append(item)
|
|
return events
|
|
|
|
|
|
def validate_events(case_name, events):
|
|
pids, final = set(), {}
|
|
for name, rows in events.items():
|
|
obstacle = case_name == "explicit_write_failure" or name == "normal_bad"
|
|
stages = ["ready"]
|
|
if obstacle:
|
|
stages += ["obstacle_held", "obstacle_reaped", "obstacle_removed"]
|
|
if name in ("execve", "execv", "execvp", "execl"):
|
|
stages += ["exec_held"]
|
|
if name == "failed_exec":
|
|
stages += ["execve_failed", "execv_failed", "execvp_failed", "execl_failed"]
|
|
stages += ["reaped"]
|
|
if [row["stage"] for row in rows] != stages:
|
|
raise Infrastructure("missing, duplicate, or unordered child events: " + name)
|
|
pid = rows[0]["pid"]
|
|
if pid in pids or any(row["pid"] != pid for row in rows):
|
|
raise Infrastructure("child PID evidence inconsistent")
|
|
pids.add(pid)
|
|
if rows[0]["marker"] != 1 or rows[0]["code"] != 0:
|
|
raise Infrastructure("post-atfork initial marker was not observed")
|
|
expected_status = 128 + signal.SIGKILL if name == "setup_killed" else 0
|
|
if rows[-1]["code"] != expected_status or rows[-1]["marker"] < 0:
|
|
raise Infrastructure("child was not reaped with its expected status")
|
|
for row in rows[1:-1]:
|
|
if row["stage"].startswith("obstacle_"):
|
|
good = row["code"] == 1 and row["marker"] == -1
|
|
else:
|
|
good = row["marker"] >= 0 and row["code"] == (errno.ENOENT if name == "failed_exec" else 0)
|
|
if not good:
|
|
raise Infrastructure("child gate/obstacle control failed")
|
|
final[name] = rows[-1]
|
|
return final
|
|
|
|
|
|
def validate_native_errors(stderr, expected_paths):
|
|
found = set()
|
|
for line in stderr.splitlines():
|
|
if line.startswith("coverage child fixture failed:") or line.startswith("coverage profile write failed:"):
|
|
raise Infrastructure("native fixture or normal-parent coverage failed")
|
|
if line.startswith("LLVM Profile Error:"):
|
|
match = re.fullmatch(r'LLVM Profile Error: Failed to write file "(.*)": (.+)', line)
|
|
if not match:
|
|
raise Infrastructure("unknown LLVM diagnostic precondition")
|
|
path = os.path.normpath(match.group(1))
|
|
if path not in expected_paths:
|
|
raise Infrastructure("LLVM write failure did not name an owned obstacle")
|
|
found.add(path)
|
|
if found != expected_paths:
|
|
raise Infrastructure("intended genuine LLVM write failure was not observed")
|
|
|
|
|
|
def exact_positive_count(text, function):
|
|
blocks = []
|
|
current = None
|
|
for line in text.splitlines():
|
|
heading = re.fullmatch(r" (.+):", line)
|
|
if heading:
|
|
current = {"name": heading.group(1), "counts": []}
|
|
blocks.append(current)
|
|
elif current is not None:
|
|
count = re.fullmatch(r" Function count: ([0-9]+)", line)
|
|
if count:
|
|
current["counts"].append(int(count.group(1)))
|
|
exact = [block for block in blocks if block["name"] == function]
|
|
if len(exact) != 1 or len(exact[0]["counts"]) != 1 or exact[0]["counts"][0] <= 0:
|
|
raise Infrastructure("exact child-only function lacks one positive native count: " + function)
|
|
return exact[0]["counts"][0]
|
|
|
|
|
|
def profile_controls(case, suite_dir, tool, environment, witnesses):
|
|
profiles = sorted(suite_dir.glob("*.profraw"))
|
|
if not profiles or len(profiles) > 64:
|
|
raise Infrastructure("unexpected finite profile inventory")
|
|
results = []
|
|
for index, raw in enumerate(profiles):
|
|
if not regular_nonempty(raw):
|
|
raise Infrastructure("profile is not regular/nonempty: " + str(raw))
|
|
merged = case / ("profile-%02d.profdata" % index)
|
|
record = run_process(case, "merge-%02d" % index,
|
|
[tool, "merge", "--instr", "--output=" + str(merged), str(raw)], environment)
|
|
require_process(record)
|
|
if not regular_nonempty(merged):
|
|
raise Infrastructure("matching profdata produced no valid indexed profile")
|
|
item = {"raw": str(raw), "merged": str(merged), "valid": True}
|
|
if raw.name in witnesses:
|
|
function = witnesses[raw.name]
|
|
shown = run_process(case, "count-%02d" % index,
|
|
[tool, "show", "--counts", "--function=" + function, str(merged)], environment)
|
|
require_process(shown)
|
|
item["function"] = function
|
|
item["function_count"] = exact_positive_count(read_log(case, shown, "stdout"), function)
|
|
results.append(item)
|
|
if set(witnesses) - {Path(item["raw"]).name for item in results}:
|
|
raise Infrastructure("expected genuine child profile is absent")
|
|
return results
|
|
|
|
|
|
def reducer_worker():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--reduce-worker", action="store_true", required=True)
|
|
parser.add_argument("--reducer", required=True)
|
|
parser.add_argument("--suite", required=True)
|
|
parser.add_argument("--suite-dir", required=True)
|
|
parser.add_argument("--profdata", required=True)
|
|
parser.add_argument("--runner-returncode", required=True, type=int)
|
|
args = parser.parse_args()
|
|
sys.dont_write_bytecode = True
|
|
spec = importlib.util.spec_from_file_location("coverage_child_actual_reducer", args.reducer)
|
|
if spec is None or spec.loader is None:
|
|
raise Infrastructure("cannot load actual reducer")
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
result = module.reduce_suite(args.suite, args.suite_dir, args.profdata, args.runner_returncode == 0)
|
|
rows = {name: {"status": row[0], "reason": row[1], "names_count": len(row[2])}
|
|
for name, row in result.items()}
|
|
print(json.dumps(rows, sort_keys=True))
|
|
return 0
|
|
|
|
|
|
def reduce_actual(case, suite, suite_dir, tool, reducer, runner_record, environment):
|
|
argv = [sys.executable, str(Path(__file__).resolve()), "--reduce-worker",
|
|
"--reducer", reducer, "--suite", suite, "--suite-dir", str(suite_dir),
|
|
"--profdata", tool, "--runner-returncode", str(runner_record["returncode"])]
|
|
record = run_process(case, "reduce", argv, environment)
|
|
require_process(record)
|
|
try:
|
|
rows = json.loads(read_log(case, record, "stdout"))
|
|
except ValueError as exc:
|
|
raise Infrastructure("actual reducer did not return valid JSON") from exc
|
|
if not isinstance(rows, dict) or len(rows) > 16:
|
|
raise Infrastructure("unexpected reducer row inventory")
|
|
for row in rows.values():
|
|
if (not isinstance(row, dict) or set(row) != {"status", "reason", "names_count"}
|
|
or row["status"] not in ("complete", "incomplete") or not isinstance(row["reason"], str)
|
|
or type(row["names_count"]) is not int or row["names_count"] < 0):
|
|
raise Infrastructure("invalid actual reducer row")
|
|
return rows
|
|
|
|
|
|
def features(case_name, tests, events, final, rows):
|
|
problems = []
|
|
retained = []
|
|
for name, row in final.items():
|
|
expected = case_name in ("explicit_write_failure", "normal_exit", "setup_uncertain")
|
|
expected = expected or (case_name == "exec_wrappers" and name != "failed_exec")
|
|
if row["marker"] != int(expected):
|
|
problems.append(name + ": final marker retirement incorrect")
|
|
if expected:
|
|
retained.append(str(row["pid"]))
|
|
for held in events[name]:
|
|
if held["stage"] == "exec_held" or held["stage"].endswith("_failed"):
|
|
if held["marker"] != 1:
|
|
problems.append(name + ": marker absent at " + held["stage"])
|
|
expected_keys = set(tests) | {"*"}
|
|
if set(rows) != expected_keys:
|
|
problems.append("actual reducer emitted missing or synthetic runnable rows")
|
|
uncertain_key = "*" if case_name == "setup_uncertain" else tests[0]
|
|
reason = "unaccounted forked child: " + ",".join(sorted(retained)) if retained else ""
|
|
for key in expected_keys:
|
|
expected_reason = reason if key == uncertain_key else ""
|
|
status = "incomplete" if expected_reason else "complete"
|
|
row = rows.get(key)
|
|
if row is None or row["status"] != status or row["reason"] != expected_reason:
|
|
problems.append("actual reducer status/reason mismatch: " + key)
|
|
return problems
|
|
|
|
|
|
def run_case(root, definition, runner, tool, reducer):
|
|
name, suite, tests, ids = definition
|
|
case = root / name
|
|
case.mkdir(mode=0o700)
|
|
coverage = case / "coverage"
|
|
coverage.mkdir(mode=0o700)
|
|
suite_dir = coverage / suite
|
|
result = {"case": name, "suite": suite, "tests": tests, "controls_passed": False}
|
|
environment = os.environ.copy()
|
|
environment["LLVM_PROFILE_FILE"] = "/dev/null"
|
|
environment["CBM_TEST_COVERAGE_DIR"] = str(coverage)
|
|
environment["CBM_TEST_ONLY"] = ",".join(suite + ":" + test for test in tests)
|
|
environment.pop("CBM_TEST_ONLY_FILE", None)
|
|
try:
|
|
record = run_process(case, "runner", [runner, suite], environment)
|
|
result["runner"] = record
|
|
require_process(record)
|
|
stdout, stderr = read_log(case, record, "stdout"), read_log(case, record, "stderr")
|
|
validate_test_output(stdout, tests)
|
|
events = parse_events(stderr, ids)
|
|
final = validate_events(name, events)
|
|
result["events"] = events
|
|
witnesses, obstacles = {}, set()
|
|
stem = "_setup.child" if name.startswith("setup_") else tests[0]
|
|
suffixes = {"lower": "lower", "upper": "upper", "normal_ok": "normal",
|
|
"failed_exec": "failed_exec", "setup_ok": "setup"}
|
|
for child_id, event in final.items():
|
|
raw = suite_dir / (stem + "." + str(event["pid"]) + ".profraw")
|
|
marker = raw.with_suffix(".forked")
|
|
present = marker.exists()
|
|
if present != bool(event["marker"]) or (present and not stat.S_ISREG(marker.lstat().st_mode)):
|
|
raise Infrastructure("recorded final marker differs from completed filesystem")
|
|
obstructed = name == "explicit_write_failure" or child_id == "normal_bad"
|
|
if obstructed:
|
|
obstacles.add(os.path.normpath(str(raw)))
|
|
if os.path.lexists(str(raw)):
|
|
raise Infrastructure("owned empty obstruction was not removed after reap")
|
|
elif child_id == "setup_killed":
|
|
if os.path.lexists(str(raw)):
|
|
raise Infrastructure("deliberately killed held child unexpectedly wrote a profile")
|
|
elif child_id in suffixes:
|
|
witnesses[raw.name] = COUNT_PREFIX + suffixes[child_id]
|
|
validate_native_errors(stderr, obstacles)
|
|
for test in tests:
|
|
if not regular_nonempty(suite_dir / (test + ".parent.profraw")):
|
|
raise Infrastructure("passing selected test lacks its genuine parent profile")
|
|
result["profiles"] = profile_controls(case, suite_dir, tool, environment, witnesses)
|
|
result["rows"] = reduce_actual(case, suite, suite_dir, tool, reducer, record, environment)
|
|
result["feature_problems"] = features(name, tests, events, final, result["rows"])
|
|
if name in ("explicit_success", "setup_success") and result["feature_problems"]:
|
|
raise Infrastructure("positive retirement/reducer control failed")
|
|
result["controls_passed"] = True
|
|
except (Infrastructure, OSError, ValueError, KeyboardInterrupt) as exc:
|
|
result["infrastructure_error"] = type(exc).__name__ + ": " + str(exc)
|
|
finally:
|
|
save(case / "result.json", result)
|
|
return result
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--runner", required=True)
|
|
parser.add_argument("--llvm-profdata", required=True)
|
|
parser.add_argument("--reducer", required=True)
|
|
parser.add_argument("--output-dir", required=True, help="new owned evidence directory")
|
|
args = parser.parse_args()
|
|
if os.name != "posix":
|
|
print("INFRASTRUCTURE: this fixture requires the frozen POSIX coverage boundary", file=sys.stderr)
|
|
return 2
|
|
try:
|
|
inputs = {"runner": identity(args.runner, True), "profdata": identity(args.llvm_profdata, True),
|
|
"reducer": identity(args.reducer), "driver": identity(__file__)}
|
|
root = Path(args.output_dir).resolve()
|
|
if any(char in str(root) for char in ("%", "\n", "\r")):
|
|
raise Infrastructure("output path must not contain LLVM pattern tokens or newlines")
|
|
root.mkdir(mode=0o700)
|
|
except (OSError, Infrastructure) as exc:
|
|
print("INFRASTRUCTURE: " + str(exc), file=sys.stderr)
|
|
return 2
|
|
receipt = {"schema": 1, "fixed_oracle": True, "runner_invocations": 6,
|
|
"deadline_seconds": DEADLINE, "termination_grace_seconds": GRACE,
|
|
"log_bytes_per_stream": LOG_CAP, "inputs": inputs, "cases": [],
|
|
"overall": "infrastructure_error",
|
|
"capture_limit": "driver streams only; existing reducer internal capture is unchanged"}
|
|
try:
|
|
for definition in MATRIX:
|
|
result = run_case(root, definition, inputs["runner"]["path"], inputs["profdata"]["path"],
|
|
inputs["reducer"]["path"])
|
|
receipt["cases"].append(result)
|
|
if not result["controls_passed"]:
|
|
break
|
|
for name, value in inputs.items():
|
|
if identity(value["path"], name in ("runner", "profdata")) != value:
|
|
raise Infrastructure("proof input changed: " + name)
|
|
if len(receipt["cases"]) == 6 and all(case["controls_passed"] for case in receipt["cases"]):
|
|
failed = False
|
|
for case in receipt["cases"]:
|
|
case["classification"] = "regression_failure" if case["feature_problems"] else "pass"
|
|
failed = failed or bool(case["feature_problems"])
|
|
print(case["case"] + ": " + case["classification"])
|
|
receipt["overall"] = "regression_failure" if failed else "pass"
|
|
except (Infrastructure, OSError, ValueError, KeyboardInterrupt) as exc:
|
|
receipt["error"] = type(exc).__name__ + ": " + str(exc)
|
|
finally:
|
|
receipt["processes"] = PROCESS_RECORDS
|
|
receipt["all_owned_groups_quiescent"] = all(record["quiescent"] for record in PROCESS_RECORDS
|
|
if "pid" in record)
|
|
commands = {(inputs["runner"]["path"], definition[1]) for definition in MATRIX}
|
|
receipt["runner_invocations_actual"] = sum(tuple(record["argv"]) in commands
|
|
for record in PROCESS_RECORDS)
|
|
save(root / "result.json", receipt)
|
|
return {"pass": 0, "regression_failure": 1, "infrastructure_error": 2}[receipt["overall"]]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(reducer_worker() if "--reduce-worker" in sys.argv[1:] else main())
|