#!/bin/bash
|
# Round01 minimized-window QA. It launches a temporary AppKit helper, lets that
|
# helper miniaturize its own window, then verifies the real snapshot sees it.
|
|
set -euo pipefail
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
OUTPUT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
# shellcheck source=build-output-paths.sh
|
source "$SCRIPT_DIR/build-output-paths.sh"
|
SOURCE_ROOT="$OUTPUT_ROOT/C1.source"
|
APP="$BUILD_CURRENT_APP"
|
REPORT="$BUILD_REPORT_ROOT/round01-minimized-window-qa-snapshot.json"
|
SAMPLE_TITLE="Aligner Round01 Minimized QA Sample"
|
HELPER_HOLD_SECONDS="${ALIGNER_ROUND1_MINIMIZED_HELPER_HOLD_SECONDS:-20.0}"
|
READY_ATTEMPTS="${ALIGNER_ROUND1_MINIMIZED_READY_ATTEMPTS:-16}"
|
READY_INTERVAL="${ALIGNER_ROUND1_MINIMIZED_READY_INTERVAL:-0.5}"
|
|
HELPER_PID=""
|
|
cleanup() {
|
if [[ -n "$HELPER_PID" ]] && kill -0 "$HELPER_PID" 2>/dev/null; then
|
kill "$HELPER_PID" 2>/dev/null || true
|
wait "$HELPER_PID" 2>/dev/null || true
|
fi
|
}
|
trap cleanup EXIT
|
|
cd "$SOURCE_ROOT"
|
swift build >&2
|
"$SCRIPT_DIR/package-app.sh" >&2
|
|
swift "$SCRIPT_DIR/round1-minimized-window-helper.swift" "$HELPER_HOLD_SECONDS" &
|
HELPER_PID=$!
|
|
snapshot() {
|
"$APP/Contents/MacOS/Aligner" \
|
--round0-skip-permissions \
|
--round01-dump-window-snapshot \
|
--round01-dump-window-snapshot-pretty > "$REPORT"
|
}
|
|
snapshot_has_minimized_sample() {
|
/usr/bin/python3 - "$REPORT" "$SAMPLE_TITLE" <<'PY'
|
import json
|
import sys
|
|
report_path, sample_title = sys.argv[1:3]
|
def stable_fingerprint(value):
|
hash_value = 0xCBF29CE484222325
|
for byte in (value or "").encode("utf-8"):
|
hash_value ^= byte
|
hash_value = (hash_value * 0x100000001B3) & 0xFFFFFFFFFFFFFFFF
|
return f"{hash_value:016x}"
|
|
sample_title_hash = stable_fingerprint(sample_title)
|
try:
|
with open(report_path, "r", encoding="utf-8") as handle:
|
data = json.load(handle)
|
except Exception:
|
sys.exit(1)
|
|
windows = data.get("windows", [])
|
sample = [
|
window for window in windows
|
if window.get("titleHash") == sample_title_hash
|
and window.get("isMinimized") is True
|
]
|
sys.exit(0 if sample else 1)
|
PY
|
}
|
|
for _ in $(seq 1 "$READY_ATTEMPTS"); do
|
snapshot
|
if snapshot_has_minimized_sample; then
|
break
|
fi
|
sleep "$READY_INTERVAL"
|
done
|
|
/usr/bin/python3 - "$REPORT" "$SAMPLE_TITLE" <<'PY'
|
import json
|
import sys
|
|
report_path, sample_title = sys.argv[1:3]
|
def stable_fingerprint(value):
|
hash_value = 0xCBF29CE484222325
|
for byte in (value or "").encode("utf-8"):
|
hash_value ^= byte
|
hash_value = (hash_value * 0x100000001B3) & 0xFFFFFFFFFFFFFFFF
|
return f"{hash_value:016x}"
|
|
sample_title_hash = stable_fingerprint(sample_title)
|
with open(report_path, "r", encoding="utf-8") as handle:
|
data = json.load(handle)
|
|
windows = data.get("windows", [])
|
minimized = [window for window in windows if window.get("isMinimized") is True]
|
sample_minimized = [
|
window for window in minimized
|
if window.get("titleHash") == sample_title_hash
|
]
|
sample_synthetic = [
|
window for window in sample_minimized
|
if window.get("identifierSource") == "syntheticAX"
|
and window.get("isSyntheticWindowID") is True
|
]
|
sample_cg = [
|
window for window in sample_minimized
|
if window.get("identifierSource") == "cgWindow"
|
and window.get("isSyntheticWindowID") is False
|
]
|
synthetic = [
|
window for window in minimized
|
if window.get("identifierSource") == "syntheticAX"
|
or window.get("isSyntheticWindowID") is True
|
]
|
missing_identifier_source = [window.get("id") for window in windows if "identifierSource" not in window]
|
|
if missing_identifier_source:
|
print(f"Missing identifierSource on windows: {missing_identifier_source}", file=sys.stderr)
|
sys.exit(1)
|
|
if not sample_minimized:
|
print(
|
f"Expected minimized helper window '{sample_title}' in snapshot; "
|
f"minimizedWindowCount={len(minimized)}",
|
file=sys.stderr,
|
)
|
sys.exit(1)
|
|
if not sample_synthetic and not sample_cg:
|
print(
|
f"Expected minimized helper window '{sample_title}' to use cgWindow or syntheticAX; "
|
f"sampleMinimized={sample_minimized}",
|
file=sys.stderr,
|
)
|
sys.exit(1)
|
|
summary = {
|
"windowCount": len(windows),
|
"minimizedWindowCount": len(minimized),
|
"sampleMinimizedCount": len(sample_minimized),
|
"syntheticAXCount": len(synthetic),
|
"sampleWindows": [
|
{
|
"id": window.get("id"),
|
"titleHash": window.get("titleHash"),
|
"titleLength": window.get("titleLength"),
|
"identifierSource": window.get("identifierSource"),
|
"isSyntheticWindowID": window.get("isSyntheticWindowID"),
|
}
|
for window in sample_minimized
|
],
|
}
|
print(json.dumps(summary, ensure_ascii=False, indent=2, sort_keys=True))
|
PY
|