diff --git a/.vsts-ci/templates/ci-build.yml b/.vsts-ci/templates/ci-build.yml index e64ab4967a2..c502a9a3d46 100644 --- a/.vsts-ci/templates/ci-build.yml +++ b/.vsts-ci/templates/ci-build.yml @@ -1,16 +1,50 @@ parameters: - pool: 'windows-latest' - jobName: 'win_build' - displayName: Windows Build + - name: pool + default: 'windows-latest' + - name: imageName + default: 'PSWindows11-ARM64' + - name: jobName + default: 'win_build' + - name: displayName + default: Windows Build + - name: PoolType + default: AzDoHosted + type: string + values: + - AzDoHosted + - 1esHosted jobs: - job: ${{ parameters.jobName }} pool: - vmImage: ${{ parameters.pool }} + ${{ if eq( parameters.PoolType, 'AzDoHosted') }}: + vmImage: ${{ parameters.pool }} + ${{ else }}: + name: ${{ parameters.pool }} + demands: + - ImageOverride -equals ${{ parameters.imageName }} displayName: ${{ parameters.displayName }} steps: + - powershell: | + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 + $pwsh = Get-Command pwsh -ErrorAction SilentlyContinue -CommandType Application + + if ($null -eq $pwsh) { + $powerShellPath = Join-Path -Path $env:AGENT_TEMPDIRECTORY -ChildPath 'powershell' + Invoke-WebRequest -Uri https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.ps1 -outfile ./install-powershell.ps1 + ./install-powershell.ps1 -Destination $powerShellPath + $vstsCommandString = "vso[task.setvariable variable=PATH]$powerShellPath;$env:PATH" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + } + + displayName: Install PowerShell + + - checkout: self + fetchDepth: 1000 + - pwsh: | Get-ChildItem -Path env: displayName: Capture Environment @@ -26,6 +60,9 @@ jobs: - pwsh: | Import-Module .\tools\ci.psm1 Invoke-CIInstall -SkipUser + Write-Verbose -Verbose "Start Sync-PSTags" + Sync-PSTags -AddRemoteIfMissing + Write-Verbose -Verbose "End Sync-PSTags" displayName: Bootstrap condition: succeeded() diff --git a/.vsts-ci/templates/windows-test.yml b/.vsts-ci/templates/windows-test.yml index 2e5d5b67e24..50ff67a32a8 100644 --- a/.vsts-ci/templates/windows-test.yml +++ b/.vsts-ci/templates/windows-test.yml @@ -1,5 +1,6 @@ parameters: pool: 'windows-2019' + imageName: 'PSWindows11-ARM64' parentJobs: [] purpose: '' tagSet: 'CI' @@ -9,11 +10,32 @@ jobs: dependsOn: ${{ parameters.parentJobs }} pool: - vmImage: ${{ parameters.pool }} + ${{ if startsWith( parameters.pool, 'windows-') }}: + vmImage: ${{ parameters.pool }} + ${{ else }}: + name: ${{ parameters.pool }} + demands: + - ImageOverride -equals ${{ parameters.imageName }} displayName: Windows Test - ${{ parameters.purpose }} - ${{ parameters.tagSet }} steps: + - powershell: | + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 + $pwsh = Get-Command pwsh -ErrorAction SilentlyContinue -CommandType Application + + if ($null -eq $pwsh) { + $powerShellPath = Join-Path -Path $env:AGENT_TEMPDIRECTORY -ChildPath 'powershell' + Invoke-WebRequest -Uri https://raw.githubusercontent.com/PowerShell/PowerShell/master/tools/install-powershell.ps1 -outfile ./install-powershell.ps1 + ./install-powershell.ps1 -Destination $powerShellPath + $vstsCommandString = "vso[task.setvariable variable=PATH]$powerShellPath;$env:PATH" + Write-Host "sending " + $vstsCommandString + Write-Host "##$vstsCommandString" + } + + displayName: Install PowerShell if missing + condition: ne('${{ parameters.pool }}', 'windows-2019') + - pwsh: | Get-ChildItem -Path env: displayName: Capture Environment diff --git a/.vsts-ci/windows-arm64.yml b/.vsts-ci/windows-arm64.yml new file mode 100644 index 00000000000..be4cfcbaf4c --- /dev/null +++ b/.vsts-ci/windows-arm64.yml @@ -0,0 +1,95 @@ +name: PR-$(System.PullRequest.PullRequestNumber)-$(Date:yyyyMMdd)$(Rev:.rr) +trigger: + # Batch merge builds together while a merge build is running + batch: true + branches: + include: + - master + - release* + - feature* + paths: + include: + - '*' + exclude: + - .vsts-ci/misc-analysis.yml + - .github/ISSUE_TEMPLATE/* + - .dependabot/config.yml + - test/perf/* +pr: + branches: + include: + - master + - release* + - feature* + paths: + include: + - '*' + exclude: + - .dependabot/config.yml + - .github/ISSUE_TEMPLATE/* + - .vsts-ci/misc-analysis.yml + - tools/cgmanifest.json + - LICENSE.txt + - test/common/markdown/* + - test/perf/* + - tools/packaging/* + - tools/releaseBuild/* + - tools/releaseBuild/azureDevOps/templates/* + - README.md + - .spelling + +variables: + - name: GIT_CONFIG_PARAMETERS + value: "'core.autocrlf=false'" + - name: DOTNET_CLI_TELEMETRY_OPTOUT + value: 1 + - name: POWERSHELL_TELEMETRY_OPTOUT + value: 1 + # Avoid expensive initialization of dotnet cli, see: https://donovanbrown.com/post/Stop-wasting-time-during-NET-Core-builds + - name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE + value: 1 + - name: __SuppressAnsiEscapeSequences + value: 1 + - group: PoolNames + +resources: +- repo: self + clean: true + +stages: +- stage: BuildWin + displayName: Build for Windows + jobs: + - template: templates/ci-build.yml + parameters: + pool: $(armPool) + PoolType: 1esHosted + +- stage: TestWin + displayName: Test for Windows + jobs: + - template: templates/windows-test.yml + parameters: + purpose: UnelevatedPesterTests + tagSet: CI + pool: $(armPool) + + - template: templates/windows-test.yml + parameters: + purpose: ElevatedPesterTests + tagSet: CI + pool: $(armPool) + + - template: templates/windows-test.yml + parameters: + purpose: UnelevatedPesterTests + tagSet: Others + pool: $(armPool) + + - template: templates/windows-test.yml + parameters: + purpose: ElevatedPesterTests + tagSet: Others + pool: $(armPool) + + - template: templates/verify-xunit.yml diff --git a/.vsts-ci/windows.yml b/.vsts-ci/windows.yml index f886d2bd337..ef6241800e4 100644 --- a/.vsts-ci/windows.yml +++ b/.vsts-ci/windows.yml @@ -45,6 +45,7 @@ variables: # Avoid expensive initialization of dotnet cli, see: https://donovanbrown.com/post/Stop-wasting-time-during-NET-Core-builds DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 __SuppressAnsiEscapeSequences: 1 + NugetSecurityAnalysisWarningLevel: none resources: - repo: self diff --git a/build.psm1 b/build.psm1 index fd2858ba288..3b808c562cf 100644 --- a/build.psm1 +++ b/build.psm1 @@ -19,7 +19,7 @@ $script:Options = $null $dotnetMetadata = Get-Content $PSScriptRoot/DotnetRuntimeMetadata.json | ConvertFrom-Json $dotnetCLIChannel = $dotnetMetadata.Sdk.Channel $dotnetCLIQuality = $dotnetMetadata.Sdk.Quality -$dotnetAzureFeed = $env:__DONET_RUNTIME_FEED ?? $dotnetMetadata.Sdk.azureFeed +$dotnetAzureFeed = if (-not $env:__DONET_RUNTIME_FEED ) { $dotnetMetadata.Sdk.azureFeed } $dotnetAzureFeedSecret = $env:__DONET_RUNTIME_FEED_KEY $dotnetSDKVersionOveride = $dotnetMetadata.Sdk.sdkImageOverride $dotnetCLIRequiredVersion = $(Get-Content $PSScriptRoot/global.json | ConvertFrom-Json).Sdk.Version @@ -138,6 +138,7 @@ function Get-EnvironmentInformation { $environment += @{'IsAdmin' = (New-Object Security.Principal.WindowsPrincipal ([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)} $environment += @{'nugetPackagesRoot' = "${env:USERPROFILE}\.nuget\packages", "${env:NUGET_PACKAGES}"} + $environment += @{ 'OSArchitecture' = [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture } } else { @@ -1343,7 +1344,7 @@ function Start-PSPester { $command += " *> $outputBufferFilePath; '__UNELEVATED_TESTS_THE_END__' >> $outputBufferFilePath" } - Write-Verbose $command + Write-Verbose $command -Verbose $script:nonewline = $true $script:inerror = $false @@ -1600,11 +1601,17 @@ function script:Start-UnelevatedProcess [string]$process, [string[]]$arguments ) + if (-not $environment.IsWindows) { throw "Start-UnelevatedProcess is currently not supported on non-Windows platforms" } + if (-not $environment.OSArchitecture -eq 'arm64') + { + throw "Start-UnelevatedProcess is currently not supported on arm64 platforms" + } + runas.exe /trustlevel:0x20000 "$process $arguments" } diff --git a/test/powershell/Host/ConsoleHost.Tests.ps1 b/test/powershell/Host/ConsoleHost.Tests.ps1 index 7ee7fd07a46..e821df9b457 100644 --- a/test/powershell/Host/ConsoleHost.Tests.ps1 +++ b/test/powershell/Host/ConsoleHost.Tests.ps1 @@ -93,6 +93,10 @@ Describe "ConsoleHost unit tests" -tags "Feature" { } It "Clear-Host does not injects data into PowerShell output stream" { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "ARM64 runs in non-interactively mode and Clear-Host does not work." + } + & { Clear-Host; 'hi' } | Should -BeExactly 'hi' } @@ -997,6 +1001,10 @@ public enum ShowWindowCommands : int ) { param ($WindowStyle) + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "All windows are showing up as hidden or ARM64" + } + try { $ps = Start-Process $powershell -ArgumentList "-WindowStyle $WindowStyle -noexit -interactive" -PassThru $startTime = Get-Date diff --git a/test/powershell/Host/ScreenReader.Tests.ps1 b/test/powershell/Host/ScreenReader.Tests.ps1 index 35f86459861..1b11a0e3ffa 100644 --- a/test/powershell/Host/ScreenReader.Tests.ps1 +++ b/test/powershell/Host/ScreenReader.Tests.ps1 @@ -44,8 +44,12 @@ Describe "Validate start of console host" -Tag CI { } It "PSReadLine should not be auto-loaded when screen reader status is active" -Skip:(-not $IsWindows) { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "Needs investigation, PSReadline loads on ARM64" + } + $output = & "$PSHOME/pwsh" -noprofile -noexit -c "Get-Module PSReadLine; exit" - $output.Length | Should -BeExactly 2 + $output.Length | Should -BeExactly 2 -Because "There should be two lines of output but we got: $output" ## The warning message about screen reader should be returned, but the PSReadLine module should not be loaded. $output[0] | Should -BeLike "Warning:*'Import-Module PSReadLine'." diff --git a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 index 982085ff268..3ed99228d7a 100644 --- a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 +++ b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 @@ -1213,6 +1213,9 @@ Verb-Noun -Param1 Hello ^ } It "Tab completion UNC path" -Skip:(!$IsWindows) { + if (!$env:HOMEDRIVE) { + Set-ItResult -Skipped -Because "Homerdrive is not set" + } $homeDrive = $env:HOMEDRIVE.Replace(":", "$") $beforeTab = "\\localhost\$homeDrive\wind" $afterTab = "& '\\localhost\$homeDrive\Windows'" @@ -1995,6 +1998,11 @@ dir -Recurse ` It "Input '' should successfully complete" -TestCases $testCases -Skip:(!$IsWindows) { param($inputStr, $expected) + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "TBD" + } + + $res = TabExpansion2 -inputScript $inputStr -cursorColumn $inputStr.Length $res.CompletionMatches.Count | Should -BeGreaterThan 0 $res.CompletionMatches[0].CompletionText | Should -BeExactly $expected diff --git a/test/powershell/Language/Scripting/NativeExecution/NativeCommandProcessor.Tests.ps1 b/test/powershell/Language/Scripting/NativeExecution/NativeCommandProcessor.Tests.ps1 index d62230bb45a..d736d4b3945 100644 --- a/test/powershell/Language/Scripting/NativeExecution/NativeCommandProcessor.Tests.ps1 +++ b/test/powershell/Language/Scripting/NativeExecution/NativeCommandProcessor.Tests.ps1 @@ -145,6 +145,10 @@ Describe "Native Command Processor" -tags "Feature" { } It "Should not block running Windows executables" -Skip:(!$IsWindows -or !(Get-Command notepad.exe)) { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "Needs investigation" + } + function FindNewNotepad { Get-Process -Name notepad -ErrorAction Ignore | Where-Object { $_.Id -NotIn $dontKill } diff --git a/test/powershell/Language/Scripting/NativeExecution/NativeStreams.Tests.ps1 b/test/powershell/Language/Scripting/NativeExecution/NativeStreams.Tests.ps1 index 755ea27f794..53ed45fe4da 100644 --- a/test/powershell/Language/Scripting/NativeExecution/NativeStreams.Tests.ps1 +++ b/test/powershell/Language/Scripting/NativeExecution/NativeStreams.Tests.ps1 @@ -53,7 +53,11 @@ Describe "Native streams behavior with PowerShell" -Tags 'CI' { ($out | Out-String).Replace("`r", '') | Should -BeExactly "foo`n`nbar`n`nbazmiddlefoo`n`nbar`n`nbaz`n" } - It 'does not get truncated or split when redirected' { + It 'Does not get truncated or split when redirected' { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "IOException: The handle is invalid." + } + $longtext = "0123456789" while ($longtext.Length -lt [console]::WindowWidth) { $longtext += $longtext diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 index a4e9e1e5116..8ab4047c279 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/PSSessionConfiguration.Tests.ps1 @@ -10,7 +10,8 @@ try $originalWarningPreference = $WarningPreference $WarningPreference = "SilentlyContinue" # Skip all tests if can't write to $PSHOME as Register-PSSessionConfiguration writes to $PSHOME - $IsNotSkipped = ($IsWindows -and $IsCoreCLR -and (Test-IsElevated) -and (Test-CanWriteToPsHome)) + # or if the processor architecture is Arm64 + $IsNotSkipped = ($IsWindows -and $IsCoreCLR -and (Test-IsElevated) -and (Test-CanWriteToPsHome) -and [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture -ne [System.Runtime.InteropServices.Architecture]::Arm64) $PSDefaultParameterValues["it:skip"] = !$IsNotSkipped # @@ -830,6 +831,12 @@ namespace PowershellTestConfigNamespace Describe "Validate Enable-PSSession Cmdlet" -Tags @("Feature", 'RequireAdminOnWindows') { BeforeAll { + if (Test-IsWindowsArm64) { + Write-Verbose "remoting is not setup on ARM64, skipping tests" -Verbose + $PSDefaultParameterValues["it:skip"] = $true + return + } + if ($IsNotSkipped) { Enable-PSRemoting } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 index 5e55630c06c..786be05935a 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 @@ -349,6 +349,10 @@ Describe "Basic FileSystem Provider Tests" -Tags "CI" { ) { param ($cmdline, $expectedError) + if (Test-IsElevated) { + Set-ItResult -Skipped -Because "Process must NOT be elevated" + } + $scriptBlock = [scriptblock]::Create($cmdline) $scriptBlock | Should -Throw -ErrorId $expectedError } @@ -1551,6 +1555,9 @@ Describe "Remove-Item UnAuthorized Access" -Tags "CI", "RequireAdminOnWindows" { } It "Access-denied test for removing a folder" -Skip:(-not $IsWindows) { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "runas.exe /trustlevel:0x20000 is not supported on ARM64" + } # The expected error is returned when there is a empty directory with the user does not have authorization to is deleted. # It cannot have 'System. 'Hidden' or 'ReadOnly' attribute as well as -Force should not be used. diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-HotFix.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-HotFix.Tests.ps1 index 02f6bbf9c4f..b3539df487b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-HotFix.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-HotFix.Tests.ps1 @@ -9,6 +9,12 @@ Describe "Get-HotFix Tests" -Tag CI { if (!$IsWindows) { $skip = $true } + elseif (Test-IsWindowsArm64) { + # Win32Exception: Failed to load required native library 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\wminet_utils.dll'. + Write-Verbose "needed provider not on ARM64, skipping tests" -Verbose + $PSDefaultParameterValues["it:skip"] = $true + return + } else { # skip the tests if there are no hotfixes returned $qfe = Get-CimInstance Win32_QuickFixEngineering diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 index 4cde8baefee..90e20a2c479 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 @@ -79,6 +79,10 @@ Describe "Get-Process" -Tags "CI" { } It "Should fail to run Get-Process with -IncludeUserName without admin" -Skip:(!$IsWindows) { + if (Test-IsElevated) { + Set-ItResult -Skipped -Because "must NOT be run as admin" + } + { Get-Process -IncludeUserName } | Should -Throw -ErrorId "IncludeUserNameRequiresElevation,Microsoft.PowerShell.Commands.GetProcessCommand" } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Environment-Variables.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Environment-Variables.Tests.ps1 index 4c2b839259b..cdc9a5fe584 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Environment-Variables.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Environment-Variables.Tests.ps1 @@ -20,6 +20,10 @@ Describe "Environment-Variables" -Tags "CI" { It "Should have the correct HOME" { if ($IsWindows) { + if (!$ENV:HOMEPATH) { + Set-ItResult -Skipped -Because "Homepath is not set" + } + # \Windows\System32 is found as $env:HOMEPATH for temporary profiles $expected = "\Users", "\Windows" Split-Path $ENV:HOMEPATH -Parent | Should -BeIn $expected diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 index f5bbae4b0b5..6f93c3903e9 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 @@ -6,6 +6,13 @@ Describe "Format-Table" -Tags "CI" { $outputRendering = $PSStyle.OutputRendering $PSStyle.OutputRendering = 'plaintext' } + $noConsole = $true + try { + if ([Console]::WindowHeight -ne 0) { + $noConsole = $false + } + } catch { + } } AfterAll { @@ -805,7 +812,7 @@ A Name B } } - It "-RepeatHeader should output the header at every screen full" -Skip:([Console]::WindowHeight -eq 0) { + It "-RepeatHeader should output the header at every screen full" -Skip:$noConsole { $numHeaders = 4 $numObjects = [Console]::WindowHeight * $numHeaders $out = 1..$numObjects | ForEach-Object { @{foo=$_} } | Format-Table -RepeatHeader | Out-String @@ -813,7 +820,7 @@ A Name B ($lines | Select-String "Name\s*Value").Count | Should -Be ($numHeaders + 1) } - It "-RepeatHeader should output the header at every screen full for custom table" -Skip:([Console]::WindowHeight -eq 0) { + It "-RepeatHeader should output the header at every screen full for custom table" -Skip:$noConsole { $numHeaders = 4 $numObjects = [Console]::WindowHeight * $numHeaders $out = 1..$numObjects | ForEach-Object { [pscustomobject]@{foo=$_;bar=$_;hello=$_;world=$_} } | Format-Table -Property hello, world -RepeatHeader | Out-String diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 index 72ab978b69f..64ee47b3ecb 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 @@ -214,6 +214,10 @@ Categories=Application; It "Should invoke a folder without error" -Skip:(!$supportedEnvironment) { if ($IsWindows) { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "Shell.Application errors with COMException: The server process could not be started because the configured identity is incorrect. Check the username and password." + } + $shell = New-Object -ComObject "Shell.Application" $windows = $shell.Windows() diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Date.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Date.Tests.ps1 index f382c6fa214..f189879d35b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Date.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Date.Tests.ps1 @@ -32,6 +32,10 @@ Describe "Set-Date for admin" -Tag @('CI', 'RequireAdminOnWindows', 'RequireSudo Describe "Set-Date" -Tag 'CI' { It "Set-Date should produce an error in a non-elevated context" { + if (Test-IsElevated) { + Set-ItResult -Skipped -Because "must NOT be run as admin" + } + { Get-Date | Set-Date } | Should -Throw -ErrorId "System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.SetDateCommand" } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Debug.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Debug.Tests.ps1 index 5dfc696b150..f93027cc578 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Debug.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Debug.Tests.ps1 @@ -3,8 +3,12 @@ Describe "Write-Debug tests" -Tags "CI" { It "Should not have added line breaks" { $text = "0123456789" - while ($text.Length -lt [Console]::WindowWidth) { - $text += $text + try { + while ($text.Length -lt [Console]::WindowWidth) { + $text += $text + } + } catch { + # Ignore errors if the console doesn't support WindowWidth } $origDebugPref = $DebugPreference $DebugPreference = "Continue" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Error.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Error.Tests.ps1 index 45ff1614d42..47886aab0f3 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Error.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Error.Tests.ps1 @@ -98,8 +98,12 @@ Describe "Write-Error Tests" -Tags "CI" { It "ErrorRecord should not be truncated or have inserted newlines when redirected from another process" { $longtext = "0123456789" - while ($longtext.Length -lt [console]::WindowWidth) { - $longtext += $longtext + try{ + while ($longtext.Length -lt [console]::WindowWidth) { + $longtext += $longtext + } + } catch { + # Ignore if the console is doesn't support WindowWidth } $PSNativeCommandUseErrorActionPreference = $false $result = & "$PSHOME/pwsh" -noprofile -command "`$ErrorView = 'NormalView'; Write-Error -Message '$longtext'" 2>&1 diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Progress.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Progress.Tests.ps1 index 0f62cbcb6a6..97fd19da1b8 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Progress.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Progress.Tests.ps1 @@ -24,7 +24,12 @@ Describe "Write-Progress DRT Unit Tests" -Tags "CI" { } It 'Activity longer than console width works' { - $activity = 'a' * ([console]::WindowWidth + 1) + try { + $activity = 'a' * ([console]::WindowWidth + 1) + } catch { + Set-ItResult -Skipped -Because 'Console width is not supported' + } + { Write-Progress -Activity $activity -Status ('b' * ([console]::WindowWidth + 1)) -Id 1 } | Should -Not -Throw Write-Progress -Activity $activity -Id 1 -Completed } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Verbose.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Verbose.Tests.ps1 index 3630ef0cf3e..f12086206db 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Verbose.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Verbose.Tests.ps1 @@ -31,8 +31,12 @@ Describe "Write-Verbose" -Tags "CI" { It "Should not have added line breaks" { $text = "0123456789" - while ($text.Length -lt [Console]::WindowWidth) { - $text += $text + try { + while ($text.Length -lt [Console]::WindowWidth) { + $text += $text + } + } catch { + # Ignore errors if the console doesn't support WindowWidth } $origVerbosePref = $VerbosePreference $VerbosePreference = "continue" diff --git a/test/powershell/Modules/Microsoft.WSMan.Management/CredSSP.Tests.ps1 b/test/powershell/Modules/Microsoft.WSMan.Management/CredSSP.Tests.ps1 index 0f13e8e6aad..224064541d5 100644 --- a/test/powershell/Modules/Microsoft.WSMan.Management/CredSSP.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.WSMan.Management/CredSSP.Tests.ps1 @@ -113,6 +113,10 @@ Describe "CredSSP cmdlet error cases tests" -Tags 'Feature' { ) { param ($cmdline, $cmd) + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "WSManCredSSP results in InvalidOperationException on ARM64." + } + $scriptBlock = [scriptblock]::Create($cmdline) $scriptBlock | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.WSMan.Management.$cmd" } diff --git a/test/powershell/engine/Basic/GroupPolicySettings.Tests.ps1 b/test/powershell/engine/Basic/GroupPolicySettings.Tests.ps1 index 44080453e90..9c6765f0e17 100644 --- a/test/powershell/engine/Basic/GroupPolicySettings.Tests.ps1 +++ b/test/powershell/engine/Basic/GroupPolicySettings.Tests.ps1 @@ -57,6 +57,10 @@ Describe 'Group policy settings tests' -Tag CI,RequireAdminOnWindows { } It 'Module logging policy test' { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "There is no PowerShellCore event provider on ARM64 until we have an MSI" + } + function TestFeature { param([string]$KeyPath) @@ -85,7 +89,9 @@ Describe 'Group policy settings tests' -Tag CI,RequireAdminOnWindows { Remove-Item $ModuleNamesKeyPath -Recurse -Force # usually event becomes visible in the log after ~500 ms # set timeout for 5 seconds - Wait-UntilTrue -sb { Get-WinEvent -FilterHashtable @{ ProviderName="PowerShellCore"; Id = 4103 } -MaxEvents 5 | ? {$_.Message.Contains($RareCommand)} } -TimeoutInMilliseconds (5*1000) -IntervalInMilliseconds 100 | Should -BeTrue + Wait-UntilTrue -sb { Get-WinEvent -FilterHashtable @{ ProviderName="PowerShellCore"; Id = 4103 } -MaxEvents 5 | + Where-Object {$_.Message.Contains($RareCommand)} } -TimeoutInMilliseconds (5*1000) -IntervalInMilliseconds 100 | + Should -BeTrue } $KeyPath = Join-Path $KeyRoot 'ModuleLogging' @@ -101,6 +107,10 @@ Describe 'Group policy settings tests' -Tag CI,RequireAdminOnWindows { } It 'ScriptBlock logging policy test' { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "There is no PowerShellCore event provider on ARM64 until we have an MSI" + } + function TestFeature { param([string]$KeyPath) diff --git a/test/powershell/engine/COM/COM.Basic.Tests.ps1 b/test/powershell/engine/COM/COM.Basic.Tests.ps1 index 28974e15420..5265a256256 100644 --- a/test/powershell/engine/COM/COM.Basic.Tests.ps1 +++ b/test/powershell/engine/COM/COM.Basic.Tests.ps1 @@ -106,6 +106,10 @@ Describe 'Basic COM Tests' -Tags "CI" { } It "InvokeMember binder should differentiate PSObject that wraps COM object from other PSObjects" { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "COMException: The server process could not be started because the configured identity is incorrect. Check the username and password." + } + ## InvokeMember on the member name 'Windows' $shell | ForEach-Object { $_.Windows() } > $null diff --git a/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 b/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 index 02c4ad856b7..802531ab39e 100644 --- a/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 +++ b/test/powershell/engine/ExperimentalFeature/Get-ExperimentalFeature.Tests.ps1 @@ -180,6 +180,10 @@ Describe "Default enablement of Experimental Features" -Tags CI { } It "On preview builds, Experimental Features are enabled" -Skip:(!$isPreview) { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "Needs investigation" + } + (Join-Path -Path $PSHOME -ChildPath 'powershell.config.json') | Should -Exist foreach ($expFeature in Get-ExperimentalFeature) diff --git a/test/powershell/engine/Help/HelpSystem.Tests.ps1 b/test/powershell/engine/Help/HelpSystem.Tests.ps1 index 06e4e4ae22b..2786e64ee0e 100644 --- a/test/powershell/engine/Help/HelpSystem.Tests.ps1 +++ b/test/powershell/engine/Help/HelpSystem.Tests.ps1 @@ -69,6 +69,10 @@ Describe "Validate that //default.help.txt is present" -Tags @( Describe "Validate that the Help function can Run in strict mode" -Tags @('CI') { It "Help doesn't fail when strict mode is on" { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "IOException: The handle is invalid." + } + $help = & { # run in nested scope to keep strict mode from affecting other tests @@ -404,16 +408,28 @@ Describe "Get-Help should find pattern alias" -Tags "CI" { Describe "help function uses full view by default" -Tags "CI" { It "help should return full view without -Full switch" { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "IOException: The handle is invalid." + } + $gpsHelp = (help Microsoft.PowerShell.Management\Get-Process) $gpsHelp | Where-Object {$_ -cmatch '^PARAMETERS'} | Should -Not -BeNullOrEmpty } It "help should return full view even with -Full switch" { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "IOException: The handle is invalid." + } + $gpsHelp = (help Microsoft.PowerShell.Management\Get-Process -Full) $gpsHelp | Where-Object {$_ -cmatch '^PARAMETERS'} | Should -Not -BeNullOrEmpty } It "help should not append -Full when not using AllUsersView parameter set" { + if (Test-IsWindowsArm64) { + Set-ItResult -Pending -Because "IOException: The handle is invalid." + } + $gpsHelp = (help Microsoft.PowerShell.Management\Get-Process -Parameter Name) $gpsHelp | Where-Object {$_ -cmatch '^PARAMETERS'} | Should -BeNullOrEmpty } diff --git a/test/powershell/engine/Remoting/InvokeCommandRemoteDebug.Tests.ps1 b/test/powershell/engine/Remoting/InvokeCommandRemoteDebug.Tests.ps1 index fef7da0e75e..886bceb363d 100644 --- a/test/powershell/engine/Remoting/InvokeCommandRemoteDebug.Tests.ps1 +++ b/test/powershell/engine/Remoting/InvokeCommandRemoteDebug.Tests.ps1 @@ -126,6 +126,12 @@ Describe "Invoke-Command remote debugging tests" -Tags 'Feature','RequireAdminOn $PSDefaultParameterValues["it:skip"] = $true return } + elseif (Test-IsWindowsArm64) { + Write-Verbose "remoting is not setup on ARM64, skipping tests" -Verbose + $PSDefaultParameterValues["it:skip"] = $true + return + } + $sb = [scriptblock]::Create('"Hello!"') diff --git a/test/tools/Modules/HelpersCommon/HelpersCommon.psd1 b/test/tools/Modules/HelpersCommon/HelpersCommon.psd1 index 43d2ada88cc..8facd270576 100644 --- a/test/tools/Modules/HelpersCommon/HelpersCommon.psd1 +++ b/test/tools/Modules/HelpersCommon/HelpersCommon.psd1 @@ -18,24 +18,25 @@ Description = 'Temporary module contains functions for using in tests' FunctionsToExport = @( 'Add-TestDynamicType' - 'Test-CanWriteToPsHome' 'Disable-Testhook' 'Enable-Testhook' + 'Get-PlatformInfo' 'Get-RandomFileName' - 'New-RandomHexString' + 'Get-WSManSupport' 'New-ComplexPassword' + 'New-RandomHexString' 'Send-VstsLogFile' 'Set-TesthookResult' 'Start-NativeExecution' + 'Test-CanWriteToPsHome' 'Test-IsElevated' 'Test-IsRoot' 'Test-IsVstsLinux' 'Test-IsVstsWindows' + 'Test-IsWindowsArm64' 'Test-TesthookIsSet' 'Wait-FileToBePresent' 'Wait-UntilTrue' - 'Get-PlatformInfo' - 'Get-WSManSupport' ) CmdletsToExport= @() diff --git a/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 b/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 index f0706650bb9..ef0683a6abe 100644 --- a/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 +++ b/test/tools/Modules/HelpersCommon/HelpersCommon.psm1 @@ -396,3 +396,7 @@ function Get-WsManSupport { } return $false } + +function Test-IsWindowsArm64 { + return $IsWindows -and [System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture -eq [System.Runtime.InteropServices.Architecture]::Arm64 +} diff --git a/tools/ci.psm1 b/tools/ci.psm1 index e2feca60dd3..731ab4eaebf 100644 --- a/tools/ci.psm1 +++ b/tools/ci.psm1 @@ -263,10 +263,17 @@ function Invoke-CITest $ExperimentalFeatureTests = Get-ExperimentalFeatureTests if ($Purpose -eq 'UnelevatedPesterTests') { + $unelevate = $true + $environment = Get-EnvironmentInformation + if ($environment.OSArchitecture -eq 'arm64') { + Write-Verbose -Verbose "running on arm64, running unelevated tests as elevated" + $unelevate = $false + } + $arguments = @{ Bindir = $env:CoreOutput OutputFile = $testResultsNonAdminFile - Unelevate = $true + Unelevate = $unelevate Terse = $true Tag = @() ExcludeTag = $ExcludeTag + 'RequireAdminOnWindows'