tests/lib/worker.ps1
|
# 测试 worker:在独立进程中执行单个构建或单个用例,保证环境变量/工作目录隔离。 param( [Parameter(Mandatory)][ValidateSet('Build', 'Test')][string]$Mode, [Parameter(Mandatory)][string]$JobFile, [Parameter(Mandatory)][string]$ResultFile ) $ErrorActionPreference = 'Stop' . (Join-Path $PSScriptRoot 'common.ps1') . (Join-Path $PSScriptRoot 'exec.ps1') . (Join-Path $PSScriptRoot 'assert.ps1') . (Join-Path $PSScriptRoot 'framework.ps1') $repoRoot = $script:RepoRoot $job = ConvertTo-HashtableDeep (Read-JsonFile -Path $JobFile) $result = @{ Success = $false; OutputPath = $null; Error = $null; Stack = $null; Assertions = 0 } function Find-TestCase { param([string]$Name) $cases = @(Get-AllTestCases) $case = $cases | Where-Object { $_.Name -eq $Name } | Select-Object -First 1 if (-not $case) { throw "找不到用例:$Name" } return $case } function Invoke-BuildSpec { param([hashtable]$Spec) if ($Spec.Env) { foreach ($k in @($Spec.Env.Keys)) { Set-Item -Path "Env:$k" -Value ([string]$Spec.Env[$k]) } } $outDir = [string]$job.OutputDir New-Item -ItemType Directory -Path $outDir -Force | Out-Null $outputName = if ($Spec.Output) { [string]$Spec.Output } else { 'out.exe' } $outPath = Join-Path $outDir $outputName $named = @{} if ($Spec.Params) { foreach ($k in @($Spec.Params.Keys)) { $named[$k] = $Spec.Params[$k] } } Import-Module $repoRoot -Force if ($Spec.Compiler -eq 'ps2exe') { Initialize-Ps2exeShim -RepoRoot $repoRoot if ($null -ne $Spec.InputText) { $inputFile = Join-Path $outDir 'input.ps1' [System.IO.File]::WriteAllText($inputFile, [string]$Spec.InputText, [System.Text.UTF8Encoding]::new($true)) $null = [string]$Spec.InputText | ps2exe @named -outputFile $outPath } else { $inputFile = [string]$Spec.InputFile if (-not [System.IO.Path]::IsPathRooted($inputFile)) { $inputFile = Join-Path $repoRoot $inputFile } if (-not (Test-Path -LiteralPath $inputFile -PathType Leaf)) { throw "构建输入不存在:$inputFile" } $null = ps2exe @named -inputFile $inputFile -outputFile $outPath } } elseif ($null -ne $Spec.InputText) { $inputFile = Join-Path $outDir 'input.ps1' [System.IO.File]::WriteAllText($inputFile, [string]$Spec.InputText, [System.Text.UTF8Encoding]::new($true)) $null = [string]$Spec.InputText | ps12exe @named -outputFile $outPath -NoUpdateCheck } else { $inputFile = [string]$Spec.InputFile if (-not [System.IO.Path]::IsPathRooted($inputFile)) { $inputFile = Join-Path $repoRoot $inputFile } if (-not (Test-Path -LiteralPath $inputFile -PathType Leaf)) { throw "构建输入不存在:$inputFile" } $null = ps12exe @named -inputFile $inputFile -outputFile $outPath -NoUpdateCheck } if (-not (Test-Path -LiteralPath $outPath -PathType Leaf)) { throw "构建未产出:$outPath" } return $outPath } try { switch ($Mode) { 'Build' { $case = Find-TestCase -Name ([string]$job.CaseName) $specs = Get-CaseBuildSpecs -Case $case $entry = $specs | Where-Object { $_.Name -eq ([string]$job.BuildName) } | Select-Object -First 1 if (-not $entry) { throw "用例 $($job.CaseName) 不存在构建 $($job.BuildName)" } $result.OutputPath = Invoke-BuildSpec -Spec $entry.Spec $result.Success = $true } 'Test' { $case = Find-TestCase -Name ([string]$job.Name) Import-Module $repoRoot -Force New-Item -ItemType Directory -Path ([string]$job.WorkDir) -Force | Out-Null $builds = @{} if ($job.Builds) { foreach ($k in $job.Builds.Keys) { $builds[$k] = [string]$job.Builds[$k] } } $ctx = @{ RepoRoot = $repoRoot WorkDir = [string]$job.WorkDir CacheDir = [string]$job.CacheDir Builds = $builds Case = $case } if ($case.Run) { & $case.Run $ctx } $result.Success = $true } } } catch { $result.Success = $false $result.Error = $_.Exception.Message $result.Stack = $_.ScriptStackTrace } finally { $result.Assertions = Get-AssertionCount Write-JsonFile -Path $ResultFile -Object $result } |