Skip to content

multiwindow/gg: add cross-platform multiwindow services and lifecycle safety #6087

multiwindow/gg: add cross-platform multiwindow services and lifecycle safety

multiwindow/gg: add cross-platform multiwindow services and lifecycle safety #6087

Workflow file for this run

name: CI Windows TCC
on:
workflow_dispatch:
push:
branches:
- master
paths-ignore:
- 'vlib/v3/**'
- '**.md'
- '**.yml'
- '!**.bat'
- '!**/windows_ci_tcc.yml'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
pull_request:
paths-ignore:
- 'vlib/v3/**'
- '**.md'
- '**.yml'
- '!**.bat'
- '!**/windows_ci_tcc.yml'
- '!**/windows-install-sqlite.bat'
- 'cmd/tools/**'
- '!cmd/tools/builders/**.v'
concurrency:
group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }}
cancel-in-progress: true
jobs:
tcc-windows:
runs-on: windows-2022
timeout-minutes: 60
env:
VFLAGS: -cc tcc -no-retry-compilation
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- name: Install OpenSSL
run: |
choco install openssl -y --no-progress
# choco's openssl package (Win64OpenSSL installer under the hood)
# deploys to `C:\Program Files\OpenSSL\`, matching
# ecdsa.c.v/rsa_pss.c.v's SECOND `#flag windows` fallback path --
# NOT the first one (`...OpenSSL-Win64\...`), confirmed by an
# actual CI run after guessing wrong the first time.
$opensslBin = 'C:\Program Files\OpenSSL\bin'
if (-not (Test-Path $opensslBin)) {
throw "OpenSSL bin directory not found at $opensslBin after choco install"
}
Add-Content -Path $env:GITHUB_PATH -Value $opensslBin
Write-Host "OpenSSL install:"
Get-ChildItem 'C:\Program Files\OpenSSL\lib\VC\x64\MD'
Write-Host "OpenSSL bin DLLs:"
Get-ChildItem $opensslBin -Filter *.dll
# TCC resolves `-lcrypto`/`-lssl` by searching the -L dir for
# `lib<name>.def` FIRST (confirmed against tinycc's own source,
# tcc_add_library's PE search-pattern array: "%s/%s.def",
# "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll"), and when a .def
# file is found, tccpe.c's pe_load_def reads the file's own
# `LIBRARY <name>` directive via get_token() to get the DLL
# filename to embed in the import table. Confirmed against
# tinycc's own source that get_token() does NOT strip surrounding
# double quotes, and the extracted name is used AS-IS with no
# `.dll` extension appended. This OpenSSL 4.0.1 package's
# libcrypto.def/libssl.def declare `LIBRARY "libcrypto-4-x64"` /
# `LIBRARY "libssl-4-x64"` -- quoted, no extension -- so TCC
# embeds the LITERAL string `"libcrypto-4-x64"` (quote characters
# included, no `.dll`) as the runtime DLL name. `"` is illegal in
# a Windows filename, so NO real file can ever match that name --
# guaranteeing STATUS_DLL_NOT_FOUND (exit -1073741515, empty
# output) for every TCC-linked test touching
# crypto.ecdsa/crypto.rsa_pss/net.quic, confirmed via an actual CI
# failure, regardless of what DLLs actually exist in bin\ (MSVC
# is unaffected: it reads the DLL name from the .lib's own
# build-time metadata, which is already a valid, unquoted,
# extensioned filename). A file-aliasing workaround (mirroring
# msvc-windows' crypto.lib/libcrypto.lib alias) CANNOT fix this --
# you cannot create a file whose name contains a literal `"` on
# Windows. Fix at the source instead: rewrite each .def's LIBRARY
# line in place, stripping the quotes and appending `.dll` if
# missing, before TCC ever reads it. The rewritten name
# (`libcrypto-4-x64.dll`) already exists as a real file in bin\
# (this package ships both v3 and v4 runtime DLLs side by side),
# so no aliasing is needed once the .def itself is correct.
$libDir = 'C:\Program Files\OpenSSL\lib\VC\x64\MD'
foreach ($name in @('libcrypto', 'libssl')) {
$defPath = Join-Path $libDir "$name.def"
if (-not (Test-Path $defPath)) {
Write-Host "$name.def not found at $defPath, skipping LIBRARY-line fix"
continue
}
$lines = Get-Content $defPath
$fixedAny = $false
$newLines = $lines | ForEach-Object {
if ($_ -match '^(\s*LIBRARY\s+)"?([^"\s]+)"?\s*$') {
$dllName = $Matches[2]
if ($dllName -notmatch '\.dll$') {
$dllName = "$dllName.dll"
}
Write-Host "${name}: rewriting LIBRARY line '$_' -> 'LIBRARY $dllName'"
$fixedAny = $true
"LIBRARY $dllName"
} else {
$_
}
}
if ($fixedAny) {
Set-Content -Path $defPath -Value $newLines
} else {
Write-Host "${name}: no LIBRARY line found to rewrite in $defPath"
}
}
- name: Build with makev.bat -tcc
run: |
.\makev.bat -tcc
.\v.exe symlink
- name: Pkg-config regression (TCC dynamic isolation)
run: |
.\v.exe -cc tcc -no-retry-compilation test vlib\v\checker\pkgconfig_static_mode_test.v
if ($LASTEXITCODE -ne 0) {
throw "pkg-config TCC isolation regression failed with exit code $LASTEXITCODE"
}
- name: All code is formatted
run: v -silent test-cleancode
- name: Test new v.c
run: |
v -o v.c cmd/v
$direct_c_flags = @(
'-Ithirdparty/zip'
'-Ithirdparty/cJSON'
'-Ithirdparty/mbedtls/library'
'-Ithirdparty/mbedtls/include'
'-Ithirdparty/mbedtls/3rdparty/everest/include'
'-Ithirdparty/mbedtls/3rdparty/everest/include/everest'
'-Ithirdparty/mbedtls/3rdparty/everest/include/everest/kremlib'
'-Ithirdparty/vschannel'
)
# Match makev.bat's Windows stack reserve; the direct TCC-built
# compiler can otherwise crash while compiling net.http-heavy scripts.
.\thirdparty\tcc\tcc.exe -Werror -w @direct_c_flags -ladvapi32 -lws2_32 -bt10 '-Wl,-stack=33554432' v.c
- name: Install dependencies
run: |
v retry -- v setup-freetype
.\.github\workflows\windows-install-sqlite.bat
- name: v -g self
run: v -g self
- name: v doctor
run: |
v doctor
- name: Verify `v test` works
run: |
v cmd/tools/test_if_v_test_system_works.v
.\cmd\tools\test_if_v_test_system_works.exe
- name: Legacy gg import multiwindow isolation
run: v test vlib/gg/legacy_import_multiwindow_isolation_test.v
- name: Verify `v vlib/v/gen/c/coutput_test.v` works
run: v vlib/v/gen/c/coutput_test.v
- name: Make sure running TCC64 instead of TCC32
run: v test .github\workflows\make_sure_ci_run_with_64bit_compiler_test.v
- name: Test ./v doc -v clipboard *BEFORE building tools*
run: v doc -v clipboard
- name: Test v build-tools
run: v -silent -W build-tools
- name: Test pure V math module
run: v -silent -exclude @vlib/math/*.c.v test vlib/math/
- name: Multiwindow render runtime contract
run: .\v.exe -silent vlib\gg\multiwindow_render_runtime_contract_test.v
- name: Self tests
run: v -silent test-self vlib
- name: Test v->js
run: v -o hi.js examples/js_hello_world.v && node hi.js
- name: Test v binaries
run: v build-vbinaries
- name: Build examples
run: v build-examples
- name: Compile and run the veb example (fasthttp) and check its HTML
run: v run .github/workflows/veb_example_windows_smoke.v
- name: v2 self compilation
run: v -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v && .\v3.exe -o v4.exe cmd/v
tcc-multiwindow:
runs-on: windows-2022
timeout-minutes: 60
env:
VTEST_SHOW_LONGEST_BY_RUNTIME: 3
VTEST_SHOW_LONGEST_BY_COMPTIME: 3
VTEST_SHOW_LONGEST_BY_TOTALTIME: 3
steps:
- uses: actions/checkout@v7
- name: Build with makev.bat -tcc
run: |
.\makev.bat -tcc
.\v.exe symlink
- name: Checkout pinned Windows TCC bundle
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
repository: vlang/tccbin
ref: f48b48b2a2a027ee91cec7634395d1ec48d3e325
path: .ci/tccbin-windows-amd64
persist-credentials: false
- name: Route TCC validation to pinned bundle
shell: pwsh
run: |
$expectedSha = 'f48b48b2a2a027ee91cec7634395d1ec48d3e325'
$bundle = (Resolve-Path '.\.ci\tccbin-windows-amd64').Path
$actualSha = (git -C $bundle rev-parse HEAD).Trim()
if ($actualSha -cne $expectedSha) {
throw "expected tccbin $expectedSha, got $actualSha"
}
$tcc = Join-Path $bundle 'tcc.exe'
if (-not (Test-Path -LiteralPath $tcc -PathType Leaf)) {
throw "pinned TCC executable is missing: $tcc"
}
$tccLink = Join-Path $env:GITHUB_WORKSPACE 'thirdparty\tcc'
if (Test-Path -LiteralPath $tccLink) {
Remove-Item -LiteralPath $tccLink -Recurse -Force
}
New-Item -ItemType Junction -Path $tccLink -Target $bundle | Out-Null
$junctionTarget = [string](Get-Item -LiteralPath $tccLink).Target
if ([IO.Path]::GetFullPath($junctionTarget) -cne [IO.Path]::GetFullPath($bundle)) {
throw "thirdparty/tcc does not target the pinned bundle: $junctionTarget"
}
Add-Content -Path $env:GITHUB_PATH -Value $bundle
Add-Content -Path $env:GITHUB_ENV -Value "PINNED_TCC=$tcc"
Add-Content -Path $env:GITHUB_ENV `
-Value "VFLAGS=-cc $tcc -no-retry-compilation"
- name: Verify pinned TCC command resolution
shell: pwsh
run: |
$resolvedTcc = (Get-Command tcc.exe -CommandType Application -ErrorAction Stop).Source
if ([IO.Path]::GetFullPath($resolvedTcc) -cne [IO.Path]::GetFullPath($env:PINNED_TCC)) {
throw "tcc.exe resolved to '$resolvedTcc', expected '$env:PINNED_TCC'"
}
Write-Host "Pinned TCC command: $resolvedTcc"
- name: Legacy gg import multiwindow isolation
run: v test vlib/gg/legacy_import_multiwindow_isolation_test.v
- name: Public gg Win32 services no-flag contract
run: v test vlib/gg/multiwindow_win32_public_services_contract_windows_test.v
- name: Win32 W3 native/public GREEN contracts
shell: pwsh
run: |
.\.github\workflows\run_multiwindow_win32_w3_green.ps1 -Compiler tcc `
-ExpectedCompositeSha256 '836c1d52c3042f8ec85d0c64489f1b0d1ead8ffafcfdb2a06f567a9b52e2785f' `
-ExpectedRunnerSha256 '9326948a5be280164fb5c6706295b2c35facae252b2ea1c11e26c5a9129cf955'
- name: Multiwindow render runtime contract
run: .\v.exe -silent vlib\gg\multiwindow_render_runtime_contract_test.v
- name: Public gg Win32 proven W1 services enabled contract
shell: pwsh
run: |
$testFile = (Resolve-Path `
'.\vlib\gg\multiwindow_win32_public_services_contract_windows_test.v').Path
$discoveredTests = @(
Select-String -LiteralPath $testFile -Pattern '^fn (test_[A-Za-z0-9_]+)\(\)' |
ForEach-Object { $_.Matches[0].Groups[1].Value }
)
if ($discoveredTests.Count -eq 0) {
throw "no public Win32 service tests were discovered in $testFile"
}
$noFlagOnlyTest = 'test_win32_public_services_stay_disabled_without_opt_in'
$diagnosticTest = 'test_win32_public_controls_publish_observed_state_red'
$w3GreenTest = 'test_win32_public_monitor_projection_and_event_order_red'
$w4RedTest = 'test_win32_public_clipboard_cf_unicodetext_bmp_astral_roundtrip_red'
$tests = @(
'test_win32_public_hwnd_borrow_route_red'
'test_win32_public_conditional_focus_refusal_is_not_a_capability_error_red'
'test_win32_public_partial_focus_is_never_reported_as_success_red'
)
$classifiedTests = @($noFlagOnlyTest) + $tests + @(
$diagnosticTest
$w3GreenTest
$w4RedTest
)
$missingTests = @(
$classifiedTests | Where-Object { $discoveredTests -cnotcontains $_ }
)
$unclassifiedTests = @(
$discoveredTests | Where-Object { $classifiedTests -cnotcontains $_ }
)
if ($missingTests.Count -ne 0 -or $unclassifiedTests.Count -ne 0) {
throw "public Win32 service test classification mismatch: missing=$($missingTests -join ',') unclassified=$($unclassifiedTests -join ',')"
}
foreach ($test in $tests) {
Write-Host "W1_TCC_CASE_BEGIN name=$test"
$startInfo = [System.Diagnostics.ProcessStartInfo]::new()
$startInfo.FileName = (Resolve-Path '.\v.exe').Path
$startInfo.UseShellExecute = $false
$startInfo.RedirectStandardOutput = $true
$startInfo.RedirectStandardError = $true
$startInfo.CreateNoWindow = $true
foreach ($argument in @(
'-d', 'gg_multiwindow',
'-run-only', $test,
'test', $testFile
)) {
[void]$startInfo.ArgumentList.Add($argument)
}
$process = [System.Diagnostics.Process]::new()
$process.StartInfo = $startInfo
try {
if (-not $process.Start()) {
throw "failed to start public Win32 service test $test"
}
$stdoutTask = $process.StandardOutput.ReadToEndAsync()
$stderrTask = $process.StandardError.ReadToEndAsync()
$timedOut = -not $process.WaitForExit(45000)
if ($timedOut) {
$process.Kill($true)
[void]$process.WaitForExit(5000)
} else {
$process.WaitForExit()
}
$stdout = $stdoutTask.GetAwaiter().GetResult()
$stderr = $stderrTask.GetAwaiter().GetResult()
if ($stdout) {
Write-Host $stdout.TrimEnd()
}
if ($stderr) {
[Console]::Error.WriteLine($stderr.TrimEnd())
}
$exitCode = if ($timedOut) { 'timeout' } else { [string]$process.ExitCode }
Write-Host "W1_TCC_CASE_END name=$test timeout=$timedOut exit=$exitCode"
if ($timedOut) {
throw "public Win32 service test timed out: $test"
}
if ($process.ExitCode -ne 0) {
throw "first failing public Win32 service test: $test (exit $($process.ExitCode))"
}
$summaryLines = @(
([string]$stdout -split "\r?\n") |
Where-Object { $_ -cmatch '^Summary for all V _test\.v files:' }
)
$combinedOutput = ([string]$stdout) + "`n" + ([string]$stderr)
$selectionAnomalies = @(
($combinedOutput -split "\r?\n") |
Where-Object { $_ -match '(?i)\bretrying\b|\bSKIP(?:PED)?\b' }
)
$summaryMatchesSelection = (
$summaryLines.Count -eq 1 -and
$summaryLines[0] -cmatch '^Summary for all V _test\.v files: 1 passed, 1 total\.' -and
$selectionAnomalies.Count -eq 0
)
if (-not $summaryMatchesSelection) {
$foundSummary = if ($summaryLines.Count -eq 0) {
'<none>'
} else {
$summaryLines -join ' | '
}
$foundAnomalies = if ($selectionAnomalies.Count -eq 0) {
'<none>'
} else {
$selectionAnomalies -join ' | '
}
throw "selection/summary mismatch for ${test}: expected exactly one '1 passed, 1 total' summary without skip/retry; summary=$foundSummary anomalies=$foundAnomalies"
}
} finally {
$process.Dispose()
}
}
- name: Package 2 native Win32 RED matrix
shell: pwsh
run: .\.github\workflows\run_multiwindow_win32_package2_red.ps1 -Compiler tcc
- name: Win32 W4 clipboard contracts
shell: pwsh
env:
VFLAGS: ''
run: |
.\.github\workflows\run_multiwindow_win32_w4.ps1 `
-Compiler tcc `
-Expectation Green `
-ExpectedOracleSha256 '804e8cbc5f5f7c390e90736d54a60d65d19b649a94afa4915bd9cb4e95c4e04d' `
-ExpectedNativeTestSha256 '1796d8221d14f9bc40c74e163d797b50f4eeb09a67aee0c4703834880354ef66' `
-ExpectedPublicTestSha256 'd08eafb919ae97b185fc480c22f6d990973396152e9a0b3a01035c3e9a30275c' `
-ExpectedNoOptProbeSha256 '288f148ca15b6694481f117c03be5f80c4045baf76d3b0e90db61b5e0596741c' `
-ExpectedServiceBackendSha256 '8ad39d63360446ef7049c726544200780eff61ff39917830f7024243dfd363be' `
-ExpectedEventDeliverySha256 'd38c868f574c02fc46e047da25e770e5b9f672500d796694b5ef35bf042cdae0' `
-ExpectedWin32BackendSha256 '57b7e02241fb3624ffde0619cf99441b0ae91cc112734cffb29433adbfe7b191' `
-ExpectedWin32ServiceBackendSha256 'faaf67be3e0381ea8a0e7a753b477b7965dde6e655f83f220eca036da19c5df6' `
-ExpectedWin32ServiceNativeSha256 '2ffc93e245a43c4a557fd7cc66ebcdda8874b9783ec3050ba754657a97efd033' `
-ExpectedRedSurfaceSha256 'fe7fa76370ee25883e4da25e72b339daeba9d1b47ff70b8b56b0ada87a0027c6' `
-ExpectedGreenSurfaceSha256 '703041609ba8ed459c785d567bba74e2b90470eb73c6edf99982ab24cf68ccd9' `
-ExpectedRunnerSha256 '9a38a51e00f609a3e04dbace876028c35bff3cd1a02326c1af40798374ea137a'
- name: Win32 W5 raw-input A0 preflight
shell: pwsh
run: |
.\.github\workflows\run_multiwindow_win32_w5_a0.ps1 -Compiler tcc `
-ExpectedHeaderSha256 '9decdc2e825c91da2b9d2ce0c98cb8ccdad5c4800a690863d166135eb188e916' `
-ExpectedMainSha256 '5f30869ae97f680032e622273ea69986d612cc82cad2adf53e4c3b1415154301' `
-ExpectedTupleSha256 '99ef24bf101dc83543f26f86cb23a80c82607e0f1b35c32e9dbb431368ecc7c4' `
-ExpectedRunnerSha256 'ce4da58e24730899f970a7566dc65d82eb0c07d38f74efcaeeb02c450a011b68'
- name: Win32 W5 raw-input A1 public GREEN
shell: pwsh
env:
VFLAGS: ''
run: |
.\.github\workflows\run_multiwindow_win32_w5_a1.ps1 -Compiler tcc `
-Expectation Green `
-ExpectedTestSha256 '005d3f7c7668bd18d593ba5f42e94cf247058c5f61ca46ce6d6a42bac03b5000' `
-ExpectedOracleSha256 '7362f17f06ea6b0ab5a64c74abf2407a0e284cbace2c10809a5235d406d16461' `
-ExpectedTupleSha256 '16739d9b8b73d9615ba3037c9e18219d6bf1271ef1d2f7dba4b2f2e53b1efac5' `
-ExpectedA0HeaderSha256 '9decdc2e825c91da2b9d2ce0c98cb8ccdad5c4800a690863d166135eb188e916' `
-ExpectedA0MainSha256 '5f30869ae97f680032e622273ea69986d612cc82cad2adf53e4c3b1415154301' `
-ExpectedA0TupleSha256 '99ef24bf101dc83543f26f86cb23a80c82607e0f1b35c32e9dbb431368ecc7c4' `
-ExpectedA0RunnerSha256 'ce4da58e24730899f970a7566dc65d82eb0c07d38f74efcaeeb02c450a011b68' `
-ExpectedGgFacadeSha256 'e5a944c1bb86bf9af11bfc9d1d137566ac6659d5f56ddabd08cdb49792afbb46' `
-ExpectedGgNoFlagSha256 'ad528c64cf18bce9415dd0e50513fb87d8d0b58c8ac4a99025a5c8955e7d9549' `
-ExpectedGgServiceTypesSha256 '9f17334ba5e5aff51f26d55476c83878856a8494a890aa64ee6434a52c1ecfeb' `
-ExpectedAppSha256 'af32eec55c119907a8bbf544842131018d36d3887347e26486e067a79d78a946' `
-ExpectedTypesSha256 '0a9058ba7928945e24284c867eb6182336ea3b1d41e1337786c71105b1fe93b3' `
-ExpectedBackendSha256 'dcd0f088c235ae030f8bbc9ab63082c38d93f6f1194373e74d8dcb454d100a3f' `
-ExpectedServiceApiSha256 'b7e4bc26e85f897a72387e82f4a7a3d545f21230be5c6b9df4fa40a4c82b701f' `
-ExpectedServiceTypesSha256 'cd8326b81201727618e758d79970b7a77223fd6418e18afda44a526a3b0b4267' `
-ExpectedServiceRegistrySha256 'db244497fd23974c1739d6c7a8bc57a2e3137c8765d4bc7f789efd80a59066b7' `
-ExpectedEventDeliverySha256 'd38c868f574c02fc46e047da25e770e5b9f672500d796694b5ef35bf042cdae0' `
-ExpectedPublicRoutingSurfaceSha256 '3993513f6865922d0dd47daa32e5ea0a7fd4d7e6c2480b79d1db8f568802aad2' `
-ExpectedServiceBackendSha256 '8ad39d63360446ef7049c726544200780eff61ff39917830f7024243dfd363be' `
-ExpectedEventDispatchSha256 '7ef6c7cbd34511d6c19c1a3a269b46876db791b9412bb88e3a8d4dcd543bfd4e' `
-ExpectedWin32BackendSha256 '57b7e02241fb3624ffde0619cf99441b0ae91cc112734cffb29433adbfe7b191' `
-ExpectedWin32BackendHelpersSha256 'ba0021ce46731b25d540a68bf7c7832c7302a7343a90e1398df91cc5e409754d' `
-ExpectedWin32ServiceBackendSha256 'faaf67be3e0381ea8a0e7a753b477b7965dde6e655f83f220eca036da19c5df6' `
-ExpectedWin32ServiceNativeSha256 '2ffc93e245a43c4a557fd7cc66ebcdda8874b9783ec3050ba754657a97efd033' `
-ExpectedGreenProductionSurfaceSha256 'c1796663110d256b5ba6bc59e3ea0d2ec28863ab2c8b697dd8ee39882afe0928' `
-ExpectedRunnerSha256 '1a3b1c562843a641faaaf79c4bd6fd6ab58594d5a75d9ae7b488c7d23d934112'
- name: Public gg Win32 controls/state native diagnostic
if: ${{ always() }}
shell: pwsh
run: |
$testFile = (Resolve-Path `
'.\vlib\gg\multiwindow_win32_public_services_contract_windows_test.v').Path
$test = 'test_win32_public_controls_publish_observed_state_red'
$discoveredTests = @(
Select-String -LiteralPath $testFile -Pattern '^fn (test_[A-Za-z0-9_]+)\(\)' |
ForEach-Object { $_.Matches[0].Groups[1].Value }
)
if ($discoveredTests -cnotcontains $test) {
throw "controls/state native diagnostic test was not discovered: $test"
}
Write-Host "W1_TCC_NATIVE_DIAG_BEGIN name=$test"
$startInfo = [System.Diagnostics.ProcessStartInfo]::new()
$startInfo.FileName = (Resolve-Path '.\v.exe').Path
$startInfo.UseShellExecute = $false
$startInfo.RedirectStandardOutput = $true
$startInfo.RedirectStandardError = $true
$startInfo.CreateNoWindow = $true
foreach ($argument in @(
'-d', 'gg_multiwindow',
'-run-only', $test,
'test', $testFile
)) {
[void]$startInfo.ArgumentList.Add($argument)
}
$process = [System.Diagnostics.Process]::new()
$process.StartInfo = $startInfo
try {
if (-not $process.Start()) {
throw "failed to start controls/state native diagnostic $test"
}
$stdoutTask = $process.StandardOutput.ReadToEndAsync()
$stderrTask = $process.StandardError.ReadToEndAsync()
$timedOut = -not $process.WaitForExit(45000)
if ($timedOut) {
$process.Kill($true)
[void]$process.WaitForExit(5000)
} else {
$process.WaitForExit()
}
$stdout = $stdoutTask.GetAwaiter().GetResult()
$stderr = $stderrTask.GetAwaiter().GetResult()
if ($stdout) {
Write-Host $stdout.TrimEnd()
}
if ($stderr) {
[Console]::Error.WriteLine($stderr.TrimEnd())
}
$exitCode = if ($timedOut) { 'timeout' } else { [string]$process.ExitCode }
Write-Host "W1_TCC_NATIVE_DIAG_END name=$test timeout=$timedOut exit=$exitCode"
if ($timedOut) {
throw "controls/state native diagnostic timed out: $test"
}
if ($process.ExitCode -ne 0) {
throw "controls/state native diagnostic failed: $test (exit $($process.ExitCode))"
}
$summaryLines = @(
([string]$stdout -split "\r?\n") |
Where-Object { $_ -cmatch '^Summary for all V _test\.v files:' }
)
$combinedOutput = ([string]$stdout) + "`n" + ([string]$stderr)
$selectionAnomalies = @(
($combinedOutput -split "\r?\n") |
Where-Object { $_ -match '(?i)\bretrying\b|\bSKIP(?:PED)?\b' }
)
$summaryMatchesSelection = (
$summaryLines.Count -eq 1 -and
$summaryLines[0] -cmatch '^Summary for all V _test\.v files: 1 passed, 1 total\.' -and
$selectionAnomalies.Count -eq 0
)
if (-not $summaryMatchesSelection) {
$foundSummary = if ($summaryLines.Count -eq 0) {
'<none>'
} else {
$summaryLines -join ' | '
}
$foundAnomalies = if ($selectionAnomalies.Count -eq 0) {
'<none>'
} else {
$selectionAnomalies -join ' | '
}
throw "selection/summary mismatch for ${test}: expected exactly one '1 passed, 1 total' summary without skip/retry; summary=$foundSummary anomalies=$foundAnomalies"
}
} finally {
$process.Dispose()
}