<# verify_log.ps1 - Check a captured MCU debug log against boot/test markers. Used by the @test loop: after flashing, the fresh boot log is extracted from the serial assistant log (tools/serial_tool), then this script greps it and prints a structured verdict. Usage: powershell -ExecutionPolicy Bypass -File verify_log.ps1 ` -LogPath ` [-Required 'marker1;marker2'] ` [-Forbidden 'FAIL;ERROR;HardFault'] ` [-ShowTailLines 40] Exit code: 0 = PASS (every required marker found, no forbidden pattern matched) 1 = FAIL (missing required marker or forbidden pattern present) 2 = ERROR (log file not found / unreadable) Default required markers match the STM32F4-Base boot sequence (see App/app_main.c + App/task/net_task.c). Override per test case, e.g.: -Required 'App init OK;net init: OK;PHY: 100M FULL' -Forbidden 'FAIL;ERROR;HardFault;assert' NOTE: ASCII-only on purpose - project source files contain Chinese and must never be rewritten by encoding-sensitive PowerShell. Keep this script ASCII. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$LogPath, [string]$Required = 'App init OK;Network Init;net init: OK', [string]$Forbidden = 'FAIL;ERROR;HardFault;assert', [int]$ShowTailLines = 40 ) $ErrorActionPreference = 'Stop' if (-not (Test-Path -LiteralPath $LogPath)) { Write-Output "VERIFY_ERROR: log file not found: $LogPath" exit 2 } try { $content = Get-Content -LiteralPath $LogPath -Encoding UTF8 -ErrorAction Stop } catch { # Fall back to default encoding if UTF-8 read fails try { $content = Get-Content -LiteralPath $LogPath -ErrorAction Stop } catch { Write-Output "VERIFY_ERROR: cannot read log file: $LogPath" exit 2 } } $all = $content -join "`n" $requiredList = @($Required -split ';' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }) $forbiddenList = @($Forbidden -split ';' | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }) Write-Output "=== Log verdict: $LogPath ===" Write-Output ("Lines: {0}, bytes: {1}" -f $content.Count, (Get-Item -LiteralPath $LogPath).Length) $missing = @() foreach ($m in $requiredList) { if ($all.Contains($m)) { Write-Output ("[OK] required marker found: {0}" -f $m) } else { Write-Output ("[MISS] required marker NOT found: {0}" -f $m) $missing += $m } } $hits = @() foreach ($f in $forbiddenList) { $matches = @($content | Where-Object { $_ -like "*$f*" }) if ($matches.Count -gt 0) { Write-Output ("[HIT] forbidden pattern: {0} ({1} line(s))" -f $f, $matches.Count) $hits += $f } else { Write-Output ("[OK] forbidden pattern absent: {0}" -f $f) } } if ($ShowTailLines -gt 0 -and $content.Count -gt 0) { Write-Output "" Write-Output "=== Last $ShowTailLines line(s) of log ===" $start = [Math]::Max(0, $content.Count - $ShowTailLines) $content[$start..($content.Count - 1)] | ForEach-Object { Write-Output $_ } } if ($missing.Count -gt 0 -or $hits.Count -gt 0) { Write-Output "" Write-Output "VERDICT: FAIL" exit 1 } Write-Output "" Write-Output "VERDICT: PASS" exit 0