diff --git a/.github/scripts/Set-ScreenResolution.Tests.ps1 b/.github/scripts/Set-ScreenResolution.Tests.ps1 new file mode 100644 index 000000000000..f3762e7d5044 --- /dev/null +++ b/.github/scripts/Set-ScreenResolution.Tests.ps1 @@ -0,0 +1,76 @@ +#!/usr/bin/env pwsh +#Requires -Modules Pester + +BeforeAll { + $screenResolutionScript = Join-Path $PSScriptRoot '../../eng/scripts/Set-ScreenResolution.ps1' + $tokens = $null + $parseErrors = $null + $ast = [System.Management.Automation.Language.Parser]::ParseFile( + $screenResolutionScript, + [ref]$tokens, + [ref]$parseErrors) + + if ($parseErrors.Count -gt 0) { + throw "Set-ScreenResolution.ps1 has parse errors: $($parseErrors -join '; ')" + } + + $functionDefinitions = $ast.FindAll({ + param($node) + $node -is [System.Management.Automation.Language.FunctionDefinitionAst] + }, $true) + + foreach ($functionName in @( + 'Get-ScreenResolutionProbeAction', + 'Test-ScreenResolutionApplySucceeded' + )) { + $definition = $functionDefinitions | + Where-Object Name -EQ $functionName | + Select-Object -First 1 + + if ($null -eq $definition) { + throw "Function '$functionName' was not found in Set-ScreenResolution.ps1" + } + + Invoke-Expression $definition.Extent.Text + } + + $setResolutionDefinition = $functionDefinitions | + Where-Object Name -EQ 'Set-ScreenResolution' | + Select-Object -First 1 + + if ($null -eq $setResolutionDefinition) { + throw "Function 'Set-ScreenResolution' was not found in Set-ScreenResolution.ps1" + } + + $setResolutionBody = $setResolutionDefinition.Extent.Text +} + +Describe 'Set-ScreenResolution native result decisions' { + It 'returns for CDS_TEST result ' -ForEach @( + @{ Result = 0; Expected = 'Apply' } + @{ Result = -1; Expected = 'Apply' } + @{ Result = -2; Expected = 'Reject' } + @{ Result = -3; Expected = 'Apply' } + @{ Result = -4; Expected = 'Apply' } + @{ Result = -5; Expected = 'Apply' } + ) { + Get-ScreenResolutionProbeAction -Result $Result | Should -Be $Expected + } + + It 'returns for real apply result ' -ForEach @( + @{ Result = 0; Expected = $true } + @{ Result = 1; Expected = $true } + @{ Result = -1; Expected = $false } + @{ Result = -2; Expected = $false } + @{ Result = -3; Expected = $false } + @{ Result = -4; Expected = $false } + @{ Result = -5; Expected = $false } + ) { + Test-ScreenResolutionApplySucceeded -Result $Result | Should -Be $Expected + } + + It 'uses the pure decisions in the native flow' { + $setResolutionBody | Should -Match 'Get-ScreenResolutionProbeAction\s+-Result\s+\$testResult' + $setResolutionBody | Should -Match 'Test-ScreenResolutionApplySucceeded\s+-Result\s+\$changeResult' + } +} diff --git a/eng/scripts/Set-ScreenResolution.ps1 b/eng/scripts/Set-ScreenResolution.ps1 index acefd73f8128..bf73a9c0a9cc 100644 --- a/eng/scripts/Set-ScreenResolution.ps1 +++ b/eng/scripts/Set-ScreenResolution.ps1 @@ -37,6 +37,26 @@ param ( Set-StrictMode -Version 2.0 $ErrorActionPreference = "Stop" +function Get-ScreenResolutionProbeAction { + param ( + [int]$Result + ) + + if ($Result -eq -2) { + return "Reject" + } + + return "Apply" +} + +function Test-ScreenResolutionApplySucceeded { + param ( + [int]$Result + ) + + return ($Result -eq 0 -or $Result -eq 1) +} + function Set-ScreenResolution { param ( [int]$Width, @@ -167,34 +187,35 @@ namespace DisplaySettings if ($testResult -ne [DisplaySettings.NativeMethods]::DISP_CHANGE_SUCCESSFUL) { Write-Warning "Resolution test returned code: $testResult" - - switch ($testResult) { - ([DisplaySettings.NativeMethods]::DISP_CHANGE_BADMODE) { - Write-Error "The resolution ${Width}x${Height} is not supported by this display (BADMODE)" - return $false - } - ([DisplaySettings.NativeMethods]::DISP_CHANGE_FAILED) { - Write-Error "The resolution change test failed (FAILED)" - return $false - } - default { - Write-Warning "Unexpected test result, attempting to apply anyway..." - } + + if ((Get-ScreenResolutionProbeAction -Result $testResult) -eq "Reject") { + Write-Error "The resolution ${Width}x${Height} is not supported by this display (BADMODE)" + return $false + } + + if ($testResult -eq [DisplaySettings.NativeMethods]::DISP_CHANGE_FAILED) { + Write-Warning "CDS_TEST returned DISP_CHANGE_FAILED ($testResult) for target ${Width}x${Height}; attempting to apply the resolution anyway..." + } + else { + Write-Warning "Unexpected test result, attempting to apply anyway..." } } # Apply the resolution change $changeResult = [DisplaySettings.NativeMethods]::ChangeDisplaySettings([ref]$devMode, [DisplaySettings.NativeMethods]::CDS_UPDATEREGISTRY) - - switch ($changeResult) { - ([DisplaySettings.NativeMethods]::DISP_CHANGE_SUCCESSFUL) { - Write-Host "Successfully set screen resolution to ${Width}x${Height}" - return $true - } - ([DisplaySettings.NativeMethods]::DISP_CHANGE_RESTART) { + + if (Test-ScreenResolutionApplySucceeded -Result $changeResult) { + if ($changeResult -eq [DisplaySettings.NativeMethods]::DISP_CHANGE_RESTART) { Write-Host "Screen resolution set to ${Width}x${Height}. A restart may be required for some applications." - return $true } + else { + Write-Host "Successfully set screen resolution to ${Width}x${Height}" + } + + return $true + } + + switch ($changeResult) { ([DisplaySettings.NativeMethods]::DISP_CHANGE_BADMODE) { Write-Error "The resolution ${Width}x${Height} is not supported by this display" return $false