Bind Android smoke to build provenance and actual PCM assertions

This commit is contained in:
NINI
2026-10-05 03:46:17 +09:00
parent d656efe0dc
commit 4936180e45
7 changed files with 239 additions and 11 deletions
+32 -2
View File
@@ -18,8 +18,12 @@ function Assert-Check([string]$Name,[bool]$Condition,[string]$Actual) {
$result = [ordered]@{ milestone=$Milestone; serial=$Serial; sourceCommit=(& git rev-parse HEAD); sourceDirty=[bool](& git status --porcelain); status='failed'; commands=@(); checks=@() }
try {
Assert-Check 'clean-source' (!$result.sourceDirty) $result.sourceCommit
$buildRecord = Get-Content -LiteralPath (Join-Path $EvidenceDir 'androidbuild-evidence.json') -Raw | ConvertFrom-Json
$buildMetadata = Get-Content -LiteralPath (Join-Path $EvidenceDir 'apk-metadata.json') -Raw | ConvertFrom-Json
$actualApkHash = (Get-FileHash -LiteralPath $ApkPath -Algorithm SHA256).Hash
Assert-Check 'verified-build-provenance' ($buildRecord.status -eq 'passed' -and $buildRecord.exitCode -eq 0 -and $buildRecord.sourceDirty -eq $false -and $buildRecord.sourceDirtyEnd -eq $false -and $buildRecord.sourceCommit -eq $result.sourceCommit -and $buildRecord.sourceCommitEnd -eq $result.sourceCommit -and $buildRecord.apkSha256 -eq $actualApkHash -and $buildMetadata.sourceCommit -eq $buildRecord.sourceCommit -and $buildMetadata.apkSha256 -eq $actualApkHash -and $buildMetadata.sourceDirty -eq $false) $actualApkHash
& (Join-Path $PSScriptRoot 'inspect-apk.ps1') -ApkPath $ApkPath -EvidenceDir $EvidenceDir
$apk = Get-Content -LiteralPath (Join-Path $EvidenceDir 'apk-metadata.json') -Raw | ConvertFrom-Json
$apk = Get-Content -LiteralPath (Join-Path $EvidenceDir 'apk-inspection.json') -Raw | ConvertFrom-Json
$result.apkSha256 = $apk.apkSha256
$supported = (Invoke-Adb @('shell','getprop','ro.product.cpu.abilist')) -split ','
$native = $supported[0]
@@ -44,14 +48,40 @@ try {
$required = @('landscape-korean-assets','precollect-tap','direct-collection','camera-orbit','incomplete-restore','count-success-same-board','free-move','free-restore','offline-collection-count','offline-restore','guide-collect-playback','guide-count-playback','count01-playback')
foreach ($id in $required) {
$observations = @($manual.cases | Where-Object id -eq $id)
Assert-Check "observation-$id" ($observations.Count -eq 1 -and $observations[0].passed -eq $true -and $observations[0].actual -and $observations[0].procedure) (($observations | ForEach-Object actual) -join ' ')
Assert-Check "observation-$id" ($observations.Count -eq 1 -and $observations[0].passed -eq $true -and $observations[0].actual -and $observations[0].procedure -and $observations[0].expected) (($observations | ForEach-Object actual) -join ' ')
foreach ($file in $observations[0].evidence) {
$path = Join-Path $EvidenceDir $file
Assert-Check "evidence-$id-$file" ((Test-Path -LiteralPath $path) -and (Get-Item -LiteralPath $path).Length -gt 0) $file
}
Assert-Check "has-evidence-$id" (@($observations[0].evidence).Count -gt 0) (@($observations[0].evidence) -join ',')
}
$voiceHashes = [ordered]@{
guide_collect='62E15C9E38C36F4094A6C7E9C5148510141290B5F41DB5AAD9DC1D8F1A158594';
guide_count='DEBE29B89F3E2856F2BF4C5E01707A5F0A0657E5768C03BE385EC88FA2328B40';
count_01='13A882CE1620140D447635E14F2D4758045D5E348960C17386DF1C720050C100'
}
$audioMatches = @()
foreach ($voiceId in $voiceHashes.Keys) {
$reference = Join-Path (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) "Assets/MagnetismHeroes/UnityRuntime/Presentation/Audio/Voice/$voiceId.wav"
Assert-Check "approved-wave-$voiceId" ((Get-FileHash -LiteralPath $reference -Algorithm SHA256).Hash -eq $voiceHashes[$voiceId]) $voiceHashes[$voiceId]
$comparisonPath = Join-Path $EvidenceDir "audio-offline-$voiceId-match.json"
$capturedPath = Join-Path $EvidenceDir 'audio-offline.wav'
& pwsh -NoProfile -File (Join-Path $PSScriptRoot 'compare-audio.ps1') -ReferencePath $reference -CapturedPath $capturedPath -OutputPath $comparisonPath
$comparisonExit = $LASTEXITCODE
$comparison = Get-Content -LiteralPath $comparisonPath -Raw | ConvertFrom-Json
Assert-Check "actual-pcm-$voiceId" ($comparisonExit -eq 0 -and $comparison.passed -eq $true -and $comparison.normalizedCorrelation -ge 0.95 -and $comparison.rmsPcm -gt 32 -and $comparison.referenceSha256 -eq $voiceHashes[$voiceId]) ($comparison | ConvertTo-Json -Compress)
$audioMatches += $comparison
}
Assert-Check 'offline-voice-order' ($audioMatches[0].onsetSeconds + $audioMatches[0].referenceDurationSeconds -le $audioMatches[1].onsetSeconds -and $audioMatches[1].onsetSeconds + $audioMatches[1].referenceDurationSeconds -le $audioMatches[2].onsetSeconds) (($audioMatches | ForEach-Object onsetSeconds) -join ',')
$result.audioComparisons=$audioMatches
$result.manualObservations = $manual
$state = Get-Content -LiteralPath (Join-Path $EvidenceDir 'android-state-checks.json') -Raw | ConvertFrom-Json
Assert-Check 'state-checks-provenance' ($state.sourceCommit -eq $result.sourceCommit -and $state.sourceDirty -eq $false -and $state.apkSha256 -eq $actualApkHash -and $state.serial -eq $Serial) $state.sourceCommit
Assert-Check 'state-checks-passed' ($state.status -eq 'passed' -and @($state.checks).Count -ge 8 -and @($state.checks | Where-Object passed -ne $true).Count -eq 0) "$(@($state.checks).Count)"
foreach ($id in @('direct-collection-required','collected-with-empty-count','incomplete-json-restored','completion-atomic-state','success-preserves-board-camera','free-move-changes-position','free-json-restored','restore-no-historical-voice','offline-network-disabled','offline-collected-unfinished','offline-collection-count-actually-success','offline-free-move-changes-position','offline-json-restored')) {
Assert-Check "required-state-$id" (@($state.checks | Where-Object { $_.id -eq $id -and $_.passed -eq $true }).Count -eq 1) $id
}
$result.stateChecks=$state
$result.status='passed'
} catch { $result.error=$_.Exception.Message; Write-Host $result.error -ForegroundColor Red }
finally {