Files
cproudlock eaf2dbf167 test harness: smoke-pass B-enforce, fix four issues
Harness now passes 9/9 across baseline + heal + idempotent phases on the
win11 VM (Standard/Machine), with 6 drift scenarios applied + healed
between the baseline and heal cycles in ~30s total.

Fixes:

1. lib/qga-run.py - extracted the qga round-trip out of an inline
   `python3 - <<PY` heredoc. The inline form clobbered stdin (heredoc
   replaces stdin to feed python the script, leaving sys.stdin empty
   for the PowerShell snippet the function caller piped in).
2. lib/qga.sh - dropped `set -euo pipefail`. When sourced, it leaked
   into the harness shell. Then any captured `out=$(qga_run_ps ...)`
   that exited non-zero (verify-state.ps1 returns 1 on any FAIL,
   normal during drift phases) would silently abort the harness.
   Callers handle non-zero with `|| rc=$?`.
3. B-enforce/run.sh do_verify - rewritten to capture rc, parse summary
   line, distinguish expect_pass=true vs false, route to ok / fail
   helper without aborting the harness on a normal non-zero verify.
4. matrix.json WJF Defect Tracker entry - switched detection from File
   to Registry (uninstall key DisplayVersion). The MSI does not drop
   the Defect_Tracker.exe artifact at the documented path even though
   the manifest's File detection treats it as installed; the uninstall
   reg entry is the reliable install marker. v2 manifest's File
   detection path may also need fixing, separate task.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 17:45:06 -04:00

43 lines
1.6 KiB
Python

#!/usr/bin/env python3
# qga-run.py - run a PowerShell snippet inside the win11 VM via qemu-guest-agent.
# Stdin = PS snippet. Stdout = combined stdout, then optional STDERR block,
# then "--- exit N ---". Exit code 0 on PS rc 0, 1 otherwise.
import base64, json, os, subprocess, sys, time
DOMAIN = os.environ.get('VM_DOMAIN', 'win11')
TIMEOUT = int(os.environ.get('QGA_TIMEOUT', '300'))
def virsh(cmd):
p = subprocess.run(
['virsh', '-c', 'qemu:///system', 'qemu-agent-command', DOMAIN, json.dumps(cmd)],
capture_output=True, text=True, timeout=120,
)
if p.returncode != 0:
sys.exit(f"virsh err: {p.stderr.strip()}")
return json.loads(p.stdout)['return']
snippet = sys.stdin.read()
if not snippet.strip():
sys.exit("qga-run.py: empty PowerShell snippet on stdin")
args = ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', snippet]
pid = virsh({'execute': 'guest-exec',
'arguments': {'path': 'powershell.exe', 'arg': args, 'capture-output': True}})['pid']
deadline = time.time() + TIMEOUT
while time.time() < deadline:
st = virsh({'execute': 'guest-exec-status', 'arguments': {'pid': pid}})
if st.get('exited'):
out = base64.b64decode(st.get('out-data', '')).decode('utf-8', 'replace')
err = base64.b64decode(st.get('err-data', '')).decode('utf-8', 'replace')
rc = st.get('exitcode')
sys.stdout.write(out)
if err:
sys.stdout.write('\n--- STDERR ---\n')
sys.stdout.write(err)
sys.stdout.write(f'\n--- exit {rc} ---\n')
sys.exit(0 if rc == 0 else 1)
time.sleep(0.5)
sys.exit(f"timeout waiting for pid {pid}")