# Run the tests as SYSTEM via a scheduled task.
#
# The credential vault is only reachable from a logon session that has a credential set.
# A network logon (ci runner, ssh) has none, so every wincred call there fails with
# ERROR_NO_SUCH_LOGON_SESSION. SYSTEM has one, needs no password and needs nobody logged on.
#
# Usage: scripts\test_windows.ps1 [-Filter '<nextest filter expression>']
param(
[string]$Filter = ""
)
$ErrorActionPreference = "Stop"
$root = Split-Path -Parent $PSScriptRoot
$task = "keyring-manager-tests"
$out = Join-Path $root "windows-test-output.txt"
$inner = Join-Path $root "scripts\.test_windows_inner.cmd"
# SYSTEM gets none of this job's environment, and cargo.exe is a rustup proxy that finds
# no toolchain without RUSTUP_HOME, so bake all of it in.
$cargoHome = if ($env:CARGO_HOME) { $env:CARGO_HOME } else { Join-Path $env:USERPROFILE ".cargo" }
$rustupHome = if ($env:RUSTUP_HOME) { $env:RUSTUP_HOME } else { Join-Path $env:USERPROFILE ".rustup" }
$filterArg = if ($Filter) { "-E `"$Filter`"" } else { "" }
@"
@echo off
set CARGO_HOME=$cargoHome
set RUSTUP_HOME=$rustupHome
set PATH=$cargoHome\bin;%PATH%
cd /d "$root"
cargo nextest run --profile ci $filterArg > "$out" 2>&1
exit /b %ERRORLEVEL%
"@ | Set-Content -Path $inner -Encoding ASCII
Remove-Item $out -ErrorAction SilentlyContinue
# Build outside the task: a compile failure should look like a compile failure, and this
# keeps the task doing one thing.
Write-Host "=== building tests ==="
& cargo nextest run --profile ci --no-run
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Write-Host "=== running tests as SYSTEM ==="
$action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/c `"$inner`"" -WorkingDirectory $root
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName $task -Action $action -Principal $principal -Force | Out-Null
try {
Start-ScheduledTask -TaskName $task
# Give the scheduler a moment to move the task out of Ready before polling.
Start-Sleep -Seconds 2
$deadline = (Get-Date).AddMinutes(30)
while ((Get-ScheduledTask -TaskName $task).State -eq "Running") {
if ((Get-Date) -gt $deadline) { throw "windows test task did not finish within 30 minutes" }
Start-Sleep -Seconds 5
}
$rc = (Get-ScheduledTaskInfo -TaskName $task).LastTaskResult
} finally {
Unregister-ScheduledTask -TaskName $task -Confirm:$false -ErrorAction SilentlyContinue
Remove-Item $inner -ErrorAction SilentlyContinue
}
if (Test-Path $out) { Get-Content $out } else { Write-Host "no test output was produced" }
exit $rc