tests/Invoke-DFBoundedProcess.Tests.ps1
|
BeforeAll { . "$PSScriptRoot/TestSupport.ps1" foreach ($f in Get-DFTestModuleFile) { . $f } $script:Pwsh = (Get-Process -Id $PID).Path } Describe 'Invoke-DFBoundedProcess' { It 'returns the output lines and exit code' { $r = Invoke-DFBoundedProcess -FilePath $script:Pwsh -ArgumentList '-NoProfile', '-Command', 'Write-Output one; Write-Output two; exit 3' -TimeoutSeconds 30 $r.Lines | Should -Be @('one', 'two') $r.ExitCode | Should -Be 3 } It 'passes each argument as one argument, spaces included' { $r = Invoke-DFBoundedProcess -FilePath $script:Pwsh -ArgumentList '-NoProfile', '-Command', 'Write-Output "a b"' -TimeoutSeconds 30 $r.Lines | Should -Be @('a b') } It 'leaves stderr out of the lines' { $r = Invoke-DFBoundedProcess -FilePath $script:Pwsh -ArgumentList '-NoProfile', '-Command', '[Console]::Error.WriteLine("noise"); Write-Output kept' -TimeoutSeconds 30 $r.Lines | Should -Be @('kept') } It 'kills a process that runs past the timeout and throws, naming the command' { $marker = "df-bounded-$(Get-Random)" $clock = [System.Diagnostics.Stopwatch]::StartNew() { Invoke-DFBoundedProcess -FilePath $script:Pwsh -ArgumentList '-NoProfile', '-Command', "Start-Sleep 60 # $marker" -TimeoutSeconds 1 } | Should -Throw "*did not finish within 1 s*" $clock.Elapsed.TotalSeconds | Should -BeLessThan 20 Start-Sleep -Milliseconds 500 @(Get-CimInstance Win32_Process -Filter "Name = 'pwsh.exe'" | Where-Object CommandLine -like "*$marker*") | Should -HaveCount 0 } } Describe 'winget CLI seams are bounded' { BeforeEach { Mock Get-Command { [pscustomobject]@{ Source = 'C:\fake\winget.exe' } } Mock Invoke-DFBoundedProcess { [pscustomobject]@{ Lines = @('line 1', 'line 2'); ExitCode = 0 } } } It 'runs winget search through the bounded runner' { Invoke-DFCatalogWingetCli -Query 'ripgrep' | Should -Be @('line 1', 'line 2') Should -Invoke Invoke-DFBoundedProcess -Times 1 -Exactly -ParameterFilter { $FilePath -eq 'C:\fake\winget.exe' -and $TimeoutSeconds -gt 0 -and ($ArgumentList -join ' ') -eq 'search --query ripgrep --source winget --disable-interactivity' } } It 'runs winget show through the bounded runner' { Invoke-DFCatalogWingetShowCli -PackageId 'BurntSushi.ripgrep.MSVC' | Should -Be @('line 1', 'line 2') Should -Invoke Invoke-DFBoundedProcess -Times 1 -Exactly -ParameterFilter { $FilePath -eq 'C:\fake\winget.exe' -and $TimeoutSeconds -gt 0 -and ($ArgumentList -join ' ') -eq 'show --id BurntSushi.ripgrep.MSVC --exact --source winget --disable-interactivity' } } } |