tests/Test-PSAOAIEnv.ps1
|
[CmdletBinding()] param() $ErrorActionPreference = 'Stop' $root = Split-Path $PSScriptRoot -Parent $script:passed = 0 $script:failed = 0 function Assert-True($Condition) { if (-not $Condition) { throw 'Assertion failed (synthetic fixture only).' } } function Test-Case($Name, [scriptblock]$Body) { try { & $Body; $script:passed++; Write-Host "PASS $Name" } catch { $script:failed++; Write-Host "FAIL $Name : $($_.Exception.GetType().Name)" } } # Redirect the legacy static User query for RED too: never read real persistent values. $source = Get-Content (Join-Path $root 'Public/Get-PSAOAIEnv.ps1') -Raw $source = $source.Replace('[Environment]::GetEnvironmentVariables("user")', '(Get-PSAOAIEnvironmentVariables -Scope User)') . ([scriptblock]::Create($source)) $script:empty = $false $script:calls = @() function Get-PSAOAIEnvironmentVariables { param($Scope) $script:calls += $Scope if ($script:empty) { return @{ OTHER_VARIABLE = 'ignored' } } if ($Scope -eq 'Process') { # Read only known synthetic names; no real secret enumeration or output. return @{ PSAOAI_TEST_DUPLICATE = [Environment]::GetEnvironmentVariable('PSAOAI_TEST_DUPLICATE', 'Process'); PSAOAI_API_AZURE_OPENAI_KEY = 'synthetic-process-key'; PSAOAI_TEST_EMPTY = ''; OTHER_VARIABLE = 'ignored' } } return @{ PSAOAI_TEST_DUPLICATE = "synthetic-$Scope"; PSAOAI_API_AZURE_OPENAI_KEY = "synthetic-$Scope-key"; PSAOAI_OTHER_API_KEY = ''; OTHER_VARIABLE = 'ignored' } } # A new child process owns this synthetic value; no User/Machine mutation. [Environment]::SetEnvironmentVariable('PSAOAI_TEST_DUPLICATE', 'synthetic-Process', 'Process') foreach ($scope in @('Process', 'User', 'Machine')) { Test-Case "single scope $scope objects and filtering" { $script:calls = @() $rows = @(Get-PSAOAIEnv -Scope $scope) Assert-True ($rows.Count -eq 3) Assert-True (($script:calls -join ',') -eq $scope) foreach ($row in $rows) { Assert-True ($row -is [pscustomobject]) Assert-True ($row.Scope -eq $scope) Assert-True ($row.Name -like 'PSAOAI*') Assert-True ($row.PSObject.Properties.Name -contains 'Value') } Assert-True (($rows | Where-Object Name -eq PSAOAI_TEST_DUPLICATE).Value -eq "synthetic-$scope") } } Test-Case 'default all scopes preserves duplicate names' { $script:calls = @() $rows = @(Get-PSAOAIEnv) Assert-True ($rows.Count -eq 9) Assert-True (($script:calls -join ',') -eq 'Process,User,Machine') Assert-True (@($rows | Where-Object Name -eq PSAOAI_TEST_DUPLICATE).Count -eq 3) } Test-Case 'all API keys fully masked including empty keys' { $rows = @(Get-PSAOAIEnv) $keys = @($rows | Where-Object Name -match 'API.*KEY') Assert-True ($keys.Count -eq 5) foreach ($key in $keys) { Assert-True ($key.Value -ceq '****'); Assert-True ($key.Info -notmatch 'encoded|encrypted') } } Test-Case 'empty ordinary value remains data' { $rows = @(Get-PSAOAIEnv -Scope Process) Assert-True (($rows | Where-Object Name -eq PSAOAI_TEST_EMPTY).Value -ceq '') } Test-Case 'empty result emits information not a data row' { $script:empty = $true try { $messages = @() $rows = @(Get-PSAOAIEnv -InformationVariable messages -InformationAction SilentlyContinue) Assert-True ($rows.Count -eq 0) Assert-True ($messages.Count -eq 1) Assert-True ("$($messages[0])" -match 'No PSAOAI environment variables') } finally { $script:empty = $false } } Test-Case 'invalid scope rejected before lookup' { $script:calls = @() $caught = $false try { Get-PSAOAIEnv -Scope Invalid | Out-Null } catch [System.Management.Automation.ParameterBindingException] { $caught = $true } Assert-True $caught Assert-True ($script:calls.Count -eq 0) } Test-Case 'case insensitive scope accepted and canonicalized' { $rows = @(Get-PSAOAIEnv -Scope process) Assert-True ($rows[0].Scope -ceq 'Process') } Write-Host "RESULT passed=$script:passed failed=$script:failed" if ($script:failed) { exit 1 } |