MegaBites-AI/Windows-powershell
0372
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3Describe "History cmdlet test cases" -Tags "CI" {4 Context "Simple History Tests" {5 BeforeEach {6 $setting = [system.management.automation.psinvocationsettings]::New()7 $setting.AddToHistory = $true8 $ps = [PowerShell]::Create("NewRunspace")9 # we need to be sure that history is added, so use the proper10 # Invoke variant11 $null = $ps.addcommand("Get-Date").Invoke($null, $setting)12 $ps.commands.clear()13 $null = $ps.addscript("1+1").Invoke($null, $setting)14 $ps.commands.clear()15 $null = $ps.addcommand("Get-Location").Invoke($null, $setting)16 $ps.commands.clear()17 }18 AfterEach {19 $ps.Dispose()20 }21 It "Get-History returns proper history" {22 # for this case, we'll *not* add to history23 $result = $ps.AddCommand("Get-History").Invoke()24 $result.Count | Should -Be 325 $result[0].CommandLine | Should -BeExactly "Get-Date"26 $result[1].CommandLine | Should -Be "1+1"27 $result[2].CommandLine | Should -BeExactly "Get-Location"28 }29 It "Invoke-History invokes proper command" {30 $result = $ps.AddScript("Invoke-History 2").Invoke()31 $result | Should -Be 232 }33 It "Clear-History removes history" {34 $ps.AddCommand("Clear-History").Invoke()35 $ps.commands.clear()36 $result = $ps.AddCommand("Get-History").Invoke()37 $result | Should -BeNullOrEmpty38 }39 It "Add-History actually adds to history" {40 # add this invocation to history41 $ps.AddScript("Get-History|Add-History").Invoke($null, $setting)42 # that's 4 history lines * 243 $ps.Commands.Clear()44 $result = $ps.AddCommand("Get-History").Invoke()45 $result.Count | Should -Be 846 for ($i = 0; $i -lt 4; $i++) {47 $result[$i + 4].CommandLine | Should -BeExactly $result[$i].CommandLine48 }49 }50 }51 52 Context 'Conversions and Culture tests' {53 54 BeforeAll {55 $cultureTestCases = @(56 @{57 Culture = 'en-us'58 StartTime = '08/18/2021 16:43:50'59 EndTime = '08/18/2021 16:44:50'60 }61 @{62 Culture = 'en-au'63 StartTime = '18/08/2021 16:43:50'64 EndTime = '18/08/2021 16:44:50'65 }66 )67 68 $oldCulture = [cultureinfo]::CurrentCulture69 }70 71 AfterEach {72 [cultureinfo]::CurrentCulture = $oldCulture73 }74 75 It "respects current culture settings when handling datetime conversions" -TestCases $cultureTestCases {76 param($Culture, $StartTime, $EndTime)77 78 [cultureinfo]::CurrentCulture = [cultureinfo]::GetCultureInfo($Culture)79 80 $history = [PSCustomObject] @{81 CommandLine = "test-command"82 ExecutionStatus = [Management.Automation.Runspaces.PipelineState]::Completed83 StartExecutionTime = $StartTime84 EndExecutionTime = $EndTime85 }86 87 { $history | Add-History -ErrorAction Stop } | Should -Not -Throw -Because 'the datetime should be converted according to the current culture'88 }89 90 It "throws an error when asked to convert a date format that doesn't match the current culture" {91 [cultureinfo]::CurrentCulture = [cultureinfo]::GetCultureInfo('en-au')92 $history = [PSCustomObject] @{93 CommandLine = "test-command"94 ExecutionStatus = [Management.Automation.Runspaces.PipelineState]::Completed95 StartExecutionTime = '08/18/2021 16:43:50'96 EndExecutionTime = '08/18/2021 16:44:50'97 }98 99 $errorMessage = 'Cannot add history because the input object has a format that is not valid.'100 { $history | Add-History -ErrorAction Stop } | Should -Throw -ExpectedMessage $errorMessage101 }102 }103 104 It "Tests Invoke-History on a cmdlet that generates output on all streams" {105 $streamSpammer = '106 function StreamSpammer107 {108 [CmdletBinding()]109 param()110 111 Write-Debug "Debug"112 Write-Error "Error"113 Write-Information "Information"114 Write-Progress "Progress"115 Write-Verbose "Verbose"116 Write-Warning "Warning"117 "Output"118 }119 120 $InformationPreference = "Continue"121 $DebugPreference = "Continue"122 $VerbosePreference = "Continue"123 '124 125 $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings126 $invocationSettings.AddToHistory = $true127 $ps = [PowerShell]::Create()128 $null = $ps.AddScript($streamSpammer).Invoke()129 $ps.Commands.Clear()130 $null = $ps.AddScript("StreamSpammer");131 $null = $ps.Invoke($null, $invocationSettings)132 $ps.Commands.Clear()133 $null = $ps.AddScript("Invoke-History -id 1")134 $result = $ps.Invoke($null, $invocationSettings)135 $outputCount = $(136 $ps.Streams.Error;137 $ps.Streams.Progress;138 $ps.Streams.Verbose;139 $ps.Streams.Debug;140 $ps.Streams.Warning;141 $ps.Streams.Information).Count142 $ps.Dispose()143 144 ## Twice per stream - once for the original invocation, and once for the re-invocation145 $outputCount | Should -Be 12146 }147 148 It "Tests Invoke-History on a private command" {149 150 $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings151 $invocationSettings.AddToHistory = $true152 $ps = [PowerShell]::Create()153 $null = $ps.AddScript("(Get-Command Get-Process).Visibility = 'Private'").Invoke()154 $ps.Commands.Clear()155 $null = $ps.AddScript("Get-Process -id $PID")156 $null = $ps.Invoke($null, $invocationSettings)157 $ps.Commands.Clear()158 $null = $ps.AddScript("Invoke-History -id 1")159 $result = $ps.Invoke($null, $invocationSettings)160 $errorResult = $ps.Streams.Error[0].FullyQualifiedErrorId161 $ps.Dispose()162 163 $errorResult | Should -BeExactly 'CommandNotFoundException'164 }165 166 It "HistoryInfo calculates Duration" {167 $start = [datetime]::new(2001, 01, 01, 10, 01, 01)168 $duration = [timespan] "1:2:21"169 $end = $start + $duration170 $history = [PSCustomObject] @{171 CommandLine = "command"172 ExecutionStatus = [Management.Automation.Runspaces.PipelineState]::Completed173 StartExecutionTime = $start174 EndExecutionTime = $end175 }176 $history | Add-History177 $h = Get-History -Count 1178 $h.Duration | Should -Be $duration179 }180 181 It "Simple recursive invocation of 'Invoke-History' can be detected" {182 Set-Content -Path $TestDrive/history.csv -Value @'183#TYPE Microsoft.PowerShell.Commands.HistoryInfo184"Id","CommandLine","ExecutionStatus","StartExecutionTime","EndExecutionTime","Duration"185"1","Invoke-History","Completed","7/16/2020 4:33:43 PM","7/16/2020 4:33:43 PM","00:00:00.0724719"186'@187 try {188 $ps = [PowerShell]::Create()189 $ps.AddScript("Import-Csv $TestDrive/history.csv | Add-History").Invoke() > $null190 $ps.Commands.Clear()191 $ps.AddCommand("Invoke-History").Invoke() > $null192 193 $ps.Streams.Error.Count | Should -BeExactly 1194 $ps.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'InvokeHistoryLoopDetected,Microsoft.PowerShell.Commands.InvokeHistoryCommand'195 }196 finally {197 $ps.Dispose()198 }199 }200 201 It "Nested recursive invocation of 'Invoke-History' can be detected" {202 Set-Content -Path $TestDrive/history.csv -Value @'203#TYPE Microsoft.PowerShell.Commands.HistoryInfo204"Id","CommandLine","ExecutionStatus","StartExecutionTime","EndExecutionTime","Duration"205"1","Invoke-History 2","Completed","7/16/2020 9:54:45 PM","7/16/2020 9:54:45 PM","00:00:00.0859151"206"2","tt 1","Completed","7/16/2020 9:54:50 PM","7/16/2020 9:54:50 PM","00:00:00.1687306"207'@208 try {209 $ps = [PowerShell]::Create()210 $ps.AddScript("Import-Csv $TestDrive/history.csv | Add-History; Set-Alias -Name tt -Value Invoke-History").Invoke() > $null211 $ps.Commands.Clear()212 $ps.AddCommand("Invoke-History").Invoke() > $null213 214 $ps.Streams.Error.Count | Should -BeExactly 1215 $ps.Streams.Error[0].FullyQualifiedErrorId | Should -BeExactly 'InvokeHistoryLoopDetected,Microsoft.PowerShell.Commands.InvokeHistoryCommand'216 }217 finally {218 $ps.Dispose()219 }220 }221}222 