Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
ConsoleHost.Tests.ps11254 linesDownload Raw Back to Host
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3using namespace System.Diagnostics4 5# Minishell (Singleshell) is a powershell concept.6# Its primary use-case is when somebody executes a scriptblock in the new powershell process.7# The objects are automatically marshelled to the child process and8# back to the parent session, so users can avoid custom9# serialization to pass objects between two processes.10 11Describe 'minishell for native executables' -Tag 'CI' {12 13    BeforeAll {14        $powershell = Join-Path -Path $PSHOME -ChildPath "pwsh"15    }16 17    Context 'Streams from minishell' {18 19        It 'gets a hashtable object from minishell' {20            $output = & $powershell -noprofile { @{'a' = 'b'} }21            ($output | Measure-Object).Count | Should -Be 122            $output | Should -BeOfType Hashtable23            $output['a'] | Should -Be 'b'24        }25 26        It 'gets the error stream from minishell' {27            $PSNativeCommandUseErrorActionPreference = $false28            $output = & $powershell -noprofile { Write-Error 'foo' } 2>&129            ($output | Measure-Object).Count | Should -Be 130            $output | Should -BeOfType System.Management.Automation.ErrorRecord31            $output.FullyQualifiedErrorId | Should -Be 'Microsoft.PowerShell.Commands.WriteErrorException'32        }33 34        It 'gets the information stream from minishell' {35            $output = & $powershell -noprofile { Write-Information 'foo' } 6>&136            ($output | Measure-Object).Count | Should -Be 137            $output | Should -BeOfType System.Management.Automation.InformationRecord38            $output | Should -Be 'foo'39        }40    }41 42    Context 'Streams to minishell' {43        It "passes input into minishell" {44            $a = 1,2,345            $val  = $a | & $powershell -noprofile -command { $input }46            $val.Count | Should -Be 347            $val[0] | Should -Be 148            $val[1] | Should -Be 249            $val[2] | Should -Be 350        }51    }52}53 54Describe "ConsoleHost unit tests" -tags "Feature" {55 56    BeforeAll {57        $powershell = Join-Path -Path $PSHOME -ChildPath "pwsh"58        $ExitCodeBadCommandLineParameter = 6459 60        function NewProcessStartInfo([string]$CommandLine, [switch]$RedirectStdIn)61        {62            return [ProcessStartInfo]@{63                FileName               = $powershell64                Arguments              = $CommandLine65                RedirectStandardInput  = $RedirectStdIn66                RedirectStandardOutput = $true67                RedirectStandardError  = $true68                UseShellExecute        = $false69            }70        }71 72        function RunPowerShell([ProcessStartInfo]$si)73        {74            $process = [Process]::Start($si)75 76            return $process77        }78 79        function EnsureChildHasExited([Process]$process, [int]$WaitTimeInMS = 15000)80        {81            $process.WaitForExit($WaitTimeInMS)82 83            if (!$process.HasExited)84            {85                $process.HasExited | Should -BeTrue86                $process.Kill()87            }88        }89    }90 91    AfterEach {92        $error.Clear()93    }94 95    It "Clear-Host does not injects data into PowerShell output stream" {96        if (Test-IsWindowsArm64) {97            Set-ItResult -Pending -Because "ARM64 runs in non-interactively mode and Clear-Host does not work."98        }99 100        & { Clear-Host; 'hi' } | Should -BeExactly 'hi'101    }102 103    Context "ShellInterop" {104        It "Verify Parsing Error Output Format Single Shell should throw exception" {105            { & $powershell -outp blah -comm { $input } } | Should -Throw -ErrorId "IncorrectValueForFormatParameter"106        }107 108        It "Verify Validate Output Format As Text Explicitly Child Single Shell does not throw" {109            {110                "blahblah" | & $powershell -noprofile -out text -com { $input }111            } | Should -Not -Throw112        }113 114        It "Verify Parsing Error Input Format Single Shell should throw exception" {115            { & $powershell -input blah -comm { $input } } | Should -Throw -ErrorId "IncorrectValueForFormatParameter"116        }117    }118 119    Context "CommandLine" {120        It "simple -args" {121            & $powershell -noprofile { $args[0] } -args "hello world" | Should -Be "hello world"122        }123 124        It "array -args" {125            & $powershell -noprofile { $args[0] } -args 1,(2,3) | Should -Be 1126            (& $powershell -noprofile { $args[1] } -args 1,(2,3))[1]  | Should -Be 3127        }128        foreach ($x in "--help", "-help", "-h", "-?", "--he", "-hel", "--HELP", "-hEl") {129            It "Accepts '$x' as a parameter for help" {130                & $powershell -noprofile $x | Where-Object { $_ -match "pwsh[.exe] -Help | -? | /?" } | Should -Not -BeNullOrEmpty131            }132        }133 134        It "Should accept a Base64 encoded command" {135            $commandString = "Get-Location"136            $encodedCommand = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($commandString))137            # We don't compare to `Get-Location` directly because object and formatted output comparisons are difficult138            $expected = & $powershell -noprofile -command $commandString139            $actual = & $powershell -noprofile -EncodedCommand $encodedCommand140            $actual | Should -Be $expected141        }142 143        It "-Version should return the engine version using: -version <value>" -TestCases @(144            @{value = ""},145            @{value = "2"},146            @{value = "-command 1-1"}147        ) {148            $currentVersion = "PowerShell " + $PSVersionTable.GitCommitId.ToString()149            $observed = & $powershell -version $value 2>&1150            $observed | Should -Be $currentVersion151            $LASTEXITCODE | Should -Be 0152        }153 154        It "-File should be default parameter" {155            Set-Content -Path $testdrive/test.ps1 -Value "'hello'"156            $observed = & $powershell -NoProfile $testdrive/test.ps1157            $observed | Should -Be "hello"158        }159 160        It "-File accepts scripts with .ps1 extension" {161            $Filename = 'test.ps1'162            Set-Content -Path $testdrive/$Filename -Value "'hello'"163            $observed = & $powershell -NoProfile -File $testdrive/$Filename164            $observed | Should -Be "hello"165        }166 167        It "-File accepts scripts without .ps1 extension to support shebang" -Skip:($IsWindows) {168            $Filename = 'test.xxx'169            Set-Content -Path $testdrive/$Filename -Value "'hello'"170            $observed = & $powershell -NoProfile -File $testdrive/$Filename171            $observed | Should -Be "hello"172        }173 174        It "-File should fail for script without .ps1 extension" -Skip:(!$IsWindows) {175            $Filename = 'test.xxx'176            Set-Content -Path $testdrive/$Filename -Value "'hello'"177            & $powershell -NoProfile -File $testdrive/$Filename 2>&1 $null178            $LASTEXITCODE | Should -Be 64179        }180 181        It "-File should pass additional arguments to script" {182            Set-Content -Path $testdrive/script.ps1 -Value 'foreach($arg in $args){$arg}'183            $observed = & $powershell -NoProfile $testdrive/script.ps1 foo bar184            $observed.Count | Should -Be 2185            $observed[0] | Should -Be "foo"186            $observed[1] | Should -Be "bar"187        }188 189        It "-File should be able to pass bool string values as string to parameters: <BoolString>" -TestCases @(190            # validates case is preserved191            @{BoolString = '$truE'},192            @{BoolString = '$falSe'},193            @{BoolString = 'trUe'},194            @{BoolString = 'faLse'}195        ) {196            param([string]$BoolString)197            Set-Content -Path $testdrive/test.ps1 -Value 'param([string]$bool) $bool'198            $observed = & $powershell -NoProfile -Nologo -File $testdrive/test.ps1 -Bool $BoolString199            $observed | Should -Be $BoolString200        }201 202        It "-File should be able to pass bool string values as string to positional parameters: <BoolString>" -TestCases @(203            # validates case is preserved204            @{BoolString = '$tRue'},205            @{BoolString = '$falSe'},206            @{BoolString = 'tRUe'},207            @{BoolString = 'fALse'}208        ) {209            param([string]$BoolString)210            Set-Content -Path $testdrive/test.ps1 -Value 'param([string]$bool) $bool'211            $observed = & $powershell -NoProfile -Nologo -File $testdrive/test.ps1 $BoolString212            $observed | Should -BeExactly $BoolString213        }214 215        It "-File should be able to pass bool string values as bool to switches: <BoolString>" -TestCases @(216            @{BoolString = '$tRue'; BoolValue = 'True'},217            @{BoolString = '$faLse'; BoolValue = 'False'},218            @{BoolString = 'tRue'; BoolValue = 'True'},219            @{BoolString = 'fAlse'; BoolValue = 'False'}220        ) {221            param([string]$BoolString, [string]$BoolValue)222            Set-Content -Path $testdrive/test.ps1 -Value 'param([switch]$switch) $switch.IsPresent'223            $observed = & $powershell -NoProfile -Nologo -File $testdrive/test.ps1 -switch:$BoolString224            $observed | Should -Be $BoolValue225        }226 227        It "-File should return exit code from script" {228            $Filename = 'test.ps1'229            Set-Content -Path $testdrive/$Filename -Value 'exit 123'230            & $powershell $testdrive/$Filename231            $LASTEXITCODE | Should -Be 123232        }233 234        It "A single dash should be passed as an arg" {235            $testScript = @'236    [CmdletBinding()]param(237        [string]$p1,238        [string]$p2,239        [Parameter(ValueFromPipeline)][string]$InputObject240    )241    process{242        $input.replace($p1, $p2)243    }244'@245            $testFilePath = Join-Path $TestDrive "test.ps1"246            Set-Content -Path $testFilePath -Value $testScript247            $observed = echo hello | & $powershell -noprofile $testFilePath e -248            $observed | Should -BeExactly "h-llo"249        }250 251        It "Missing command should fail" {252            & $powershell -noprofile -c253            $LASTEXITCODE | Should -Be 64254        }255 256        It "Empty space command should succeed on non-Windows" -skip:$IsWindows {257            & $powershell -noprofile -c '' | Should -BeNullOrEmpty258            $LASTEXITCODE | Should -Be 0259        }260 261        It "Whitespace command should succeed" {262            & $powershell -noprofile -c ' ' | Should -BeNullOrEmpty263            $LASTEXITCODE | Should -Be 0264        }265    }266 267    Context "-Login pwsh switch" {268        BeforeAll {269            $profilePath = "~/.profile"270            $backupProfilePath = "profile.bak"271            if (Test-Path $profilePath) {272                Move-Item -Path $profilePath -Destination $backupProfilePath -Force273            }274 275            $envVarName = 'PSTEST_PROFILE_LOAD'276 277            $guid = New-Guid278 279            Set-Content -Force -Path $profilePath -Value @"280export $envVarName='$guid'281"@282        }283 284        AfterAll {285            if (Test-Path $backupProfilePath) {286                Move-Item -Path $backupProfilePath -Destination $profilePath -Force287            }288        }289 290        It "Doesn't run the login profile when -Login not used" {291            $result = & $powershell -noprofile -Command "`$env:$envVarName"292            $result | Should -BeNullOrEmpty293            $LASTEXITCODE | Should -Be 0294        }295 296        It "Doesn't falsely recognise -Login when elsewhere in the invocation" {297            $result = & $powershell -nop -c 'Write-Output "-login"'298            $result | Should -BeExactly '-login'299            $LASTEXITCODE | Should -Be 0300        }301 302        It "Doesn't falsely recognise -Login when used after -Command" {303            $result = & $powershell -nop -c 'Write-Output' -Login304            $result | Should -BeExactly '-Login'305            $LASTEXITCODE | Should -Be 0306        }307 308        It "Accepts the <LoginSwitch> switch for -Login and behaves correctly" -TestCases @(309            @{ LoginSwitch = '-l' }310            @{ LoginSwitch = '-L' }311            @{ LoginSwitch = '-login' }312            @{ LoginSwitch = '-Login' }313            @{ LoginSwitch = '-LOGIN' }314            @{ LoginSwitch = '-log' }315        ) {316            param($LoginSwitch)317 318            $result = & $powershell $LoginSwitch -NoProfile -Command "`$env:$envVarName"319 320            if ($IsWindows) {321                $result | Should -BeNullOrEmpty322                $LASTEXITCODE | Should -Be 0323                return324            }325 326            $result | Should -BeExactly $guid327            $LASTEXITCODE | Should -Be 0328        }329 330        It "Starts as a login shell with '-' prepended to name" -Skip:(-not (Get-Command -Name /bin/bash -ErrorAction Ignore)) {331            $quoteEscapedPwsh = $powershell.Replace("'", "\'")332            $pwshCommand = "`$env:$envVarName"333            $bashCommand = "exec -a '-pwsh' '$quoteEscapedPwsh' -NoProfile -Command '`$env:$envVarName' ''"334            $result = /bin/bash -c $bashCommand335            $result | Should -BeExactly $guid336            $LASTEXITCODE | Should -Be 0 # Exit code will be PowerShell's since it was exec'd337        }338    }339 340    Context "-SettingsFile Commandline switch" {341 342        BeforeAll {343            if ($IsWindows) {344                $CustomSettingsFile = Join-Path -Path $TestDrive -ChildPath 'Powershell.test.json'345                $DefaultExecutionPolicy = 'RemoteSigned'346            }347        }348        BeforeEach {349            if ($IsWindows) {350                # reset the content of the settings file to a known state.351                Set-Content -Path $CustomSettingsfile -Value "{`"Microsoft.PowerShell:ExecutionPolicy`":`"$DefaultExecutionPolicy`"}" -ErrorAction Stop352            }353        }354 355        # NOTE: The -settingsFile command-line option only reads settings for the local machine. As a result, the tests that use Set/Get-ExecutionPolicy356        # must use an explicit scope of LocalMachine to ensure the setting is written to the expected file.357        # Skip the tests on Unix platforms because *-ExecutionPolicy cmdlets don't work by design.358 359        It "Verifies PowerShell reads from the custom -settingsFile" -Skip:(!$IsWindows) {360            $actualValue = & $powershell -NoProfile -SettingsFile $CustomSettingsFile -Command {(Get-ExecutionPolicy -Scope LocalMachine).ToString()}361            $actualValue  | Should -Be $DefaultExecutionPolicy362        }363 364        It "Verifies PowerShell writes to the custom -settingsFile" -Skip:(!$IsWindows) {365            $expectedValue = 'AllSigned'366 367            # Update the execution policy; this should update the settings file.368            & $powershell -NoProfile -SettingsFile $CustomSettingsFile -Command {Set-ExecutionPolicy -ExecutionPolicy AllSigned -Scope LocalMachine }369 370            # ensure the setting was written to the settings file.371            $content = (Get-Content -Path $CustomSettingsFile | ConvertFrom-Json)372            $content.'Microsoft.PowerShell:ExecutionPolicy' | Should -Be $expectedValue373 374            # ensure the setting is applied on next run375            $actualValue = & $powershell -NoProfile -SettingsFile $CustomSettingsFile -Command {(Get-ExecutionPolicy -Scope LocalMachine).ToString()}376            $actualValue  | Should -Be $expectedValue377        }378 379        It "Verify PowerShell removes a setting from the custom -settingsFile" -Skip:(!$IsWindows) {380            # Remove the LocalMachine execution policy; this should update the settings file.381            & $powershell -NoProfile -SettingsFile $CustomSettingsFile -Command {Set-ExecutionPolicy -ExecutionPolicy Undefined -Scope LocalMachine }382 383            # ensure the setting was removed from the settings file.384            $content = (Get-Content -Path $CustomSettingsFile | ConvertFrom-Json)385            $content.'Microsoft.PowerShell:ExecutionPolicy' | Should -Be $null386        }387    }388 389    Context "-SettingsFile Commandline switch set 'PSModulePath'" {390 391        BeforeAll {392            $CustomSettingsFile = Join-Path -Path $TestDrive -ChildPath 'powershell.test.json'393            $mPath1 = Join-Path $PSHOME 'Modules'394            $mPath2 = Join-Path $TestDrive 'NonExist'395            $pathSep = [System.IO.Path]::PathSeparator396 397            ## Use multiple paths in the setting.398            $ModulePath = "${mPath1}${pathSep}${mPath2}".Replace('\', "\\")399            Set-Content -Path $CustomSettingsfile -Value "{`"Microsoft.PowerShell:ExecutionPolicy`":`"Unrestricted`", `"PSModulePath`": `"$ModulePath`" }" -ErrorAction Stop400        }401 402        It "Verify PowerShell PSModulePath should contain paths from config file" {403            $psModulePath = & $powershell -NoProfile -SettingsFile $CustomSettingsFile -Command '$env:PSModulePath'404 405            ## $mPath1 already exists in the value of env PSModulePath, so it won't be added again.406            $index = $psModulePath.IndexOf("${mPath1}${pathSep}", [System.StringComparison]::OrdinalIgnoreCase)407            $index | Should -BeGreaterThan 0408            $index += $mPath1.Length409            $psModulePath.IndexOf($mPath1, $index, [System.StringComparison]::OrdinalIgnoreCase) | Should -BeExactly -1410 411            ## $mPath2 should be added at the index position 0.412            $psModulePath.StartsWith("${mPath2}${pathSep}", [System.StringComparison]::OrdinalIgnoreCase) | Should -BeTrue413        }414    }415 416    Context "Pipe to/from powershell" {417        BeforeAll {418            if ($null -ne $PSStyle) {419                $outputRendering = $PSStyle.OutputRendering420                $PSStyle.OutputRendering = 'plaintext'421            }422 423            $p = [PSCustomObject]@{X=10;Y=20}424        }425 426        AfterAll {427            if ($null -ne $PSStyle) {428                $PSStyle.OutputRendering = $outputRendering429            }430        }431 432        It "xml input" {433            $p | & $powershell -noprofile { $input | ForEach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } } | Should -Be 30434            $p | & $powershell -noprofile -inputFormat xml { $input | ForEach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } } | Should -Be 30435        }436 437        It "text input" {438            # Join (multiple lines) and remove whitespace (we don't care about spacing) to verify we converted to string (by generating a table)439            $p | & $powershell -noprofile -inputFormat text { -join ($input -replace "\s","") } | Should -Be "XY--1020"440        }441 442        It "xml output" {443            & $powershell -noprofile { [PSCustomObject]@{X=10;Y=20} } | ForEach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } | Should -Be 30444            & $powershell -noprofile -outputFormat xml { [PSCustomObject]@{X=10;Y=20} } | ForEach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } | Should -Be 30445        }446 447        It "text output" {448            # Join (multiple lines) and remove whitespace (we don't care about spacing) to verify we converted to string (by generating a table)449            -join (& $powershell -noprofile -outputFormat text { $PSStyle.OutputRendering = 'PlainText'; [PSCustomObject]@{X=10;Y=20} }) -replace "\s","" | Should -Be "XY--1020"450        }451 452        It "errors are in text if error is redirected, encoded command, non-interactive, and outputformat specified" {453            $p = [Diagnostics.Process]::new()454            $p.StartInfo.FileName = "pwsh"455            $encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes('throw "boom"'))456            $p.StartInfo.Arguments = "-EncodedCommand $encoded -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -OutputFormat text"457            $p.StartInfo.UseShellExecute = $false458            $p.StartInfo.RedirectStandardError = $true459            $p.Start() | Out-Null460            $out = $p.StandardError.ReadToEnd()461            $out | Should -Not -BeNullOrEmpty462            $out = $out.Split([Environment]::NewLine)[0]463            [System.Management.Automation.Internal.StringDecorated]::new($out).ToString("PlainText") | Should -BeExactly "Exception: boom"464        }465 466        It "Progress is not emitted when stdout is redirected" {467            $ps = [powershell]::Create()468            $null = $ps.AddScript('$a = & ([Environment]::ProcessPath) -Command "Write-Progress -Activity progress"; $a')469            $actual = $ps.Invoke()470 471            $ps.HadErrors | Should -BeFalse472            $actual | Should -BeNullOrEmpty473            $ps.Streams.Progress | Should -BeNullOrEmpty474        }475 476        It "Progress is still emitted with redireciton with XML output" {477            $ps = [powershell]::Create()478            $null = $ps.AddScript('$a = & ([Environment]::ProcessPath) -OutputFormat xml -Command "Write-Progress -Activity progress"; $a')479            $actual = $ps.Invoke()480 481            $ps.HadErrors | Should -BeFalse482            $actual | Should -BeNullOrEmpty483            $ps.Streams.Progress.Count | Should -Be 1484            $ps.Streams.Progress[0].Activity | Should -Be progress485        }486    }487 488    Context "Redirected standard output" {489        It "Simple redirected output" {490            $si = NewProcessStartInfo "-noprofile -c 1+1"491            $process = RunPowerShell $si492            $process.StandardOutput.ReadToEnd() | Should -Be 2493            EnsureChildHasExited $process494        }495    }496 497    Context "Input redirected but not reading from stdin (not really interactive)" {498        # Tests under this context are testing that we do not read from StandardInput499        # even though it is redirected - we want to make sure we don't stop responding.500        # So none of these tests should close StandardInput501 502        It "Redirected input w/ implicit -Command w/ -NonInteractive" {503            $si = NewProcessStartInfo "-NonInteractive -noprofile -c 1+1" -RedirectStdIn504            $process = RunPowerShell $si505            $process.StandardOutput.ReadToEnd() | Should -Be 2506            EnsureChildHasExited $process507        }508 509        It "Redirected input w/ implicit -Command w/o -NonInteractive" {510            $si = NewProcessStartInfo "-noprofile -c 1+1" -RedirectStdIn511            $process = RunPowerShell $si512            $process.StandardOutput.ReadToEnd() | Should -Be 2513            EnsureChildHasExited $process514        }515 516        It "Redirected input w/ explicit -Command w/ -NonInteractive" {517            $si = NewProcessStartInfo "-NonInteractive -noprofile -Command 1+1" -RedirectStdIn518            $process = RunPowerShell $si519            $process.StandardOutput.ReadToEnd() | Should -Be 2520            EnsureChildHasExited $process521        }522 523        It "Redirected input w/ explicit -Command w/o -NonInteractive" {524            $si = NewProcessStartInfo "-noprofile -Command 1+1" -RedirectStdIn525            $process = RunPowerShell $si526            $process.StandardOutput.ReadToEnd() | Should -Be 2527            EnsureChildHasExited $process528        }529 530        It "Redirected input w/ -File w/ -NonInteractive" {531            '1+1' | Out-File -Encoding Ascii -FilePath TestDrive:test.ps1 -Force532            $si = NewProcessStartInfo "-noprofile -NonInteractive -File $testDrive\test.ps1" -RedirectStdIn533            $process = RunPowerShell $si534            $process.StandardOutput.ReadToEnd() | Should -Be 2535            EnsureChildHasExited $process536        }537 538        It "Redirected input w/ -File w/o -NonInteractive" {539            '1+1' | Out-File -Encoding Ascii -FilePath TestDrive:test.ps1 -Force540            $si = NewProcessStartInfo "-noprofile -File $testDrive\test.ps1" -RedirectStdIn541            $process = RunPowerShell $si542            $process.StandardOutput.ReadToEnd() | Should -Be 2543            EnsureChildHasExited $process544        }545    }546 547    Context "Redirected standard input for 'interactive' use" {548        BeforeAll {549            $nl = [Environment]::Newline550            $oldColor = $env:NO_COLOR551            $env:NO_COLOR = 1552        }553 554        AfterAll {555            $env:NO_COLOR = $oldColor556        }557 558        # All of the following tests replace the prompt (either via an initial command or interactively)559        # so that we can read StandardOutput and reliably know exactly what the prompt is.560 561        It "Interactive redirected input: <InteractiveSwitch>" -Pending:($IsWindows) -TestCases @(562            @{InteractiveSwitch = ""}563            @{InteractiveSwitch = " -IntERactive"}564            @{InteractiveSwitch = " -i"}565        ) {566            param($interactiveSwitch)567            $si = NewProcessStartInfo "-noprofile -nologo$interactiveSwitch" -RedirectStdIn568            $process = RunPowerShell $si569            $process.StandardInput.Write("`$function:prompt = { 'PS> ' }`n")570            $null = $process.StandardOutput.ReadLine()571            $process.StandardInput.Write("1+1`n")572            $process.StandardOutput.ReadLine() | Should -Be "PS> 1+1"573            $process.StandardOutput.ReadLine() | Should -Be "2"574            $process.StandardInput.Write("1+2`n")575            $process.StandardOutput.ReadLine() | Should -Be "PS> 1+2"576            $process.StandardOutput.ReadLine() | Should -Be "3"577 578            # Backspace should work as expected579            $process.StandardInput.Write("1+2`b3`n")580            # A real console should render 2`b3 as just 3, but we're just capturing exactly what is written581            $process.StandardOutput.ReadLine() | Should -Be "PS> 1+2`b3"582            $process.StandardOutput.ReadLine() | Should -Be "4"583            $process.StandardInput.Close()584            $process.StandardOutput.ReadToEnd() | Should -Be "PS> "585            EnsureChildHasExited $process586        }587 588        It "Interactive redirected input w/ initial command" -Pending:($IsWindows) {589            $si = NewProcessStartInfo "-noprofile -noexit -c ""`$function:prompt = { 'PS> ' }""" -RedirectStdIn590            $process = RunPowerShell $si591            $process.StandardInput.Write("1+1`n")592            $process.StandardOutput.ReadLine() | Should -Be "PS> 1+1"593            $process.StandardOutput.ReadLine() | Should -Be "2"594            $process.StandardInput.Write("1+2`n")595            $process.StandardOutput.ReadLine() | Should -Be "PS> 1+2"596            $process.StandardOutput.ReadLine() | Should -Be "3"597            $process.StandardInput.Close()598            $process.StandardOutput.ReadToEnd() | Should -Be "PS> "599            EnsureChildHasExited $process600        }601 602        It "Redirected input explicit prompting (-File -)" -Pending:($IsWindows) {603            $si = NewProcessStartInfo "-noprofile -" -RedirectStdIn604            $process = RunPowerShell $si605            $process.StandardInput.Write("`$function:prompt = { 'PS> ' }`n")606            $null = $process.StandardOutput.ReadLine()607            $process.StandardInput.Write("1+1`n")608            $process.StandardOutput.ReadLine() | Should -Be "PS> 1+1"609            $process.StandardOutput.ReadLine() | Should -Be "2"610            $process.StandardInput.Close()611            $process.StandardOutput.ReadToEnd() | Should -Be "PS> "612            EnsureChildHasExited $process613        }614 615        It "Redirected input no prompting (-Command -)" -Pending:($IsWindows) {616            $si = NewProcessStartInfo "-noprofile -Command -" -RedirectStdIn617            $process = RunPowerShell $si618            $process.StandardInput.Write("1+1`n")619            $process.StandardOutput.ReadLine() | Should -Be "2"620 621            # Multi-line input622            $process.StandardInput.Write("if (1)`n{`n    42`n}`n`n")623            $process.StandardOutput.ReadLine() | Should -Be "42"624            $process.StandardInput.Write(@"625function foo626{627    'in foo'628}629 630foo631 632"@)633            $process.StandardOutput.ReadLine() | Should -Be "in foo"634 635            # Backspace sent through stdin should be in the final string636            $process.StandardInput.Write("`"a`bc`".Length`n")637            $process.StandardOutput.ReadLine() | Should -Be "3"638 639            # Last command with no newline - should be accepted and640            # produce output after closing stdin.641            $process.StandardInput.Write('22 + 22')642            $process.StandardInput.Close()643            $process.StandardOutput.ReadLine() | Should -Be "44"644 645            EnsureChildHasExited $process646        }647 648        It "Redirected input w/ nested prompt" -Pending:($IsWindows) {649            $si = NewProcessStartInfo "-noprofile -noexit -c ""`$function:prompt = { 'PS' + ('>'*(`$NestedPromptLevel+1)) + ' ' }""" -RedirectStdIn650            $process = RunPowerShell $si651            $process.StandardInput.Write("`$PSStyle.OutputRendering='plaintext'`n")652            $null = $process.StandardOutput.ReadLine()653            $process.StandardInput.Write("`$Host.EnterNestedPrompt()`n")654            $process.StandardOutput.ReadLine() | Should -Be "PS> `$Host.EnterNestedPrompt()"655            $process.StandardInput.Write("exit`n")656            $process.StandardOutput.ReadLine() | Should -Be "PS>> exit"657            $process.StandardInput.Close()658            $process.StandardOutput.ReadToEnd() | Should -Be "PS> "659            EnsureChildHasExited $process660        }661    }662 663    Context "Exception handling" {664        BeforeAll {665            # the default stack size in PowerShell is 10000000, set the stack666            # to something much smaller which will produce the error much faster667            # I saw a reduction from 65 seconds to 79 milliseconds.668            $classDefinition = @'669using System;670using System.Management.Automation;671using System.Management.Automation.Runspaces;672using System.Threading;673namespace StackTest {674    public class StackDepthTest {675        public static PowerShell ps;676        public static int size = 512 * 1024;677        public static void CauseError() {678            Thread t = new Thread(RunPS, size);679            t.Start();680            t.Join();681        }682        public static void RunPS() {683            InitialSessionState iss = InitialSessionState.CreateDefault2();684            iss.ThreadOptions = PSThreadOptions.UseCurrentThread;685            ps = PowerShell.Create(iss);686            ps.AddScript("function recurse { recurse }; recurse").Invoke();687        }688        public static void GetPSError() {689            if ( ps.Streams.Error.Count > 0) {690                throw ps.Streams.Error[0].Exception.InnerException;691            }692        }693    }694}695'@696            $TestType = Add-Type -PassThru -TypeDefinition $classDefinition697        }698 699        It "Should handle a CallDepthOverflow" {700            $TestType::CauseError()701            { $TestType::GetPSError() } | Should -Throw -ErrorId "CallDepthOverflow"702        }703    }704 705    Context "Data, Config, and Cache locations" {706        BeforeEach {707            $XDG_CACHE_HOME = $env:XDG_CACHE_HOME708            $XDG_DATA_HOME = $env:XDG_DATA_HOME709            $XDG_CONFIG_HOME = $env:XDG_CONFIG_HOME710        }711 712        AfterEach {713            $env:XDG_CACHE_HOME = $XDG_CACHE_HOME714            $env:XDG_DATA_HOME = $XDG_DATA_HOME715            $env:XDG_CONFIG_HOME = $XDG_CONFIG_HOME716        }717 718        It "Should start if Data, Config, and Cache location is not accessible" -Skip:($IsWindows) {719            $env:XDG_CACHE_HOME = "/dev/cpu"720            $env:XDG_DATA_HOME = "/dev/cpu"721            $env:XDG_CONFIG_HOME = "/dev/cpu"722            $output = & $powershell -noprofile -Command { (Get-Command).count }723            [int]$output | Should -BeGreaterThan 0724        }725    }726 727    Context "HOME environment variable" {728        It "Should start if HOME is not defined" -Skip:($IsWindows) {729            bash -c "unset HOME;$powershell -c '1+1'" | Should -BeExactly 2730        }731 732        It "Same user should use the same temporary HOME directory for different sessions" -Skip:($IsWindows) {733            $results = bash -c @"734unset HOME;735$powershell -c '[System.Management.Automation.Platform]::SelectProductNameForDirectory([System.Management.Automation.Platform+XDG_Type]::DEFAULT)';736$powershell -c '[System.Management.Automation.Platform]::SelectProductNameForDirectory([System.Management.Automation.Platform+XDG_Type]::DEFAULT)';737"@738            $results | Should -HaveCount 2739            $results[0] | Should -BeExactly $results[1]740 741            $tempHomeName = "pwsh-{0}-98288ff9-5712-4a14-9a11-23693b9cd91a" -f [System.Environment]::UserName742            $defaultPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath "$tempHomeName/.config/powershell"743            $results[0] | Should -BeExactly $defaultPath744        }745    }746 747    Context "PATH environment variable" {748        It "`$PSHOME should be in front so that pwsh.exe starts current running PowerShell" {749            & $powershell -v | Should -Match $PSVersionTable.GitCommitId750        }751 752        It "powershell starts if PATH is not set" -Skip:($IsWindows) {753            bash -c "unset PATH;$powershell -nop -c '1+1'" | Should -BeExactly 2754        }755    }756 757    Context "Ambiguous arguments" {758        It "Ambiguous argument '<testArg>' should return possible matches" -TestCases @(759            @{testArg="-no";expectedMatches=@("-nologo","-noexit","-noprofile","-noninteractive")},760            @{testArg="-format";expectedMatches=@("-inputformat","-outputformat")}761        ) {762            param($testArg, $expectedMatches)763            $output = & $powershell $testArg -File foo 2>&1764            $LASTEXITCODE | Should -Be $ExitCodeBadCommandLineParameter765            $outString = [String]::Join(",", $output)766            foreach ($expectedMatch in $expectedMatches)767            {768                $outString | Should -Match $expectedMatch769            }770        }771    }772 773    Context "-WorkingDirectory parameter" {774        BeforeAll {775            $folderName = (New-Guid).ToString() + " test";776            New-Item -Path ~/$folderName -ItemType Directory777            $ExitCodeBadCommandLineParameter = 64778        }779 780        AfterAll {781            Remove-Item ~/$folderName -Force -ErrorAction SilentlyContinue782        }783 784        It "Can set working directory to '<value>'" -TestCases @(785            @{ value = "~"            ; expectedPath = $((Get-Item ~).FullName) },786            @{ value = "~/$folderName"; expectedPath = $((Get-Item ~/$folderName).FullName) },787            @{ value = "~\$folderName"; expectedPath = $((Get-Item ~\$folderName).FullName) }788        ) {789            param($value, $expectedPath)790            $output = & $powershell -NoProfile -WorkingDirectory "$value" -Command '(Get-Location).Path'791            $output | Should -BeExactly $expectedPath792        }793 794        It "Can use '<parameter>' to set working directory" -TestCases @(795            @{ parameter = '-workingdirectory' },796            @{ parameter = '-wd' },797            @{ parameter = '-wo' }798        ) {799            param($parameter)800            $output = & $powershell -NoProfile $parameter ~ -Command "`$PWD.Path"801            $output | Should -BeExactly $((Get-Item ~).FullName)802        }803 804        It "Error case if -WorkingDirectory isn't given argument as last on command line" {805            $output = & $powershell -WorkingDirectory 2>&1806            $LASTEXITCODE | Should -Be $ExitCodeBadCommandLineParameter807            $output | Should -Not -BeNullOrEmpty808        }809 810        It "-WorkingDirectory should be processed before profiles" {811 812            if (Test-Path $PROFILE) {813                $currentProfile = Get-Content $PROFILE814            }815            else {816                New-Item -ItemType File -Path $PROFILE -Force817            }818 819            @"820                (Get-Location).Path821                Set-Location $testdrive822"@ > $PROFILE823 824            try {825                $out = & $powershell -workingdirectory ~ -c '(Get-Location).Path'826                $out | Should -HaveCount 2827                $out[0] | Should -BeExactly (Get-Item ~).FullName828                $out[1] | Should -BeExactly "$testdrive"829            }830            finally {831                if ($currentProfile) {832                    Set-Content $PROFILE -Value $currentProfile833                }834                else {835                    Remove-Item $PROFILE836                }837            }838        }839    }840 841    Context "CustomPipeName startup tests" {842 843        It "Should create pipe file if CustomPipeName is specified" {844            $pipeName = [System.IO.Path]::GetRandomFileName()845            $pipePath = Get-PipePath $pipeName846 847            # The pipePath should be created by the time the -Command is executed.848            & $powershell -CustomPipeName $pipeName -Command "Test-Path '$pipePath'" | Should -BeTrue849        }850 851        It "Should throw if CustomPipeName is too long on Linux or macOS" -Skip:($IsWindows) {852            # Generate a string that is larger than the max pipe name length.853            $longPipeName = [string]::new("A", 200)854 855            "`$PID" | & $powershell -CustomPipeName $longPipeName -c -856            $LASTEXITCODE | Should -Be $ExitCodeBadCommandLineParameter857        }858    }859 860    Context "ApartmentState WPF tests" -Tag Slow {861 862        It "WPF requires STA and will work" -Skip:(!$IsWindows -or [System.Management.Automation.Platform]::IsNanoServer) {863            Add-Type -AssemblyName presentationframework864 865            $xaml = [xml]@"866            <Window867                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"868                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"869                x:Name="Window" Title="Initial Window" WindowStartupLocation = "CenterScreen"870                Width = "400" Height = "300" ShowInTaskbar = "True">871            </Window>872"@873 874            $reader = [System.Xml.XmlNodeReader]::new($xaml)875            $Window = [System.Windows.Markup.XamlReader]::Load($reader)876            # This will throw an exception if MTA877            { $Window.Show() } | Should -Not -Throw878            $Window.Close()879        }880 881    }882 883    Context "ApartmentState tests" {884 885        It "Default apartment state for main thread is STA" -Skip:(!$IsWindows -or [System.Management.Automation.Platform]::IsNanoServer) {886            [System.Threading.Thread]::CurrentThread.GetApartmentState() | Should -BeExactly "STA"887        }888 889        It "Default apartment state for new runspace is MTA" -Skip:(!$IsWindows) {890            $ps = [powershell]::Create()891            $ps.AddScript({[System.Threading.Thread]::CurrentThread.GetApartmentState()})892            $ps.Invoke() | Should -BeExactly "MTA"893        }894 895        It "Should be able to set apartment state to: <apartment>" -Skip:(!$IsWindows -or [System.Management.Automation.Platform]::IsNanoServer) -TestCases @(896            @{ apartment = "STA"; switch = "-sta" }897            @{ apartment = "MTA"; switch = "-mta" }898        ) {899            param ($apartment, $switch)900 901            & $powershell $switch -noprofile -command "[System.Threading.Thread]::CurrentThread.GetApartmentState()" | Should -BeExactly $apartment902        }903 904        It "Should fail to set apartment state to: <switch>" -Skip:($IsWindows -and ![System.Management.Automation.Platform]::IsNanoServer) -TestCases @(905            @{ switch = "-sta" }906            @{ switch = "-mta" }907        ) {908            param ($switch)909 910            & $powershell $switch -noprofile -command exit911            $LASTEXITCODE | Should -Be $ExitCodeBadCommandLineParameter912        }913    }914 915    Context "Startup banner text tests" -Tag Slow {916        BeforeAll {917            $outputPath = "Temp:\StartupBannerTest-Output-${Pid}.txt"918            $inputPath  = "Temp:\StartupBannerTest-Input.txt"919            "exit" > $inputPath920 921            # Not testing update notification banner text here922            $oldPowerShellUpdateCheck = $env:POWERSHELL_UPDATECHECK923            $env:POWERSHELL_UPDATECHECK = "Off"924 925            # Set TERM to "dumb" to avoid DECCKM codes in the output926            $oldTERM = $env:TERM927            $env:TERM = "dumb"928 929            $escPwd = [regex]::Escape($pwd)930            $expectedPromptPattern = "^PS ${escPwd}> exit`$"931 932            $spArgs = @{933                FilePath = $powershell934                ArgumentList = @("-NoProfile")935                RedirectStandardInput = $inputPath936                RedirectStandardOutput = $outputPath937                WorkingDirectory = $pwd938                PassThru = $true939                NoNewWindow = $true940                UseNewEnvironment = $false941            }942        }943        AfterAll {944            $env:TERM = $oldTERM945            $env:POWERSHELL_UPDATECHECK = $oldPowerShellUpdateCheck946 947            Remove-Item $inputPath -Force -ErrorAction Ignore948            Remove-Item $outputPath -Force -ErrorAction Ignore949        }950        BeforeEach {951            Remove-Item $outputPath -Force -ErrorAction Ignore952        }953        It "Displays expected startup banner text by default" {954            $process = Start-Process @spArgs955            Wait-UntilTrue -sb { $process.HasExited } -TimeoutInMilliseconds 5000 -IntervalInMilliseconds 250 | Should -BeTrue956 957            $out = @(Get-Content $outputPath)958            $out.Count | Should -Be 2959            $out[0] | Should -BeExactly "PowerShell $($PSVersionTable.GitCommitId)"960            $out[1] | Should -MatchExactly $expectedPromptPattern961        }962        It "Displays only the prompt with -NoLogo" {963            $spArgs["ArgumentList"] += "-NoLogo"964            $process = Start-Process @spArgs965            Wait-UntilTrue -sb { $process.HasExited } -TimeoutInMilliseconds 5000 -IntervalInMilliseconds 250 | Should -BeTrue966 967            $out = @(Get-Content $outputPath)968            $out.Count | Should -Be 1969            $out[0] | Should -MatchExactly $expectedPromptPattern970        }971    }972 973    Context 'CommandWithArgs tests' {974        It 'Should be able to run a pipeline with arguments using <param>' -TestCases @(975            @{ param = '-commandwithargs' }976            @{ param = '-cwa' }977        ){978            param($param)979            $out = pwsh -nologo -noprofile $param '$args | % { "[$_]" }'  '$fun' '@times'980            $out.Count | Should -Be 2 -Because ($out | Out-String)981            $out[0] | Should -BeExactly '[$fun]'982            $out[1] | Should -BeExactly '[@times]'983        }984 985        It 'Should be able to handle boolean switch: <param>' -TestCases @(986            @{ param = '-switch:$true'; expected = 'True'}987            @{ param = '-switch:$false'; expected = 'False'}988        ){989            param($param, $expected)990            $out = pwsh -nologo -noprofile -cwa 'param([switch]$switch) $switch.IsPresent' $param991            $out | Should -Be $expected992        }993    }994 995    It 'Errors for invalid ExecutionPolicy string' {996        $out = pwsh -nologo -noprofile -executionpolicy NonExistingExecutionPolicy -c 'exit 0' 2>&1997        $out | Should -Not -BeNullOrEmpty998        $LASTEXITCODE | Should -Be $ExitCodeBadCommandLineParameter999    }1000}1001 1002Describe "WindowStyle argument" -Tag Feature {1003    BeforeAll {1004        $defaultParamValues = $PSDefaultParameterValues.Clone()1005        $PSDefaultParameterValues["it:skip"] = !$IsWindows1006 1007        if ($IsWindows)1008        {1009            $ExitCodeBadCommandLineParameter = 641010            Add-Type -Name User32 -Namespace Test -MemberDefinition @"1011public static WINDOWPLACEMENT GetPlacement(IntPtr hwnd)1012{1013    WINDOWPLACEMENT placement = new WINDOWPLACEMENT();1014    placement.length = Marshal.SizeOf(placement);1015 1016    if (!GetWindowPlacement(hwnd, ref placement))1017    {1018        throw new System.ComponentModel.Win32Exception();1019    }1020 1021    return placement;1022}1023 1024[DllImport("user32.dll", SetLastError = true)]1025[return: MarshalAs(UnmanagedType.Bool)]1026public static extern bool GetWindowPlacement(1027    IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);1028 1029[Serializable]1030[StructLayout(LayoutKind.Sequential)]1031public struct WINDOWPLACEMENT1032{1033    public int length;1034    public int flags;1035    public ShowWindowCommands showCmd;1036    public System.Drawing.Point ptMinPosition;1037    public System.Drawing.Point ptMaxPosition;1038    public System.Drawing.Rectangle rcNormalPosition;1039}1040 1041public enum ShowWindowCommands : int1042{1043    Hidden = 0,1044    Normal = 1,1045    Minimized = 2,1046    Maximized = 3,1047}1048"@1049        }1050    }1051 1052    AfterAll {1053        $global:PSDefaultParameterValues = $defaultParamValues1054    }1055 1056    It "-WindowStyle <WindowStyle> should work on Windows" -Pending -TestCases @(1057            @{WindowStyle="Normal"},1058            @{WindowStyle="Minimized"},1059            @{WindowStyle="Maximized"}  # hidden doesn't work in CI/Server Core1060        ) {1061        param ($WindowStyle)1062 1063        if (Test-IsWindowsArm64) {1064            Set-ItResult -Pending -Because "All windows are showing up as hidden or ARM64"1065        }1066 1067        try {1068            $ps = Start-Process $powershell -ArgumentList "-WindowStyle $WindowStyle -noexit -interactive" -PassThru1069            $startTime = Get-Date1070            $showCmd = "Unknown"1071            while (((Get-Date) - $startTime).TotalSeconds -lt 10 -and $showCmd -ne $WindowStyle) {1072                Start-Sleep -Milliseconds 1001073                $showCmd = ([Test.User32]::GetPlacement($ps.MainWindowHandle)).showCmd1074            }1075 1076            $showCmd | Should -BeExactly $WindowStyle1077        } finally {1078            $ps | Stop-Process -Force1079        }1080    }1081 1082    It "Invalid -WindowStyle returns error" {1083        & $powershell -WindowStyle invalid1084        $LASTEXITCODE | Should -Be $ExitCodeBadCommandLineParameter1085    }1086}1087 1088Describe "Console host api tests" -Tag CI {1089    Context "String escape and control sequences" {1090        $esc = [char]0x1b1091        $csi = [char]0x9b1092        $testCases =1093            @{InputObject = "abc"; Length = 3; Name = "No escapes"},1094            @{InputObject = "${esc} [31mabc"; Length = 9; Name = "Malformed escape - extra space"},1095            @{InputObject = "${esc}abc"; Length = 4; Name = "Malformed escape - no csi"},1096            @{InputObject = "[31mabc"; Length = 7; Name = "Malformed escape - no escape"}1097 1098        $testCases += if ($Host.UI.SupportsVirtualTerminal)1099        {1100            @{InputObject = "$esc[31mabc"; Length = 3; Name = "Escape at start"}1101            @{InputObject = "$esc[31mabc$esc[0m"; Length = 3; Name = "Escape at start and end"}1102            @{InputObject = "${csi}31mabc"; Length = 3; Name = "C1 CSI at start"}1103            @{InputObject = "${csi}31mabc${csi}0m"; Length = 3; Name = "C1 CSI at start and end"}1104            @{InputObject = "abc${csi}m"; Length = 3; Name = "C1 CSI, no params"}1105            @{InputObject = "abc${csi}#{"; Length = 3; Name = "C1 CSI, XTPUSHSGR"}1106            @{InputObject = "abc${csi}#}"; Length = 3; Name = "C1 CSI, XTPOPSGR"}1107            @{InputObject = "abc${csi}#p"; Length = 3; Name = "C1 CSI, XTPUSHSGR (alias)"}1108            @{InputObject = "abc${csi}#q"; Length = 3; Name = "C1 CSI, XTPOPSGR (alias)"}1109            @{InputObject = "abc${esc}[0#p"; Length = 3; Name = "XTPUSHSGR, with param"}1110            @{InputObject = "${esc}[0;1#qabc"; Length = 3; Name = "XTPOPSGR, with multiple params"}1111        }1112        else1113        {1114            @{InputObject = "$esc[31mabc"; Length = 8; Name = "Escape at start - no virtual term support"}1115            @{InputObject = "$esc[31mabc$esc[0m"; Length = 12; Name = "Escape at start and end - no virtual term support"}1116            @{InputObject = "${csi}31mabc"; Length = 7; Name = "C1 CSI at start - no virtual term support"}1117            @{InputObject = "${csi}31mabc${csi}0m"; Length = 10; Name = "C1 CSI at start and end - no virtual term support"}1118            @{InputObject = "abc${csi}m"; Length = 5; Name = "C1 CSI, no params - no virtual term support"}1119            @{InputObject = "abc${csi}#{"; Length = 6; Name = "C1 CSI, XTPUSHSGR - no virtual term support"}1120            @{InputObject = "abc${csi}#}"; Length = 6; Name = "C1 CSI, XTPOPSGR - no virtual term support"}1121            @{InputObject = "abc${csi}#p"; Length = 6; Name = "C1 CSI, XTPUSHSGR (alias) - no virtual term support"}1122            @{InputObject = "abc${csi}#q"; Length = 6; Name = "C1 CSI, XTPOPSGR (alias) - no virtual term support"}1123            @{InputObject = "abc${esc}[0#p"; Length = 8; Name = "XTPUSHSGR, with param - no virtual term support"}1124            @{InputObject = "${esc}[0;1#qabc"; Length = 10; Name = "XTPOPSGR, with multiple params - no virtual term support"}1125        }1126 1127        It "Should properly calculate buffer cell width of '<Name>'" -TestCases $testCases {1128            param($InputObject, $Length)1129            $Host.UI.RawUI.LengthInBufferCells($InputObject) | Should -Be $Length1130        }1131    }1132}1133 1134Describe "Pwsh exe resources tests" -Tag CI {1135    It "Resource strings are embedded in the executable" -Skip:(!$IsWindows) {1136        $pwsh = Get-Item -Path "$PSHOME\pwsh.exe"1137        $pwsh.VersionInfo.FileVersion | Should -Match $PSVersionTable.PSVersion.ToString().Split("-")[0]1138        $productVersion = $pwsh.VersionInfo.ProductVersion.Replace("-dirty","").Replace(" Commits: ","-").Replace(" SHA: ","-g")1139        if ($PSVersionTable.GitCommitId.Contains("-g")) {1140            $productVersion | Should -BeExactly $PSVersionTable.GitCommitId1141        } else {1142            $productVersion | Should -Match $PSVersionTable.GitCommitId1143        }1144        $pwsh.VersionInfo.ProductName | Should -BeExactly "PowerShell"1145    }1146 1147    It "Manifest contains compatibility section" -Skip:(!$IsWindows) {1148        $osversion = [System.Environment]::OSVersion.Version1149        $PSVersionTable.os | Should -MatchExactly "$($osversion.Major).$($osversion.Minor)"1150    }1151}1152 1153Describe 'Pwsh startup in directories that contain wild cards' -Tag CI {1154    BeforeAll {1155        $powershell = Join-Path -Path $PSHOME -ChildPath "pwsh"1156        $dirnames = "[T]est","[Test","T][est","Test"1157        $testcases = @()1158        foreach ( $d in $dirnames ) {1159            $null = New-Item -type Directory -Path "${TESTDRIVE}/$d"1160            $testcases += @{ Dirname = $d }1161        }1162    }1163 1164    It "pwsh can startup in a directory named <dirname>" -TestCases $testcases {1165        param ( $dirname )1166        try {1167            Push-Location -LiteralPath "${TESTDRIVE}/${dirname}"1168            $result = & $powershell -noprofile -c '(Get-Item .).Name'1169            $result | Should -BeExactly $dirname1170        }1171        finally {1172            Pop-Location1173        }1174    }1175}1176 1177Describe 'Pwsh startup and PATH' -Tag CI {1178    BeforeEach {1179        $oldPath = $env:PATH1180    }1181 1182    AfterEach {1183        $env:PATH = $oldPath1184    }1185 1186    It 'Calling pwsh starts the same version of PowerShell as currently running' {1187        $version = pwsh -v1188        $version | Should -BeExactly "PowerShell $($PSVersionTable.GitCommitId)"1189    }1190 1191    It 'pwsh starts even if PATH is not defined' {1192        $pwsh = Join-Path -Path $PSHOME -ChildPath "pwsh"1193        Remove-Item Env:\PATH1194        $path = & $pwsh -noprofile -command '$env:PATH'1195        $path | Should -BeExactly ($PSHOME + [System.IO.Path]::PathSeparator)1196    }1197}1198 1199Describe 'Console host name' -Tag CI {1200    It 'Name is pwsh' {

Showing the first 1,200 of 1254 lines. Download the file for the rest.