cat / goq
clone

turns a linux box into a private steam streaming appliance: plug in, tap your key, play from another computer

fix/docs-activation-truth
goq / scripts / tests / hardware-matrix.sh
hardware-matrix.sh 15.5K executable
1#!/usr/bin/env bash23set -euo pipefail4export LC_ALL=C56script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"7default_repo_dir="$(cd "$script_dir/../.." && pwd)"8repo_dir="${GOQ_HARDWARE_MATRIX_REPO_DIR:-$default_repo_dir}"9matrix="$repo_dir/docs/hardware-uat/MATRIX.md"1011fail() {12 printf 'hardware matrix test failed: %s\n' "$*" >&213 exit 114}1516trim() {17 sed 's/^[[:space:]]*//; s/[[:space:]]*$//'18}1920require_regular_file() {21 local path="$1"22 local description="$2"2324 [[ -f "$path" && ! -L "$path" ]] || fail "$description is missing or unsafe: $path"25}2627exact_report_value() {28 local report="$1"29 local field="$2"30 local prefix="- $field: \`"3132 awk -v prefix="$prefix" '33 index($0, prefix) == 1 && substr($0, length($0), 1) == "`" {34 count += 135 value = substr($0, length(prefix) + 1, length($0) - length(prefix) - 1)36 }37 END {38 if (count == 1 && length(value) > 0) {39 print value40 } else {41 exit 142 }43 }44 ' "$report"45}4647exact_env_value() {48 local document="$1"49 local key="$2"50 local count51 local value5253 count="$(grep -c "^${key}=" "$document" || true)"54 [[ "$count" == 1 ]] || return 155 value="$(sed -n "s/^${key}=//p" "$document")"56 [[ -n "$value" ]] || return 157 printf '%s\n' "$value"58}5960require_exact_env_schema() {61 local document="$1"62 shift63 local expected_keys=("$@")64 local actual_lines65 local key6667 require_regular_file "$document" "structured evidence"68 actual_lines="$(wc -l <"$document" | tr -d '[:space:]')"69 [[ "$actual_lines" == "${#expected_keys[@]}" ]] \70 || fail "structured evidence has extra, missing, or unterminated fields: $document"71 for key in "${expected_keys[@]}"; do72 exact_env_value "$document" "$key" >/dev/null \73 || fail "structured evidence requires exactly one nonempty $key: $document"74 done75}7677sha256_file() {78 local path="$1"7980 if command -v sha256sum >/dev/null 2>&1; then81 sha256sum "$path" | awk '{print $1}'82 else83 shasum -a 256 "$path" | awk '{print $1}'84 fi85}8687require_bounded_text() {88 local value="$1"89 local field="$2"9091 [[ "${#value}" -ge 1 && "${#value}" -le 128 ]] \92 || fail "$field must contain 1-128 characters"93 [[ "$value" != *$'\n'* && "$value" != *$'\r'* ]] \94 || fail "$field contains a line break"95}9697require_positive_integer() {98 local value="$1"99 local field="$2"100101 [[ "$value" =~ ^[1-9][0-9]*$ ]] || fail "$field must be a positive integer"102}103104require_bounded_positive_integer() {105 local value="$1"106 local maximum="$2"107 local field="$3"108109 require_positive_integer "$value" "$field"110 if ((${#value} > ${#maximum})) ||111 { ((${#value} == ${#maximum})) && [[ "$value" > "$maximum" ]]; }; then112 fail "$field exceeds $maximum"113 fi114}115116require_minimum_positive_integer() {117 local value="$1"118 local minimum="$2"119 local field="$3"120121 require_positive_integer "$value" "$field"122 if ((${#value} < ${#minimum})) ||123 { ((${#value} == ${#minimum})) && [[ "$value" < "$minimum" ]]; }; then124 fail "$field is below $minimum"125 fi126}127128require_regular_file "$matrix" "hardware matrix"129git -C "$repo_dir" rev-parse --git-dir >/dev/null 2>&1 \130 || fail "hardware matrix repository is not a Git worktree"131132row_ids=(133 native-1280x800-handheld134 physically-headless-desktop-dgpu135)136manifest_keys=(137 schema138 exact_commit139 candidate_kind140 sigil_asset141 sigil_sha256142 portal_asset143 portal_sha256144)145evidence_keys=(146 schema147 matrix_row148 exact_commit149 workflow_run_id150 host_model151 os_family152 gpu_topology153 connector_state154 native_width155 native_height156 native_refresh_millihz157 os_version158 kernel_version159 gamescope_version160 mesa_version161 gstreamer_version162 encoder_plugin_version163 render_node164 encoder_factory165 fixed_capture_result166 fixed_capture_fps_milli167 fixed_post_encode_drops168 native_capture_result169 native_capture_fps_milli170 native_post_encode_drops171 portal_transport172 portal_video173 portal_audio174 portal_input175 portal_reconnect176 portal_second_client_rejection177 restoration178)179pass_commits=()180pass_artifact_sets=()181pass_manifests=()182pass_reports=()183pass_candidate_kinds=()184pending=false185186for row_id in "${row_ids[@]}"; do187 row="$(awk -F '|' -v id="$row_id" '188 {189 key = $2190 gsub(/^[[:space:]]+|[[:space:]]+$/, "", key)191 if (key == id) {192 count += 1193 value = $0194 }195 }196 END {197 if (count == 1) {198 print value199 }200 }201 ' "$matrix")"202 [[ -n "$row" ]] || fail "required row is missing or duplicated: $row_id"203204 status="$(cut -d '|' -f 4 <<<"$row" | trim)"205 report="$(cut -d '|' -f 5 <<<"$row" | trim)"206 case "$status" in207 pending)208 [[ "$report" == pending ]] \209 || fail "pending row must use pending evidence: $row_id"210 pending=true211 ;;212 pass)213 [[ "$report" == "docs/hardware-uat/"[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/"$row_id"/REPORT.md ]] \214 || fail "passing row has an invalid or cross-row report path: $row_id"215 report_path="$repo_dir/$report"216 require_regular_file "$report_path" "passing report"217218 report_row="$(exact_report_value "$report_path" "Matrix row")" \219 || fail "passing report does not bind exactly one matrix row: $report"220 [[ "$report_row" == "$row_id" ]] \221 || fail "passing report binds the wrong matrix row: $report"222 commit="$(exact_report_value "$report_path" "Exact commit")" \223 || fail "passing report does not bind exactly one commit: $report"224 [[ "$commit" =~ ^[0-9a-f]{40}$ ]] \225 || fail "passing report commit is not exact lowercase hex: $report"226 git -C "$repo_dir" cat-file -e "$commit^{commit}" 2>/dev/null \227 || fail "passing report commit is not present in repository history: $report"228 [[ "$report" == "docs/hardware-uat/${commit:0:12}/$row_id/REPORT.md" ]] \229 || fail "passing report directory does not match its exact commit: $report"230231 workflow_run="$(exact_report_value "$report_path" "Workflow run")" \232 || fail "passing report does not bind exactly one workflow run: $report"233 require_bounded_positive_integer \234 "$workflow_run" 999999999999999999 "workflow run"235 artifact_set="$(exact_report_value \236 "$report_path" "Candidate artifact set SHA256")" \237 || fail "passing report does not bind exactly one candidate artifact set: $report"238 [[ "$artifact_set" =~ ^[0-9a-f]{64}$ ]] \239 || fail "candidate artifact set is not exact lowercase SHA256: $report"240 manifest="$(exact_report_value "$report_path" "Candidate artifact manifest")" \241 || fail "passing report does not bind exactly one artifact manifest: $report"242 expected_manifest="docs/hardware-uat/${commit:0:12}/candidate-artifacts.env"243 [[ "$manifest" == "$expected_manifest" ]] \244 || fail "passing report does not use its commit-scoped artifact manifest: $report"245 manifest_path="$repo_dir/$manifest"246 require_exact_env_schema "$manifest_path" "${manifest_keys[@]}"247 [[ "$(exact_env_value "$manifest_path" schema)" == \248 goq-hardware-matrix-artifacts-v1 ]] \249 || fail "candidate artifact manifest has the wrong schema: $manifest"250 [[ "$(exact_env_value "$manifest_path" exact_commit)" == "$commit" ]] \251 || fail "candidate artifact manifest is bound to another commit: $manifest"252 candidate_kind="$(exact_env_value "$manifest_path" candidate_kind)"253 [[ "$candidate_kind" == development || "$candidate_kind" == release ]] \254 || fail "candidate artifact kind must be development or release: $manifest"255 sigil_asset="$(exact_env_value "$manifest_path" sigil_asset)"256 portal_asset="$(exact_env_value "$manifest_path" portal_asset)"257 [[ "$sigil_asset" =~ ^[[:alnum:]][[:alnum:]_.+-]*$ ]] \258 || fail "Sigil candidate asset name is unsafe: $manifest"259 [[ "$portal_asset" =~ ^[[:alnum:]][[:alnum:]_.+-]*$ ]] \260 || fail "Portal candidate asset name is unsafe: $manifest"261 [[ "$sigil_asset" != "$portal_asset" ]] \262 || fail "Sigil and Portal candidate assets must be distinct: $manifest"263 sigil_sha256="$(exact_env_value "$manifest_path" sigil_sha256)"264 portal_sha256="$(exact_env_value "$manifest_path" portal_sha256)"265 [[ "$sigil_sha256" =~ ^[0-9a-f]{64}$ && "$sigil_sha256" =~ [1-9a-f] ]] \266 || fail "Sigil candidate digest is invalid: $manifest"267 [[ "$portal_sha256" =~ ^[0-9a-f]{64}$ && "$portal_sha256" =~ [1-9a-f] ]] \268 || fail "Portal candidate digest is invalid: $manifest"269 [[ "$(sha256_file "$manifest_path")" == "$artifact_set" ]] \270 || fail "candidate artifact set digest does not match its manifest: $report"271272 evidence="$(exact_report_value "$report_path" "Evidence summary")" \273 || fail "passing report does not bind exactly one evidence summary: $report"274 expected_evidence="docs/hardware-uat/${commit:0:12}/$row_id/EVIDENCE.env"275 [[ "$evidence" == "$expected_evidence" ]] \276 || fail "passing report does not use its row-scoped evidence summary: $report"277 evidence_path="$repo_dir/$evidence"278 require_exact_env_schema "$evidence_path" "${evidence_keys[@]}"279 [[ "$(exact_env_value "$evidence_path" schema)" == \280 goq-hardware-matrix-evidence-v1 ]] \281 || fail "hardware evidence has the wrong schema: $evidence"282 [[ "$(exact_env_value "$evidence_path" matrix_row)" == "$row_id" ]] \283 || fail "hardware evidence is bound to another row: $evidence"284 [[ "$(exact_env_value "$evidence_path" exact_commit)" == "$commit" ]] \285 || fail "hardware evidence is bound to another commit: $evidence"286 [[ "$(exact_env_value "$evidence_path" workflow_run_id)" == "$workflow_run" ]] \287 || fail "hardware evidence is bound to another workflow run: $evidence"288289 host_model="$(exact_env_value "$evidence_path" host_model)"290 require_bounded_text "$host_model" "host model"291 for version_key in \292 os_version kernel_version gamescope_version mesa_version \293 gstreamer_version encoder_plugin_version; do294 require_bounded_text \295 "$(exact_env_value "$evidence_path" "$version_key")" "$version_key"296 done297 os_family="$(exact_env_value "$evidence_path" os_family)"298 gpu_topology="$(exact_env_value "$evidence_path" gpu_topology)"299 connector_state="$(exact_env_value "$evidence_path" connector_state)"300 native_width="$(exact_env_value "$evidence_path" native_width)"301 native_height="$(exact_env_value "$evidence_path" native_height)"302 native_refresh="$(exact_env_value "$evidence_path" native_refresh_millihz)"303 require_bounded_positive_integer "$native_width" 16384 "native width"304 require_bounded_positive_integer "$native_height" 16384 "native height"305 require_bounded_positive_integer \306 "$native_refresh" 1000000 "native refresh"307308 case "$row_id" in309 native-1280x800-handheld)310 [[ "$os_family" == steamos-upstream ]] \311 || fail "handheld row requires upstream SteamOS: $evidence"312 [[ "$gpu_topology" == integrated ]] \313 || fail "handheld row requires an integrated GPU: $evidence"314 [[ "$connector_state" == native-panel-connected ]] \315 || fail "handheld row requires its native panel: $evidence"316 [[ "$native_width" == 1280 && "$native_height" == 800 ]] \317 || fail "handheld row requires a native 1280x800 mode: $evidence"318 ;;319 physically-headless-desktop-dgpu)320 [[ "$os_family" == steamos-upstream || \321 "$os_family" == steamos-inspired ]] \322 || fail "desktop row requires SteamOS or a SteamOS-inspired OS: $evidence"323 [[ "$gpu_topology" == discrete ]] \324 || fail "desktop row requires a discrete GPU: $evidence"325 [[ "$connector_state" == physically-headless ]] \326 || fail "desktop row requires no physical connector: $evidence"327 ;;328 esac329330 render_node="$(exact_env_value "$evidence_path" render_node)"331 encoder_factory="$(exact_env_value "$evidence_path" encoder_factory)"332 [[ "$render_node" =~ ^/dev/dri/renderD[0-9]+$ ]] \333 || fail "render node must be capability-discovered and explicit: $evidence"334 [[ "$encoder_factory" =~ ^[[:alnum:]_.+-]+$ ]] \335 || fail "encoder factory is invalid: $evidence"336 [[ "$(exact_env_value "$evidence_path" fixed_capture_result)" == pass ]] \337 || fail "fixed capture did not pass: $evidence"338 fixed_fps="$(exact_env_value "$evidence_path" fixed_capture_fps_milli)"339 require_bounded_positive_integer \340 "$fixed_fps" 1000000 "fixed capture fps"341 require_minimum_positive_integer "$fixed_fps" 55000 "fixed capture fps"342 [[ "$(exact_env_value "$evidence_path" fixed_post_encode_drops)" == 0 ]] \343 || fail "fixed capture has post-encode drops: $evidence"344 [[ "$(exact_env_value "$evidence_path" native_capture_result)" == pass ]] \345 || fail "native capture did not pass: $evidence"346 native_fps="$(exact_env_value "$evidence_path" native_capture_fps_milli)"347 require_bounded_positive_integer \348 "$native_fps" 1000000 "native capture fps"349 [[ "$(exact_env_value "$evidence_path" native_post_encode_drops)" == 0 ]] \350 || fail "native capture has post-encode drops: $evidence"351 [[ "$(exact_env_value "$evidence_path" portal_transport)" == iroh-moq ]] \352 || fail "Portal matrix session must use the preferred transport: $evidence"353 for pass_key in \354 portal_video portal_audio portal_input portal_reconnect \355 portal_second_client_rejection restoration; do356 [[ "$(exact_env_value "$evidence_path" "$pass_key")" == pass ]] \357 || fail "$pass_key did not pass: $evidence"358 done359360 pass_commits+=("$commit")361 pass_artifact_sets+=("$artifact_set")362 pass_manifests+=("$manifest")363 pass_reports+=("$report")364 pass_candidate_kinds+=("$candidate_kind")365 ;;366 *)367 fail "row status must be pending or pass: $row_id"368 ;;369 esac370done371372claim_files=()373for claim_root in "$repo_dir/README.md" "$repo_dir/website" "$repo_dir/docs"; do374 [[ -e "$claim_root" ]] || continue375 if [[ -f "$claim_root" ]]; then376 claim_files+=("$claim_root")377 continue378 fi379 while IFS= read -r claim_file; do380 [[ "$claim_file" == "$matrix" ]] || claim_files+=("$claim_file")381 done < <(find "$claim_root" -type f \( -name '*.md' -o -name '*.html' \) -print)382done383384if [[ "$pending" == true ]]; then385 if ((${#claim_files[@]} > 0)) &&386 grep -HinE \387 '(^|[^[:alnum:]_])(matrix-proven|hardware-proven)([^[:alnum:]_]|$)' \388 "${claim_files[@]}"; then389 fail "public claims must not say matrix-proven or hardware-proven while rows are pending"390 fi391else392 [[ "${#pass_commits[@]}" -eq "${#row_ids[@]}" ]] \393 || fail "every required row must have passing evidence"394 [[ "${pass_commits[0]}" == "${pass_commits[1]}" ]] \395 || fail "required rows do not prove the same exact commit"396 [[ "${pass_artifact_sets[0]}" == "${pass_artifact_sets[1]}" ]] \397 || fail "required rows do not prove the same candidate artifact set"398 [[ "${pass_manifests[0]}" == "${pass_manifests[1]}" ]] \399 || fail "required rows do not use one shared candidate manifest"400 [[ "${pass_reports[0]}" != "${pass_reports[1]}" ]] \401 || fail "required rows must have distinct host reports"402 if [[ "${pass_candidate_kinds[0]}" != release || \403 "${pass_candidate_kinds[1]}" != release ]]; then404 if ((${#claim_files[@]} > 0)) &&405 grep -HinE \406 '(^|[^[:alnum:]_])release-matrix-proven([^[:alnum:]_]|$)' \407 "${claim_files[@]}"; then408 fail "release-matrix-proven requires release candidate evidence"409 fi410 fi411fi412413echo 'hardware_matrix_tests=ok'