param([int]$TimeoutSeconds = 3600) $ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot & (Join-Path $PSScriptRoot 'sync.ps1') $report = Join-Path $root 'artifacts\validation.json' if (Test-Path -LiteralPath $report) { Move-Item -LiteralPath $report -Destination (Join-Path $root "artifacts\validation-previous-$([DateTime]::Now.ToString('yyyyMMdd-HHmmss')).json") } $engine = Join-Path $root ((Get-Content -LiteralPath (Join-Path $root 'data\runtime-path.txt') -Raw).Trim()) $env:QI_ROOT = $root $previousTest = $env:QI_TEST $env:QI_TEST = '1' $profile = Join-Path $root ("artifacts\test-profiles\" + [Guid]::NewGuid().ToString('N')) New-Item -ItemType Directory -Path $profile -Force | Out-Null $params = @('--user-cfg', ('"' + (Join-Path $profile 'user.cfg') + '"'), '--system-cfg', ('"' + (Join-Path $profile 'system.cfg') + '"'), '--log-file', ('"' + (Join-Path $root 'logs\validation.log') + '"'), ('"' + (Join-Path $PSScriptRoot 'startup.FCMacro') + '"')) $process = $null try { $process = Start-Process -FilePath $engine -ArgumentList $params -WorkingDirectory $root -WindowStyle Hidden -PassThru $deadline = [DateTime]::UtcNow.AddSeconds($TimeoutSeconds) while (-not $process.WaitForExit(1000)) { if ([DateTime]::UtcNow -gt $deadline) { Stop-Process -Id $process.Id -ErrorAction SilentlyContinue throw "Истекло время проверки интерфейса. Подробности: logs\validation.log и artifacts\validation.json." } } } finally { if ($null -eq $previousTest) { Remove-Item Env:QI_TEST -ErrorAction SilentlyContinue } else { $env:QI_TEST = $previousTest } } if (-not (Test-Path -LiteralPath $report)) { Get-Content -LiteralPath (Join-Path $root 'logs\validation.log') -Tail 60 throw 'Проверка не создала отчёт.' } $result = Get-Content -LiteralPath $report -Raw | ConvertFrom-Json $result | Add-Member -NotePropertyName native_exit_code -NotePropertyValue $process.ExitCode -Force if ($process.ExitCode -ne 0) { # A native crash during shutdown can follow Python's final passing report. # Persist the process outcome so -SkipTests cannot package that report. $result.status = 'failed' $result.failed = [Math]::Max(1, [int]$result.failed) $result | Add-Member -NotePropertyName native_error -NotePropertyValue "CAD-процесс завершился с кодом $($process.ExitCode). Подробности: logs\validation.log." -Force } $stagedReport = "$report.parent-tmp" $result | ConvertTo-Json -Depth 40 | Set-Content -LiteralPath $stagedReport -Encoding utf8 Move-Item -LiteralPath $stagedReport -Destination $report -Force if ($process.ExitCode -ne 0 -or $result.status -ne 'passed') { Write-Host "Проверка не пройдена: $($result.failed) ошибок. Отчёт: $report" foreach ($check in $result.checks | Where-Object { -not $_.passed }) { $detail = [string]$check.error if ($detail.Length -gt 1200) { $detail = $detail.Substring(0, 1200) + '…' } Write-Host "$($check.name): $detail" } throw 'Проверка QInventor завершилась с ошибками.' } $result | Select-Object @{Name='Состояние';Expression={'Пройдена'}}, @{Name='Успешных проверок';Expression={$_.passed}}, @{Name='Ошибок';Expression={$_.failed}}, @{Name='Версия';Expression={$_.version}} | Format-List Write-Host "Отчёт проверки: $report"