Merge pull request #2067 from JamesWTruher/jameswtruher/testgapfile-002

Fill more gaps in cmdlet test coverage
This commit is contained in:
Jason Shirk
2016-09-01 11:16:32 -07:00
committed by GitHub
10 changed files with 361 additions and 43 deletions
+49
View File
@@ -0,0 +1,49 @@
function Wait-CompleteExecution
{
[CmdletBinding()]
param (
[ScriptBlock]$sb,
[int]$TimeoutInMilliseconds = 10000,
[int]$IntervalInMilliseconds = 1000
)
# Get the current time
$startTime = [DateTime]::Now
# Loop until the script block evaluates to true
while (-not ($sb.Invoke())) {
# Sleep for the specified interval
start-sleep -mil $intervalInMilliseconds
# If the timeout period has passed, throw an exception
if (([DateTime]::Now - $startTime).TotalMilliseconds -gt $timeoutInMilliseconds)
{
return $false
}
}
return $true
}
function Test-IsElevated
{
$IsElevated = $False
if ( $IsWindows ) {
# on Windows we can determine whether we're executing in an
# elevated context
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$windowsPrincipal = new-object 'Security.Principal.WindowsPrincipal' $identity
if ($windowsPrincipal.IsInRole("Administrators") -eq 1)
{
$IsElevated = $true
}
}
else {
# on Linux, tests run via sudo will generally report "root" for whoami
if ( (whoami) -match "root" ) {
$IsElevated = $true
}
}
return $IsElevated
}
export-modulemember -function Wait-CompleteExecution,Test-IsElevated
+14 -2
View File
@@ -86,7 +86,6 @@ namespace TestHost
public class Streams
{
public ArrayList ConsoleOutput = new ArrayList();
public ArrayList Output = new ArrayList();
public ArrayList Input = new ArrayList();
public ArrayList Error = new ArrayList();
public ArrayList Verbose = new ArrayList();
@@ -95,6 +94,17 @@ namespace TestHost
public ArrayList Information = new ArrayList();
public ArrayList Progress = new ArrayList();
public ArrayList Prompt = new ArrayList();
public void Clear() {
ConsoleOutput.Clear();
Input.Clear();
Error.Clear();
Verbose.Clear();
Debug.Clear();
Warning.Clear();
Information.Clear();
Progress.Clear();
Prompt.Clear();
}
}
public class TestPSHostUserInterface : PSHostUserInterface
{
@@ -112,7 +122,9 @@ namespace TestHost
public override Dictionary<string, PSObject> Prompt(string caption, string message, Collection<FieldDescription> descriptions)
{
Streams.Prompt.Add(caption + ":" + message);
string s = String.Empty;
if ( descriptions[0] != null ) { s = descriptions[0].Name; }
Streams.Prompt.Add(caption + ":" + message + ":" + s);
Dictionary<string, PSObject> d = new Dictionary<string, PSObject>();
d.Add(descriptions[0].ToString(), new PSObject(promptResponse));
return d;
@@ -0,0 +1,95 @@
$script1 = @'
'aaa'.ToString() > $null
'aa' > $null
"a" 2> $null | % { $_ }
'bb' > $null
'bb'.ToSTring() > $null
'bbb'
'@
$script2 = @'
"line 1"
"line 2"
"line 3"
'@
$testroot = resolve-path (join-path $psscriptroot ../../..)
$common = join-path $testroot Common
$helperModule = join-path $common Test.Helpers.psm1
Describe "Breakpoints when set should be hit" -tag "CI" {
BeforeAll {
$path = setup -pass -f TestScript_1.ps1 -content $script1
$bps = 1..6 | %{ set-psbreakpoint -script $path -line $_ -Action { continue } }
}
AfterAll {
$bps | Remove-PSBreakPoint
}
It "A redirected breakpoint is hit" {
& $path
foreach ( $bp in $bps ) {
$bp.HitCount | should be 1
}
}
}
Describe "It should be possible to reset runspace debugging" -tag "Feature" {
BeforeAll {
import-module $helperModule -force
$path = setup -pass -f TestScript_2.ps1 -content $script2
$scriptPath = "$testdrive/TestScript_2.ps1"
$iss = [initialsessionstate]::CreateDefault2();
$rs = [runspacefactory]::CreateRunspace($iss)
$rs.Name = "TestRunspaceDebuggerReset"
$rs.Open()
$rs | Enable-RunspaceDebug
$debuggerBeforeReset = $rs.Debugger
# Create PowerShell to run script.
$ps = [powershell]::Create()
$ps.Runspace = $rs
# Set breakpoints in runspace.
$result = $ps.AddScript("Set-PSBreakpoint -Script '$scriptPath' -line 1").Invoke()
$ps.Commands.Clear()
$result = $ps.AddScript("Set-PSBreakpoint -Script '$scriptPath' -line 3").Invoke()
$ps.Commands.Clear()
$breakpoints = $ps.AddScript("Get-PSBreakpoint").Invoke()
# Run script file until breakpoint hit.
$ar = $ps.AddScript("$scriptPath").BeginInvoke()
$completed = Wait-CompleteExecution { $rs.Debugger.InBreakPoint -eq $true } -timeout 10000 -interval 200
$ps.Stop()
$rs.ResetRunspaceState()
}
AfterAll {
if ( $ps -ne $null ) { $ps.Dispose() }
if ( $ss -ne $null ) { $rs.Dispose() }
}
It "2 breakpoints should have been set" {
$breakpoints.Count | Should be 2
}
It "The breakpoint Should have been hit" {
$completed | should be $true
}
It "The reset debugger should not be in a breakpoint" {
$rs.Debugger.InBreakPoint | should be $false
}
It "The reset debugger should not be active" {
$rs.Debugger.IsActive | should be $false
}
It "The reset debugger mode should be set to 'Default'" {
$rs.Debugger.DebugMode | should be "Default"
}
It "The debugger should be the same before and after the reset" {
$rs.Debugger | Should be $debuggerBeforeReset
}
It "The breakpoints should be gone after reset" {
$ps.Commands.clear()
$ps.AddCommand("Get-PSBreakpoint").Invoke() | Should BeNullOrEmpty
}
It "The script should run without a break" {
$ps.Commands.Clear()
$ps.addscript("$testdrive/TestScript_2.ps1").Invoke().Count | should be 3
}
}
@@ -14,7 +14,7 @@ Describe "Start-Process" -Tags @("CI","SLOW") {
# This has been fixed on Linux, but not on OS X
It "Should process arguments without error" {
$process = Start-Process ping -ArgumentList $pingParam -PassThru
$process = Start-Process ping -ArgumentList $pingParam -PassThru -RedirectStandardOutput "$TESTDRIVE/output"
$process.Length | Should Be 1
$process.Id | Should BeGreaterThan 1
@@ -22,7 +22,7 @@ Describe "Start-Process" -Tags @("CI","SLOW") {
}
It "Should work correctly when used with full path name" {
$process = Start-Process $pingCommand -ArgumentList $pingParam -PassThru
$process = Start-Process $pingCommand -ArgumentList $pingParam -PassThru -RedirectStandardOutput "$TESTDRIVE/output"
$process.Length | Should Be 1
$process.Id | Should BeGreaterThan 1
@@ -30,7 +30,7 @@ Describe "Start-Process" -Tags @("CI","SLOW") {
}
It "Should invoke correct path when used with FilePath argument" {
$process = Start-Process -FilePath $pingCommand -ArgumentList $pingParam -PassThru
$process = Start-Process -FilePath $pingCommand -ArgumentList $pingParam -PassThru -RedirectStandardOutput "$TESTDRIVE/output"
$process.Length | Should Be 1
$process.Id | Should BeGreaterThan 1
@@ -38,11 +38,11 @@ Describe "Start-Process" -Tags @("CI","SLOW") {
}
It "Should wait for command completion if used with Wait argument" {
$process = Start-Process ping -ArgumentList $pingParam -Wait -PassThru
$process = Start-Process ping -ArgumentList $pingParam -Wait -PassThru -RedirectStandardOutput "$TESTDRIVE/output"
}
It "Should work correctly with WorkingDirectory argument" {
$process = Start-Process ping -WorkingDirectory $pingDirectory -ArgumentList $pingParam -PassThru
$process = Start-Process ping -WorkingDirectory $pingDirectory -ArgumentList $pingParam -PassThru -RedirectStandardOutput "$TESTDRIVE/output"
$process.Length | Should Be 1
$process.Id | Should BeGreaterThan 1
@@ -50,7 +50,7 @@ Describe "Start-Process" -Tags @("CI","SLOW") {
}
It "Should should handle stderr redirection without error" {
$process = Start-Process ping -ArgumentList $pingParam -PassThru -RedirectStandardError $tempFile
$process = Start-Process ping -ArgumentList $pingParam -PassThru -RedirectStandardError $tempFile -RedirectStandardOutput "$TESTDRIVE/output"
$process.Length | Should Be 1
$process.Id | Should BeGreaterThan 1
@@ -59,13 +59,13 @@ Describe "Start-Process" -Tags @("CI","SLOW") {
It "Should should handle stdout redirection without error" {
$process = Start-Process ping -ArgumentList $pingParam -Wait -RedirectStandardOutput $tempFile
$dirEntry = dir $tempFile
$dirEntry = get-childitem $tempFile
$dirEntry.Length | Should BeGreaterThan 0
}
It "Should should handle stdin redirection without error" {
$process = Start-Process sort -Wait -RedirectStandardOutput $tempFile -RedirectStandardInput $assetsFile
$dirEntry = dir $tempFile
$dirEntry = get-childitem $tempFile
$dirEntry.Length | Should BeGreaterThan 0
}
@@ -0,0 +1,45 @@
Describe "SecureString conversion tests" -Tags "CI" {
BeforeAll {
$string = "ABCD"
$secureString = [System.Security.SecureString]::New()
$string.ToCharArray() | foreach-object { $securestring.AppendChar($_) }
$defaultParamValues = $PSdefaultParameterValues.Clone()
$PSdefaultParameterValues = @{}
if ( ! $IsWindows ) { $PSdefaultParameterValues["it:pending"] = $true }
}
AfterAll {
$PSdefaultParameterValues = $defaultParamValues
}
It "using null arguments to ConvertFrom-SecureString produces an exception" {
try {
ConvertFrom-SecureString -secureString $null -key $null
}
catch {
$_.FullyQualifiedErrorId | should be "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand"
}
}
It "using a bad key produces an exception" {
try {
$badkey = [byte[]]@(1,2)
ConvertFrom-SecureString -securestring $secureString -key $badkey
throw "Command did not throw exception"
}
catch {
$_.FullyQualifiedErrorId | should be "Argument,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand"
}
}
It "Can convert to a secure string" {
$ss = ConvertTo-SecureString -AsPlainText -Force abcd
$ss.GetType().Name | should be "SecureString"
}
It "can convert back from a secure string" {
$secret = "abcd"
$ss1 = ConvertTo-SecureString -AsPlainText -Force $secret
$ss2 = convertfrom-securestring $ss1 | convertto-securestring
[pscredential]::New("user",$ss2).GetNetworkCredential().Password | should be $secret
}
}
@@ -0,0 +1,59 @@
Describe "Debug-Runspace" -tag "CI" {
BeforeAll {
$rs1 = [runspacefactory]::CreateRunspace()
$rs1.Open()
$rs1.Name = "MyRunspace1"
$rs2 = [runspacefactory]::CreateRunspace()
$rs2.Open()
$rs2.Name = "MyRunspace2"
}
AfterAll {
if ( $rs1 ) { $rs1.Dispose() }
if ( $rs2 ) { $rs1.Dispose() }
}
It "Debugging a runspace should fail if the name is ambiguous" {
try {
Debug-Runspace -Name "My*" -ea stop
throw "Command did not throw exception"
}
catch {
$_.FullyQualifiedErrorId | should be "DebugRunspaceTooManyRunspaceFound,Microsoft.PowerShell.Commands.DebugRunspaceCommand"
}
}
It "Debugging a runspace should fail if the name is not found" {
try {
Debug-Runspace -Name "dflkjsdkfjldkjssldfj" -ea stop
throw "Command did not throw exception"
}
catch {
$_.FullyQualifiedErrorId | should be "DebugRunspaceNoRunspaceFound,Microsoft.PowerShell.Commands.DebugRunspaceCommand"
}
}
It "Debugging a runspace should fail if the runspace is not open" {
try {
$rs2.Close()
Debug-Runspace -runspace $rs2 -ea stop
throw "Command did not throw exception"
}
catch {
$_.FullyQualifiedErrorId | should be "InvalidOperation,Microsoft.PowerShell.Commands.DebugRunspaceCommand"
}
}
It "Debugging a runspace should fail if the runspace has no debugger" {
try {
$rs1.Debugger.SetDebugMode("None")
Debug-Runspace -runspace $rs1 -ea stop
throw "Command did not throw exception"
}
catch {
$_.FullyQualifiedErrorId | should be "InvalidOperation,Microsoft.PowerShell.Commands.DebugRunspaceCommand"
}
}
}
@@ -0,0 +1,21 @@
Describe "Enable and Disable PSBreakpoints" -Tag "CI" {
BeforeAll {
$path = Setup -F testbp.ps1 -content "get-command`nget-date`nget-location" -pass
$bp = set-psbreakpoint -script $path -line 2
disable-psbreakpoint $bp
}
AfterAll {
$bp | remove-psbreakpoint
}
It "Enable-PSBreakpoint should enable the breakpoint" {
$bp.Enabled | should be $false
Enable-PSBreakpoint $bp
$bp.Enabled | Should be $true
}
It "Disable-PSBreakpoint should disable the breakpoint" {
Enable-PSBreakpoint $bp
$bp.Enabled | Should be $true
Disable-PSBreakpoint $bp
$bp.Enabled | Should be $false
}
}
@@ -1,83 +1,63 @@
Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "Feature" {
Describe "Tests for the Import-PowerShellDataFile cmdlet" -Tags "CI" {
It "Validates error on a missing path" {
$foundError = ""
try
{
Import-PowerShellDataFile -Path /SomeMissingDirectory -ErrorAction Stop
Throw "Command did not throw exception"
}
catch
{
$foundError = $_.FullyQualifiedErrorId
$_.FullyQualifiedErrorId | Should be "PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand"
}
$foundError | Should be "PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand"
}
It "Validates error on a directory" {
$foundError = ""
try
{
Import-PowerShellDataFile ${TESTDRIVE} -ErrorAction Stop
Throw "Command did not throw exception"
}
catch
{
$foundError = $_.FullyQualifiedErrorId
$_.FullyQualifiedErrorId | Should be "CouldNotParseAsPowerShellDataFile,Import-PowerShellDataFile"
}
$foundError | Should be "CouldNotParseAsPowerShellDataFile,Import-PowerShellDataFile"
}
It "Generates a good error on an insecure file" {
$path = New-TemporaryFile
Set-Content $path '@{ Foo = Get-Process }'
$foundError = ""
$path = Setup -f insecure.psd1 -content '@{ Foo = Get-Process }' -pass
try
{
Import-PowerShellDataFile $path -ErrorAction Stop
Throw "Command did not throw exception"
}
catch
{
$foundError = $_.FullyQualifiedErrorId
$_.FullyQualifiedErrorId | Should be "InvalidOperationException,Import-PowerShellDataFile"
}
finally
{
Remove-Item $path
}
$foundError | Should be "InvalidOperationException,Import-PowerShellDataFile"
}
It "Generates a good error on a file that isn't a PowerShell Data File (missing the hashtable root)" {
$path = New-TemporaryFile
Set-Content $path '"Hello World"'
$foundError = ""
$path = setup -f NotAPSDataFile -content '"Hello World"' -Pass
try
{
Import-PowerShellDataFile $path -ErrorAction Stop
Import-PowerShellDataFile $path -ErrorAction Stop
Throw "Command did not throw exception"
}
catch
{
$foundError = $_.FullyQualifiedErrorId
$_.FullyQualifiedErrorId | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Import-PowerShellDataFile"
}
finally
{
Remove-Item $path
}
$foundError | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Import-PowerShellDataFile"
}
It "Can parse a PowerShell Data File (detailed tests are in AST.SafeGetValue tests)" {
$path = New-TemporaryFile
Set-Content $path '@{ "Hello" = "World" }'
$path = Setup -F gooddatafile -content '@{ "Hello" = "World" }' -pass
$result = Import-PowerShellDataFile $path -ErrorAction Stop
$result.Hello | Should be "World"
@@ -0,0 +1,42 @@
if ( ! (get-module -ea silentlycontinue TestHostCS ))
{
$root = git rev-parse --show-toplevel
$pestertestroot = join-path $root test/powershell
$common = join-path $pestertestroot Common
$hostmodule = join-path $common TestHostCS.psm1
import-module $hostmodule
}
Describe "Read-Host Test" -tag "CI" {
BeforeAll {
$th = New-TestHost
$rs = [runspacefactory]::Createrunspace($th)
$rs.open()
$ps = [powershell]::Create()
$ps.Runspace = $rs
$ps.Commands.Clear()
}
AfterEach {
$ps.Commands.Clear()
}
AfterAll {
$rs.Close()
$rs.Dispose()
$ps.Dispose()
}
It "Read-Host returns expected string" {
$result = $ps.AddCommand("Read-Host").Invoke()
$result | Should Be $th.UI.ReadLineData
}
It "Read-Host sets the prompt correctly" {
$result = $ps.AddScript("Read-Host -prompt myprompt").Invoke()
$prompt = $th.ui.streams.prompt[0]
$prompt | should Not BeNullOrEmpty
$prompt.split(":")[-1] | should be myprompt
}
It "Read-Host returns a secure string when using -AsSecureString parameter" {
$result = $ps.AddScript("Read-Host -AsSecureString").Invoke() | select-object -first 1
$result.GetType().Name | should be "SecureString"
[pscredential]::New("foo",$result).GetNEtworkCredential().Password | should BeExactly TEST
}
}
@@ -0,0 +1,15 @@
# first check to see which platform we're on. If we're on windows we should be able
# to be sure whether we're running elevated. If we're on Linux, we can use whoami to
# determine whether we're elevated
Describe "Set-Date" -Tag "CI" {
BeforeAll {
Import-Module (join-path $psscriptroot "../../Common/Test.Helpers.psm1")
$IsElevated = Test-IsElevated
}
It "Set-Date should be able to set the date in an elevated context" -Skip:(! $IsElevated) {
{ get-date | set-date } | Should not throw
}
It "Set-Date should produce an error in a non-elevated context" -Skip:($IsElevated) {
{ get-date |set-date} | should throw
}
}