#!/bin/bash # Round01 performance gate. Runs the interactive-cost PoC metrics and the # 100-cycle overlay lifecycle leak check as one QA entry point. 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" POC_REPORT="$BUILD_REPORT_ROOT/round01-performance-poc-report.json" LIFECYCLE_REPORT="$BUILD_REPORT_ROOT/round01-performance-lifecycle-report.json" LIFECYCLE_CYCLES="${ALIGNER_ROUND1_POC_LIFECYCLE_CYCLES:-100}" LIFECYCLE_INTERVAL="${ALIGNER_ROUND1_POC_LIFECYCLE_INTERVAL:-0.01}" LIFECYCLE_VISIBLE_DURATION="${ALIGNER_ROUND1_POC_LIFECYCLE_VISIBLE_DURATION:-0.24}" validate_positive_integer() { local name="$1" local value="$2" if ! [[ "$value" =~ ^[1-9][0-9]*$ ]]; then echo "$name must be a positive integer, got: $value" >&2 exit 1 fi } validate_nonnegative_number() { local name="$1" local value="$2" if ! /usr/bin/python3 - "$name" "$value" <<'PY' import sys name, value = sys.argv[1:3] try: parsed = float(value) except ValueError: print(f"{name} must be a non-negative number, got: {value}", file=sys.stderr) sys.exit(1) if parsed < 0: print(f"{name} must be a non-negative number, got: {value}", file=sys.stderr) sys.exit(1) PY then exit 1 fi } validate_positive_integer "ALIGNER_ROUND1_POC_LIFECYCLE_CYCLES" "$LIFECYCLE_CYCLES" validate_nonnegative_number "ALIGNER_ROUND1_POC_LIFECYCLE_INTERVAL" "$LIFECYCLE_INTERVAL" validate_nonnegative_number "ALIGNER_ROUND1_POC_LIFECYCLE_VISIBLE_DURATION" "$LIFECYCLE_VISIBLE_DURATION" require_json_value() { local report="$1" local key="$2" local expected="$3" if ! /usr/bin/python3 - "$report" "$key" "$expected" <<'PY' import json import sys path, key, expected = sys.argv[1:4] with open(path, "r", encoding="utf-8") as handle: data = json.load(handle) actual = data.get(key) if expected == "true": ok = actual is True elif expected == "false": ok = actual is False else: ok = str(actual) == expected if not ok: print(f"{path}: {key}: expected {expected}, got {actual}", file=sys.stderr) sys.exit(1) PY then exit 1 fi } require_json_number_at_most() { local report="$1" local key="$2" local maximum="$3" if ! /usr/bin/python3 - "$report" "$key" "$maximum" <<'PY' import json import sys path, key, maximum = sys.argv[1:4] with open(path, "r", encoding="utf-8") as handle: data = json.load(handle) actual = data.get(key) if actual is None or float(actual) > float(maximum): print(f"{path}: {key}: expected <= {maximum}, got {actual}", file=sys.stderr) sys.exit(1) PY then exit 1 fi } "$SCRIPT_DIR/round1-performance-poc.sh" >&2 cd "$SOURCE_ROOT" swift build >&2 "$SCRIPT_DIR/package-app.sh" >&2 rm -f "$LIFECYCLE_REPORT" "$APP/Contents/MacOS/Aligner" \ --round0-skip-permissions \ --round01-performance-poc \ --round01-poc-lifecycle-cycles="$LIFECYCLE_CYCLES" \ --round01-poc-lifecycle-interval="$LIFECYCLE_INTERVAL" \ --round01-poc-lifecycle-visible-duration="$LIFECYCLE_VISIBLE_DURATION" \ --round01-poc-report="$LIFECYCLE_REPORT" if [[ ! -f "$LIFECYCLE_REPORT" ]]; then echo "Round01 performance lifecycle report was not created: $LIFECYCLE_REPORT" >&2 exit 1 fi require_json_value "$LIFECYCLE_REPORT" lifecycleTargetCycles "$LIFECYCLE_CYCLES" require_json_value "$LIFECYCLE_REPORT" lifecycleCompletedCycles "$LIFECYCLE_CYCLES" require_json_value "$LIFECYCLE_REPORT" lifecycleGatePassed true require_json_value "$LIFECYCLE_REPORT" firstFrameLatencySampleCount "$LIFECYCLE_CYCLES" require_json_number_at_most "$LIFECYCLE_REPORT" firstFrameLatencyP95Milliseconds 150 require_json_number_at_most "$LIFECYCLE_REPORT" lifecycleMaximumOverlayWindows 1 require_json_value "$LIFECYCLE_REPORT" lifecycleResidualVisibleOverlayWindows 0 require_json_number_at_most "$LIFECYCLE_REPORT" lifecycleResidualOverlayWindows 1 require_json_number_at_most "$LIFECYCLE_REPORT" lifecycleMaximumVisibleOverlayWindows 1 require_json_value "$LIFECYCLE_REPORT" overlayVisible false require_json_value "$LIFECYCLE_REPORT" visibleOverlayWindowCount 0 require_json_number_at_most "$LIFECYCLE_REPORT" overlayWindowCount 1 require_json_value "$LIFECYCLE_REPORT" cardLayerCount 200 require_json_value "$LIFECYCLE_REPORT" appLayerCount 20 require_json_value "$LIFECYCLE_REPORT" thumbnailLayerCount 200 require_json_value "$LIFECYCLE_REPORT" simulatedScreenshotRefillCount 200 cat <