tests/DotNetTestHarvesting.Tests.ps1
|
BeforeAll { $script:RepoRoot = Split-Path -Parent $PSScriptRoot $script:ModulePath = Join-Path $script:RepoRoot 'Skyline.DataMiner.QAOps.PipelineLibrary.psd1' Import-Module $script:ModulePath -Force } Describe 'Invoke-DotNetTestHarvesting' { BeforeEach { $script:Content = Join-Path $TestDrive 'content' New-Item -Path (Join-Path $script:Content 'TestHarvesting') -ItemType Directory -Force | Out-Null New-Item -Path (Join-Path $script:Content 'TestPackagePipeline') -ItemType Directory -Force | Out-Null } It 'returns parsed harvest report and sends token only through child environment' { InModuleScope Skyline.DataMiner.QAOps.PipelineLibrary -Parameters @{ Content = $script:Content } { Mock Install-QAFrameworkTool { [pscustomobject]@{} } Mock Invoke-QAFrameworkDotNet { [pscustomobject]@{ ExitCode = 0; StdOut = '{"schemaVersion":1,"command":"harvest-dotnet","status":"completed","sidecarPath":"sidecar","assemblies":[],"counts":{"tests":1,"declared":0,"reviewedManifest":0,"gitFallback":0,"unresolved":0,"conflicts":0},"diagnostics":[]}'; StdErr = ''; TimedOut = $false } } $secure = ConvertTo-SecureString 'secret-token' -AsPlainText -Force $report = Invoke-DotNetTestHarvesting -TestPackageContentPath $Content -GitHubToken $secure -TestAssemblyPath 'tests.generated\A.dll' -GitHubOrganizations SkylineCommunications -AllowedEmailDomains skyline.be $report.status | Should -Be 'completed' Should -Invoke Invoke-QAFrameworkDotNet -Times 1 -ParameterFilter { $Arguments -contains 'harvest-dotnet' -and $Arguments -notcontains 'secret-token' -and $Environment['QAOPS_GITHUB_TOKEN'] -eq 'secret-token' } } } It 'synthesizes skipped when tool install fails offline' { InModuleScope Skyline.DataMiner.QAOps.PipelineLibrary -Parameters @{ Content = $script:Content } { Mock Install-QAFrameworkTool { throw 'offline' } $report = Invoke-DotNetTestHarvesting -TestPackageContentPath $Content -WarningVariable warnings 3>$null $report.status | Should -Be 'skipped' $report.diagnostics[0].code | Should -Be 'toolInstallFailed' @($warnings).Count | Should -Be 1 } } It 'synthesizes skipped when tool is too old' { InModuleScope Skyline.DataMiner.QAOps.PipelineLibrary -Parameters @{ Content = $script:Content } { Mock Install-QAFrameworkTool { [pscustomobject]@{} } Mock Invoke-QAFrameworkDotNet { [pscustomobject]@{ ExitCode = 1; StdOut = ''; StdErr = 'Unrecognized command harvest-dotnet'; TimedOut = $false } } $report = Invoke-DotNetTestHarvesting -TestPackageContentPath $Content -WarningVariable warnings 3>$null $report.status | Should -Be 'skipped' $report.diagnostics[0].code | Should -Be 'toolTooOld' @($warnings).Count | Should -Be 1 } } It 'synthesizes skipped for timeout and non-JSON output' { InModuleScope Skyline.DataMiner.QAOps.PipelineLibrary -Parameters @{ Content = $script:Content } { Mock Install-QAFrameworkTool { [pscustomobject]@{} } Mock Invoke-QAFrameworkDotNet { [pscustomobject]@{ ExitCode = -1; StdOut = ''; StdErr = ''; TimedOut = $true } } (Invoke-DotNetTestHarvesting -TestPackageContentPath $Content -WarningVariable w1 3>$null).diagnostics[0].code | Should -Be 'toolTimeout' Mock Invoke-QAFrameworkDotNet { [pscustomobject]@{ ExitCode = 0; StdOut = 'not-json'; StdErr = ''; TimedOut = $false } } (Invoke-DotNetTestHarvesting -TestPackageContentPath $Content -WarningVariable w2 3>$null).diagnostics[0].code | Should -Be 'nonJsonOutput' } } } Describe 'Invoke-DotNetTestHarvesting lock contention' { It 'skips with one warning when the tool-cache lock is contended and no cached tool exists' { $content = Join-Path $TestDrive 'content-lock' New-Item -Path (Join-Path $content 'TestHarvesting') -ItemType Directory -Force | Out-Null New-Item -Path (Join-Path $content 'TestPackagePipeline') -ItemType Directory -Force | Out-Null $oldLocal = $env:LOCALAPPDATA $oldTimeout = $env:QAOPS_QAFRAMEWORK_TOOL_LOCK_TIMEOUT_SECONDS $env:LOCALAPPDATA = Join-Path $TestDrive 'localappdata' $env:QAOPS_QAFRAMEWORK_TOOL_LOCK_TIMEOUT_SECONDS = '0' New-Item -Path $env:LOCALAPPDATA -ItemType Directory -Force | Out-Null $mutex = New-Object System.Threading.Mutex($false, 'Global\Skyline.QAOps.QAFrameworkOrchestrator.ToolCache') $taken = $mutex.WaitOne([TimeSpan]::FromSeconds(1)) try { InModuleScope Skyline.DataMiner.QAOps.PipelineLibrary -Parameters @{ Content = $content } { Mock Install-QAFrameworkTool { throw 'should not install while lock is held' } $report = Invoke-DotNetTestHarvesting -TestPackageContentPath $Content -WarningVariable warnings 3>$null $report.status | Should -Be 'skipped' $report.diagnostics[0].code | Should -Be 'toolInstallContention' @($warnings).Count | Should -Be 1 } } finally { if ($taken) { $mutex.ReleaseMutex() | Out-Null } $mutex.Dispose() $env:LOCALAPPDATA = $oldLocal $env:QAOPS_QAFRAMEWORK_TOOL_LOCK_TIMEOUT_SECONDS = $oldTimeout } } } |