├── Commands
└── Cmdlets
│ ├── ClearRecycleBin.Tests.ps1
│ ├── ClearRecycleBinHelperFunctions.psm1
│ ├── Clipboard.Tests.ps1
│ ├── ClipboardHelperFunctions.psm1
│ ├── FormatHex.Tests.ps1
│ ├── HelperMethods.psm1
│ ├── MiscCmdletUpdates.Tests.ps1
│ ├── NewGuid.Tests.ps1
│ ├── NewTemporaryFile.Tests.ps1
│ ├── PSODataUtils.HelperMethods.psm1
│ ├── Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1
│ ├── Pester.Commands.Cmdlets.StartProcessWaitPassThru.Tests.ps1
│ ├── Pester.ConvertString.Tests.ps1
│ ├── Pester.DelimitedText.Tests.ps1
│ ├── Pester.History.Tests.ps1
│ ├── Pester.Management.Copy.Item.Tests.ps1
│ ├── StringManipulationData
│ └── ConvertString
│ │ ├── incorrect-examples.csv
│ │ └── replace-name-by-empty.csv
│ ├── SymbolicLinksGenerator.psm1
│ ├── pester.commands.cmdlets.process.tests.ps1
│ ├── pester.core.job.tests.ps1
│ ├── pester.diagnostics.counter.tests.ps1
│ ├── pester.management.computersecurechannel.tests.ps1
│ ├── pester.utility.alias.tests.ps1
│ ├── pester.utility.clixml.tests.ps1
│ ├── pester.utility.command.tests.ps1
│ ├── pester.utility.formatdata.tests.ps1
│ ├── pester.utility.object.tests.ps1
│ ├── pester.utility.string.tests.ps1
│ └── pester.utility.xml.tests.ps1
├── Contribution.md
├── LICENSE
├── README.md
├── Scripting
├── Classes
│ ├── Classes.Completion.Tests.ps1
│ ├── MSFT_778492.psm1
│ ├── ProtectedAccess.Tests.ps1
│ ├── Scripting.Classes.Attributes.Tests.ps1
│ ├── Scripting.Classes.BasicParsing.Tests.ps1
│ ├── Scripting.Classes.Break.Tests.ps1
│ ├── Scripting.Classes.Exceptions.Tests.ps1
│ ├── Scripting.Classes.Modules.Tests.ps1
│ ├── scripting.classes.NestedModules.tests.ps1
│ ├── scripting.classes.inheritance.tests.ps1
│ ├── scripting.classes.miscops.tests.ps1
│ ├── scripting.classes.using.tests.ps1
│ ├── scripting.classes.using.variants.tests.ps1
│ └── scripting.enums.tests.ps1
├── CompletionTestSupport.psm1
├── LanguageTestSupport.psm1
└── LanguageandParser
│ ├── BNotOperator.Tests.ps1
│ ├── Completion.Tests.ps1
│ ├── ExtensibleCompletion.Tests.ps1
│ ├── LanguageAndParser.TestFollowup.Tests.ps1
│ ├── MethodInvocation.Tests.ps1
│ ├── ParameterBinding.Tests.ps1
│ ├── Pester.Ast.Tests.ps1
│ ├── Pester.RedirectionOperator.Tests.ps1
│ ├── TypeAccelerator.Tests.ps1
│ ├── UsingAssembly.Tests.ps1
│ └── UsingNamespace.Tests.ps1
├── Security
├── Pester.Acl.Tests.ps1
├── Pester.Authenticode.Tests.ps1
├── Pester.SuspiciousScriptBlockLogging.Tests.ps1
└── pester.security.credential.tests.ps1
├── engine
├── EngineAPIs
│ ├── Engine.Tests.ps1
│ ├── Pester.GetPowerShellAPI.Tests.ps1
│ ├── WMI.Tests.ps1
│ └── XmlAdapter.Tests.ps1
├── ExtensibleTypeSystem
│ ├── ETS.Tests.ps1
│ ├── Pester.FileVersionInfo.Tests.ps1
│ └── Pester.PSObject.Tests.ps1
├── Other
│ └── Pester.Engine.Other.InformationStream.Tests.ps1
└── Runspace
│ └── Pester.Runspace.Tests.ps1
├── provider
└── Providers
│ ├── Pester.Get-ChildItem.Depth.Tests.ps1
│ ├── Pester.Provider.Providers.tests.ps1
│ ├── Pester.Providers.DrivePersistence.Tests.ps1
│ └── pester.management.junction.tests.ps1
└── remoting
└── Cmdlets
└── NoReboot.tests.ps1
/Commands/Cmdlets/ClearRecycleBin.Tests.ps1:
--------------------------------------------------------------------------------
1 | # This is a Pester test suite to validate the Clear-RecycleBin cmdlet in the Microsoft.PowerShell.Management module.
2 | #
3 | # Copyright (c) Microsoft Corporation, 2015
4 | #
5 | # These tests are not portable as they required functions from the ClearRecycleBinHelperFunctions.psm1 module.
6 | #
7 |
8 | $currentDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
9 | $helperModule = Join-Path $currentDirectory "ClearRecycleBinHelperFunctions.psm1"
10 | if (-not $helperModule)
11 | {
12 | throw "Helper module $helperModule is not available."
13 | }
14 | Import-Module $helperModule -Force
15 |
16 | if (-not (ShouldRun))
17 | {
18 | write-verbose "Shell.Application namespace is not available, skipping tests..."
19 | return
20 | }
21 |
22 | # The number of test files to create and send to the recycle bin.
23 | $numberOfTestFiles = 10
24 |
25 | # Setup
26 | Setup
27 |
28 | <#
29 | Purpose:
30 | Verify that Clear-RecycleBin with no parameters clears the recycle bin.
31 |
32 | Action:
33 | Run Clear-RecycleBin with no parameters.
34 |
35 | Expected Result:
36 | All contents of the recycle bin are deleted.
37 | #>
38 |
39 | Describe "ClearRecycleBinWithNoParameters" {
40 |
41 | It "Clear-RecycleBin -Force" {
42 | TestCaseSetup -numberOfFiles $numberOfTestFiles
43 | $result = @{
44 | InitialFileCount = GetRecycleBinFileCount
45 | FinalFileCount = $null
46 | }
47 | Clear-RecycleBin -Force
48 | $result.FinalFileCount = GetRecycleBinFileCount
49 |
50 | $result.InitialFileCount - $numberOfTestFiles | should be 0
51 | $result.FinalFileCount | should be 0
52 | }
53 | }
54 |
55 |
56 | <#
57 | Purpose:
58 | Verify that Clear-RecycleBin -DriveLetter parameter supports the following formats: C, C: and C:\.
59 |
60 | Action:
61 | Run Clear-RecycleBin -DriveLetter using various supported formats.
62 |
63 | Expected Result:
64 | All contents of the recycle bin for the default drive are deleted.
65 | #>
66 |
67 | $supportedFormats = @()
68 | $supportedFormats += $env:SystemDrive.Replace(":","")
69 | $supportedFormats += $env:SystemDrive
70 | $supportedFormats += ($env:SystemDrive + "\")
71 | Describe "ClearRecycleBinSupportedDriveLetterFormats" {
72 |
73 | foreach ($inputParam in $supportedFormats)
74 | {
75 | It "Clear-RecycleBin -DriveLetter $inputParam -Force" {
76 | TestCaseSetup -numberOfFiles $numberOfTestFiles
77 | $result = @{
78 | InitialFileCount = GetRecycleBinFileCount
79 | FinalFileCount = $null
80 | }
81 | Clear-RecycleBin -Force -DriveLetter $inputParam
82 | $result.FinalFileCount = GetRecycleBinFileCount
83 |
84 | $result.InitialFileCount - $numberOfTestFiles | should be 0
85 | $result.FinalFileCount | should be 0
86 | }
87 | }
88 | }
89 |
90 |
91 | <#
92 | Purpose:
93 | Verify that Clear-RecycleBin -DriveLetter throws the correct exception for $null and empty.
94 |
95 | Action:
96 | Run Clear-RecycleBin -DriveLetter using $null and empty.
97 |
98 | Expected Result:
99 | The correct exception is thrown and the FullyQualifiedErrorId is ParameterArgumentValidationError,Microsoft.PowerShell.Commands.ClearRecycleBinCommand.
100 | #>
101 |
102 | $invalidInputs = @($null, "")
103 | Describe "ClearRecycleBinHandlesNullAndEmptyInputs" {
104 |
105 | foreach ($inputParam in $invalidInputs)
106 | {
107 | It "Clear-RecycleBin -DriveLetter null or empty" {
108 | try
109 | {
110 | Clear-RecycleBin -Force -DriveLetter $inputParam -ErrorAction Stop
111 | throw "CodeExecuted"
112 | }
113 | catch
114 | {
115 | $_.FullyQualifiedErrorId | should be "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.ClearRecycleBinCommand"
116 | }
117 | }
118 | }
119 | }
120 |
121 |
122 | <#
123 | Purpose:
124 | Verify that Clear-RecycleBin -DriveLetter throws the correct exception for a drive that does not exist.
125 |
126 | Action:
127 | Run Clear-RecycleBin -DriveLetter using an unknown drive.
128 |
129 | Expected Result:
130 | The correct exception is thrown and the FullyQualifiedErrorId is DriveNotFound,Microsoft.PowerShell.Commands.ClearRecycleBinCommand.
131 | #>
132 |
133 | # Get a drive letter between F and Y that is not being used for the drive name.
134 | $driveLetter = [char[]](70..89) | Where-Object {$_ -notin (Get-PSDrive).Name} | Select-Object -Last 1
135 |
136 | Describe "ClearRecycleBinThrowsDriveNotFoundForDrivesThatDoNotExist" {
137 | It "Clear-RecycleBin -Force -DriveLetter $driveLetter -ErrorAction Stop" {
138 | try
139 | {
140 | Clear-RecycleBin -Force -DriveLetter $driveLetter -ErrorAction Stop
141 | throw "CodeExecuted"
142 | }
143 | catch
144 | {
145 | $_.FullyQualifiedErrorId | should be "DriveNotFound,Microsoft.PowerShell.Commands.ClearRecycleBinCommand"
146 | }
147 | }
148 | }
149 |
150 |
151 | <#
152 | Purpose:
153 | Verify that Clear-RecycleBin -DriveLetter throws the correct exception for a drive name in the incorrect format.
154 |
155 | Action:
156 | Run Clear-RecycleBin -DriveLetter c:\\\.
157 |
158 | Expected Result:
159 | The correct exception is thrown and the FullyQualifiedErrorId is InvalidDriveNameFormat,Microsoft.PowerShell.Commands.ClearRecycleBinCommand.
160 | #>
161 |
162 | $driveName = ($env:SystemDrive + "\\\")
163 | Describe "ClearRecycleBinThrowsInvalidDriveNameFormatForInvalidDriveNames" {
164 | It "Clear-RecycleBin -Force -DriveLetter $driveName" {
165 | try
166 | {
167 | Clear-RecycleBin -Force -DriveLetter $driveName -ErrorAction Stop
168 | throw "CodeExecuted"
169 | }
170 | catch
171 | {
172 | $_.FullyQualifiedErrorId | should be "InvalidDriveNameFormat,Microsoft.PowerShell.Commands.ClearRecycleBinCommand"
173 | }
174 | }
175 | }
176 |
177 | <#
178 | Purpose:
179 | Verify that Clear-RecycleBin works using piping.
180 |
181 | Action:
182 | Run Get-Volume for the default drive, and pipe the output to Clear-RecycleBin.
183 |
184 | Expected Result:
185 | All contents of the recycle bin for the default drive are deleted.
186 | #>
187 | $driveName = $env:SystemDrive.Replace(":","")
188 | Describe "ClearRecycleBinSupportsPiping" {
189 |
190 | It "Get-Volume -DriveLetter $driveName | Clear-RecycleBin -Force" {
191 | TestCaseSetup -numberOfFiles $numberOfTestFiles
192 | $result = @{
193 | InitialFileCount = GetRecycleBinFileCount
194 | FinalFileCount = $null
195 | }
196 | Get-Volume -DriveLetter $driveName | Clear-RecycleBin -Force
197 | $result.FinalFileCount = GetRecycleBinFileCount
198 |
199 | $result.InitialFileCount - $numberOfTestFiles | should be 0
200 | $result.FinalFileCount | should be 0
201 | }
202 | }
203 |
204 | # Clean up
205 | CleanUp
206 |
207 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/ClearRecycleBinHelperFunctions.psm1:
--------------------------------------------------------------------------------
1 | # This is a helper module for a Pester test suite to validate the Clear-RecycleBin cmdlet
2 | # in the Microsoft.PowerShell.Management module.
3 | #
4 | # Copyright (c) Microsoft Corporation, 2015
5 | #
6 |
7 | # Get the current directory, and create a folder to generate test files.
8 | $currentDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
9 |
10 | # Returns the guid for the current system drive.
11 | #
12 | function GetDriveID
13 | {
14 | $defaultDrive = $env:SystemDrive.Replace(":", "")
15 | $driveID = $null
16 | try
17 | {
18 | $defaultVolume = Get-Volume -DriveLetter $defaultDrive -ErrorAction Stop
19 | $defaultVolume = $defaultVolume.Path.Replace("\\?\Volume", "")
20 | $driveID = $defaultVolume.Replace("\", "")
21 | }
22 | catch
23 | {
24 | Write-Verbose "Failed to get system drive Id. Error: $_" -Verbose
25 | }
26 | return $driveID
27 | }
28 |
29 | # By default this function returns false.
30 | #
31 | function ShouldRun
32 | {
33 | # If the Shell API is not available, skip the test suite.
34 | try
35 | {
36 | $shell = new-object -comobject "Shell.Application"
37 | }
38 | catch
39 | {
40 | # ignore the error and return false.
41 | return $false
42 | }
43 |
44 | if ($shell -eq $null)
45 | {
46 | return $false
47 | }
48 |
49 | # Check the registry to see if the user has disable sending files to the recycle bin.
50 | $systemDriveID = GetDriveID
51 | if ($systemDriveID -ne $null)
52 | {
53 | $registrySettingsPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket\Volume\'
54 | $allDrives = @(Get-ChildItem $registrySettingsPath)
55 | if ($allDrives.Count -gt 0)
56 | {
57 | foreach ($drive in $allDrives)
58 | {
59 | if ($drive.PSChildName -match $systemDriveID)
60 | {
61 | # Save the original key value
62 | $keySettingPath = $registrySettingsPath + $drive.PSChildName
63 | $recybleBinKey = Get-ItemProperty -path $keySettingPath -Name NukeOnDelete
64 | if ($recybleBinKey.NukeOnDelete -eq 0)
65 | {
66 | return $true
67 | }
68 | }
69 | }
70 | }
71 | }
72 | return $false
73 | }
74 |
75 | function Setup
76 | {
77 | # Get the current directory, and create a folder to generate test files.
78 | $script:testFolderPath = join-path $currentDirectory "ClearRecycleBinTests"
79 | write-verbose "Test folder path: $testFolderPath"
80 | if (test-path $script:testFolderPath)
81 | {
82 | Remove-Item $script:testFolderPath -Recurse -Force -ea SilentlyContinue
83 | }
84 | New-Item $script:testFolderPath -ItemType Directory -Force|out-null
85 |
86 | # Script level variables for recycleBin manipulations.
87 | $script:shell = new-object -comobject "Shell.Application"
88 | $script:recycleBin = $script:shell.NameSpace(0xa)
89 | }
90 |
91 | function CleanUp
92 | {
93 | if (test-path $script:testFolderPath)
94 | {
95 | Remove-Item $script:testFolderPath -Recurse -Force -ea SilentlyContinue
96 | }
97 | }
98 |
99 | function TestCaseSetup
100 | {
101 | param
102 | (
103 | [int]$numberOfFiles = 10
104 | )
105 |
106 | # Script level variables for recycleBin manipulations.
107 | $script:shell = new-object -comobject "Shell.Application"
108 | $script:recycleBin = $script:shell.NameSpace(0xa)
109 |
110 | # Ensure that the recycle bin is empty.
111 | $script:recycleBin.Items() | Remove-Item -Force -Recurse -ea SilentlyContinue
112 |
113 | # Generate $numberOfFiles and send them to the RecycleBin.
114 | 1..$numberOfFiles | % {
115 | $filePath = Join-Path $script:testFolderPath ($_.ToString() + ".txt")
116 | Set-Content -Value $_ -Path $filePath
117 | $item = $script:shell.Namespace(0).ParseName("$filePath")
118 | $item.InvokeVerb("delete")
119 | }
120 |
121 | # Ensure that the RecycleBin is not empty.
122 | $results = @($script:recycleBin.Items())
123 | if (-not ($results.Count -gt 0))
124 | {
125 | throw "Failed to populate recycleBin with test files."
126 | }
127 | }
128 |
129 | function GetRecycleBinFileCount
130 | {
131 | return @($script:recycleBin.Items()).Count
132 | }
133 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/Clipboard.Tests.ps1:
--------------------------------------------------------------------------------
1 | # This is a Pester test suite to validate the Clipboard cmdlets in the Microsoft.PowerShell.Management module.
2 | #
3 | # Copyright (c) Microsoft Corporation, 2015
4 | #
5 | # These tests are not portable as they required functions from the ClipboardHelperFunctions.psm1 module.
6 | #
7 |
8 | $currentDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
9 | $helperModule = Join-Path $currentDirectory "ClipboardHelperFunctions.psm1"
10 | $script:testFolderPath = join-path $env:TEMP "ClipboardTests"
11 | $script:rdpProcessOn = $false;
12 |
13 | if (-not $helperModule)
14 | {
15 | throw "Helper module $helperModule is not available."
16 | }
17 | Import-Module $helperModule -Force
18 |
19 | if (-not (ShouldRun))
20 | {
21 | write-verbose "System.Windows.Clipborad namespace is not available, skipping tests..."
22 | return
23 | }
24 |
25 | # The number of test files to create for file copy.
26 | $numberOfTestFiles = 10
27 |
28 | # Setup
29 | Setup -numberOfFiles $numberOfTestFiles
30 |
31 | # If the test is running on the lab machine logged in from host,
32 | # the rdpclip.exe will share the clipboard content between host and lab machine. It needs to be temporary disabled.
33 |
34 | if ((Get-Process rdpclip -ErrorAction SilentlyContinue).count -ne 0)
35 | {
36 | Get-Process rdpclip | Stop-Process -force
37 | $rdpProcessOn = $true
38 | }
39 |
40 | <#
41 | Purpose:
42 | Verify that Get/Set-Clipboard works with text format.
43 |
44 | Action:
45 | Run set/Get Clipboard cmdltes with text input
46 |
47 | Expected Result:
48 | The Get-Clipboard should return what Set-Clipboard sets.
49 | #>
50 |
51 | Describe "ClipboardWorksWithTextFormats" {
52 |
53 | It "Get text content from clipboard" {
54 | $text = "Content is set to Clipboard."
55 | Set-Clipboard -Value $text
56 | Get-Clipboard | should be $text
57 | }
58 |
59 | It "Set Clipboard With Append swtich" {
60 | $text1 = "text1 set to Clipboard."
61 | $text2 = "text2 set to Clipboard."
62 | Set-Clipboard -Value $text1
63 | Set-Clipboard -Value $text2 -Append
64 | $result = New-Object -TypeName "System.Text.StringBuilder"
65 | $result.AppendLine($text1)
66 | $result.Append($text2)
67 | Get-Clipboard -Raw | should be $result.ToString()
68 | }
69 |
70 | It "Set Clipboard works with pipe line as Text." {
71 | $filePath = Join-Path $script:testFolderPath "1.txt"
72 | $content = Get-Content $filePath
73 | Get-Content $filePath | Set-Clipboard
74 | Get-Clipboard -Raw | should be $content
75 | }
76 |
77 | It "Set Clipboard works with multiple pipe line." {
78 | $content = "string1", "string2"
79 | $content | Set-Clipboard
80 | $result = Get-Clipboard
81 | $result.Count | should be 2
82 | $result[0] | should be "string1"
83 | $result[1] | should be "string2"
84 | }
85 | }
86 |
87 |
88 | <#
89 | Purpose:
90 | Verify that Get/Set-Clipboard works with file format.
91 |
92 | Action:
93 | Run set/Get Clipboard cmdltes with file format
94 |
95 | Expected Result:
96 | The Get-Clipboard should return what Set-Clipboard sets.
97 | #>
98 |
99 | Describe "ClipboardWorksWithFileFormats" {
100 |
101 | It "Get text content from clipboard contains file format" {
102 | $filePath = Join-Path $script:testFolderPath "1.txt"
103 | Set-Clipboard -Path $filePath
104 | [Windows.Clipboard]::ContainsFileDropList() | should be $true
105 | (Get-Clipboard -Format FileDropList).fullname | should be $filePath
106 | }
107 |
108 | It "Set file format to Clipboard With Append swtich" {
109 | $filePath1 = Join-Path $script:testFolderPath "1.txt"
110 | $filePath2 = Join-Path $script:testFolderPath "2.txt"
111 | Set-Clipboard -Path $filePath1
112 | Set-Clipboard -Path $filePath2 -Append
113 | [Windows.Clipboard]::ContainsFileDropList() | should be $true
114 | $result = Get-Clipboard -Format FileDropList -Raw
115 | $result.Contains($filePath1) | should be $true
116 | $result.Contains($filePath2) | should be $true
117 | }
118 |
119 | It "Set Clipboard works with file format" {
120 | $filePath = Join-Path $script:testFolderPath "1.txt"
121 | Set-Clipboard -Value "Test Value"
122 | [Windows.Clipboard]::ContainsText() | should be $true
123 | Set-Clipboard -Path $filePath
124 | [Windows.Clipboard]::ContainsFileDropList() | should be $true
125 | }
126 |
127 | It "Set Clipboard works with wild card file name" {
128 | $filePath = Join-Path $script:testFolderPath "*"
129 | Set-Clipboard -Path $filePath
130 | [Windows.Clipboard]::ContainsFileDropList() | should be $true
131 | $result = [Windows.Clipboard]::GetFileDropList()
132 | $result.Count | should be $numberOfTestFiles
133 | }
134 |
135 | It "Set Clipboard works pipeLine as file format" {
136 | Get-ChildItem $script:testFolderPath | Set-Clipboard
137 | [Windows.Clipboard]::ContainsFileDropList() | should be $true
138 | $result = [Windows.Clipboard]::GetFileDropList()
139 | $result.Count | should be $numberOfTestFiles
140 | }
141 |
142 | It "Set Clipboard won't add duplicated file names" {
143 | Get-ChildItem $script:testFolderPath | Set-Clipboard
144 | [Windows.Clipboard]::ContainsFileDropList() | should be $true
145 | $result = [Windows.Clipboard]::GetFileDropList()
146 | $result.Count | should be $numberOfTestFiles
147 | Get-ChildItem $script:testFolderPath | Set-Clipboard -Append
148 | $result = [Windows.Clipboard]::GetFileDropList()
149 | $result.Count | should be $numberOfTestFiles
150 | }
151 |
152 | It "Set Clipboard won't add non-existed file names" {
153 | $filePath = Join-Path $script:testFolderPath "invalidFile"
154 | $fullyQualifiedErrorId = "FailedToSetClipboard,Microsoft.PowerShell.Commands.SetClipboardCommand"
155 | $Error.Clear()
156 | try
157 | {
158 | Set-Clipboard -Path $filePath -ErrorAction Stop
159 | throw "Set-Clipboard doesn't throw expected exception"
160 | }
161 | catch
162 | {
163 | $_.FullyQualifiedErrorId | should be $fullyQualifiedErrorId
164 |
165 | }
166 | }
167 |
168 | It "Set Clipboard works with literal path file format" {
169 | $filePath = Join-Path $script:testFolderPath "[1].txt"
170 | Set-Content -Value "[1].txt" -Path $filePath
171 | Set-Clipboard -LiteralPath $filePath
172 | [Windows.Clipboard]::ContainsFileDropList() | should be $true
173 | $result = Get-Clipboard -Format FileDropList -Raw
174 | $result.Contains($filePath) | should be $true
175 | }
176 | }
177 |
178 |
179 | # Clean up
180 | CleanUp
181 |
182 | if ($rdpProcessOn)
183 | {
184 | Start-Process rdpclip -ErrorAction Ignore
185 | }
186 |
187 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/ClipboardHelperFunctions.psm1:
--------------------------------------------------------------------------------
1 | # This is a helper module for a Pester test suite to validate the Clipboard cmdlet
2 | # in the Microsoft.PowerShell.Management module.
3 | #
4 | # Copyright (c) Microsoft Corporation, 2015
5 | #
6 |
7 | function ShouldRun
8 | {
9 | # If the presentationCore is not available, skip the test suite.
10 | try
11 | {
12 | Add-Type -Assembly PresentationCore
13 | }
14 | catch
15 | {
16 | # ignore the error and return false.
17 | return $false
18 | }
19 |
20 | return $true
21 | }
22 |
23 | function Setup
24 | {
25 | param
26 | (
27 | [int]$numberOfFiles = 10
28 | )
29 |
30 | # Get the temp directory, and create a folder to generate test files.
31 | $script:testFolderPath = join-path $env:TEMP "ClipboardTests"
32 | write-verbose "Test folder path: $testFolderPath"
33 | if (test-path $script:testFolderPath)
34 | {
35 | Remove-Item $script:testFolderPath -Recurse -Force -ea SilentlyContinue
36 | }
37 | New-Item $script:testFolderPath -ItemType Directory -Force | out-null
38 |
39 | # Generate $numberOfFiles.
40 | 1..$numberOfFiles | % {
41 | $filePath = Join-Path $script:testFolderPath ($_.ToString() + ".txt")
42 | Set-Content -Value $_ -Path $filePath}
43 |
44 | }
45 |
46 | function CleanUp
47 | {
48 | if (test-path $script:testFolderPath)
49 | {
50 | Remove-Item $script:testFolderPath -Recurse -Force -ea SilentlyContinue
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/FormatHex.Tests.ps1:
--------------------------------------------------------------------------------
1 | # This is a Pester test suite to validate the Format-Hex cmdlet in the Microsoft.PowerShell.Utility module.
2 | #
3 | # Copyright (c) Microsoft Corporation, 2015
4 | #
5 |
6 | <#
7 | Purpose:
8 | Verify that Format-Hex display the Hexa decmial value for the input data.
9 |
10 | Action:
11 | Run Format-Fex.
12 |
13 | Expected Result:
14 | Hexa decimal equivalent of the input data is displayed.
15 | #>
16 |
17 | Describe "FormatHex" {
18 |
19 | New-Item TestDrive:\FormatHexDataDir -Type Directory -Force | Out-Null
20 | $inputFile = "TestDrive:\FormatHexDataDir\SourceFile-1.txt"
21 | $inputText = 'Hello World'
22 | Set-Content -Value $inputText -Path $inputFile
23 |
24 | # This test is to validate to pipeline support in Format-Hex cmdlet.
25 | It "ValidatePipelineSupport" {
26 |
27 | # InputObject Parameter set should get invoked and
28 | # the input data should be treated as string.
29 | $result = $inputText | Format-Hex
30 | $result | Should Not Be $null
31 | $result.GetType().Name | Should Be 'ByteCollection'
32 | $actualResult = $result.ToString()
33 | ($actualResult -match $inputText) | Should Be $true
34 | }
35 |
36 | # This test is to validate to pipeline support in Format-Hex cmdlet.
37 | It "ValidateByteArrayInputSupport" {
38 |
39 | # InputObject Parameter set should get invoked and
40 | # the input data should be treated as byte[].
41 | $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($inputText)
42 |
43 | $result = Format-Hex -InputObject $inputBytes
44 | $result | Should Not Be $null
45 | $result.GetType().Name | Should Be 'ByteCollection'
46 | $actualResult = $result.ToString()
47 | ($actualResult -match $inputText) | Should Be $true
48 | }
49 |
50 | # This test is to validate to input given through Path paramter set in Format-Hex cmdlet.
51 | It "ValidatePathParameterSet" {
52 |
53 | $result = Format-Hex -Path $inputFile
54 | $result | Should Not Be $null
55 | $result.GetType().Name | Should Be 'ByteCollection'
56 | $actualResult = $result.ToString()
57 | ($actualResult -match $inputText) | Should Be $true
58 | }
59 |
60 | # This test is to validate to Path paramter set is considered as default in Format-Hex cmdlet.
61 | It "ValidatePathAsDefaultParameterSet" {
62 |
63 | $result = Format-Hex $inputFile
64 | $result | Should Not Be $null
65 | $result.GetType().Name | Should Be 'ByteCollection'
66 | $actualResult = $result.ToString()
67 | ($actualResult -match $inputText) | Should Be $true
68 | }
69 |
70 | # This test is to validate to input given through LiteralPath paramter set in Format-Hex cmdlet.
71 | It "ValidateLiteralPathParameterSet" {
72 |
73 | $result = Format-Hex -LiteralPath $inputFile
74 | $result | Should Not Be $null
75 | $result.GetType().Name | Should Be 'ByteCollection'
76 | $actualResult = $result.ToString()
77 | ($actualResult -match $inputText) | Should Be $true
78 | }
79 |
80 | # This test is to validate to input given through pipeline. The input being piped from results of Get-hildItem
81 | It "ValidateFileInfoPipelineInput" {
82 |
83 | $result = Get-ChildItem $inputFile | Format-Hex
84 | $result | Should Not Be $null
85 | $result.GetType().Name | Should Be 'ByteCollection'
86 | $actualResult = $result.ToString()
87 | ($actualResult -match $inputText) | Should Be $true
88 | }
89 |
90 | # This test is to validate Encoding formats functionality of Format-Hex cmdlet.
91 | It "ValidateEncodingFormats" {
92 |
93 | $result = Format-Hex -InputObject $inputText -Encoding ASCII
94 | $result | Should Not Be $null
95 | $result.GetType().Name | Should Be 'ByteCollection'
96 | $actualResult = $result.ToString()
97 | ($actualResult -match $inputText) | Should Be $true
98 | }
99 |
100 | # This test is to validate the alias for Format-Hex cmdlet.
101 | It "ValidateCmdletAlias" {
102 |
103 | try
104 | {
105 | $result = Get-Command fhx -ErrorAction Stop
106 | $result | Should Not Be $null
107 | $result.CommandType | Should Not Be $null
108 | $result.CommandType.ToString() | Should Be "Alias"
109 | }
110 | catch
111 | {
112 | $_ | Should Be $null
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/MiscCmdletUpdates.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "GetDateFormatUpdates" {
2 |
3 | It "Verifies that FileDate format works" {
4 | $date = Get-Date
5 | $expectedFormat = "{0:yyyyMMdd}" -f $date
6 | $actualFormat = Get-Date -Date $date -Format FileDate
7 |
8 | $actualFormat | Should be $expectedFormat
9 | }
10 |
11 | It "Verifies that FileDateUniversal format works" {
12 | $date = (Get-Date).ToUniversalTime()
13 | $expectedFormat = "{0:yyyyMMddZ}" -f $date
14 | $actualFormat = Get-Date -Date $date -Format FileDateUniversal
15 |
16 | $actualFormat | Should be $expectedFormat
17 | }
18 |
19 | It "Verifies that FileDateTime format works" {
20 | $date = Get-Date
21 | $expectedFormat = "{0:yyyyMMddTHHmmssffff}" -f $date
22 | $actualFormat = Get-Date -Date $date -Format FileDateTime
23 |
24 | $actualFormat | Should be $expectedFormat
25 | }
26 |
27 | It "Verifies that FileDateTimeUniversal format works" {
28 | $date = (Get-Date).ToUniversalTime()
29 | $expectedFormat = "{0:yyyyMMddTHHmmssffffZ}" -f $date
30 | $actualFormat = Get-Date -Date $date -Format FileDateTimeUniversal
31 |
32 | $actualFormat | Should be $expectedFormat
33 | }
34 |
35 | }
36 |
37 | Describe "GetRandomMiscTests" {
38 | It "Shouldn't overflow when using max range" {
39 |
40 | $hadError = $false
41 |
42 | try
43 | {
44 | ## Don't actually need to validate
45 | Get-Random -Minimum ([Int32]::MinValue) -Maximum ([Int32]::MaxValue) -ErrorAction Stop
46 | }
47 | catch
48 | {
49 | $hadError = $true
50 | }
51 |
52 | $hadError | Should be $false
53 | }
54 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/NewGuid.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe -Tags "Unit" "New-Guid" {
2 |
3 | It "returns a new guid" {
4 | $guid = New-Guid
5 | $guid.GetType().FullName | Should Be "System.Guid"
6 | }
7 |
8 | It "should not be all zeros" {
9 | $guid = New-Guid
10 | $guid.ToString() | Should Not Be "00000000-0000-0000-0000-000000000000"
11 | }
12 |
13 | It "should return different guids with each call" {
14 | $guid1 = New-Guid
15 | $guid2 = New-Guid
16 | $guid1.ToString() | Should Not Be $guid2.ToString()
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/NewTemporaryFile.Tests.ps1:
--------------------------------------------------------------------------------
1 | # This is a Pester test suite to validate the New-TemporaryFile cmdlet in the Microsoft.PowerShell.Utility module.
2 | #
3 | # Copyright (c) Microsoft Corporation, 2015
4 | #
5 |
6 | <#
7 | Purpose:
8 | Verify that New-TemporaryFile creates a temporary file.
9 |
10 | Action:
11 | Run New-TemporaryFile.
12 |
13 | Expected Result:
14 | A FileInfo object for the temporary file is returned.
15 | #>
16 |
17 | Describe "NewTemporaryFile" {
18 |
19 | It "creates a new temporary file" {
20 | $tempFile = New-TemporaryFile
21 |
22 | Test-Path $tempFile | Should be $true
23 | $tempFile.GetType().Name | Should be "FileInfo"
24 |
25 | if(Test-Path $tempFile)
26 | {
27 | Remove-Item $tempFile -ErrorAction SilentlyContinue -Force
28 | }
29 | }
30 |
31 | It "with WhatIf does not create a file" {
32 | New-TemporaryFile -WhatIf | Should Be $null
33 | }
34 |
35 | It "has an OutputType of System.IO.FileInfo" {
36 | (Get-Command New-TemporaryFile).OutputType | Should Be "System.IO.FileInfo"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/Pester.Commands.Cmdlets.NoNewlineParameter.Tests.ps1:
--------------------------------------------------------------------------------
1 | # Tests related to TFS item 1370133 [PSUpgrade] Need -NoNewline parameter on Out-File, Add-Content and Set-Content
2 | # Connect request https://connect.microsoft.com/PowerShell/feedback/details/524739/need-nonewline-parameter-on-out-file-add-content-and-set-content
3 |
4 | Describe "Tests for -NoNewline parameter of Out-File, Add-Content and Set-Content" {
5 |
6 | It "NoNewline parameter works on Out-File" {
7 | $temp = New-TemporaryFile
8 | 1..5 | Out-File $temp.FullName -Encoding 'ASCII' -NoNewline
9 | (Get-Content $temp -Encoding Byte).Count | Should Be 5
10 | Remove-Item $temp -ErrorAction SilentlyContinue -Force
11 | }
12 |
13 | It "NoNewline parameter works on Set-Content" {
14 | $temp = New-TemporaryFile
15 | Set-Content -Path $temp.FullName -Value 'a','b','c' -Encoding 'ASCII' -NoNewline
16 | (Get-Content $temp -Encoding Byte).Count | Should Be 3
17 | Remove-Item $temp -ErrorAction SilentlyContinue -Force
18 | }
19 |
20 | It "NoNewline parameter works on Add-Content" {
21 | $temp = New-TemporaryFile
22 | 1..9 | %{Add-Content -Path $temp.FullName -Value $_ -Encoding 'ASCII' -NoNewline}
23 | (Get-Content $temp -Encoding Byte).Count | Should Be 9
24 | Remove-Item $temp -ErrorAction SilentlyContinue -Force
25 | }
26 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/Pester.Commands.Cmdlets.StartProcessWaitPassThru.Tests.ps1:
--------------------------------------------------------------------------------
1 | # Tests related to Bug 2817913 Start-Process -Wait sometimes doesn't wait
2 | # It seems when passing SafeHandle of the process to AssignProcessToJobObject, the handle gets corrupted sometimes.
3 | # The fix is to revert back to use raw handle (IntPtr) of the process for both FullCLR and CoreCLR.
4 |
5 | Describe "Tests for Start-Process -Wait -PassThru" -Tags "Innerloop", "BVT" {
6 |
7 | It "Process object returned from Start-Process -Wait -PassThru should have ExitCode to be 0" {
8 | $iterations = 5
9 | $errorCount = 0
10 | while ($iterations -gt 0)
11 | {
12 | $p = Start-Process cmd.exe -WindowStyle Hidden -ArgumentList "/C echo 1" -PassThru -Wait
13 | If ($p.ExitCode -eq $null -or $p.ExitCode -ne 0) {
14 | $errorCount ++
15 | }
16 | $iterations --
17 | }
18 | $errorCount | Should Be 0
19 | }
20 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/Pester.ConvertString.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path
2 | $data = Join-Path $here "StringManipulationData\ConvertString"
3 |
4 | Describe "Convert-String test cases" {
5 |
6 | It "Changes first and last name with one Example" {
7 |
8 | $result = "Gustavo Soares" | Convert-String -Example "camilla araujo=araujo, c."
9 | $result | Should be "Soares, G."
10 | }
11 |
12 | It "Changes first and last name with one Example, and three inputs" {
13 |
14 | $result = "Lee Holmes", "Gustavo Soares", "Sumit Gulwani", "Vu Le" |
15 | Convert-String -Example "camilla araujo=araujo, c."
16 |
17 | $result[0] | Should be "Holmes, L."
18 | $result[1] | Should be "Soares, G."
19 | $result[2] | Should be "Gulwani, S."
20 | $result[3] | Should be "Le, V."
21 | }
22 |
23 | It "Changes first and last name with two Examples" {
24 |
25 | $examples = [PSCustomObject] @{ Before = 'camilla araujo'; After = 'araujo, c.' },
26 | [PSCustomObject] @{ Before = 'lee holmes'; After = 'holmes, l.' }
27 | $result = "Gustavo Soares" | Convert-String -Example $examples
28 |
29 | $result | Should be "Soares, G."
30 | }
31 |
32 | It "Changes first and last name with one dictionary example" {
33 | $result = "Gustavo Soares" | Convert-String -Example @{ Before = "camilla araujo"; After = "araujo, c." }
34 | }
35 |
36 | It "Changes first and last name with two dictionary example" {
37 | $result = "Gustavo Soares" | Convert-String -Example @(@{ Before = "camilla araujo"; After = "araujo, c." },@{ Before = "vu le"; After = "le, v." })
38 | }
39 |
40 | It "Check invalid text example" {
41 | { "Gustavo Soares" | Convert-String -Example "camilla araujo" } | Should Throw
42 | }
43 |
44 | It "Check invalid psobject examples" {
45 | $examples = Import-Csv $data\incorrect-examples.csv
46 | { "Gustavo Soares" | Convert-String -Example $examples } | Should Throw
47 | }
48 |
49 | It "Replace by empty" {
50 | $examples = Import-Csv $data\replace-name-by-empty.csv
51 | $result = "Gustavo Soares" | Convert-String -Example $examples
52 | $result.length -eq 0 | Should be true
53 | }
54 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/Pester.DelimitedText.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "DelimitedText" {
2 |
3 | It "verifies automatic property generation" {
4 |
5 | $result = "Hello 9", "Hello 10", "Hello 90" | ConvertFrom-String
6 |
7 | ## Verify first properties got extracted
8 | $result[0].P1 | Should be 'Hello'
9 | $result[1].P1 | Should be 'Hello'
10 | $result[2].P1 | Should be 'Hello'
11 |
12 | ## Verify second properties got extracted
13 | $result[0].P2 | Should be 9
14 | $result[1].P2 | Should be 10
15 | $result[2].P2 | Should be 90
16 | }
17 |
18 | It "verifies property overflow generation" {
19 |
20 | $result = "Hello 9" | ConvertFrom-String -PropertyNames A
21 |
22 | $result.A | Should be 'Hello'
23 | $result.P2 | Should be 9
24 | }
25 |
26 | It "verifies property renaming" {
27 |
28 | $result = "Hello 9" | ConvertFrom-String -PN B,C
29 |
30 | $result.B | Should be 'Hello'
31 | $result.C | Should be '9'
32 | }
33 |
34 | It "verifies property typing of numbers" {
35 |
36 | $result = "Hello 9" | ConvertFrom-String -Property B,C
37 | $result.C.GetType().FullName | Should be 'System.Byte'
38 | }
39 |
40 | It "verifies property typing of TimeSpan" {
41 |
42 | $result = "Hello 1:00" | ConvertFrom-String -Property B,C
43 | $result.C.GetType().FullName | Should be 'System.TimeSpan'
44 | }
45 |
46 | It "verifies property typing of DateTime" {
47 |
48 | $result = "Hello 1/1/2012" | ConvertFrom-String -Property B,C
49 | $result.C.GetType().FullName | Should be 'System.DateTime'
50 | }
51 |
52 | It "verifies property typing of Char" {
53 |
54 | $result = "Hello A" | ConvertFrom-String -Property B,C
55 | $result.C.GetType().FullName | Should be 'System.Char'
56 | }
57 |
58 | It "verifies empty strings don't turn into INTs" {
59 |
60 | $result = "Hello" | ConvertFrom-String -Delimiter 'l'
61 | $result.P2.GetType().FullName | Should be 'System.String'
62 | }
63 |
64 | It "verifies property typing of String" {
65 |
66 | $result = "Hello World" | ConvertFrom-String -Property B,C
67 | $result.C.GetType().FullName | Should be 'System.String'
68 | }
69 |
70 | It "verifies the ability to change the delimiter" {
71 |
72 | $result = "Hello-World" | ConvertFrom-String -Delimiter '-'
73 | $result.P1 | Should be 'Hello'
74 | $result.P2 | Should be 'World'
75 | }
76 |
77 | It "verifies that only matching text gets parsed" {
78 |
79 | $result = "Foo1","Hello1 World1","Hello-World" | ConvertFrom-String -Delimiter '-'
80 | $result.P1 | Should be 'Hello'
81 | $result.P2 | Should be 'World'
82 | @($result).Count | Should be 1
83 | }
84 |
85 | It "verifies that a good error message is returned from an invalid regular expression" {
86 |
87 | try
88 | {
89 | $result = "Hello World" | ConvertFrom-String -Delimiter '['
90 | }
91 | catch
92 | {
93 | $errorRecord = $_
94 | }
95 |
96 | $errorRecord.FullyQualifiedErrorId | Should be "InvalidRegularExpression,Microsoft.PowerShell.Commands.StringManipulation.ConvertFromStringCommand"
97 | }
98 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/Pester.History.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "History cmdlet test cases" {
2 |
3 | It "Tests Invoke-History on a cmdlet that generates output on all streams" {
4 | $streamSpammer = '
5 | function StreamSpammer
6 | {
7 | [CmdletBinding()]
8 | param()
9 |
10 | Write-Debug "Debug"
11 | Write-Error "Error"
12 | Write-Information "Information"
13 | Write-Progress "Progress"
14 | Write-Verbose "Verbose"
15 | Write-Warning "Warning"
16 | "Output"
17 | }
18 |
19 | $informationPreference = "Continue"
20 | $debugPreference = "Continue"
21 | $verbosePreference = "Continue"
22 | '
23 |
24 | $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings
25 | $invocationSettings.AddToHistory = $true
26 | $ps = [PowerShell]::Create()
27 | $null = $ps.AddScript($streamSpammer).Invoke()
28 | $ps.Commands.Clear()
29 | $null = $ps.AddScript("StreamSpammer");
30 | $null = $ps.Invoke($null, $invocationSettings)
31 | $ps.Commands.Clear()
32 | $null = $ps.AddScript("Invoke-History -id 1")
33 | $result = $ps.Invoke($null, $invocationSettings)
34 | $outputCount = $(
35 | $ps.Streams.Error;
36 | $ps.Streams.Progress;
37 | $ps.Streams.Verbose;
38 | $ps.Streams.Debug;
39 | $ps.Streams.Warning;
40 | $ps.Streams.Information).Count
41 | $ps.Dispose()
42 |
43 | ## Twice per stream - once for the original invocatgion, and once for the re-invocation
44 | $outputCount | Should be 12
45 | }
46 |
47 | It "Tests Invoke-History on a private command" {
48 |
49 | $invocationSettings = New-Object System.Management.Automation.PSInvocationSettings
50 | $invocationSettings.AddToHistory = $true
51 | $ps = [PowerShell]::Create()
52 | $null = $ps.AddScript("(Get-Command Get-Process).Visibility = 'Private'").Invoke()
53 | $ps.Commands.Clear()
54 | $null = $ps.AddScript("Get-Process -id $pid")
55 | $null = $ps.Invoke($null, $invocationSettings)
56 | $ps.Commands.Clear()
57 | $null = $ps.AddScript("Invoke-History -id 1")
58 | $result = $ps.Invoke($null, $invocationSettings)
59 | $errorResult = $ps.Streams.Error[0].FullyQualifiedErrorId
60 | $ps.Dispose()
61 |
62 | $errorResult | Should be CommandNotFoundException
63 | }
64 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/StringManipulationData/ConvertString/incorrect-examples.csv:
--------------------------------------------------------------------------------
1 | "before"
2 | "Camilla Araujo"
3 | "Yohanna Klafke"
4 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/StringManipulationData/ConvertString/replace-name-by-empty.csv:
--------------------------------------------------------------------------------
1 | "before","after"
2 | "Camilla Araujo",""
3 | "Yohanna Klafke",""
4 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/SymbolicLinksGenerator.psm1:
--------------------------------------------------------------------------------
1 | ParameterGenerator -name SymbolicLinkParameterValidationGenerator -definition {
2 |
3 | $returnObject = @()
4 |
5 | $targetValues = @("", $null, "$global:targetfile", "C:\NonExistentFile.txt", "HKLM:\Software")
6 | $pathValues = @("", $null, $(Join-Path $global:testDestinationRoot "ValidDestination.txt"), "Env:\APPDATA")
7 | $itemTypes = @("SymbolicLink", "Junction", "HardLink")
8 |
9 | foreach($target in $targetValues)
10 | {
11 | foreach($path in $pathValues)
12 | {
13 | foreach($type in $itemTypes)
14 | {
15 | if($path -eq $null)
16 | {
17 | $returnObject += New-Object PSObject -Property @{ Path = $path ;
18 | Target = $target;
19 | ItemType = $type;
20 | ExpectedError = "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.NewItemCommand" }
21 | }
22 | elseif(($path -eq ""))
23 | {
24 | $returnObject += New-Object PSObject -Property @{ Path = $path ;
25 | Target = $target;
26 | ItemType = $type;
27 | ExpectedError = "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.NewItemCommand" }
28 | }
29 | elseif($target -eq $null)
30 | {
31 | $returnObject += New-Object PSObject -Property @{ Path = $path ;
32 | Target = $target;
33 | ItemType = $type;
34 | ExpectedError = "ArgumentNull,Microsoft.PowerShell.Commands.NewItemCommand" }
35 | }
36 | elseif(($target -eq ""))
37 | {
38 | $returnObject += New-Object PSObject -Property @{ Path = $path ;
39 | Target = $target;
40 | ItemType = $type;
41 | ExpectedError = "ArgumentNull,Microsoft.PowerShell.Commands.NewItemCommand" }
42 | }
43 | elseif(($path -eq "C:\NonExistentFile.txt") -and ($Target -eq $(Join-Path $global:testDestinationRoot "ValidDestination.txt")))
44 | {
45 | $returnObject += New-Object PSObject -Property @{ Path = $path ;
46 | Target = $target;
47 | ItemType = $type;
48 | ExpectedError = "System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.NewItemCommand" }
49 | }
50 | elseif($target -eq "HKLM:\Software")
51 | {
52 | $returnObject += New-Object PSObject -Property @{ Path = $path ;
53 | Target = $target;
54 | ItemType = $type;
55 | ExpectedError = "NotSupported,Microsoft.PowerShell.Commands.NewItemCommand" }
56 | }
57 | }
58 | }
59 | }
60 |
61 | $returnObject
62 | }
63 |
64 | ParameterGenerator -name SymbolicLinkValidParametersGenerator -definition {
65 |
66 | $returnObject = @()
67 |
68 | $destinationDirectory = join-path $global:testDestinationRoot "SymbolicDirectory"
69 | $destinationFile = join-path $global:testDestinationRoot "SymbolicFile.txt"
70 |
71 | $otherDrive = Get-OtherFileSystemDrive -path $global:targetfile
72 | $otherDriveDestination = Join-path $otherDrive "symbolicLink.txt"
73 | $returnObject += New-Object PSObject -Property @{ Target = $global:targetfile ; Path = $otherDriveDestination }
74 |
75 |
76 | $shareRoot = Get-ShareRoot
77 | $shareDestination = Join-Path $shareRoot "shareSymbolicLink.txt"
78 | $shareSource = Join-Path $shareRoot "targetfile.txt"
79 | $returnObject += New-Object PSObject -Property @{ Target = $global:targetfile ; Path = $shareDestination }
80 | $returnObject += New-Object PSObject -Property @{ Target = $shareSource ; Path = $shareDestination }
81 | $returnObject += New-Object PSObject -Property @{ Target = $shareSource ; Path = $destinationFile }
82 |
83 | ##On non English machine this will contain non-english characters.
84 | #$nonEnglishDestination = Join-Path $env:APPDATA "TODO"
85 | #$returnObject += New-Object PSObject -Property @{ Path = $shareSource ; LinkDestination = $nonEnglishDestination }
86 |
87 | $returnObject
88 | }
89 |
90 | function Get-OtherFileSystemDrive($path)
91 | {
92 | $currentDrive = [system.io.path]::GetPathRoot($path)
93 | $drives = Get-PSDrive -PSProvider FileSystem
94 |
95 | $selectedOtherDrive = $null
96 |
97 | $drives | %{ if( ($_.Root -ne $currentDrive) -and ($_.Used -gt 0)) { $selectedOtherDrive = $_.Root ; return $selectedOtherDrive} }
98 | }
99 |
100 | function Get-ShareRoot
101 | {
102 | $exists = Get-SmbShare -Name "LoopBackShare" -ErrorAction SilentlyContinue
103 |
104 | if(-not $exists)
105 | {
106 | "\\$env:COMPUTERNAME" + "\" + (New-SmbShare -Path $global:testDestinationRoot -Name "LoopBackShare" -FullAccess "$env:USERDNSDOMAIN\$env:USERNAME").Name
107 | }
108 | else
109 | {
110 | "\\$env:COMPUTERNAME\LoopBackShare"
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.commands.cmdlets.process.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Process cmdlets" {
2 |
3 | Context "Start Process" {
4 | BeforeAll {
5 | $username = "StartProcessTest"
6 | $password = "pass@word1"
7 | $computerName = $env:COMPUTERNAME
8 |
9 | ## Setup test user
10 | Start-Process -FilePath net.exe -ArgumentList ("user $username $password /add") -NoNewWindow -Wait
11 |
12 | ## Create credential for the user.
13 | $secureString = $password | ConvertTo-SecureString -AsPlainText -Force
14 | $credential = New-Object System.Management.Automation.PSCredential $username, $secureString
15 | }
16 |
17 | ## Test starts a command on powershell launched with a credential. Followup of bug Win8:545033
18 |
19 | It "can start process with credentials" {
20 |
21 | $output = "$env:temp\output.txt"
22 | ## Start a process with credential
23 | Start-Process powershell.exe -Credential $credential -ArgumentList ("-command whoami") -NoNewWindow -Wait -WorkingDirectory $env:SystemDrive -RedirectStandardOutput $output -LoadUserProfile
24 |
25 | ## Read the output of whoami
26 | $result = Get-Content $output
27 | $result | Should Be "$computerName\$username"
28 | }
29 |
30 | AfterAll {
31 | ## Remove test user
32 | Start-Process -FilePath net.exe -ArgumentList ("user $username /delete") -NoNewWindow -Wait
33 | Remove-Item $output -Force -ErrorAction SilentlyContinue
34 |
35 | $query = "select * from Win32_UserProfile where LocalPath LIKE '%$username%'"
36 | $userProfile = Get-CimInstance -Query $query
37 |
38 | if($userProfile)
39 | {
40 | ## Remove localpath
41 | Remove-Item -Recurse -Path ($userProfile.LocalPath) -ErrorAction SilentlyContinue -Force
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.core.job.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Job cmdlets" -Tags 'innerloop' {
2 | Context "Start-Job" {
3 | It "should be able to load by definitionName and type" {
4 | $jobname = "StartJobShouldBeAbleLoadByDefinitionNameAndType"
5 | try
6 | {
7 | $scheduledjob = Get-ScheduledJob -Name $jobname -ErrorAction SilentlyContinue
8 |
9 | if (!$scheduledjob)
10 | {
11 | $scheduledjob = Register-ScheduledJob -Name $jobname -ScriptBlock {echo $args[0]} -ArgumentList ($jobname)
12 | }
13 |
14 | $job = Start-Job -DefinitionName $jobname -Type "*ScheduledJob*"
15 | $actual = $job | Wait-Job | Receive-Job
16 | $actual | Should Be $jobname
17 | }
18 | finally
19 | {
20 | Remove-Job -Name $jobname -Force -ErrorAction SilentlyContinue
21 | Unregister-ScheduledJob -Name $jobname -Force -ErrorAction SilentlyContinue
22 | }
23 | }
24 |
25 | It "no recurse should not return result from child jobs" {
26 | $message = "StartJobNoRecurseShouldNotReturnTheResultsFromAnyChildJobs"
27 | try
28 | {
29 | $job = Start-Job {echo $args[0]} -ArgumentList ($message)
30 | $result = $job | Wait-Job | Receive-Job -NoRecurse
31 | $result | Should BeNullOrEmpty
32 |
33 | $result = $job.ChildJobs | Receive-Job
34 | $result | Should Be $message
35 | }
36 | finally
37 | {
38 | $job | Remove-Job -Force
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.diagnostics.counter.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Get-Counter" -Tags "innerloop" {
2 | It "should run for 5 iterations in continuous mode" {
3 | $result = [Powershell]::Create().AddScript('$a = 0; get-counter -Continuous | %{ $a++; if ($a -eq 5) {$a; break}}').Invoke()
4 | $result | Should Be 5
5 | }
6 |
7 | It "returns expected max count" {
8 | (get-counter -MaxSamples 5).Count | Should Be 5
9 | }
10 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.management.computersecurechannel.tests.ps1:
--------------------------------------------------------------------------------
1 | function ShouldRun($testCaseName)
2 | {
3 | # test-computersecurechannel only works if the test machine is on a domain
4 | if($env:PROCESSOR_ARCHITECTURE -eq "ARM")
5 | {
6 | return $false
7 | }
8 | return $true
9 | }
10 |
11 | if(ShouldRun)
12 | {
13 | Describe "Test-ComputerSecureChannel" -Tags "innerloop" {
14 |
15 | BeforeAll {
16 | $localHostNames = @(
17 | "localHost",
18 | ".",
19 | "::1",
20 | "127.0.0.1",
21 | $env:COMPUTERNAME,
22 | ($env:COMPUTERNAME + '.' + [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties().DomainName)
23 | )
24 | }
25 |
26 | It "works with localhost" {
27 | $localHostNames | % { Test-ComputerSecureChannel -Server $_ | Should Be $true }
28 | }
29 |
30 | It -pending "works with repair" {
31 | Test-ComputerSecureChannel -Repair | Should Be $true
32 | }
33 |
34 | It "throws error with invalid server name" {
35 | try
36 | {
37 | Test-ComputerSecureChannel -Server TestComputerSecureChannelFailsWithInvalidServerName
38 | }
39 | catch
40 | {
41 | $secureChannelError = $_
42 | }
43 |
44 | $secureChannelError.FullyQualifiedErrorId | Should Be 'AddressResolutionException,Microsoft.PowerShell.Commands.TestComputerSecureChannelCommand'
45 | }
46 |
47 | It "throws error with null credential" {
48 | try
49 | {
50 | Test-ComputerSecureChannel -Credential
51 | }
52 | catch
53 | {
54 | $secureChannelError = $_
55 | }
56 |
57 | $secureChannelError.FullyQualifiedErrorId | Should Be 'MissingArgument,Microsoft.PowerShell.Commands.TestComputerSecureChannelCommand'
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.utility.alias.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Alias tests" -Tags "innerloop" {
2 |
3 | BeforeAll {
4 | $testPath = Join-Path testdrive:\ ("testAlias\[.test")
5 | New-Item -ItemType Directory -Path $testPath -Force | Out-Null
6 |
7 | class TestData
8 | {
9 | [string] $testName
10 | [string] $testFile
11 | [string] $expectedError
12 |
13 | TestData($name, $file, $error)
14 | {
15 | $this.testName = $name
16 | $this.testFile = $file
17 | $this.expectedError = $error
18 | }
19 | }
20 | }
21 |
22 | Context "Export-Alias literal path" {
23 | BeforeAll {
24 | $csvFile = Join-Path $testPath "alias.csv"
25 | $ps1File = Join-Path $testPath "alias.ps1"
26 |
27 | $testCases = @()
28 | $testCases += [TestData]::new("CSV", $csvFile, [NullString]::Value)
29 | $testCases += [TestData]::new("PS1", $ps1File, [NullString]::Value)
30 | $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand")
31 | $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportAliasCommand")
32 | $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportAliasCommand")
33 | }
34 |
35 | $testCases | % {
36 |
37 | It "for $($_.testName)" {
38 |
39 | $test = $_
40 | try
41 | {
42 | Export-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue
43 | }
44 | catch
45 | {
46 | $exportAliasError = $_
47 | }
48 |
49 | if($test.expectedError -eq $null)
50 | {
51 | Test-Path -LiteralPath $test.testFile | Should Be $true
52 | }
53 | else
54 | {
55 | $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError
56 | }
57 | }
58 |
59 | AfterEach {
60 | Remove-Item -LiteralPath $test.testFile -Force -ErrorAction SilentlyContinue
61 | }
62 | }
63 |
64 | It "when file exists with NoClobber" {
65 | Export-Alias -LiteralPath $csvFile
66 |
67 | try
68 | {
69 | Export-Alias -LiteralPath $csvFile -NoClobber
70 | }
71 | catch
72 | {
73 | $exportAliasError = $_
74 | }
75 |
76 | $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand"
77 | }
78 | }
79 |
80 | Context "Export-All inside a literal path" {
81 | BeforeEach {
82 | Push-Location -LiteralPath $testPath
83 | }
84 |
85 | It "with a CSV file" {
86 | Export-Alias "alias.csv"
87 | Test-Path -LiteralPath (Join-Path $testPath "alias.csv") | Should Be $true
88 | }
89 |
90 | It "with NoClobber" {
91 | $path = Export-Alias alias.csv
92 |
93 | try
94 | {
95 | Export-Alias alias.csv -NoClobber
96 | }
97 | catch
98 | {
99 | $exportAliasError = $_
100 | }
101 |
102 | $exportAliasError.FullyQualifiedErrorId | Should Be "NoClobber,Microsoft.PowerShell.Commands.ExportAliasCommand"
103 | }
104 |
105 | AfterEach {
106 | Pop-Location
107 | }
108 | }
109 |
110 | Context "Import-Alias literal path" {
111 |
112 | BeforeAll {
113 | $csvFile = Join-Path $testPath "alias.csv"
114 | $ps1File = Join-Path $testPath "alias.ps1"
115 |
116 | $testCases = @()
117 | $testCases += [TestData]::new("Empty string", "", "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand")
118 | $testCases += [TestData]::new("Null", [NullString]::Value, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportAliasCommand")
119 | $testCases += [TestData]::new("Non filesystem provider", 'cert:\alias.ps1', "NotSupported,Microsoft.PowerShell.Commands.ImportAliasCommand")
120 | }
121 |
122 | $testCases | % {
123 |
124 | It "for $($_.testName)" {
125 | $test = $_
126 |
127 | try
128 | {
129 | Import-Alias -LiteralPath $test.testFile -ErrorAction SilentlyContinue
130 | }
131 | catch
132 | {
133 | $exportAliasError = $_
134 | }
135 |
136 | $exportAliasError.FullyqualifiedErrorId | Should Be $test.expectedError
137 | }
138 | }
139 |
140 | It "can be done from a CSV file" {
141 |
142 | # alias file definition content
143 | $aliasDefinition = @'
144 | "myuh","update-help","","ReadOnly, AllScope"
145 | '@
146 |
147 | $aliasFile = Join-Path $testPath "alias.csv"
148 | $aliasDefinition | Out-File -LiteralPath $aliasFile
149 |
150 | Import-Alias -LiteralPath $aliasFile
151 |
152 | # Verify that the alias was imported
153 | $definedAlias = Get-Alias myuh
154 |
155 | $definedAlias | Should Not Be $null
156 | $definedAlias.Name | Should Be "myuh"
157 | $definedAlias.Definition | Should Be "update-help"
158 | }
159 | }
160 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.utility.clixml.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "CliXml test" -Tags "innerloop" {
2 |
3 | BeforeAll {
4 | $testFilePath = Join-Path "testdrive:\" "testCliXml"
5 | $subFilePath = Join-Path $testFilePath ".test"
6 |
7 | if(test-path $testFilePath)
8 | {
9 | Remove-Item $testFilePath -Force -Recurse
10 | }
11 |
12 | # Create the test File and push the location into specified path
13 | New-Item -Path $testFilePath -ItemType Directory | Out-Null
14 | New-Item -Path $subFilePath -ItemType Directory | Out-Null
15 | Push-Location $testFilePath
16 |
17 | class TestData
18 | {
19 | [string] $testName
20 | [object] $inputObject
21 | [string] $expectedError
22 | [string] $testFile
23 |
24 | TestData($name, $file, $inputObj, $error)
25 | {
26 | $this.testName = $name
27 | $this.inputObject = $inputObj
28 | $this.expectedError = $error
29 | $this.testFile = $file
30 | }
31 | }
32 | }
33 |
34 | AfterAll {
35 | Pop-Location
36 | }
37 |
38 | Context "Export-CliXml" {
39 | BeforeAll {
40 | $gpsList = Get-Process powershell
41 | $gps = $gpsList | Select-Object -First 1
42 | $filePath = Join-Path $subFilePath 'gps.xml'
43 |
44 | $testData = @()
45 | $testData += [TestData]::new("with path as Null", [NullString]::Value, $gps, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand")
46 | $testData += [TestData]::new("with path as Empty string", "", $gps, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ExportClixmlCommand")
47 | $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $gps, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ExportClixmlCommand")
48 | }
49 |
50 | AfterEach {
51 | Remove-Item $filePath -Force -ErrorAction SilentlyContinue
52 | }
53 |
54 | $testData | % {
55 |
56 | It "$($_.testName)" {
57 | $test = $_
58 |
59 | try
60 | {
61 | Export-Clixml -LiteralPath $test.testFile -InputObject $test.inputObject -Force
62 | }
63 | catch
64 | {
65 | $exportCliXmlError = $_
66 | }
67 |
68 | $exportCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError
69 | }
70 | }
71 |
72 | It "can be created with literal path" {
73 |
74 | $filePath = Join-Path $subFilePath 'gps.xml'
75 | Export-Clixml -LiteralPath $filePath -InputObject ($gpsList | Select-Object -First 1)
76 |
77 | $filePath | Should Exist
78 |
79 | $fileContent = Get-Content $filePath
80 | $isExisted = $false
81 |
82 | foreach($item in $fileContent)
83 | {
84 | foreach($gpsItem in $gpsList)
85 | {
86 | $checkId = $gpsItem.Id
87 | if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id")))
88 | {
89 | $isExisted = $true
90 | break;
91 | }
92 | }
93 | }
94 |
95 | $isExisted | Should Be $true
96 | }
97 |
98 | It "can be created with literal path using pipeline" {
99 |
100 |
101 | $filePath = Join-Path $subFilePath 'gps.xml'
102 | ($gpsList | Select-Object -First 1) | Export-Clixml -LiteralPath $filePath
103 |
104 | $filePath | Should Exist
105 |
106 | $fileContent = Get-Content $filePath
107 | $isExisted = $false
108 |
109 | foreach($item in $fileContent)
110 | {
111 | foreach($gpsItem in $gpsList)
112 | {
113 | $checkId = $gpsItem.Id
114 | if (($null -ne $(Select-String -InputObject $item -SimpleMatch $checkId)) -and ($null -ne $(Select-String -InputObject $item -SimpleMatch "Id")))
115 | {
116 | $isExisted = $true
117 | break;
118 | }
119 | }
120 | }
121 |
122 | $isExisted | Should Be $true
123 | }
124 | }
125 |
126 | Context "Import-CliXML" {
127 | BeforeAll {
128 | $gpsList = Get-Process powershell
129 | $gps = $gpsList | Select-Object -First 1
130 | $filePath = Join-Path $subFilePath 'gps.xml'
131 |
132 | $testData = @()
133 | $testData += [TestData]::new("with path as Null", [NullString]::Value, $null, "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand")
134 | $testData += [TestData]::new("with path as Empty string", "", $null, "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ImportClixmlCommand")
135 | $testData += [TestData]::new("with path as non filesystem provider", "cert:\", $null, "ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ImportClixmlCommand")
136 | }
137 |
138 | $testData | % {
139 |
140 | It "$($_.testName)" {
141 | $test = $_
142 |
143 | try
144 | {
145 | Import-Clixml -LiteralPath $test.testFile
146 | }
147 | catch
148 | {
149 | $importCliXmlError = $_
150 | }
151 |
152 | $importCliXmlError.FullyQualifiedErrorId | Should Be $test.expectedError
153 | }
154 | }
155 |
156 | It "can import from a literal path" {
157 | Export-Clixml -LiteralPath $filePath -InputObject $gps
158 | $filePath | Should Exist
159 |
160 | $fileContent = Get-Content $filePath
161 | $fileContent | Should Not Be $null
162 |
163 | $importedProcess = Import-Clixml $filePath
164 | $gps.ProcessName | Should Be $importedProcess.ProcessName
165 | $gps.Id | Should Be $importedProcess.Id
166 | }
167 |
168 | It "can import from a literal path using pipeline" {
169 | $gps | Export-Clixml -LiteralPath $filePath
170 | $filePath | Should Exist
171 |
172 | $fileContent = Get-Content $filePath
173 | $fileContent | Should Not Be $null
174 |
175 | $importedProcess = Import-Clixml $filePath
176 | $gps.ProcessName | Should Be $importedProcess.ProcessName
177 | $gps.Id | Should Be $importedProcess.Id
178 | }
179 | }
180 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.utility.command.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Trace-Command" {
2 |
3 | Context "Listner options" {
4 | BeforeAll {
5 | $logFile = New-Item "TestDrive:\traceCommandLog.txt" -Force
6 | $actualLogFile = New-Item "TestDrive:\actualTraceCommandLog.txt" -Force
7 | }
8 |
9 | AfterEach {
10 | Remove-Item "TestDrive:\traceCommandLog.txt" -Force -ErrorAction SilentlyContinue
11 | Remove-Item "TestDrive:\actualTraceCommandLog.txt" -Force -ErrorAction SilentlyContinue
12 | }
13 |
14 | It "LogicalOperationStack works" {
15 | $keyword = "Trace_Command_ListenerOption_LogicalOperationStack_Foo"
16 | $stack = [System.Diagnostics.Trace]::CorrelationManager.LogicalOperationStack
17 | $stack.Push($keyword)
18 |
19 | Trace-Command -Name * -Expression {echo Foo} -ListenerOption LogicalOperationStack -FilePath $logfile
20 |
21 | $log = Get-Content $logfile | Where-Object {$_ -like "*LogicalOperationStack=$keyword*"}
22 | $log.Count | Should BeGreaterThan 0
23 | }
24 |
25 | It "Callstack works" {
26 | Trace-Command -Name * -Expression {echo Foo} -ListenerOption Callstack -FilePath $logfile
27 | $log = Get-Content $logfile | Where-Object {$_ -like "*Callstack= * System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)*"}
28 | $log.Count | Should BeGreaterThan 0
29 | }
30 |
31 | It "Datetime works" {
32 | $expectedDate = Trace-Command -Name * -Expression {Get-Date} -ListenerOption DateTime -FilePath $logfile
33 | $log = Get-Content $logfile | Where-Object {$_ -like "*DateTime=*"}
34 | $results = $log | ForEach-Object {[DateTime]::Parse($_.Split("=")[1])}
35 |
36 | ## allow a gap of 6 seconds. All traces should be finished within 6 seconds.
37 | $allowedGap = [timespan](60 * 1000 * 1000)
38 | $results | ForEach-Object {
39 | $actualGap = $_ - $expectedDate;
40 | if ($expectedDate -gt $_)
41 | {
42 | $actualGap = $expectedDate - $_;
43 | }
44 |
45 | $allowedGap | Should BeGreaterThan $actualGap
46 | }
47 | }
48 |
49 | It "None options has no effect" {
50 | Trace-Command -Name * -Expression {echo Foo} -ListenerOption None -FilePath $actualLogfile
51 | Trace-Command -name * -Expression {echo Foo} -FilePath $logfile
52 |
53 | Compare-Object (Get-Content $actualLogfile) (Get-Content $logfile) | Should BeNullOrEmpty
54 | }
55 |
56 | It "ThreadID works" {
57 | Trace-Command -Name * -Expression {echo Foo} -ListenerOption ThreadId -FilePath $logfile
58 | $log = Get-Content $logfile | Where-Object {$_ -like "*ThreadID=*"}
59 | $results = $log | ForEach-Object {$_.Split("=")[1]}
60 |
61 | $results | % { $_ | Should Be ([threading.thread]::CurrentThread.ManagedThreadId) }
62 | }
63 |
64 | It "Timestamp creates logs in ascending order" {
65 | Trace-Command -Name * -Expression {echo Foo} -ListenerOption Timestamp -FilePath $logfile
66 | $log = Get-Content $logfile | Where-Object {$_ -like "*Timestamp=*"}
67 | $results = $log | ForEach-Object {$_.Split("=")[1]}
68 | $sortedResults = $results | Sort-Object
69 | $sortedResults | Should Be $results
70 | }
71 |
72 | It "ProcessId logs current process Id" {
73 | Trace-Command -Name * -Expression {echo Foo} -ListenerOption ProcessId -FilePath $logfile
74 | $log = Get-Content $logfile | Where-Object {$_ -like "*ProcessID=*"}
75 | $results = $log | ForEach-Object {$_.Split("=")[1]}
76 |
77 | $results | ForEach-Object { $_ | Should Be $pid }
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.utility.formatdata.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "FormatData" {
2 |
3 | Context "Export" {
4 | It "can export all types" {
5 | try
6 | {
7 | $expectAllFormat = Get-FormatData -typename *
8 | $expectAllFormat | Export-FormatData -path $env:temp\allformat.ps1xml -IncludeScriptBlock
9 |
10 | $sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
11 | $sessionState.Formats.Clear()
12 | $sessionState.Types.Clear()
13 |
14 | $runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($sessionState)
15 | $runspace.Open()
16 |
17 | $runspace.CreatePipeline("Update-FormatData -AppendPath $env:temp\allformat.ps1xml").Invoke()
18 | $actualAllFormat = $runspace.CreatePipeline("Get-FormatData -TypeName *").Invoke()
19 |
20 | $expectAllFormat.Count | Should Be $actualAllFormat.Count
21 | Compare-Object $expectAllFormat $actualAllFormat | Should Be $null
22 | $runspace.Close()
23 | }
24 | finally
25 | {
26 | Remove-Item -Path $env:temp\allformat.ps1xml -Force -ErrorAction SilentlyContinue
27 | }
28 | }
29 |
30 | It "works with literal path" {
31 | $filename = 'TestDrive:\[formats.ps1xml'
32 | Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename
33 | (Test-Path -LiteralPath $filename) | Should Be $true
34 | }
35 |
36 | It "should overwrite the destination file" {
37 | $filename = 'TestDrive:\ExportFormatDataWithForce.ps1xml'
38 | $unexpected = "SHOULD BE OVERWRITTEN"
39 | $unexpected | Out-File -FilePath $filename -Force
40 | $file = Get-Item $filename
41 | $file.IsReadOnly = $true
42 | Get-FormatData -TypeName * | Export-FormatData -Path $filename -Force
43 |
44 | $actual = @(Get-Content $filename)[0]
45 | $actual | Should Not Be $unexpected
46 | }
47 |
48 | It "should not overwrite the destination file with NoClobber" {
49 | $filename = "TestDrive:\ExportFormatDataWithNoClobber.ps1xml"
50 | Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename
51 |
52 | try
53 | {
54 | Get-FormatData -TypeName * | Export-FormatData -LiteralPath $filename -NoClobber
55 | }
56 | catch
57 | {
58 | $exportFormatError = $_
59 | }
60 |
61 | $exportFormatError.FullyQualifiedErrorId | Should Be 'NoClobber,Microsoft.PowerShell.Commands.ExportFormatDataCommand'
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.utility.object.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Object cmdlets" -Tags 'innerloop' {
2 | Context "Group-Object" {
3 | It "AsHashtable returns a hashtable" {
4 | $result = Get-Process | Group-Object -Property ProcessName -AsHashTable
5 | $result["powershell"].Count | Should BeGreaterThan 0
6 | }
7 |
8 | It "AsString returns a string" {
9 | $processes = Get-Process | Group-Object -Property ProcessName -AsHashTable -AsString
10 | $result = $processes.Keys | ForEach-Object {$_.GetType()}
11 | $result[0].Name | Should Be "String"
12 | }
13 | }
14 |
15 | Context "Tee-Object" {
16 | It "with literal path" {
17 | $path = "TestDrive:\[TeeObjectLiteralPathShouldWorkForSpecialFilename].txt"
18 | Write-Output "Test" | Tee-Object -LiteralPath $path | Tee-Object -Variable TeeObjectLiteralPathShouldWorkForSpecialFilename
19 | $TeeObjectLiteralPathShouldWorkForSpecialFilename | Should Be (Get-Content -LiteralPath $path)
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.utility.string.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "String cmdlets" -Tags 'innerloop' {
2 | Context "Select-String" {
3 | BeforeAll {
4 | $fileName = New-Item 'TestDrive:\selectStr[ingLi]teralPath.txt'
5 | "abc" | Out-File -LiteralPath $fileName.fullname
6 | "bcd" | Out-File -LiteralPath $fileName.fullname -Append
7 | "cde" | Out-File -LiteralPath $fileName.fullname -Append
8 |
9 | $fileNameWithDots = $fileName.FullName.Replace("\", "\.\")
10 |
11 | $tempFile = New-TemporaryFile
12 | "abc" | Out-File -LiteralPath $tempFile.fullname
13 | "bcd" | Out-File -LiteralPath $tempFile.fullname -Append
14 | "cde" | Out-File -LiteralPath $tempFile.fullname -Append
15 | $driveLetter = $tempFile.PSDrive.Name
16 | $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $tempFile.FullName.SubString(2)
17 |
18 | Push-Location "$fileName\.."
19 | }
20 |
21 | AfterAll {
22 | Remove-Item $tempFile -Force -ErrorAction SilentlyContinue
23 | Pop-Location
24 | }
25 |
26 | It "LiteralPath with relative path" {
27 | (select-string -LiteralPath (Get-Item -LiteralPath $fileName).Name "b").count | Should Be 2
28 | }
29 |
30 | It "LiteralPath with absolute path" {
31 | (select-string -LiteralPath $fileName "b").count | Should Be 2
32 | }
33 |
34 | It "LiteralPath with dots in path" {
35 | (select-string -LiteralPath $fileNameWithDots "b").count | Should Be 2
36 | }
37 |
38 | It "Network path" {
39 | (select-string -LiteralPath $fileNameAsNetworkPath "b").count | Should Be 2
40 | }
41 |
42 | It "throws error for non filesystem providers" {
43 | select-string -literalPath cert:\currentuser\my "a" -ErrorAction SilentlyContinue -ErrorVariable selectStringError
44 | $selectStringError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectStringCommand'
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/Commands/Cmdlets/pester.utility.xml.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "XML cmdlets" {
2 | Context "Select-XML" {
3 | BeforeAll {
4 | $fileName = New-Item -Path 'TestDrive:\testSelectXml.xml'
5 | Push-Location "$fileName\.."
6 | "" | out-file -LiteralPath $fileName
7 | " " | out-file -LiteralPath $fileName -Append
8 | "" | out-file -LiteralPath $fileName -Append
9 |
10 | $fileNameWithDots = $fileName.FullName.Replace("\", "\.\")
11 |
12 | $driveLetter = [string]($fileName.FullName)[0]
13 | $fileNameAsNetworkPath = "\\localhost\$driveLetter`$" + $fileName.FullName.SubString(2)
14 |
15 | class TestData
16 | {
17 | [string] $testName
18 | [hashtable] $parameters
19 |
20 | TestData($name, $parameters)
21 | {
22 | $this.testName = $name
23 | $this.parameters = $parameters
24 | }
25 | }
26 |
27 | $testcases = @()
28 | $testcases += [TestData]::new('literalpath with relative paths', @{LiteralPath = $fileName.Name; XPath = 'Root'})
29 | $testcases += [TestData]::new('literalpath with absolute paths', @{LiteralPath = $fileName.FullName; XPath = 'Root'})
30 | $testcases += [TestData]::new('literalpath with path with dots', @{LiteralPath = $fileNameWithDots; XPath = 'Root'})
31 | $testcases += [TestData]::new('literalpath with network path', @{LiteralPath = $fileNameAsNetworkPath; XPath = 'Root'})
32 | $testcases += [TestData]::new('path with relative paths', @{Path = $fileName.Name; XPath = 'Root'})
33 | $testcases += [TestData]::new('path with absolute paths', @{Path = $fileName.FullName; XPath = 'Root'})
34 | $testcases += [TestData]::new('path with path with dots', @{Path = $fileNameWithDots; XPath = 'Root'})
35 | $testcases += [TestData]::new('path with network path', @{Path = $fileNameAsNetworkPath; XPath = 'Root'})
36 | }
37 |
38 | AfterAll {
39 | Remove-Item -LiteralPath $fileName -Force -ErrorAction SilentlyContinue
40 | Pop-Location
41 | }
42 |
43 | $testcases | % {
44 |
45 | $params = $_.parameters
46 |
47 | It $_.testName {
48 | @(Select-XML @params).Count | Should Be 1
49 | }
50 | }
51 |
52 | It "literalpath with non filesystem path" {
53 | Select-XML -literalPath cert:\currentuser\my "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue
54 | $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand'
55 | }
56 |
57 | It "path with non filesystem path" {
58 | Select-XML -Path cert:\currentuser\my "Root" -ErrorVariable selectXmlError -ErrorAction SilentlyContinue
59 | $selectXmlError.FullyQualifiedErrorId | Should Be 'ProcessingFile,Microsoft.PowerShell.Commands.SelectXmlCommand'
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/Contribution.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 | We will be adding new tests over time, but we are currently not able to take pull requests, but we do want your input.
3 | If you find issues or other misbehavior, please create an [issue](https://github.com/PowerShell/PowerShell-Tests/issues) and we will review them to see how we can address it.
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 |
4 | Copyright (c) 2015 Microsoft Corporation.
5 |
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 |
15 | The above copyright notice and this permission notice shall be included in all
16 | copies or substantial portions of the Software.
17 |
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | SOFTWARE.
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PowerShell-Tests
2 |
3 | *NOTE* This repo has been superceded by [PowerShell/PowerShell](https://github.com/PowerShell/PowerShell/tree/master/test) and will be deleted by Sept 1st, 2017
4 |
5 | This project represents a selection of tests that the PowerShell team
6 | uses when testing PowerShell. More than 12 years of active
7 | development on PowerShell, we have created many different script based
8 | test frameworks. Early in 2015 we started the migration process of our
9 | internally created script based framework tests to the [Pester
10 | framework](https://github.com/pester/Pester) and this project represents
11 | the early fruits of that labor. Our plan is to continue to migrate our
12 | current tests and release them in this Project, with the aim of having all
13 | of our tests available in the OSS community using OSS test frameworks.
14 |
15 | We believe that by releasing these tests, our community can better understand
16 | how we test, use these as models to better understand PowerShell, and
17 | participate with us as we release future versions.
18 |
19 | Some of the tests have either been _Skipped_ or marked as _Pending_, we
20 | expect that these tests will be activated as product changes are made available
21 | in future releases.
22 |
23 | # Feedback
24 | This project will grow over time, but we are currently not able to take
25 | pull requests, but we _do_ want your input. If you find issues or other
26 | misbehavior, please create an issue and we will review them to see how we can
27 | address it.
28 |
29 | # Invoking the tests
30 | You can either clone the project, or download a ZIP. Once the tests have
31 | been placed on your system, you can invoke them as you invoke any other
32 | Pester test:
33 | ```
34 | PS> Invoke-Pester
35 | ```
36 | Because a number of our tests create local sessions, it is suggested (for
37 | now) that you run the tests in an elevated PowerShell session as non-admins,
38 | by default, will not have the appropriate permissions.
39 |
--------------------------------------------------------------------------------
/Scripting/Classes/MSFT_778492.psm1:
--------------------------------------------------------------------------------
1 |
2 | $foo = 'MSFT_778492 script scope'
3 |
4 | class MSFT_778492
5 | {
6 | [string] F()
7 | {
8 | return $script:foo
9 | }
10 | }
11 |
12 | function Get-MSFT_778492
13 | {
14 | [MSFT_778492]::new()
15 | }
16 |
--------------------------------------------------------------------------------
/Scripting/Classes/ProtectedAccess.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | Add-Type -WarningAction Ignore @'
3 | public class Base
4 | {
5 | private int data;
6 |
7 | protected Base()
8 | {
9 | data = 10;
10 | }
11 |
12 | protected Base(int i)
13 | {
14 | data = i;
15 | }
16 |
17 | protected int Field;
18 | protected int Property { get; set; }
19 | public int Property1 { get; protected set; }
20 | public int Property2 { protected get; set; }
21 |
22 | protected int Method()
23 | {
24 | return 32 + data;
25 | }
26 | protected int OverloadedMethod1(int i)
27 | {
28 | return 32 + i + data;
29 | }
30 | protected int OverloadedMethod1(string i)
31 | {
32 | return 1 + data;
33 | }
34 | public int OverloadedMethod2(int i)
35 | {
36 | return 32 + i + data;
37 | }
38 | protected int OverloadedMethod2(string i)
39 | {
40 | return 1 + data;
41 | }
42 | protected int OverloadedMethod3(int i)
43 | {
44 | return 32 + i + data;
45 | }
46 | public int OverloadedMethod3(string i)
47 | {
48 | return 1 + data;
49 | }
50 | }
51 | '@
52 |
53 | $derived1,$derived2,$derived3 = Invoke-Expression @'
54 | class Derived : Base
55 | {
56 | Derived() : Base() {}
57 | Derived([int] $i) : Base($i) {}
58 |
59 | [int] TestPropertyAccess()
60 | {
61 | $this.Property = 1111
62 | return $this.Property
63 | }
64 |
65 | [int] TestPropertyAccess1()
66 | {
67 | $this.Property1 = 2111
68 | return $this.Property1
69 | }
70 |
71 | [int] TestPropertyAccess2()
72 | {
73 | $this.Property2 = 3111
74 | return $this.Property2
75 | }
76 |
77 | [int] TestDynamicPropertyAccess()
78 | {
79 | $p = 'Property'
80 | $this.$p = 1112
81 | return $this.$p
82 | }
83 |
84 | [int] TestFieldAccess()
85 | {
86 | $this.Field = 11
87 | return $this.Field
88 | }
89 |
90 | [int] TestDynamicFieldAccess()
91 | {
92 | $f = 'Field'
93 | $this.$f = 12
94 | return $this.$f
95 | }
96 |
97 | [int] TestMethodAccess()
98 | {
99 | return $this.Method()
100 | }
101 |
102 | [int] TestDynamicMethodAccess()
103 | {
104 | $m = 'Method'
105 | return $this.$m()
106 | }
107 |
108 | [int] TestOverloadedMethodAccess1a()
109 | {
110 | return $this.OverloadedMethod1(42)
111 | }
112 | [int] TestOverloadedMethodAccess1b()
113 | {
114 | return $this.OverloadedMethod1("abc")
115 | }
116 | [int] TestOverloadedMethodAccess2a()
117 | {
118 | return $this.OverloadedMethod2(42)
119 | }
120 | [int] TestOverloadedMethodAccess2b()
121 | {
122 | return $this.OverloadedMethod2("abc")
123 | }
124 | [int] TestOverloadedMethodAccess3a()
125 | {
126 | return $this.OverloadedMethod3(42)
127 | }
128 | [int] TestOverloadedMethodAccess3b()
129 | {
130 | return $this.OverloadedMethod3("abc")
131 | }
132 | }
133 |
134 | class Derived2 : Base {}
135 |
136 | [Derived]::new()
137 | [Derived]::new(20)
138 | [Derived2]::new()
139 | '@
140 |
141 | Describe "Protected Member Access - w/ default ctor" -Tags "DRT" {
142 | It "Method Access" { $derived1.TestMethodAccess() | Should Be 42 }
143 | It "Dynamic Method Access" { $derived1.TestDynamicMethodAccess() | Should Be 42 }
144 | It "Field Access" { $derived1.TestFieldAccess() | Should Be 11 }
145 | It "Dynamic Field Access" { $derived1.TestDynamicFieldAccess() | Should Be 12 }
146 | It "Property Access - protected get/protected set" { $derived1.TestPropertyAccess() | Should Be 1111 }
147 | It "Property Access - public get/protected set " { $derived1.TestPropertyAccess1() | Should Be 2111 }
148 | It "Property Access - protected get/public set" { $derived1.TestPropertyAccess2() | Should Be 3111 }
149 | It "Dynamic Property Access" { $derived1.TestDynamicPropertyAccess() | Should Be 1112 }
150 |
151 | It "Method Access - overloaded 1a" { $derived1.TestOverloadedMethodAccess1a() | Should Be 84 }
152 | It "Method Access - overloaded 1b" { $derived1.TestOverloadedMethodAccess1b() | Should Be 11 }
153 | It "Method Access - overloaded 2a" { $derived1.TestOverloadedMethodAccess2a() | Should Be 84 }
154 | It "Method Access - overloaded 2b" { $derived1.TestOverloadedMethodAccess2b() | Should Be 11 }
155 | It "Method Access - overloaded 3a" { $derived1.TestOverloadedMethodAccess3a() | Should Be 84 }
156 | It "Method Access - overloaded 3b" { $derived1.TestOverloadedMethodAccess3b() | Should Be 11 }
157 | It "Implicit ctor calls protected ctor" { $derived3.OverloadedMethod2(42) | Should Be 84 }
158 | }
159 |
160 | Describe "Protected Member Access - w/ non-default ctor" -Tags "DRT" {
161 | It "Method Access" { $derived2.TestMethodAccess() | Should Be 52 }
162 | It "Dynamic Method Access" { $derived2.TestDynamicMethodAccess() | Should Be 52 }
163 | It "Field Access" { $derived2.TestFieldAccess() | Should Be 11 }
164 | It "Dynamic Field Access" { $derived2.TestDynamicFieldAccess() | Should Be 12 }
165 | It "Property Access - protected get/protected set" { $derived1.TestPropertyAccess() | Should Be 1111 }
166 | It "Property Access - public get/protected set " { $derived1.TestPropertyAccess1() | Should Be 2111 }
167 | It "Property Access - protected get/public set" { $derived1.TestPropertyAccess2() | Should Be 3111 }
168 | It "Dynamic Property Access" { $derived2.TestDynamicPropertyAccess() | Should Be 1112 }
169 |
170 | It "Method Access - overloaded 1a" { $derived2.TestOverloadedMethodAccess1a() | Should Be 94 }
171 | It "Method Access - overloaded 1b" { $derived2.TestOverloadedMethodAccess1b() | Should Be 21 }
172 | It "Method Access - overloaded 2a" { $derived2.TestOverloadedMethodAccess2a() | Should Be 94 }
173 | It "Method Access - overloaded 2b" { $derived2.TestOverloadedMethodAccess2b() | Should Be 21 }
174 | It "Method Access - overloaded 3a" { $derived2.TestOverloadedMethodAccess3a() | Should Be 94 }
175 | It "Method Access - overloaded 3b" { $derived2.TestOverloadedMethodAccess3b() | Should Be 21 }
176 | }
177 |
178 | Describe "Protected Member Access - members not visible outside class" -Tags "DRT" {
179 | Set-StrictMode -v 3
180 | It "Invalid protected field Get Access" { { $derived1.Field } | Should Throw }
181 | It "Invalid protected property Get Access" { { $derived1.Property } | Should Throw }
182 | It "Invalid protected field Set Access" { { $derived1.Field = 1 } | Should Throw }
183 | It "Invalid protected property Set Access" { { $derived1.Property = 1 } | Should Throw }
184 |
185 | It "Invalid protected constructor Access" { { [Base]::new() } | Should Throw }
186 | It "Invalid protected method Access" { { $derived1.Method() } | Should Throw }
187 | }
188 |
189 |
--------------------------------------------------------------------------------
/Scripting/Classes/Scripting.Classes.Attributes.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe 'Attributes Test' -Tags "innerloop", "DRT" {
2 |
3 | BeforeAll {
4 | $dummyAttributesSource = @'
5 | using System.Management.Automation;
6 | namespace Dummy
7 | {
8 | public class DoubleStringTransformationAttribute : ArgumentTransformationAttribute
9 | {
10 | public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
11 | {
12 | string arg = inputData as string;
13 | if (arg != null)
14 | {
15 | return arg + arg;
16 | }
17 | return inputData;
18 | }
19 | }
20 |
21 | public class AppendStringTransformationAttribute : ArgumentTransformationAttribute
22 | {
23 | public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
24 | {
25 | string arg = inputData as string;
26 | if (arg != null)
27 | {
28 | return arg + "___";
29 | }
30 | return inputData;
31 | }
32 | }
33 |
34 | public class DoubleInt : ArgumentTransformationAttribute
35 | {
36 | public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
37 | {
38 | int? arg = inputData as int?;
39 | if (arg != null)
40 | {
41 | return arg + arg;
42 | }
43 | return inputData;
44 | }
45 | }
46 | }
47 | '@
48 | Add-Type -TypeDefinition $dummyAttributesSource -ReferencedAssemblies "System.Management.Automation"
49 | }
50 |
51 |
52 |
53 | Context 'Property.Instance.ValidateSet.String' {
54 | class C1 { [ValidateSet("Present", "Absent")][string]$Ensure }
55 | # This call should not throw exception
56 | [C1]::new().Ensure = "Present"
57 |
58 | It 'Error when ValidateSet should be ExceptionWhenSetting' {
59 | try
60 | {
61 | [C1]::new().Ensure = "foo"
62 | throw "Exception expected"
63 | }
64 | catch
65 | {
66 | $_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
67 | }
68 | }
69 | }
70 |
71 | Context 'Property.Static.ValidateSet.String' {
72 | class C1 { static [ValidateSet("Present", "Absent")][string]$Ensure }
73 | # This call should not throw exception
74 | [C1]::Ensure = "Present"
75 | It 'Error when ValidateSet should be ExceptionWhenSetting'{
76 | try {
77 | [C1]::Ensure = "foo"
78 | throw "Exception expected"
79 | }
80 | catch {
81 | $_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
82 | }
83 | }
84 | }
85 |
86 | Context 'Property.Instance.ValidateRange.Int' {
87 | class C1 { [ValidateRange(1, 10)][int]$f }
88 | # This call should not throw exception
89 | [C1]::new().f = 10
90 | [C1]::new().f = 1
91 | It 'Error when ValidateSet should be ExceptionWhenSetting'{
92 | try {
93 | [C1]::new().f = 20
94 | throw "Exception expected"
95 | }
96 | catch {
97 | $_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
98 | }
99 | }
100 | }
101 |
102 | Context 'Property.Static.ValidateRange.Int' {
103 | class C1 { static [ValidateRange(1, 10)][int]$f }
104 | # This call should not throw exception
105 | [C1]::f = 5
106 | It 'Error when ValidateSet should be ExceptionWhenSetting'{
107 | try {
108 | [C1]::f = 20
109 | throw "Exception expected"
110 | }
111 | catch {
112 | $_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
113 | }
114 | }
115 | }
116 |
117 | Context 'Property.Static.ValidateSet.ImplicitObject' {
118 | class C1 { static [ValidateSet("abc", 5)]$o }
119 | # This call should not throw exception
120 | [C1]::o = "abc"
121 | [C1]::o = 5
122 | It 'Error when ValidateSet should be ExceptionWhenSetting'{
123 | try {
124 | [C1]::o = 1
125 | throw "Exception expected"
126 | }
127 | catch {
128 | $_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
129 | }
130 | }
131 | }
132 |
133 | #
134 | # We use [scriptblock]::Create() here to allow SuiteSetup add Dummy.Transformation type to
135 | # the scope. Otherwise, we will need to have all classes for attributes in parse time.
136 | #
137 | # Invoke() returns an array, we need first element of it.
138 | #
139 |
140 | Context 'Property.Instance.Transformation.ImplicitObject' {
141 | $c = [scriptblock]::Create('class C1 { [Dummy.DoubleStringTransformation()]$arg }; [C1]::new()').Invoke()[0]
142 |
143 | It 'Implicitly Transform to 100' {
144 | $c.arg = 100
145 | $c.arg | should be 100
146 | }
147 | It 'Implicitly Transform to foo' {
148 | $c.arg = "foo"
149 | $c.arg | should be "foofoo"
150 | }
151 | }
152 |
153 | Context 'Property.Instance.Transformation.String' {
154 | $c = [scriptblock]::Create('class C1 { [Dummy.DoubleStringTransformation()][string]$arg }; [C1]::new()').Invoke()[0]
155 | It 'set to foo' {
156 | $c.arg = "foo"
157 | $c.arg | should be "foofoo"
158 | }
159 | }
160 |
161 | Context Property.Instance.Transformation.Int {
162 | $c = [scriptblock]::Create('class C1 { [Dummy.DoubleInt()][int]$arg }; [C1]::new()').Invoke()[0]
163 | It 'arg should be 200' {
164 | $c.arg = 100
165 | $c.arg | should be 200
166 | }
167 | It 'Set to string should fail with ExceptionWhenSetting' {
168 | try {
169 | $c.arg = "abc"
170 | throw "Exception expected"
171 | }
172 | catch {
173 | $_.FullyQualifiedErrorId | Should be 'ExceptionWhenSetting'
174 | }
175 | }
176 | }
177 |
178 | Context Property.Instance.Transformation.Nullable {
179 | $c = [scriptblock]::Create('class C1 { [Nullable[int]][Dummy.DoubleStringTransformation()]$arg }; [C1]::new()').Invoke()[0]
180 | It 'arg should be 100' {
181 | $c.arg = 100
182 | $c.arg | should be 100
183 | }
184 | }
185 |
186 | Context Property.Instance.Transformation.Order {
187 | $c = [scriptblock]::Create('class C1 { [Dummy.DoubleStringTransformation()][Dummy.AppendStringTransformation()]$arg }; [C1]::new()').Invoke()[0]
188 | It 'arg should be 100' {
189 | $c.arg = 100
190 | $c.arg | should be 100
191 | }
192 |
193 | It 'arg should be foo___foo___g' {
194 | $c.arg = "foo"
195 | $c.arg | should be "foo___foo___"
196 | }
197 | }
198 | }
199 |
200 | Describe 'Type resolution with attributes' {
201 | # There is kind of a collision between names
202 | # System.Diagnostics.Tracing.EventSource
203 | # System.Diagnostics.Tracing.EventSourceAttribute
204 | # We need to make sure that we resolve type name to the right class at each usage
205 | Context 'Name collision' {
206 |
207 | It 'Resolve System.Diagnostics.Tracing.EventSource to Attribute and to Type in the different contexts' {
208 | [System.Diagnostics.Tracing.EventSource(Name = "MyPSEventSource")]
209 | class MyEventSource : System.Diagnostics.Tracing.EventSource
210 | {
211 | [void] OnEvent([string]$Message) {}
212 | }
213 |
214 | [MyEventSource]::new() | Should Not Be $null
215 |
216 | }
217 | }
218 | }
--------------------------------------------------------------------------------
/Scripting/Classes/Scripting.Classes.Break.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe 'Break statements with classes' -Tags "DRT" {
2 |
3 | function Get-Errors([string]$sourceCode) {
4 | $tokens = $null
5 | $errors = $null
6 | $ast = [System.Management.Automation.Language.Parser]::ParseInput($sourceCode, [ref] $tokens, [ref] $errors)
7 | return $errors
8 | }
9 |
10 | Context 'break is inside a class method' {
11 | It 'reports parse error for break on non-existing label' {
12 | $errors = Get-Errors @'
13 | class A
14 | {
15 | static [int] foo()
16 | {
17 | while (1) { break some_label }
18 | return 1
19 | }
20 | }
21 | '@
22 | $errors.Count | Should be 1
23 | $errors[0].ErrorId | Should be 'LabelNotFound'
24 | }
25 |
26 | It 'reports parse error for break outside of loop' {
27 | $errors = Get-Errors @'
28 | class A
29 | {
30 | static [int] foo()
31 | {
32 | break some_label
33 | return 1
34 | }
35 | }
36 | '@
37 | $errors.Count | Should be 1
38 | $errors[0].ErrorId | Should be 'LabelNotFound'
39 | }
40 |
41 | It 'work fine, when break is legite' {
42 | class C
43 | {
44 | static [int] foo()
45 | {
46 | foreach ($i in 101..102) {
47 | break
48 | }
49 | return $i
50 | }
51 | }
52 | [C]::foo() | Should be 101
53 | }
54 | }
55 |
56 | Context 'continue inside a class method' {
57 | It 'reports parse error for continue on non-existing label' {
58 | $errors = Get-Errors @'
59 | class A
60 | {
61 | static [int] foo()
62 | {
63 | while (1) { continue some_label }
64 | return 1
65 | }
66 | }
67 | '@
68 | $errors.Count | Should be 1
69 | $errors[0].ErrorId | Should be 'LabelNotFound'
70 | }
71 | }
72 |
73 | Context 'break is in called function' {
74 | It 'doesn''t terminate caller method' -Skip {
75 |
76 | function ImBreak() {
77 | break
78 | }
79 |
80 | class C
81 | {
82 | static [int] getInt()
83 | {
84 | ImBreak
85 | return 123
86 | }
87 | }
88 |
89 | $canary = $false
90 | try {
91 | [C]::getInt() | Should Be 123
92 | $canary = $true
93 | } finally {
94 | $canary | Should be $true
95 | }
96 | }
97 |
98 | It 'doesn''t allow goto outside of function with break' -Skip {
99 |
100 | function ImBreak() {
101 | break label1
102 | }
103 |
104 | class C
105 | {
106 | static [int] getInt()
107 | {
108 | $count = 123
109 | :label1
110 | foreach ($i in 0..3) {
111 | foreach ($i in 0..3) {
112 | ImBreak
113 | $count++
114 | }
115 | }
116 | return $count
117 | }
118 | }
119 |
120 | $canary = $false
121 | try {
122 | [C]::getInt() | Should Be (123 + 4*4)
123 | $canary = $true
124 | } finally {
125 | $canary | Should be $true
126 | }
127 | }
128 | }
129 |
130 | Context 'no classes involved' {
131 |
132 | It 'doesn''t report parse error for non-existing label' {
133 | $errors = Get-Errors @'
134 | function foo()
135 | {
136 | while (1) { break some_label }
137 | while (1) { continue another_label }
138 | return 1
139 | }
140 | '@
141 | $errors.Count | Should be 0
142 | }
143 |
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/Scripting/Classes/Scripting.Classes.Exceptions.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe 'Exceptions flow for classes' -Tags "DRT" {
2 |
3 | $canaryHashtable = @{}
4 |
5 | $iss = [initialsessionstate]::CreateDefault()
6 | $iss.Variables.Add([System.Management.Automation.Runspaces.SessionStateVariableEntry]::new('canaryHashtable', $canaryHashtable, $null))
7 | $iss.Commands.Add([System.Management.Automation.Runspaces.SessionStateFunctionEntry]::new('Get-Canary', '$canaryHashtable'))
8 | $ps = [powershell]::Create($iss)
9 |
10 | BeforeEach {
11 | $canaryHashtable.Clear()
12 | $ps.Commands.Clear()
13 | }
14 |
15 | Context 'All calls are inside classes' {
16 |
17 | It 'does not execute statements after instance method with exception' {
18 |
19 | # Put try-catch outside to avoid try-catch logic altering analysis
20 | try {
21 |
22 | $ps.AddScript( @'
23 | class C
24 | {
25 | [void] m1()
26 | {
27 | $canaryHashtable = Get-Canary
28 | $canaryHashtable['canary'] = 42
29 | $this.ImThrow()
30 | $canaryHashtable['canary'] = 100
31 | }
32 |
33 | [void] ImThrow()
34 | {
35 | throw 'I told you'
36 | }
37 | }
38 | [C]::new().m1()
39 | '@).Invoke()
40 |
41 | } catch {}
42 |
43 | $canaryHashtable['canary'] | Should Be 42
44 | }
45 |
46 | It 'does not execute statements after static method with exception' {
47 |
48 | # Put try-catch outside to avoid try-catch logic altering analysis
49 | try {
50 |
51 | $ps.AddScript( @'
52 | class C
53 | {
54 | static [void] s1()
55 | {
56 | $canaryHashtable = Get-Canary
57 | $canaryHashtable['canary'] = 43
58 | [C]::ImThrow()
59 | $canaryHashtable['canary'] = 100
60 | }
61 |
62 | static [void] ImThrow()
63 | {
64 | 1 / 0
65 | }
66 | }
67 | [C]::s1()
68 | '@).Invoke()
69 |
70 | } catch {}
71 |
72 | $canaryHashtable['canary'] | Should Be 43
73 | }
74 |
75 | It 'does not execute statements after instance method with exception and deep stack' {
76 |
77 | # Put try-catch outside to avoid try-catch logic altering analysis
78 | try {
79 |
80 | $ps.AddScript( @'
81 | class C
82 | {
83 | [void] m1()
84 | {
85 | $canaryHashtable = Get-Canary
86 | $canaryHashtable['canary'] = 1
87 | $this.m2()
88 | $canaryHashtable['canary'] = -6101
89 | }
90 |
91 | [void] m2()
92 | {
93 | $canaryHashtable = Get-Canary
94 | $canaryHashtable['canary'] += 10
95 | $this.m3()
96 | $canaryHashtable['canary'] = -6102
97 | }
98 |
99 | [void] m3()
100 | {
101 | $canaryHashtable = Get-Canary
102 | $canaryHashtable['canary'] += 100
103 | $this.m4()
104 | $canaryHashtable['canary'] = -6103
105 | }
106 |
107 | [void] m4()
108 | {
109 | $canaryHashtable = Get-Canary
110 | $canaryHashtable['canary'] += 1000
111 | $this.ImThrow()
112 | $canaryHashtable['canary'] = -6104
113 | }
114 |
115 | [void] ImThrow()
116 | {
117 | $canaryHashtable = Get-Canary
118 | $canaryHashtable['canary'] += 10000
119 |
120 | 1 / 0
121 | }
122 | }
123 | [C]::new().m1()
124 | '@).Invoke()
125 |
126 | } catch {}
127 |
128 | $canaryHashtable['canary'] | Should Be 11111
129 | }
130 | }
131 |
132 | Context 'Class method call PS function' {
133 |
134 | $body = @'
135 | class C
136 | {
137 | [void] m1()
138 | {
139 | m2
140 | }
141 |
142 | static [void] s1()
143 | {
144 | s2
145 | }
146 | }
147 |
148 |
149 | function m2()
150 | {
151 | $canary = Get-Canary
152 | $canary['canaryM'] = 45
153 | ImThrow
154 | $canary['canaryM'] = 100
155 | }
156 |
157 | function s2()
158 | {
159 | $canary = Get-Canary
160 | $canary['canaryS'] = 46
161 | CallImThrow
162 | $canary['canaryS'] = 100
163 | }
164 |
165 | function CallImThrow()
166 | {
167 | ImThrow
168 | }
169 |
170 | function ImThrow()
171 | {
172 | 1 / 0
173 | }
174 |
175 | '@
176 |
177 | It 'does not execute statements after function with exception called from instance method' {
178 |
179 | # Put try-catch outside to avoid try-catch logic altering analysis
180 | try {
181 |
182 | $ps.AddScript($body).Invoke()
183 | $ps.AddScript('$c = [C]::new(); $c.m1()').Invoke()
184 |
185 | } catch {}
186 |
187 | $canaryHashtable['canaryM'] | Should Be 45
188 | }
189 |
190 | It 'does not execute statements after function with exception called from static method' {
191 |
192 | # Put try-catch outside to avoid try-catch logic altering analysis
193 | try {
194 |
195 | $ps.AddScript($body).Invoke()
196 | $ps.AddScript('[C]::s1()').Invoke()
197 |
198 | } catch {}
199 |
200 | $canaryHashtable['canaryS'] | Should Be 46
201 | }
202 |
203 | }
204 |
205 | Context "No class is involved" {
206 | It "functions calls continue execution by default" {
207 |
208 | try {
209 |
210 | $ps.AddScript( @'
211 |
212 | $canaryHashtable = Get-Canary
213 | function foo() { 1 / 0; $canaryHashtable['canary'] += 10 }
214 | $canaryHashtable['canary'] = 1
215 | foo
216 | $canaryHashtable['canary'] += 100
217 |
218 | '@).Invoke()
219 |
220 | } catch {}
221 |
222 | $canaryHashtable['canary'] | Should Be 111
223 | }
224 | }
225 | }
226 |
227 | Describe "Exception error position" -Tags "DRT" {
228 | class MSFT_3090412
229 | {
230 | static f1() { [MSFT_3090412]::bar = 42 }
231 | static f2() { throw "an error in f2" }
232 | static f3() { "".Substring(0, 10) }
233 | static f4() { dir nosuchfile -ea Stop }
234 | }
235 |
236 | It "Setting a property that doesn't exist" {
237 | try {
238 | [MSFT_3090412]::f1()
239 | throw "f1 should have thrown"
240 | } catch {
241 | $_.InvocationInfo.Line | Should Match ([regex]::Escape('[MSFT_3090412]::bar = 42'))
242 | }
243 | }
244 |
245 | It "Throwing an exception" {
246 | try {
247 | [MSFT_3090412]::f2()
248 | throw "f2 should have thrown"
249 | } catch {
250 | $_.InvocationInfo.Line | Should Match ([regex]::Escape('throw "an error in f2"'))
251 | }
252 | }
253 |
254 | It "Calling a .Net method that throws" {
255 | try {
256 | [MSFT_3090412]::f3()
257 | throw "f3 should have thrown"
258 | } catch {
259 | $_.InvocationInfo.Line | Should Match ([regex]::Escape('"".Substring(0, 10)'))
260 | }
261 | }
262 |
263 | It "Terminating error" {
264 | try {
265 | [MSFT_3090412]::f4()
266 | throw "f4 should have thrown"
267 | } catch {
268 | $_.InvocationInfo.Line | Should Match ([regex]::Escape('dir nosuchfile -ea Stop'))
269 | }
270 | }
271 | }
272 |
--------------------------------------------------------------------------------
/Scripting/Classes/Scripting.Classes.Modules.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe 'PSModuleInfo.GetExportedTypeDefinitions()' {
2 | It "doesn't throw for any module" {
3 | $discard = Get-Module -ListAvailable | % { $_.GetExportedTypeDefinitions() }
4 | $true | Should Be $true # we only verify that we didn't throw. This line contains a dummy Should to make pester happy.
5 | }
6 | }
7 |
8 | Describe 'use of a module from two runspaces' {
9 | function New-TestModule {
10 | param(
11 | [string]$Name,
12 | [string]$Content
13 | )
14 |
15 | mkdir -Force "TestDrive:\$Name" > $null
16 | $manifestParams = @{
17 | Path = "TestDrive:\$Name\$Name.psd1"
18 | }
19 |
20 | if ($Content) {
21 | Set-Content -Path TestDrive:\$Name\$Name.psm1 -Value $Content
22 | $manifestParams['RootModule'] = "$Name.psm1"
23 | }
24 |
25 | New-ModuleManifest @manifestParams
26 |
27 | $resolvedTestDrivePath = Split-Path ((ls TestDrive:\)[0].FullName)
28 | if (-not ($env:PSModulePath -like "*$resolvedTestDrivePath*")) {
29 | $env:PSModulePath += ";$resolvedTestDrivePath"
30 | }
31 | }
32 |
33 | $originalPSModulePath = $env:PSModulePath
34 | try {
35 |
36 | New-TestModule -Name 'Random' -Content @'
37 | $script:random = Get-Random
38 | class RandomWrapper
39 | {
40 | [int] getRandom()
41 | {
42 | return $script:random
43 | }
44 | }
45 | '@
46 |
47 | It -pending 'use different sessionStates for different modules' {
48 | $ps = 1..2 | % { $p = [powershell]::Create().AddScript(@'
49 | Import-Module Random
50 | '@)
51 | $p.Invoke() > $null
52 | $p
53 | }
54 | $res = 1..2 | % {
55 | 0..1 | % {
56 | $ps[$_].Commands.Clear()
57 | # The idea: instance created inside the context, in one runspace.
58 | # Method is called on instance in the different runspace, but it should know about the origin.
59 | $w = $ps[$_].AddScript('& (Get-Module Random) { [RandomWrapper]::new() }').Invoke()[0]
60 | $w.getRandom()
61 | }
62 | }
63 |
64 | $res.Count | Should Be 4
65 | $res[0] | Should Not Be $res[1]
66 | $res[0] | Should Be $res[2]
67 | $res[1] | Should Be $res[3]
68 | }
69 |
70 | } finally {
71 | $env:PSModulePath = $originalPSModulePath
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/Scripting/Classes/scripting.classes.NestedModules.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe 'NestedModules' -Tags "DRT" {
2 |
3 | Import-Module $PSScriptRoot\..\LanguageTestSupport.psm1
4 |
5 | function New-TestModule {
6 | param(
7 | [string]$Name,
8 | [string]$Content,
9 | [string[]]$NestedContents
10 | )
11 |
12 | mkdir -Force "TestDrive:\$Name" > $null
13 | $manifestParams = @{
14 | Path = "TestDrive:\$Name\$Name.psd1"
15 | }
16 |
17 | if ($Content) {
18 | Set-Content -Path TestDrive:\$Name\$Name.psm1 -Value $Content
19 | $manifestParams['RootModule'] = "$Name.psm1"
20 | }
21 |
22 | if ($NestedContents) {
23 | $manifestParams['NestedModules'] = 1..$NestedContents.Count | % {
24 | $null = mkdir TestDrive:\$Name\Nested$_
25 | $null = Set-Content -Path TestDrive:\$Name\Nested$_\Nested$_.psm1 -Value $NestedContents[$_ - 1]
26 | "Nested$_"
27 | }
28 | }
29 |
30 | New-ModuleManifest @manifestParams
31 |
32 | $resolvedTestDrivePath = Split-Path ((ls TestDrive:\)[0].FullName)
33 | if (-not ($env:PSModulePath -like "*$resolvedTestDrivePath*")) {
34 | $env:PSModulePath += ";$resolvedTestDrivePath"
35 | }
36 | }
37 |
38 | $originalPSModulePath = $env:PSModulePath
39 |
40 | try {
41 |
42 |
43 | # Create modules in TestDrive:\
44 | New-TestModule -Name NoRoot -NestedContents @(
45 | 'class A { [string] foo() { return "A1"} }',
46 | 'class A { [string] foo() { return "A2"} }'
47 | )
48 |
49 | New-TestModule -Name WithRoot -NestedContents @(
50 | 'class A { [string] foo() { return "A1"} }',
51 | 'class A { [string] foo() { return "A2"} }'
52 | ) -Content 'class A { [string] foo() { return "A0"} }'
53 |
54 | New-TestModule -Name ABC -NestedContents @(
55 | 'class A { [string] foo() { return "A"} }',
56 | 'class B { [string] foo() { return "B"} }'
57 | ) -Content 'class C { [string] foo() { return "C"} }'
58 |
59 | It 'Get-Module is able to find types' {
60 | $module = Get-Module NoRoot -ListAvailable
61 | $module.GetExportedTypeDefinitions().Count | Should Be 1
62 |
63 | $module = Get-Module WithRoot -ListAvailable
64 | $module.GetExportedTypeDefinitions().Count | Should Be 1
65 |
66 | $module = Get-Module ABC -ListAvailable
67 | $module.GetExportedTypeDefinitions().Count | Should Be 3
68 | }
69 |
70 | It 'Import-Module pick the right type' {
71 | $module = Import-Module ABC -PassThru
72 | $module.GetExportedTypeDefinitions().Count | Should Be 3
73 | $module = Import-Module ABC -PassThru -Force
74 | $module.GetExportedTypeDefinitions().Count | Should Be 3
75 |
76 | $module = Import-Module NoRoot -PassThru
77 | $module.GetExportedTypeDefinitions().Count | Should Be 1
78 | $module = Import-Module NoRoot -PassThru -Force
79 | $module.GetExportedTypeDefinitions().Count | Should Be 1
80 | [scriptblock]::Create(@'
81 | using module NoRoot
82 | [A]::new().foo()
83 | '@
84 | ).Invoke() | Should Be A2
85 |
86 | $module = Import-Module WithRoot -PassThru
87 | $module.GetExportedTypeDefinitions().Count | Should Be 1
88 | $module = Import-Module WithRoot -PassThru -Force
89 | $module.GetExportedTypeDefinitions().Count | Should Be 1
90 | [scriptblock]::Create(@'
91 | using module WithRoot
92 | [A]::new().foo()
93 | '@
94 | ).Invoke() | Should Be A0
95 | }
96 |
97 | Context 'execute type creation in the module context' {
98 |
99 | # let's define types to make it more fun
100 | class A { [string] foo() { return "local"} }
101 | class B { [string] foo() { return "local"} }
102 | class C { [string] foo() { return "local"} }
103 |
104 | # We need to think about it: should it work or not.
105 | # Currently, types are resolved in compile-time to the 'local' versions
106 | # So at runtime we don't call the module versions.
107 | It 'Can execute type creation in the module context with new()' -Skip {
108 | & (Get-Module ABC) { [C]::new().foo() } | Should Be C
109 | & (Get-Module NoRoot) { [A]::new().foo() } | Should Be A2
110 | & (Get-Module WithRoot) { [A]::new().foo() } | Should Be A0
111 | & (Get-Module ABC) { [A]::new().foo() } | Should Be A
112 | }
113 |
114 | It -pending 'Can execute type creation in the module context with New-Object' {
115 | & (Get-Module ABC) { (New-Object C).foo() } | Should Be C
116 | & (Get-Module NoRoot) { (New-Object A).foo() } | Should Be A2
117 | & (Get-Module WithRoot) { (New-Object A).foo() } | Should Be A0
118 | & (Get-Module ABC) { (New-Object A).foo() } | Should Be A
119 | }
120 | }
121 |
122 | } finally {
123 | $env:PSModulePath = $originalPSModulePath
124 | Get-Module @('ABC', 'NoRoot', 'WithRoot') | Remove-Module
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Scripting/Classes/scripting.classes.miscops.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe 'Misc Test' -Tags "innerloop", "DRT" {
2 |
3 | Context 'Where' {
4 | class C1 {
5 | [int[]] $Wheels = @(1,2,3);
6 | [string] Foo() {
7 | return (1..10).Where({ $PSItem -in $this.Wheels; }) -join ';'
8 | }
9 |
10 | [string] Bar()
11 | {
12 | return (1..10 | Where { $PSItem -in $this.Wheels; }) -join ';'
13 | }
14 | }
15 | It 'Invoke Where' {
16 | [C1]::new().Foo() | should be "1;2;3"
17 | }
18 | It 'Pipe to where' {
19 | [C1]::new().Bar() | should be "1;2;3"
20 | }
21 | }
22 |
23 | Context 'ForEach' {
24 | class C1 {
25 | [int[]] $Wheels = @(1,2,3);
26 | [string] Foo() {
27 | $ret=""
28 | Foreach($PSItem in $this.Wheels) { $ret +="$PSItem;"}
29 | return $ret
30 | }
31 |
32 | [string] Bar()
33 | {
34 | $ret = ""
35 | $this.Wheels | foreach { $ret += "$_;" }
36 | return $ret
37 | }
38 | }
39 | It 'Invoke Foreach' {
40 | [C1]::new().Foo() | should be "1;2;3;"
41 | }
42 | It 'Pipe to Foreach' {
43 | [C1]::new().Bar() | should be "1;2;3;"
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/Scripting/Classes/scripting.classes.using.variants.tests.ps1:
--------------------------------------------------------------------------------
1 | [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook("IgnoreScriptBlockCache", $true)
2 | try
3 | {
4 | . $PSScriptRoot\scripting.classes.using.tests.ps1
5 | }
6 | finally
7 | {
8 | [System.Management.Automation.Internal.InternalTestHooks]::SetTestHook("IgnoreScriptBlockCache", $false)
9 | }
10 |
--------------------------------------------------------------------------------
/Scripting/Classes/scripting.enums.tests.ps1:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) Microsoft Corporation, 2015
3 | #
4 |
5 | Describe 'enums' -Tags "DRT" {
6 |
7 | Context 'basic enums' {
8 | enum E1
9 | {
10 | e0
11 | e1
12 | e2
13 | }
14 |
15 | It "has correct value 0" { [E1]::e0 | Should Be ([E1]0) }
16 | It "has correct value 1" { [E1]::e1 | Should Be ([E1]1) }
17 | It "has correct value 2" { [E1]::e2 | Should Be ([E1]2) }
18 | It "cast from string" { [E1]::e1 | Should Be 'e1' }
19 | It "cast to string" { 'e2' | Should Be ([E1]::e2) }
20 | }
21 |
22 | Context 'Basic enum with initial value' {
23 | enum E2
24 | {
25 | e0
26 | e1 = 5
27 | e2
28 | }
29 |
30 | It "has correct value 0" { [E2]::e0 | Should Be ([E2]0) }
31 | It "has correct value 5" { [E2]::e1 | Should Be ([E2]5) }
32 | It "has correct value 6" { [E2]::e2 | Should Be ([E2]6) }
33 | It "cast from string" { [E2]::e1 | Should Be 'e1' }
34 | It "cast to string" { 'e2' | Should Be ([E2]::e2) }
35 | }
36 |
37 | Context 'Basic enum with initial value expression' {
38 | enum E3
39 | {
40 | e0
41 | e1 = 5
42 | e2 = [int]::MaxValue
43 | e3 = 1 # This shouldn't be an error even though previous member was max int
44 | }
45 |
46 | It "has correct value 0" { [E3]::e0 | Should Be ([E3]0) }
47 | It "has correct value 5" { [E3]::e1 | Should Be ([E3]5) }
48 | It "has correct value [int]::MaxValue" { [E3]::e2 | Should Be ([E3]([int]::MaxValue)) }
49 | It "has correct value 1" { [E3]::e3 | Should Be ([E3]1) }
50 | It "cast from string" { [E3]::e2 | Should Be 'e2' }
51 | It "cast to string" { 'e3' | Should Be ([E3]::e3) }
52 | }
53 |
54 | Context 'Enum with complicated initial value' {
55 | enum E4
56 | {
57 | e0 = [E5]::e0 + 2
58 | }
59 |
60 | enum E5
61 | {
62 | e0 = [E6]::e0 + 2
63 | }
64 |
65 | enum E6
66 | {
67 | e0 = 38
68 | }
69 |
70 | It 'E4 has correct value' { [E4]::e0 | Should Be ([E4]42) }
71 | It 'E5 has correct value' { [E5]::e0 | Should Be ([E5]40) }
72 | It 'E6 has correct value' { [E6]::e0 | Should Be ([E6]38) }
73 | }
74 | }
75 |
76 | Describe 'Basic enum errors' -Tags "DRT" {
77 |
78 | Import-Module $PSScriptRoot\..\LanguageTestSupport.psm1
79 |
80 | AfterAll {
81 | Remove-Module LanguageTestSupport
82 | }
83 |
84 | ShouldBeParseError 'enum' MissingNameAfterKeyword 4
85 | ShouldBeParseError 'enum foo' MissingTypeBody 8
86 | ShouldBeParseError 'enum foo {' MissingEndCurlyBrace 10
87 | ShouldBeParseError 'enum foo { x = }' ExpectedValueExpression 14
88 | ShouldBeParseError 'enum foo { x =' ExpectedValueExpression,MissingEndCurlyBrace 14,14
89 | ShouldBeParseError 'enum foo {} enum foo {}' MemberAlreadyDefined 12
90 | ShouldBeParseError 'enum foo { x; x }' MemberAlreadyDefined 14 -SkipAndCheckRuntimeError
91 | ShouldBeParseError 'enum foo { X; x }' MemberAlreadyDefined 14 -SkipAndCheckRuntimeError
92 | ShouldBeParseError 'enum foo1 { x = [foo2]::x } enum foo2 { x = [foo1]::x }' CycleInEnumInitializers,CycleInEnumInitializers 0,28 -SkipAndCheckRuntimeError
93 | ShouldBeParseError 'enum foo { e = [int]::MaxValue; e2 }' EnumeratorValueTooLarge 33 -SkipAndCheckRuntimeError
94 | ShouldBeParseError 'enum foo { e = [int]::MaxValue + 1 }' EnumeratorValueTooLarge 15 -SkipAndCheckRuntimeError
95 | ShouldBeParseError 'enum foo { e = $foo }' EnumeratorValueMustBeConstant 15 -SkipAndCheckRuntimeError
96 | ShouldBeParseError 'enum foo { e = "hello" }' CannotConvertValue 15 -SkipAndCheckRuntimeError
97 | }
98 |
--------------------------------------------------------------------------------
/Scripting/CompletionTestSupport.psm1:
--------------------------------------------------------------------------------
1 |
2 | class CompletionResult
3 | {
4 | [string]$CompletionText
5 | [string]$ListItemText
6 | [System.Management.Automation.CompletionResultType]$ResultType
7 | [string]$ToolTip
8 | [bool]$Found
9 |
10 | [bool] Equals($Other)
11 | {
12 | if ($Other -isnot [CompletionResult] -and
13 | $Other -isnot [System.Management.Automation.CompletionResult])
14 | {
15 | return $false
16 | }
17 |
18 | # Comparison is intentionally fuzzy - CompletionText and ResultType must be specified
19 | # but the other properties don't need to match if they aren't specified
20 |
21 | if ($this.CompletionText -cne $Other.CompletionText -or
22 | $this.ResultType -ne $Other.ResultType)
23 | {
24 | return $false
25 | }
26 |
27 | if ($this.ListItemText -cne $Other.ListItemText -and
28 | ![string]::IsNullOrEmpty($this.ListItemText) -and ![string]::IsNullOrEmpty($Other.ListItemText))
29 | {
30 | return $false
31 | }
32 |
33 | if ($this.ToolTip -cne $Other.ToolTip -and
34 | ![string]::IsNullOrEmpty($this.ToolTip) -and ![string]::IsNullOrEmpty($Other.ToolTip))
35 | {
36 | return $false
37 | }
38 |
39 | return $true
40 | }
41 | }
42 |
43 | class CompletionTestCase
44 | {
45 | [string]$Description
46 | [CompletionResult[]]$ExpectedResults
47 | [string[]]$NotExpectedResults
48 | [hashtable]$TestInput
49 | }
50 |
51 | function Get-Completions
52 | {
53 | [CmdletBinding()]
54 | param([string]$InputScript, [int]$CursorColumn, $Options = $null)
55 |
56 | if (!$PSBoundParameters.ContainsKey('CursorColumn'))
57 | {
58 | $CursorColumn = $InputScript.IndexOf('<#CURSOR#>')
59 | if ($CursorColumn -lt 0)
60 | {
61 | $CursorColumn = $InputScript.Length
62 | }
63 | else
64 | {
65 | $InputScript = $InputScript -replace '<#CURSOR#>',''
66 | }
67 | }
68 |
69 | $results = [System.Management.Automation.CommandCompletion]::CompleteInput(
70 | <#inputScript#> $InputScript,
71 | <#cursorColumn#> $CursorColumn,
72 | <#options#> $Options)
73 |
74 | return $results
75 | }
76 |
77 | function Get-CompletionTestCaseData
78 | {
79 | param(
80 | [Parameter(ValueFromPipeline)]
81 | [hashtable[]]$Data)
82 |
83 | process
84 | {
85 | Write-Output ([CompletionTestCase[]]$Data)
86 | }
87 | }
88 |
89 | function Test-Completions
90 | {
91 | param(
92 | [Parameter(ValueFromPipeline)]
93 | [CompletionTestCase[]]$TestCases,
94 | [string]
95 | $Description)
96 |
97 | process
98 | {
99 | foreach ($test in $TestCases)
100 | {
101 | Describe $test.Description {
102 | $hash = $Test.TestInput
103 | $results = Get-Completions @hash
104 |
105 | foreach ($expected in $test.ExpectedResults)
106 | {
107 | foreach ($result in $results.CompletionMatches)
108 | {
109 |
110 | if ($expected.Equals($result))
111 | {
112 | It "Checking for duplicates of: $($expected.CompletionText)" {
113 | # We should only find 1 of each expected result
114 | $expected.Found | Should Be $false
115 | }
116 | $expected.Found = $true
117 | }
118 | }
119 | }
120 |
121 | foreach ($expected in $test.ExpectedResults)
122 | {
123 | It "Checking for presence of expected result: $($expected.CompletionText)" {
124 | $expected.Found | Should Be $true
125 | }
126 | }
127 |
128 | foreach ($notExpected in $test.NotExpectedResults)
129 | {
130 | foreach ($result in $results.CompletionMatches)
131 | {
132 | It "Checking for results that should not be found: $notExpected" {
133 | $result.CompletionText -cne $notExpected | Should Be $true
134 | }
135 | }
136 | }
137 |
138 | }
139 | }
140 | }
141 | }
142 |
143 |
--------------------------------------------------------------------------------
/Scripting/LanguageTestSupport.psm1:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Run the new parser, return either errors or the ast
4 | #
5 | function Get-ParseResults
6 | {
7 | [CmdletBinding()]
8 | param(
9 | [Parameter(ValueFromPipeline=$True,Mandatory=$True)]
10 | [string]$src,
11 | [switch]$Ast
12 | )
13 |
14 | $errors = $null
15 | $result = [System.Management.Automation.Language.Parser]::ParseInput($src, [ref]$null, [ref]$errors)
16 | if ($Ast) { $result } else { ,$errors }
17 | }
18 |
19 | #
20 | # Run script and return errors
21 | #
22 | function Get-RuntimeError
23 | {
24 | [CmdletBinding()]
25 | param(
26 | [Parameter(ValueFromPipeline=$True,Mandatory=$True)]
27 | [string]$src
28 | )
29 |
30 | $errors = $null
31 | try
32 | {
33 | [scriptblock]::Create($src).Invoke() > $null
34 | }
35 | catch
36 | {
37 | return $_.Exception.InnerException.ErrorRecord
38 | }
39 | }
40 |
41 | function position_message
42 | {
43 | param($position)
44 |
45 | if ($position.Line.Length -lt $position.ColumnNumber)
46 | {
47 | $position.Line + " <<<<"
48 | }
49 | else
50 | {
51 | $position.Line.Insert($position.ColumnNumber, " <<<<")
52 | }
53 | }
54 |
55 |
56 | #
57 | # Run the new parser, check the errors against the expected errors
58 | #
59 | function Test-Error
60 | {
61 | [CmdletBinding()]
62 | param([string]$src, [string[]]$expectedErrors, [int[]]$expectedOffsets)
63 |
64 | Assert ($expectedErrors.Count -eq $expectedOffsets.Count) "Test case error"
65 |
66 | $errors = Get-ParseResults -Src $src
67 |
68 |
69 | if ($null -ne $errors)
70 | {
71 | Assert ($errors.Count -eq $expectedErrors.Count) "Expected $($expectedErrors.Count) errors, got $($errors.Count)"
72 | for ($i = 0; $i -lt $errors.Count; ++$i)
73 | {
74 | $err = $errors[$i]
75 | Assert ($expectedErrors[$i] -eq $err.ErrorId) ("Unexpected error: {0,-30}{1}" -f ("$($err.ErrorId):",
76 | (position_message $err.Extent.StartScriptPosition)))
77 | Assert ($expectedOffsets[$i] -eq $err.Extent.StartScriptPosition.Offset) `
78 | "Expected position: $($expectedOffsets[$i]), got $($err.Extent.StartScriptPosition.Offset)"
79 | }
80 | }
81 | else
82 | {
83 | Assert $false "Expected errors but didn't receive any."
84 | }
85 | }
86 |
87 | #
88 | # Pester friendly version of Test-Error
89 | #
90 | function ShouldBeParseError
91 | {
92 | [CmdletBinding()]
93 | param(
94 | [string]$src,
95 | [string[]]$expectedErrors,
96 | [int[]]$expectedOffsets,
97 | # This is a temporary solution after moving type creation from parse time to runtime
98 | [switch]$SkipAndCheckRuntimeError
99 | )
100 |
101 | Context "Parse error expected: <<$src>>" {
102 | # Test case error if this fails
103 | $expectedErrors.Count | Should Be $expectedOffsets.Count
104 |
105 | if ($SkipAndCheckRuntimeError)
106 | {
107 | It "error should happen at parse time, not at runtime" -Skip {}
108 | $errors = Get-RuntimeError -Src $src
109 | # for runtime errors we will only get the first one
110 | $expectedErrors = ,$expectedErrors[0]
111 | $expectedOffsets = ,$expectedOffsets[0]
112 | }
113 | else
114 | {
115 | $errors = Get-ParseResults -Src $src
116 | }
117 |
118 | It "Error count" { $errors.Count | Should Be $expectedErrors.Count }
119 | for ($i = 0; $i -lt $errors.Count; ++$i)
120 | {
121 | $err = $errors[$i]
122 |
123 | if ($SkipAndCheckRuntimeError)
124 | {
125 | $errorId = $err.FullyQualifiedErrorId
126 | }
127 | else
128 | {
129 | $errorId = $err.ErrorId
130 | }
131 | It "Error Id" { $errorId | Should Be $expectedErrors[$i] }
132 | It "Error position" -Pending:$SkipAndCheckRuntimeError { $err.Extent.StartScriptPosition.Offset | Should Be $expectedOffsets[$i] }
133 | }
134 | }
135 | }
136 |
137 |
138 | function Flatten-Ast
139 | {
140 | [CmdletBinding()]
141 | param([System.Management.Automation.Language.Ast] $ast)
142 |
143 | $ast
144 | $ast | gm -type property | ? { ($prop = $_.Name) -ne 'Parent' } | % {
145 | $ast.$prop | ? { $_ -is [System.Management.Automation.Language.Ast] } | % { Flatten-Ast $_ }
146 | }
147 | }
148 |
149 | function Test-ErrorStmt
150 | {
151 | param([string]$src, [string]$errorStmtExtent)
152 |
153 | $ast = Get-ParseResults $src -Ast
154 | $asts = @(Flatten-Ast $ast.EndBlock.Statements[0])
155 |
156 | Assert ($asts[0] -is [System.Management.Automation.Language.ErrorStatementAst]) "Expected error statement"
157 | Assert ($asts.Count -eq $args.Count + 1) "Incorrect number of nested asts"
158 | Assert ($asts[0].Extent.Text -eq $errorStmtExtent) "Error statement expected <$errorStmtExtent>, got <$($asts[0].Extent.Text)>"
159 | for ($i = 0; $i -lt $args.Count; ++$i)
160 | {
161 | Assert ($asts[$i + 1].Extent.Text -eq $args[$i]) "Nested ast incorrect: <$($asts[$i+1].Extent.Text)>, expected <$($args[$i])>"
162 | }
163 | }
164 |
165 | function Test-Ast
166 | {
167 | param([string]$src)
168 |
169 | $ast = Get-ParseResults $src -Ast
170 | $asts = @(Flatten-Ast $ast)
171 | Assert ($asts.Count -eq $args.Count) "Incorrect number of nested asts, got $($asts.Count), expected $($args.Count)"
172 | for ($i = 0; $i -lt $args.Count; ++$i)
173 | {
174 | Assert ($asts[$i].Extent.Text -eq $args[$i]) "Nested ast incorrect: <$($asts[$i].Extent.Text)>, expected <$($args[$i])>"
175 | }
176 | }
177 |
178 | Export-ModuleMember -Function Test-Error, Test-ErrorStmt, Test-Ast, ShouldBeParseError, Get-ParseResults, Get-RuntimeError
179 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/BNotOperator.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 |
3 | $baseTypes = @{
4 | [SByte] = 'sbyte'; [Byte] = 'byte'
5 | [Int16] = 'short'; [UInt16] = 'ushort'
6 | [Int32] = 'int'; [UInt32] = 'uint'
7 | [Int64] = 'long'; [UInt64] = 'ulong'
8 | }
9 |
10 | $ns = [Guid]::NewGuid() -replace '-',''
11 |
12 | $typeDefinition = "namespace ns_$ns`n{"
13 |
14 | $enumTypeNames = foreach ($baseType in $baseTypes.Keys)
15 | {
16 | $baseTypeName = $baseTypes[$baseType]
17 | $typeDefinition += @"
18 | public enum E_$baseTypeName : $baseTypeName
19 | {
20 | Min = $($baseType::MinValue),
21 | MinPlus1 = $($baseType::MinValue + 1),
22 | MaxMinus1 = $($baseType::MaxValue - 1),
23 | Max = $($baseType::MaxValue)
24 | }
25 | "@
26 |
27 | "ns_$ns.E_$baseTypeName"
28 | }
29 |
30 | $typeDefinition += "`n}"
31 |
32 | Write-Verbose $typeDefinition
33 | Add-Type $typeDefinition
34 |
35 | Describe "bnot on enums" -Tags "DRT" {
36 | foreach ($enumType in [type[]]$enumTypeNames)
37 | {
38 | Context $enumType.Name {
39 | It "max - 1" {
40 | $res = -bnot $enumType::MaxMinus1
41 | $res | Should Be $enumType::MinPlus1
42 | $res.GetType() | Should Be $enumType
43 | }
44 |
45 | It "min + 1" {
46 | $res = -bnot $enumType::MinPlus1
47 | $res | Should Be $enumType::MaxMinus1
48 | $res.GetType() | Should Be $enumType
49 | }
50 |
51 | It "Max" {
52 | $res = -bnot $enumType::Max
53 | $res | Should Be $enumType::Min
54 | $res.GetType() | Should Be $enumType
55 | }
56 |
57 | It "Min" {
58 | $res = -bnot $enumType::Min
59 | $res | Should Be $enumType::Max
60 | $res.GetType() | Should Be $enumType
61 | }
62 | }
63 | }
64 | }
65 |
66 | Describe "bnot on integral types" -Tags "DRT" {
67 | foreach ($baseType in $baseTypes.Keys)
68 | {
69 | Context $baseType.Name {
70 |
71 | $max = $baseType::MaxValue
72 | $maxMinus1 = $max - 1
73 | $min = $baseType::MinValue
74 | $minPlus1 = $min + 1
75 |
76 | if ([System.Runtime.InteropServices.Marshal]::SizeOf([type]$baseType) -lt 4)
77 | {
78 | $expectedResultType = [int]
79 | }
80 | else
81 | {
82 | $expectedResultType = $baseType
83 | }
84 |
85 | if ($baseType -eq [byte] -or $baseType -eq [uint16])
86 | {
87 | # Because of type promotion rules, unsigned types smaller than int
88 | # don't quite follow the pattern of "flip all the bits", so our
89 | # tests are a little different.
90 | It "max - 1" {
91 | $res = -bnot $maxMinus1
92 | $res | Should Be (-bnot [int]$maxMinus1)
93 | $res.GetType() | Should Be $expectedResultType
94 | }
95 |
96 | It "min + 1" {
97 | $res = -bnot $minPlus1
98 | $res | Should Be (-bnot [int]$minPlus1)
99 | $res.GetType() | Should Be $expectedResultType
100 | }
101 |
102 | It "max" {
103 | $res = -bnot $max
104 | $res | Should Be (-bnot [int]$max)
105 | $res.GetType() | Should Be $expectedResultType
106 | }
107 |
108 | It "min" {
109 | $res = -bnot $min
110 | $res | Should Be (-bnot [int]$min)
111 | $res.GetType() | Should Be $expectedResultType
112 | }
113 | return
114 | }
115 |
116 | It "max - 1" {
117 | $res = -bnot $maxMinus1
118 | $res | Should Be $minPlus1
119 | $res.GetType() | Should Be $expectedResultType
120 | }
121 |
122 | It "min + 1" {
123 | $res = -bnot $minPlus1
124 | $res | Should Be $maxMinus1
125 | $res.GetType() | Should Be $expectedResultType
126 | }
127 |
128 | It "max" {
129 | $res = -bnot $max
130 | $res | Should Be $min
131 | $res.GetType() | Should Be $expectedResultType
132 | }
133 |
134 | It "min" {
135 | $res = -bnot $min
136 | $res | Should Be $max
137 | $res.GetType() | Should Be $expectedResultType
138 | }
139 | }
140 | }
141 | }
142 |
143 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/Completion.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path
2 | Import-Module $here\..\CompletionTestSupport.psm1 -force
3 |
4 | # Convince the Pester Harness adapter that this is a pester test
5 | if ($false) { Describe; It }
6 |
7 | @{
8 | Description = "Completion doesn't cause stack overflow"
9 | ExpectedResults = @(
10 | @{CompletionText = "BaseObject"; ResultType = "Property"}
11 | @{CompletionText = "Members"; ResultType = "Property"}
12 | @{CompletionText = "GetMetaObject("; ResultType = "Method"}
13 | @{CompletionText = "Equals("; ResultType = "Method"}
14 | @{CompletionText = "ToString("; ResultType = "Method"})
15 | TestInput = @{inputScript = @'
16 | $dums = @()
17 | $dum = new-object PSObject
18 | $dum | add-member noteproperty Blah "blah"
19 | $dums += $dum
20 | foreach($dum in $dums) {
21 | $dum.<#CURSOR#>
22 | }
23 | '@ }
24 | } | Get-CompletionTestCaseData | Test-Completions
25 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/LanguageAndParser.TestFollowup.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | Describe "Clone array" {
3 | It "Cast in target expr" {
4 | (([int[]](42)).clone()) | Should Be 42
5 | (([int[]](1..5)).clone()).Length | Should Be 5
6 | (([int[]](1..5)).clone()).GetType() | Should Be ([int[]])
7 |
8 | }
9 | It "Cast not in target expr" {
10 | $e = [int[]](42)
11 | $e.Clone() | Should Be 42
12 | $e = [int[]](1..5)
13 | $e.Clone().Length | Should Be 5
14 | $e.Clone().GetType() | Should Be ([int[]])
15 | }
16 | }
17 |
18 | Describe "Set fields through PSMemberInfo" {
19 | Add-Type @"
20 | public struct AStruct { public string s; }
21 | "@
22 |
23 | It "via cast" {
24 | ([AStruct]@{s = "abc" }).s | Should Be "abc"
25 | }
26 | It "via new-object" {
27 | (new-object AStruct -prop @{s="abc"}).s | Should Be "abc"
28 | }
29 | It "via PSObject" {
30 | $x = [AStruct]::new()
31 | $x.psobject.properties['s'].Value = 'abc'
32 | $x.s | Should Be "abc"
33 | }
34 | }
35 |
36 | Describe "MSFT:3309783" {
37 | # For a reliable test, we must run this in a new process because an earlier binding in this process
38 | # could mask the bug/fix.
39 | powershell -noprofile -command "[psobject] | % FullName" | Should Be System.Management.Automation.PSObject
40 |
41 | # For good measure, do the same thing in this process
42 | [psobject] | % FullName | Should Be System.Management.Automation.PSObject
43 |
44 | # Related - make sure we can still pipe objects derived from PSObject
45 | class MyPsObj : PSObject
46 | {
47 | MyPsObj($obj) : base($obj) { }
48 | [string] ToString() {
49 | # Don't change access via .psobject, that was also a bug.
50 | return "MyObj: " + $this.psobject.BaseObject
51 | }
52 | }
53 |
54 | [MyPsObj]::new("abc").psobject.ToString() | Should Be "MyObj: abc"
55 | [MyPsObj]::new("def") | Out-String | % Trim | Should Be "MyObj: def"
56 | }
57 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/MethodInvocation.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | Describe "Interface inheritance with remoting proxies" -Tags "P1", "RI" {
3 | $src = @"
4 | using System;
5 | using System.ServiceModel;
6 |
7 | namespace MSFT_716893
8 | {
9 | [ServiceContract]
10 | public interface IInterface1
11 | {
12 | [OperationContract]string BaseOperation(int i);
13 | }
14 |
15 | [ServiceContract]
16 | public interface IInterface2 : IInterface1
17 | {
18 | [OperationContract(Name="op1")]string Operation(string a);
19 | [OperationContract(Name="op2")]string Operation(string a, string b);
20 | }
21 |
22 | public class ServiceImplementation : IInterface2
23 | {
24 | public string Operation(string a) { return "1 - " + a; }
25 | public string Operation(string a, string b) { return "2 - " + a + " " + b; }
26 | public string BaseOperation(int i) { return "3 - " + i; }
27 | }
28 |
29 | public static class Service
30 | {
31 | static ServiceHost serviceHost;
32 |
33 | public static void Init()
34 | {
35 | Uri baseAddress = new Uri("http://localhost:8080/service");
36 | serviceHost = new ServiceHost(typeof(ServiceImplementation), baseAddress);
37 | serviceHost.Open();
38 | }
39 |
40 | public static IInterface1 GetProxy()
41 | {
42 | ChannelFactory factory = new ChannelFactory(
43 | serviceHost.Description.Endpoints[0].Binding,
44 | serviceHost.Description.Endpoints[0].Address);
45 | return factory.CreateChannel();
46 | }
47 |
48 | public static void Close()
49 | {
50 | serviceHost.Close();
51 | }
52 | }
53 | }
54 | "@
55 |
56 | Add-Type -TypeDefinition $src -ReferencedAssemblies System.ServiceModel.dll
57 |
58 | BeforeEach {
59 | [MSFT_716893.Service]::Init()
60 | $proxy = [MSFT_716893.Service]::GetProxy()
61 | }
62 |
63 | AfterEach {
64 | [MSFT_716893.Service]::Close()
65 | }
66 |
67 | It "Direct invocation" {
68 | $proxy.Operation("a") | Should Be "1 - a"
69 | $proxy.Operation("a", "b") | Should Be "2 - a b"
70 | $proxy.BaseOperation(42) | Should Be "3 - 42"
71 | }
72 |
73 | It "Invocation via method constraints" {
74 | ([MSFT_716893.IInterface2]$proxy).Operation("c") | Should Be "1 - c"
75 | ([MSFT_716893.IInterface2]$proxy).Operation("d", "e") | Should Be "2 - d e"
76 | ([MSFT_716893.IInterface1]$proxy).BaseOperation(22) | Should Be "3 - 22"
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/ParameterBinding.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | Describe 'Argument transformation attribute on optional argument with explicit $null' -Tags "P1", "RI" {
3 | $mod = Add-Type -PassThru -TypeDefinition @'
4 | using System;
5 | using System.Management.Automation;
6 | using System.Reflection;
7 |
8 | namespace MSFT_1407291
9 | {
10 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
11 | public class AddressTransformationAttribute : ArgumentTransformationAttribute
12 | {
13 | public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
14 | {
15 | return (ulong) 42;
16 | }
17 | }
18 |
19 | [Cmdlet(VerbsLifecycle.Invoke, "CSharpCmdletTakesUInt64")]
20 | [OutputType(typeof(System.String))]
21 | public class Cmdlet1 : PSCmdlet
22 | {
23 | [Parameter(Mandatory = false)]
24 | [AddressTransformation]
25 | public ulong Address { get; set; }
26 |
27 | protected override void ProcessRecord()
28 | {
29 | WriteObject(Address);
30 | }
31 | }
32 |
33 | [Cmdlet(VerbsLifecycle.Invoke, "CSharpCmdletTakesObject")]
34 | [OutputType(typeof(System.String))]
35 | public class Cmdlet2 : PSCmdlet
36 | {
37 | [Parameter(Mandatory = false)]
38 | [AddressTransformation]
39 | public object Address { get; set; }
40 |
41 | protected override void ProcessRecord()
42 | {
43 | WriteObject(Address ?? "passed in null");
44 | }
45 | }
46 | }
47 | '@
48 |
49 | Import-Module $mod[0].Assembly
50 |
51 | function Invoke-ScriptFunctionTakesObject
52 | {
53 | param([MSFT_1407291.AddressTransformation()]
54 | [Parameter(Mandatory = $false)]
55 | [object]$Address = "passed in null")
56 |
57 | return $Address
58 | }
59 |
60 | function Invoke-ScriptFunctionTakesUInt64
61 | {
62 | param([MSFT_1407291.AddressTransformation()]
63 | [Parameter(Mandatory = $false)]
64 | [Uint64]$Address = 11)
65 |
66 | return $Address
67 | }
68 |
69 |
70 | Invoke-ScriptFunctionTakesObject | Should Be 42
71 | Invoke-ScriptFunctionTakesUInt64 | Should Be 42
72 | Invoke-CSharpCmdletTakesObject | Should Be "passed in null"
73 | Invoke-CSharpCmdletTakesUInt64 | Should Be 0
74 |
75 | Invoke-ScriptFunctionTakesObject -Address $null | Should Be 42
76 | Invoke-ScriptFunctionTakesUInt64 -Address $null | Should Be 42
77 | Invoke-CSharpCmdletTakesObject -Address $null | Should Be 42
78 | Invoke-CSharpCmdletTakesUInt64 -Address $null | Should Be 42
79 | }
80 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/Pester.Ast.Tests.ps1:
--------------------------------------------------------------------------------
1 | using Namespace System.Management.Automation.Language
2 | Describe "The SafeGetValue method on AST returns safe values" -Tags "DRT" {
3 | It "A hashtable is returned from a HashtableAst" {
4 | $HashtableAstType = [HashtableAst]
5 | $HtAst = {
6 | @{ one = 1 }
7 | }.ast.Find({$args[0] -is $HashtableAstType}, $true)
8 | $HtAst.SafeGetValue().GetType().Name | Should be Hashtable
9 | }
10 | It "An Array is returned from a LiteralArrayAst" {
11 | $ArrayAstType = [ArrayLiteralAst]
12 | $ArrayAst = {
13 | @( 1,2,3,4)
14 | }.ast.Find({$args[0] -is $ArrayAstType}, $true)
15 | $ArrayAst.SafeGetValue().GetType().Name | Should be "Object[]"
16 | }
17 | It "The proper error is returned when a variable is referenced" {
18 | $ast = { $a }.Ast.Find({$args[0] -is "VariableExpressionAst"},$true)
19 | try {
20 | $ast.SafeGetValue() | out-null
21 | Throw "Execution Succeeded"
22 | }
23 | catch {
24 | $_.FullyQualifiedErrorId | Should be "InvalidOperationException"
25 | $_.ToString() | Should Match '\$a'
26 | }
27 | }
28 | It "A ScriptBlock AST fails with the proper error" {
29 | try {
30 | { 1 }.Ast.SafeGetValue()
31 | Throw "Execution Succeeded"
32 | }
33 | catch {
34 | $_.FullyQualifiedErrorId | Should be "InvalidOperationException"
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/Pester.RedirectionOperator.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Redirection operator now supports encoding changes" {
2 | BeforeAll {
3 | $asciiString = "abc"
4 | $asciiCR = "`r`n"
5 |
6 | # If out-file -encoding happens to have a default, be sure to
7 | # save it away
8 | $SavedValue = $null
9 | $oldDefaultParameterValues = $psDefaultParameterValues
10 | $psDefaultParameterValues = @{}
11 | }
12 | AfterAll {
13 | # be sure to tidy up afterwards
14 | $psDefaultParameterValues = $oldDefaultParameterValues
15 | }
16 | BeforeEach {
17 | # start each test with a clean plate!
18 | $psdefaultParameterValues.Remove("out-file:encoding")
19 | }
20 | AfterEach {
21 | # end each test with a clean plate!
22 | $psdefaultParameterValues.Remove("out-file:encoding")
23 | }
24 |
25 | It "If encoding is unset, redirection should be Unicode" {
26 | $asciiString > TESTDRIVE:\file.txt
27 | $bytes = get-content -encoding byte TESTDRIVE:\file.txt
28 | # create the expected
29 | $BOM = [text.encoding]::unicode.GetPreamble()
30 | $TXT = [text.encoding]::unicode.GetBytes($asciiString)
31 | $CR = [text.encoding]::unicode.GetBytes($asciiCR)
32 | $expectedBytes = .{ $BOM; $TXT; $CR }
33 | $bytes.Count | should be $expectedBytes.count
34 | for($i = 0; $i -lt $bytes.count; $i++) {
35 | $bytes[$i] | Should be $expectedBytes[$i]
36 | }
37 | }
38 |
39 | # $availableEncodings = "unknown","string","unicode","bigendianunicode","utf8","utf7", "utf32","ascii","default","oem"
40 | $availableEncodings = (get-command out-file).Parameters["Encoding"].Attributes.ValidValues
41 |
42 | foreach($encoding in $availableEncodings) {
43 | # some of the encodings accepted by out-file aren't real,
44 | # and out-file has its own translation, so we'll
45 | # not do that logic here, but simply ignore those encodings
46 | # as they eventually are translated to "real" encoding
47 | $enc = [system.text.encoding]::$encoding
48 | if ( $enc )
49 | {
50 | $msg = "Overriding encoding for out-file is respected for $encoding"
51 | $BOM = $enc.GetPreamble()
52 | $TXT = $enc.GetBytes($asciiString)
53 | $CR = $enc.GetBytes($asciiCR)
54 | $expectedBytes = .{ $BOM; $TXT; $CR }
55 | $psdefaultparameterValues["out-file:encoding"] = $encoding
56 | $asciiString > TESTDRIVE:/file.txt
57 | $observedBytes = Get-Content -encoding Byte TESTDRIVE:/file.txt
58 | # THE TEST
59 | It -pending $msg {
60 | $observedBytes.Count | Should be $expectedBytes.Count
61 | for($i = 0;$i -lt $observedBytes.Count; $i++) {
62 | $observedBytes[$i] | Should be $expectedBytes[$i]
63 | }
64 | }
65 |
66 | }
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/TypeAccelerator.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | Describe "Type accelerators" -Tags "DRT" {
3 | $TypeAcceleratorsType = [psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")
4 |
5 | $TypeAccelerators = $TypeAcceleratorsType::Get
6 | $TypeAcceleratorsType::Add('msft_2174855', [int])
7 | $TypeAcceleratorsType::Add('msft_2174855_rm', [int])
8 |
9 | It "Basic type accelerator usage" {
10 | [msft_2174855] | Should Be ([int])
11 | }
12 |
13 | It "Can query type accelerators" {
14 | $TypeAccelerators.Count -gt 82 | Should Be $true
15 | $TypeAccelerators['xml'] | Should Be ([System.Xml.XmlDocument])
16 | $TypeAccelerators['AllowNull'] | Should Be ([System.Management.Automation.AllowNullAttribute])
17 | }
18 |
19 | It "Can remove type accelerator" {
20 | $TypeAcceleratorsType::Get['msft_2174855_rm'] | Should Be ([int])
21 | $TypeAcceleratorsType::Remove('msft_2174855_rm')
22 | $TypeAcceleratorsType::Get['msft_2174855_rm'] | Should Be $null
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/UsingAssembly.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | Describe "Using assembly" -Tags "DRT" {
3 |
4 | try
5 | {
6 | pushd $PSScriptRoot
7 | $guid = [Guid]::NewGuid()
8 |
9 | Add-Type -OutputAssembly $PSScriptRoot\UsingAssemblyTest$guid.dll -TypeDefinition @"
10 | public class ABC {}
11 | "@
12 |
13 | It 'parse reports error on non-existing assembly by relative path' {
14 | $err = $null
15 | $ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly foo.dll", [ref]$null, [ref]$err)
16 |
17 | $err.Count | Should Be 1
18 | $err[0].ErrorId | Should Be ErrorLoadingAssembly
19 | }
20 |
21 | It 'parse reports error on assembly with non-existing fully qualified name' {
22 | $err = $null
23 | $ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly 'System.Management.Automation, Version=99.0.0.0'", [ref]$null, [ref]$err)
24 |
25 | $err.Count | Should Be 1
26 | $err[0].ErrorId | Should Be ErrorLoadingAssembly
27 | }
28 |
29 | It 'not allow UNC path' {
30 | $err = $null
31 | $ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly \\networkshare\foo.dll", [ref]$null, [ref]$err)
32 |
33 | $err.Count | Should Be 1
34 | $err[0].ErrorId | Should Be CannotLoadAssemblyFromUncPath
35 | }
36 |
37 | It 'not allow http path' {
38 | $err = $null
39 | $ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly http://microsoft.com/foo.dll", [ref]$null, [ref]$err)
40 |
41 | $err.Count | Should Be 1
42 | $err[0].ErrorId | Should Be CannotLoadAssemblyWithUriSchema
43 | }
44 |
45 | It "parse does not load the assembly" {
46 | $assemblies = [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
47 | $assemblies -contains "UsingAssemblyTest$guid" | Should Be $false
48 |
49 | $err = $null
50 | $ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly .\UsingAssemblyTest$guid.dll", [ref]$null, [ref]$err)
51 |
52 | $assemblies = [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
53 | $assemblies -contains "UsingAssemblyTest$guid" | Should Be $false
54 | $err.Count | Should Be 0
55 |
56 | $ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly '$PSScriptRoot\UsingAssemblyTest$guid.dll'", [ref]$null, [ref]$err)
57 |
58 | $assemblies = [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
59 | $assemblies -contains "UsingAssemblyTest$guid" | Should Be $false
60 | $err.Count | Should Be 0
61 |
62 | $ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly `"$PSScriptRoot\UsingAssemblyTest$guid.dll`"", [ref]$null, [ref]$err)
63 |
64 | $assemblies = [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
65 | $assemblies -contains "UsingAssemblyTest$guid" | Should Be $false
66 | $err.Count | Should Be 0
67 | }
68 |
69 | It "reports runtime error about non-existing assembly with relative path" {
70 | $failed = $true
71 | try {
72 | [scriptblock]::Create("using assembly .\NonExistingAssembly.dll")
73 | $failed = $false
74 | } catch {
75 | $_.FullyQualifiedErrorId | Should be 'ParseException'
76 | $_.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should be 'ErrorLoadingAssembly'
77 | }
78 | $failed | Should be $true
79 | }
80 | #>
81 | It "Assembly loaded at runtime" {
82 | $assemblies = powershell -noprofile -command @"
83 | using assembly .\UsingAssemblyTest$guid.dll
84 | [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
85 | "@
86 | $assemblies -contains "UsingAssemblyTest$guid" | Should Be $true
87 |
88 | $assemblies = powershell -noprofile -command @"
89 | using assembly $PSScriptRoot\UsingAssemblyTest$guid.dll
90 | [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
91 | "@
92 | $assemblies -contains "UsingAssemblyTest$guid" | Should Be $true
93 |
94 |
95 | $assemblies = powershell -noprofile -command @"
96 | using assembly System.Drawing
97 | [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
98 | "@
99 | $assemblies -contains "System.Drawing" | Should Be $true
100 |
101 | $assemblies = powershell -noprofile -command @"
102 | using assembly 'System.Drawing, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
103 | [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
104 | "@
105 | $assemblies -contains "System.Drawing" | Should Be $true
106 | }
107 | }
108 | finally
109 | {
110 | Remove-Item .\UsingAssemblyTest$guid.dll
111 | popd
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Scripting/LanguageandParser/UsingNamespace.Tests.ps1:
--------------------------------------------------------------------------------
1 |
2 | # There is an automatic 'using namespace system' which is
3 | # tested by this test, so don't uncomment the following:
4 | #using namespace System
5 | using namespace System.Threading
6 | using namespace System.Timers
7 | # Test parsing more than one using statement on one line
8 | using namespace System.Diagnostics; using namespace System.Runtime.CompilerServices
9 | using namespace System.Collections.Generic
10 |
11 | Import-Module $PSScriptRoot\..\LanguageTestSupport.psm1
12 |
13 | function ShouldBeErrorId
14 | {
15 | param([Parameter(ValueFromPipeline, Mandatory)]
16 | [ScriptBlock]
17 | $sb,
18 |
19 | [Parameter(Mandatory, Position=0)]
20 | [string]
21 | $FullyQualifiedErrorId)
22 |
23 | try
24 | {
25 | & $sb
26 | throw "Unexpected"
27 | }
28 | catch
29 | {
30 | $_.FullyQualifiedErrorId | Should Be $FullyQualifiedErrorId
31 | }
32 | }
33 |
34 | # Flags is System.FlagsAttribute
35 | # This tests our implicit 'using namespace System'
36 | # despite having other explicit using namespace statements.
37 | [Flags()]
38 | enum E1
39 | {
40 | E1 = 0x01
41 | E2 = 0x02
42 | E4 = 0x04
43 | }
44 |
45 | # Test attributes that won't be found w/o using, but w/o implicit Attribute suffix
46 | [CompilerGenerated()]
47 | class C1
48 | {
49 | [Thread][CompilerGenerated()]$Thread
50 | [Int32][CompilerGenerated()]$Int
51 | [ElapsedEventHandler][CompilerGenerated()]$EventHandler
52 | }
53 |
54 | # Test attributes that won't be found w/o using, but w/ implicit Attribute suffix
55 | [CompilerGeneratedAttribute()]
56 | class C2
57 | {
58 | [Thread][CompilerGeneratedAttribute()]$Thread
59 | [Int32][CompilerGeneratedAttribute()]$Int
60 | [ElapsedEventHandler][CompilerGeneratedAttribute()]$EventHandler
61 | }
62 |
63 | Describe "Using Namespace" -Tags "DRT" {
64 | It "Type literals w/ using namespace" {
65 | [Thread].FullName | Should Be System.Threading.Thread
66 | [Int32].FullName | Should Be System.Int32
67 | [ElapsedEventHandler].FullName | Should Be System.Timers.ElapsedEventHandler
68 |
69 | [C1].GetProperty("Thread").PropertyType.FullName | Should Be System.Threading.Thread
70 | [C1].GetProperty("Int").PropertyType.FullName | Should Be System.Int32
71 | [C1].GetProperty("EventHandler").PropertyType.FullName | Should Be System.Timers.ElapsedEventHandler
72 | }
73 |
74 | It "Covert string to Type w/ using namespace" {
75 | ("Thread" -as [Type]).FullName | Should Be System.Threading.Thread
76 | ("Int32" -as [Type]).FullName | Should Be System.Int32
77 | ("ElapsedEventHandler" -as [Type]).FullName | Should Be System.Timers.ElapsedEventHandler
78 |
79 | New-Object Int32 | Should Be 0
80 | New-Object CompilerGeneratedAttribute | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
81 | }
82 |
83 | It "Attributes w/ using namespace" {
84 | function foo
85 | {
86 | [DebuggerStepThrough()]
87 | param(
88 | [CompilerGeneratedAttribute()]
89 | $a,
90 |
91 | [CompilerGenerated()]
92 | $b
93 | )
94 |
95 | "OK"
96 | }
97 |
98 | foo | Should Be OK
99 | $cmdInfo = gcm foo
100 | $cmdInfo.ScriptBlock.Attributes[0] | Should Be System.Diagnostics.DebuggerStepThroughAttribute
101 | $cmdInfo.Parameters['a'].Attributes[1] | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
102 | $cmdInfo.Parameters['b'].Attributes[1] | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
103 |
104 | [C1].GetProperty("Thread").GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
105 | [C1].GetProperty("Int").GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
106 | [C1].GetProperty("EventHandler").GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
107 |
108 | [C2].GetProperty("Thread").GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
109 | [C2].GetProperty("Int").GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
110 | [C2].GetProperty("EventHandler").GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
111 |
112 | [C1].GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
113 | [C2].GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.Runtime.CompilerServices.CompilerGeneratedAttribute
114 |
115 | [E1].GetCustomAttributesData()[0].AttributeType.FullName | Should Be System.FlagsAttribute
116 | }
117 |
118 | It "Ambiguous type reference" {
119 | { [Timer] } | ShouldBeErrorId AmbiguousTypeReference
120 | }
121 |
122 | It "Parameters" {
123 | function foo([Thread]$t = $null) { 42 }
124 |
125 | foo | Should Be 42
126 |
127 | $mod = New-Module -Name UsingNamespaceModule -ScriptBlock {
128 | function Set-Thread([Thread]$t = $null)
129 | {
130 | 44
131 | }
132 | }
133 | Import-Module $mod
134 | Set-Thread | Should Be 44
135 | Remove-Module $mod
136 | }
137 |
138 | It "Generics" {
139 | function foo([List[string]]$l)
140 | {
141 | $l | Should Be "a string"
142 | }
143 |
144 | $l = [List[string]]::new()
145 | $l.Add("a string")
146 | foo $l
147 | }
148 |
149 | ShouldBeParseError "1; using namespace System" UsingMustBeAtStartOfScript 3
150 | ShouldBeParseError "using namespace Foo = System" UsingStatementNotSupported 0
151 | # TODO: add diagnostic (low pri)
152 | # ShouldBeParseError "using namespace System; using namespace System" UsingNamespaceAlreadySpecified 24
153 | }
154 |
155 |
--------------------------------------------------------------------------------
/Security/Pester.Acl.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Tests for Get-Acl and Set-Acl" -Tags "innerloop" {
2 |
3 | It "Verifies that you can change the ACL of a file that you own, but don't have explicit access to" {
4 |
5 | $caughtError = $false
6 |
7 | try
8 | {
9 | $tempDirectory = Join-Path TestDrive: GetSetAclPrivilegeTest
10 | $null = New-Item -ItemType Directory $tempDirectory
11 | $acl = Get-Acl $tempDirectory
12 | $acl.SetSecurityDescriptorSddlForm("O:SYG:SYD:PAI")
13 | Set-Acl -AclObject $acl $tempDirectory -ErrorAction Stop
14 |
15 | $acl.SetSecurityDescriptorSddlForm("O:DUG:DUD:PAI(A;OICI;FA;;;DU)")
16 | Set-Acl -AclObject $acl $tempDirectory -ErrorAction Stop
17 | }
18 | catch
19 | {
20 | $caughtError = $true
21 | }
22 |
23 | $caughtError | Should be $false
24 | }
25 |
26 | It "invalid access policy throws an error" {
27 | $fileName = New-Item TestDrive:\newFile.txt -Force
28 | Get-Acl $fileName | Set-Acl $fileName -CentralAccessPolicy "SomeInvalidAccessPolicy" -ErrorAction SilentlyContinue -ErrorVariable setAclError
29 | $setAclError.FullyQualifiedErrorId | Should Be "SetAcl_CentralAccessPolicy,Microsoft.PowerShell.Commands.SetAclCommand"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Security/Pester.Authenticode.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Tests for authenticode cmdlets" {
2 |
3 | It "Verifies that we can retrieve catalog signatures from OS Binaries" {
4 |
5 | ## Only supported on Win8+
6 | if([Version] (Get-WmiObject Win32_OperatingSystem).Version -lt ([Version] "6.2"))
7 | {
8 | return
9 | }
10 |
11 | $signature = Get-Command wmic | Get-Item | Get-AuthenticodeSignature
12 | $signature.IsOSBinary | Should be $true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Security/Pester.SuspiciousScriptBlockLogging.Tests.ps1:
--------------------------------------------------------------------------------
1 | function Test-SuspiciousScriptBlock
2 | {
3 | param(
4 | [ScriptBlock] $ScriptBlock,
5 | $Timeout = 30
6 | )
7 |
8 | $mi = [ScriptBlock].GetMethod("CheckSuspiciousContent", [System.Reflection.BindingFlags] "InvokeMethod,Static,NonPublic")
9 | $results = $mi.Invoke($null, $ScriptBlock.Ast)
10 |
11 | if($results) { $true }
12 | else { $false }
13 | }
14 |
15 | Describe "Tests for suspicious script blocks being logged automatically" -Tags "OuterLoop" {
16 |
17 | It "Detects a bad type being used directly" {
18 | Test-SuspiciousScriptBlock { [System.Runtime.InteropServices.Marshal]::PtrToStringAuto } | Should be $true
19 | }
20 |
21 | It "Detects using a variable to access a static member" {
22 |
23 | Test-SuspiciousScriptBlock { $mshall::NumParamBytes } | Should be $true
24 | }
25 |
26 | It "Allows non-static access to a variable" {
27 | Test-SuspiciousScriptBlock -Timeout 3 { $mshall.NumParamBytes } | Should be $false
28 | }
29 |
30 | It "Detects casts to [Type]" {
31 | Test-SuspiciousScriptBlock { $mshall = [Type] ("System.Runtime.InteropService" + "s.Mars" + "hal") } | Should be $true
32 | }
33 |
34 | It "Allows casting to other object types" {
35 | Test-SuspiciousScriptBlock -Timeout 3 { $mshall = [String] ("System.Runtime.InteropService" + "s.Mars" + "hal") } | Should be $false
36 | }
37 |
38 | It "Detects access to [Type] members" {
39 | Test-SuspiciousScriptBlock { $mshall = [Type]::Equals("System.Runtime.InteropService" + "s.Mars" + "hal") } | Should be $true
40 | }
41 |
42 | It "Allows access to [Object] members" {
43 | Test-SuspiciousScriptBlock -Timeout 3 { $mshall = [Object]::Equals("System.Runtime.InteropService" + "s.Mars" + "hal") } | Should be $false
44 | }
45 |
46 | It "Detects type casting using -as" {
47 | Test-SuspiciousScriptBlock { $mshall = ("System.Runtime.InteropService" + "s.Mars" + "hal") -as [Type] } | Should be $true
48 | }
49 |
50 | It "Detects basic bad method invocation" {
51 | Test-SuspiciousScriptBlock { $foo.WriteProcessMemory() } | Should be $true
52 | }
53 |
54 | It "Detects indirect method invocation" {
55 | Test-SuspiciousScriptBlock {
56 | $foo = New-Object System.Object
57 | $method = "Write" + "ProcessMemory"
58 | $foo.$method()
59 | } | Should be $true
60 | }
61 |
62 | It "Detects PSObject method indirection" {
63 | Test-SuspiciousScriptBlock {
64 | $foo = New-Object System.Object
65 | $method = "Write" + "ProcessMemory"
66 |
67 | $foo.psobject.methods[$method].Invoke()
68 | } | Should be $true
69 | }
70 |
71 | It "Detects often-malicious methods" {
72 | Test-SuspiciousScriptBlock {
73 | $foo = New-Object System.Object
74 | [Object].GetMethods()[0].Invoke()
75 | } | Should be $true
76 | }
77 |
78 | It "Detects often-malicious methods" {
79 | Test-SuspiciousScriptBlock {
80 | $method = "Write" + "ProcessMemory"
81 | [Object].InvokeMember($method, $null)
82 | } | Should be $true
83 | }
84 |
85 | It "Detects AppDomain enumeration" {
86 | Test-SuspiciousScriptBlock {
87 | [AppDomain]::CurrentDomain.GetAssemblies()[0].GetTypes()[0].InvokeMember()
88 | } | Should be $true
89 | }
90 |
91 | It "Detects AppDomain enumeration" {
92 | Test-SuspiciousScriptBlock {
93 | [object].Assembly.GetTypes()[0].InvokeMember()
94 | } | Should be $true
95 | }
96 | }
--------------------------------------------------------------------------------
/Security/pester.security.credential.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Get-Credential" -Tags "innerloop" {
2 | It "throws error on a long message" {
3 | Get-Credential -Message ('a'*2MB) -ErrorVariable credentialError -ErrorAction SilentlyContinue
4 | $credentialError.FullyQualifiedErrorId | Should be "CouldNotPromptForCredential,Microsoft.PowerShell.Commands.GetCredentialCommand"
5 | }
6 | }
--------------------------------------------------------------------------------
/engine/EngineAPIs/WMI.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe -tags 'Innerloop', 'DRT' "COM ComplexMethodInvoke" {
2 | BeforeAll {
3 | $wmiclass=[WMICLass]"win32_processstartup"
4 |
5 | $ai = $wmiclass.createinstance()
6 | $ai.ShowWindow = 0
7 | $ai.X = 0
8 | $ai.Y = 0
9 | $wmiclass = [WMICLass]"win32_process"
10 | $pInfo = $wmiclass.Create("cmd.exe",[Environment]::CurrentDirectory,$ai)
11 |
12 | $tempId = $pInfo.ProcessId
13 | $result = get-WmiObject -query "select * from win32_process where processid=$tempId"
14 | }
15 | It "class name should be win32_process" {
16 | $wmiclass.Name | Should Be win32_Process
17 | }
18 |
19 | It "ProcessId should not be null" {
20 | $pInfo.ProcessId | Should Not BeNullOrEmpty
21 | }
22 |
23 | It "get-WmiObject -query can find process id" {
24 | $result.ProcessId | Should be $pInfo.ProcessId
25 | }
26 |
27 | AfterAll {
28 | $p= get-process -id $pInfo.ProcessId -ea SilentlyContinue
29 | if ( $null -ne $null)
30 | {
31 | $p.Kill()
32 | }
33 | }
34 | }
35 |
36 | Describe -tags 'Innerloop', 'DRT' "DateTimeConversions" {
37 | # WMI adapter testcase
38 | It "Conversion can round trip" {
39 | $wmiclass = [wmiclass]"win32_processstartup"
40 | $currentDate = [DateTime]::Now
41 | $dmtfDate = $wmiclass.ConvertFromDateTime($currentDate)
42 | $result = $wmiclass.ConvertToDateTime($dmtfDate)
43 | "$currentDate" | Should Be "$result"
44 | }
45 | }
46 |
47 | Describe -tags 'Innerloop', 'DRT' "GetMemberWMI" {
48 | # WMI adapter testcase
49 | BeforeAll {
50 | $processes = get-wmiobject win32_process
51 | $commandFromDotNet = New-Object wmisearcher -ArgumentList "select * from win32_process"
52 | $commandFromDotNetGet = $commandFromDotNet.get()
53 | $countMemberFromDotnet = ($commandFromDotNetGet | Get-Member).count
54 | $countMemberMemberTypeFromDotNet = ($commandFromDotNetGet | Get-Member -MemberType Properties).count
55 | }
56 |
57 | AfterAll {
58 | [System.GC]::Collect()
59 | [System.GC]::WaitForPendingFinalizers()
60 | }
61 |
62 | It "get-wmiobject win32_process should return at least 2 objects" {
63 | $processes.Count -gt 1 | Should Be $true
64 | }
65 |
66 | It "win32_process object returns correct number of members" {
67 | $members = $processes[0] | Get-Member
68 | $count = $members.Count
69 | $count | Should Be $countMemberFromDotnet
70 | }
71 |
72 | It "win32_process object returns correct number of properties" {
73 | $members = $processes[0] | Get-Member -membertype properties
74 | $members.Count | Should Be $countMemberMemberTypeFromDotNet
75 | }
76 | }
77 | Describe -tags 'Innerloop', 'DRT' "GetRelatedVariations" {
78 | # WMI adapter testcase
79 |
80 | BeforeAll {
81 | $wmiclass = [wmiclass]"win32_service"
82 | }
83 |
84 | It "win32_service should return atleast 1 related class" {
85 | $rClasses = $wmiclass.GetRelatedClasses()
86 | $rClasses.Count | Should Not Be 0
87 | }
88 |
89 | It "win32_service should return win32_wmisetting related class" {
90 | $rClasses = $wmiclass.GetRelatedClasses("Win32_WMISetting")
91 | $rClasses | Should Not BeNullOrEmpty
92 | }
93 |
94 | It "exception was thrown when calling GetRelationshipClasses(1,2,3,4,5)" {
95 | try {
96 | $wmiclass.GetRelationshipClasses(1,2,3,4,5)
97 | throw "Execution OK"
98 | }
99 | catch {
100 | $_.FullyQualifiedErrorId | should be "MethodCountCouldNotFindBest"
101 | }
102 | }
103 | }
104 | Describe -tags 'Innerloop', 'DRT' "GetWMIQuery" {
105 | # WMI adapter testcase
106 | It "Query returns at least one result" {
107 | $wmisearch1 = get-wmiobject -query 'Select * from Win32_process where Name="lsass.exe"'
108 | $wmisearch1 | Should Not BeNullOrEmpty
109 | }
110 |
111 | It "Associators of {win32_Service} should return 0 objects" {
112 | $wmisearch2 = get-wmiobject -query 'Associators of {win32_service}'
113 | $wmisearch2 | Should BeNullOrEmpty
114 | }
115 | }
116 | Describe -tags 'Innerloop', 'DRT' "GetWMIType" {
117 | # WMI adapter testcase
118 |
119 | It "GetType() on a [WMIClass] should return a ManagementClass" {
120 | $wmiclass = [wmiclass]"win32_process"
121 | $wmiclass.GetType() | Should be ([System.Management.ManagementClass])
122 | }
123 |
124 | It "[wmi]'win32_process.handle=0' should return management object" {
125 | $wmiobj = [wmi]"win32_process.Handle=0"
126 | $wmiobj.getType() | Should Be ([system.management.managementobject])
127 | }
128 | }
129 | Describe -tags 'Innerloop', 'DRT' "InParameters" {
130 | # Accessing InParameters of a Method should not throw exceptions.
131 | It "InParameters should not be null" {
132 | $wmiclass = [WMICLass]"win32_process"
133 | $method = @($wmiclass.Methods)[0]
134 | $parameters = $method.InParameters
135 | $parameters | Should Not BeNullOrEmpty
136 | }
137 | }
138 | Describe -tags 'Innerloop', 'DRT' "MethodInvokeStringNull" {
139 | # WMI adapter testcase
140 | # Refer Bug938036 : Invocation of WMI method with $null argument is problematic
141 | BeforeAll {
142 | $wmiclass = [WMIClass]"Win32_Process"
143 | $pInfo1 = $wmiclass.Create("ipconfig.exe",$null,$null)
144 |
145 | $mp=$wmiclass.psbase.GetMethodParameters("Create")
146 | $mp.CommandLine = "cmd.exe"
147 | $mp.CurrentDirectory = $null
148 | $mp.ProcessStartupInformation = $null
149 | $pInfo2=$wmiclass.psbase.InvokeMethod("Create",$mp,$null)
150 | }
151 | AfterAll {
152 | $p = get-process -id $pInfo1.ProcessId -ea silentlycontinue
153 | if ( $null -ne $p ) { $p.Kill() }
154 | $p = get-process -id $pInfo2.ProcessId -ea silentlycontinue
155 | if ( $null -ne $p ) { $p.Kill() }
156 | }
157 |
158 | It "WMI Create method call should succeed" {
159 | $pInfo1.ReturnValue | Should Be 0
160 | }
161 |
162 | It "ProcessId is not null" {
163 | $pInfo1.ProcessId | Should Not BeNullOrEmpty
164 | }
165 |
166 | It "Create method call should succeed" {
167 | $pInfo2.ReturnValue | Should Be 0
168 | }
169 | It "ProcessId is not null" {
170 | $pInfo2.ProcessId | Should Not BeNullOrEmpty
171 | }
172 | }
173 | Describe -tags 'Innerloop', 'DRT' "Searcher MethodInvokeWMI" {
174 | # WMI adapter testcase
175 |
176 | It "[WMISearcher] found process from id" {
177 | $searcher = [WMISearcher]"select * from win32_process where processid=$PID"
178 | $pInfo = $searcher.Get()
179 | @($pInfo).Count | should be 1
180 | }
181 | }
182 |
183 | Describe -tags 'Innerloop', 'DRT' "win8_238481" {
184 | # Win8: 238481:Name property does not work when pipelined from Get-WMIObject cmdlet.
185 | BeforeAll {
186 | $actual = @(get-WmiObject -list | select -first 1 | % { $_.name } )
187 | $w32p = get-WmiObject -list win32_process
188 | }
189 |
190 | It "get-WmiObject -list | select -first 1 | % { $_.name } returns 1 result" {
191 | $actual.count | Should Be 1
192 | }
193 |
194 | It "AliasProperty Name is not working for win32_process ManagementClass" {
195 | $w32p.Name | Should be "win32_process"
196 | }
197 |
198 | It "Setting a new value for AliasProperty works" {
199 | $w32p.Name = "blah"
200 | $w32p.Name | Should Be "blah"
201 | }
202 | }
203 |
204 | Describe -tags 'Innerloop', 'DRT' "WMI" {
205 | # WMI adapter testcase
206 | It "retrieving single service should return 1 object" {
207 | $wmi = [WMI]"win32_service.Name='winmgmt'"
208 | @($wmi).Count | Should Be 1
209 | }
210 | }
211 |
212 | Describe -tags 'Innerloop', 'DRT' "WMIBaseObjectSetProperty" {
213 | # Setting property on a ManagementBaseObject object
214 |
215 | BeforeAll {
216 | $procClass=[WMICLass]"win32_processstartup"
217 | $ai = $procClass.createinstance()
218 | $ai.ShowWindow = 0
219 | $ai.X = 0
220 | $ai.Y = 0
221 | $wmiclass = [wmiclass]"win32_process"
222 | $wmiMethodParameters = $wmiclass.psbase.GetMethodParameters("Create")
223 | $wmiMethodParameters.CommandLine = "cmd.exe"
224 | $wmiMethodParameters.CurrentDirectory = "."
225 | $wmiMethodParameters.ProcessStartupInformation = $ai
226 | $pInfoCreate = $wmiclass.psbase.InvokeMethod("Create",$wmiMethodParameters,$null);
227 | $tempId = $pInfoCreate.ProcessId
228 | $pInfoObject = get-WmiObject -query "select * from win32_process where processid=$tempId"
229 | }
230 | AfterAll {
231 | $pInfoObject.Terminate() > $null
232 | }
233 |
234 | It "Win32_Process.PsBase.InvokeMethod() method returned null" {
235 | $pInfoCreate.ReturnValue | Should Be 0
236 | }
237 | It "ProcessId is set" {
238 | $pInfoCreate.ProcessId | Should Not BeNullOrEmpty
239 | }
240 |
241 | It "get-WmiObject -query found process via id" {
242 | $pInfoObject.ProcessId | should be $pInfoCreate.ProcessId
243 | }
244 | }
245 | Describe -tags 'Innerloop', 'DRT' "WMIClass" {
246 | # WMI adapter testcase
247 | It "Cast to improper WMIClass fails" {
248 | try {
249 | [WMIClass]"non-existent-class"
250 | throw "Execution OK"
251 | } catch {
252 | $_.FullyQualifiedErrorId | Should be "InvalidCastToWMIClass"
253 | }
254 | }
255 | }
256 | Describe -tags 'Innerloop', 'DRT' "WMIClassExceptions" {
257 | # WMI adapter testcase
258 | It "setting non-existent instance property throws" {
259 | $wmiclass = [wmiclass]"win32_processstartup"
260 | try {
261 | $wmiclass.X="10"
262 | throw "Execution OK"
263 | } catch {
264 | $_.FullyQualifiedErrorId | should be "ExceptionWhenSetting"
265 | }
266 | }
267 | }
268 | Describe -tags 'Innerloop', 'DRT' "WMIObjectExceptions" {
269 | # WMI adapter testcase
270 |
271 | It "Calling incorrect method from an instance throws correctly" {
272 | try {
273 | $wmiobject = [wmisearcher]"select * from win32_process"
274 | $wmiobject.Create("cmd.exe")
275 | Throw "Execution OK"
276 | } catch {
277 | $_.FullyQualifiedErrorId | should be "MethodNotFound"
278 | }
279 | }
280 |
281 | It "Invalid cast throws correctly" {
282 | try {
283 | $wmiobject=[wmi]'win32_process.Name="nonexistentprocess"'
284 | Throw "Execution OK"
285 | } catch {
286 | $_.FullyQualifiedErrorId | should be "InvalidCastToWMI"
287 | }
288 | }
289 |
290 | }
291 | Describe -tags 'Innerloop', 'P1' "WMISearcher" {
292 | # WMI adapter testcase
293 | BeforeAll {
294 | $wmiSearcher = [WMISearcher]"Select * from Win32_Process"
295 | $searchResult = $wmiSearcher.Get()
296 | $expected = get-process
297 | }
298 | It "process count should be approximately the same" {
299 | $diff = $expected.Count - $searchResult.Count
300 | [math]::Abs($diff) -lt 5 | should be $true
301 | }
302 |
303 | It "WMI search should return atleast one result" {
304 | $system = ([WMISearcher]'Select * from win32_process where Name="System"').Get()
305 | $system | Should Not BeNullOrEmpty
306 | }
307 |
308 | It "associators of win32_service should return 0 objects" {
309 | $wmisearcher = [WMISearcher]'Associators of {win32_service}'
310 | $wmisearcher.Get().Count | Should be 0
311 | }
312 |
313 | It "associators of WinMgmt should return at least 1 object." {
314 | # added a where to reduce time - it still finds associators
315 | $wmisearcher = [WMISearcher]'Associators of {win32_service="WinMgmt"} WHERE ResultClass=Win32_ComputerSystem'
316 | $wmisearcher.Get().Count | Should Not Be 0
317 | }
318 |
319 | }
320 | Describe -tags 'Innerloop', 'DRT' "WrongArguments" {
321 | # WMI adapter testcase
322 | BeforeAll {
323 | $wmiclass = [WMIClass]"win32_process"
324 | }
325 | It "WMIClass.Create() with 5 wrong arguments should throw" {
326 | try {
327 | $wmiclass.Create("cmd.exe",1,2,3,4,5)
328 | Throw "Execution OK"
329 | } catch {
330 | $_.FullyQualifiedErrorId | Should be "MethodCountCouldNotFindBest"
331 | }
332 | }
333 |
334 | It "Create() with wrong parameter type should throw" {
335 | try {
336 | $wmiclass.Create("cmd.exe",1,2)
337 | Throw "Execution OK"
338 | } catch {
339 | $_.FullyQualifiedErrorId | Should Be "CatchFromBaseAdapterMethodInvoke"
340 | }
341 | }
342 |
343 | It "Create() with wrong type should not create process" {
344 | $pInfo = $wmiclass.Create(1)
345 | $pInfo.ReturnValue | Should Not Be 0
346 | }
347 | }
348 |
--------------------------------------------------------------------------------
/engine/EngineAPIs/XmlAdapter.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe -tags 'Innerloop', 'DRT' "bug613651" {
2 | # Bug 613651: ParameterizedProperty 'Item' mask an XML Document 'Item' tag
3 | #
4 | # The bug would produce an error when get-member was called (The XML adapter would try
5 | # to add the "Item" parameterized property of the XmlElement to a dictionary that
6 | # already contains the "Item" adapted property)
7 | #
8 | It "The number of properties is incorrect" {
9 | $x = [xml] "- 1
- 2
"
10 | $count = @(get-member -i $x.root -membertype property | measure).Count
11 | $count | Should Be 1
12 | }
13 | }
14 | Describe -tags 'Innerloop', 'DRT' "bug914412" {
15 | # Bug:914412: XML Adapter should support #cdata-section,#text sections
16 | BeforeAll {
17 | $cdata = 'some cdata content'
18 | $text = 'some text'
19 | $xmlContent = "$text"
20 | $xml = [xml]$xmlContent
21 | $xmlCdata = $xml.a."#cdata-section"
22 | $xmlText = $xml.a."#text"
23 |
24 | }
25 | Context "Getting values from Xml" {
26 | It "[xml] type accelerator gives proper type" {
27 | $xml.GetType() | Should Be ([System.Xml.XmlDocument])
28 | }
29 |
30 | It "cdata has correct value" {
31 | $XmlCdata | should Be $cdata
32 | }
33 | It "text has correct value" {
34 | $xmlText | should Be $text
35 | }
36 | }
37 |
38 | Context "Setting new values for Xml Elements" {
39 | BeforeAll {
40 | $newCdata = 'new cdata content'
41 | $newText = 'new text'
42 | $xml.a."#cdata-section" = $newCdata
43 | $xml.a."#text" = $newText
44 | $newXmlCdata = $xml.a."#cdata-section"
45 | $newXmlText = $xml.a."#text"
46 | }
47 | It "text of element has correct value" {
48 | $newXmlText | Should be $newText
49 | }
50 |
51 | It "Expected: $newCdata Actual: $xmlCdata" {
52 | $newXmlCdata | should be $newCdata
53 | }
54 | }
55 | }
56 | Describe -tags 'Innerloop', 'P1' "win8_481571" {
57 | # Win8: 481571 Enforcing "PreserveWhitespace" breaks XML pretty printing
58 | It "[xml] preserves comments" {
59 | $content = "`r`n "
60 | $xml = [xml]$content
61 | $actual = $xml.a.b.("#comment")
62 | $actual | Should Be " comment "
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/engine/ExtensibleTypeSystem/ETS.Tests.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PowerShell/PowerShell-Tests/40e562cdbd907f1aa98bec68d27af1d5374a338e/engine/ExtensibleTypeSystem/ETS.Tests.ps1
--------------------------------------------------------------------------------
/engine/ExtensibleTypeSystem/Pester.FileVersionInfo.Tests.ps1:
--------------------------------------------------------------------------------
1 | # Tests related to TFS item 1370183 [PSUpgrade] FileInfo (from Get-Item, et al) VersionInfo returns misleading binary version info
2 | # Connect request https://connect.microsoft.com/PowerShell/feedback/details/1027483/fileinfo-from-get-item-et-al-versioninfo-returns-misleading-binary-version-info
3 |
4 | Describe "Tests for new script properties of System.Diagnostics.FileVersionInfo" {
5 |
6 | It "FileVersionRaw should match 'File*Part' properties" {
7 | $hostFileVersion = Get-Process -Id $pid -FileVersionInfo
8 | $partsString = $hostFileVersion.FileMajorPart, $hostFileVersion.FileMinorPart, $hostFileVersion.FileBuildPart, $hostFileVersion.FilePrivatePart -join "."
9 | $hostFileVersion.FileVersionRaw -eq $partsString | Should Be $true
10 | }
11 |
12 | It "ProductVersionRaw should match 'Product*Part' properties" {
13 | $hostFileVersion = Get-Process -Id $pid -FileVersionInfo
14 | $partsString = $hostFileVersion.ProductMajorPart, $hostFileVersion.ProductMinorPart, $hostFileVersion.ProductBuildPart, $hostFileVersion.ProductPrivatePart -join "."
15 | $hostFileVersion.ProductVersionRaw -eq $partsString | Should Be $true
16 | }
17 | }
--------------------------------------------------------------------------------
/engine/ExtensibleTypeSystem/Pester.PSObject.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Testing of PSObject behaviour" {
2 |
3 | It "Tests that PSObject.ToString() doesn't invoke script properties" {
4 | $env:Bug_2108520_Evaluated = "False"
5 | $x = New-Object PSObject
6 | $x | Add-Member ScriptProperty "Test" { $env:Bug_2108520_Evaluated = "True" }
7 | $x | Add-Member NoteProperty "Test2" 2
8 | $env:Bug_2108520_Evaluated | Should be "False"
9 | }
10 | }
--------------------------------------------------------------------------------
/engine/Other/Pester.Engine.Other.InformationStream.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Validation for Information stream in PowerShell" {
2 | it "Supports Write-Information cmdlet and InformationVariable" {
3 | $process = Get-Process -id $pid
4 | Write-Information $process -Tags "Tag1","Tag2" -InformationVariable infoVar
5 |
6 | $infoVar.MessageData.Id | Should be $pid
7 | $infoVar.Tags[0] | Should be Tag1
8 | $infoVar.Tags[1] | Should be Tag2
9 | }
10 |
11 | it "Verifies InformationAction" {
12 | $output = Write-Information Test -Tags "Tag1","Tag2" *>&1 -InformationAction Ignore
13 | $output | Should be $null
14 | }
15 |
16 | it "Verifies InformationPreference" {
17 | $informationPreference = "Ignore"
18 | $output = Write-Information Test -Tags "Tag1","Tag2" *>&1 -InformationAction Ignore
19 | $output | Should be $null
20 | }
21 |
22 | it "Verifies Information stream redirection" {
23 | $process = Get-Process -id $pid
24 | $result = Write-Information $process -Tags "Tag1","Tag2" 6>&1
25 |
26 | $result.MessageData.Id | Should be $pid
27 | $result.Tags[0] | Should be Tag1
28 | $result.Tags[1] | Should be Tag2
29 | }
30 |
31 | it "Verifies Information stream on PowerShell object" {
32 | $ps = [PowerShell]::Create()
33 | $null = $ps.AddScript('$process = Get-Process -id $pid; $result = Write-Information $process -Tags "Tag1","Tag2"').Invoke()
34 |
35 | $result = $ps.Streams.Information[0]
36 |
37 | $result.MessageData.Id | Should be $pid
38 | $result.Tags[0] | Should be Tag1
39 | $result.Tags[1] | Should be Tag2
40 | }
41 |
42 | it "Verifies Information stream on jobs" {
43 | $j = Start-Job { Write-Information "FromJob" -Tags "Tag1","Tag2" }
44 | Wait-Job $j
45 |
46 | $result = $j.ChildJobs[0].Information[0]
47 |
48 | $result.MessageData | Should be "FromJob"
49 | $result.Tags[0] | Should be Tag1
50 | $result.Tags[1] | Should be Tag2
51 | }
52 |
53 | it "Verifies Information stream on workflow" {
54 | ## Test regular invocation
55 | workflow foo { Write-Information Bar }
56 | foo -InformationVariable bar
57 | $bar.MessageData | Should be "Bar"
58 |
59 | ## Test job invocation
60 | $j = foo -asjob
61 | Wait-Job $j
62 | $j.ChildJobs[0].Information.MessageData | Should be "Bar"
63 |
64 | ## Ensure that InformationAction works on workflow
65 | $result = foo -informationaction ignore *>&1
66 | $result | Should be $null
67 | }
68 |
69 | it "Verifies InformationVariable in workflow compilation" {
70 | workflow IVWorkflowTest { Write-Information Test -InformationVariable Test; $test }
71 | $result = IVWorkflowTest
72 | $result.MessageData | Should be "Test"
73 | }
74 |
75 | it "Verifies Information stream works over remoting" {
76 | icm localhost { Write-Information Test } -InformationVariable Test
77 | $test.MessageData | Should be "Test"
78 | }
79 |
80 | it "Verifies client-side stream redirection works over remoting" {
81 |
82 | $result = icm localhost { Write-Information Test 6>&1 }
83 | $result.MessageData | Should be "Test"
84 | }
85 |
86 | it "Verifies PowerShell-calling-PowerShell" {
87 |
88 | $result = powershell -noprofile { $pid; Write-Information Bar } *>&1
89 | $processPid = $result[0]
90 | $result[1].ProcessId | Should be $processPid
91 | }
92 |
93 | it "Verifies that host output can be redirected" {
94 | function spammer { [CmdletBinding()] param() Write-Host "Some host output" }
95 | spammer -InformationVariable spam
96 | $spam.MessageData.Message | Should be "Some host output"
97 | }
98 | }
--------------------------------------------------------------------------------
/engine/Runspace/Pester.Runspace.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Runspace operations which" {
2 | # determine whether you're elevated and skip the remote test in that case
3 | BeforeAll {
4 | $windowsIdentity = [Security.Principal.WindowsIdentity]::GetCurrent()
5 | $windowsPrincipal = new-object Security.Principal.WindowsPrincipal $windowsIdentity
6 | if ($windowsPrincipal.IsInRole("Administrators") -eq 1)
7 | {
8 | $skip = $false
9 | $skipReason = ""
10 | }
11 | else
12 | {
13 | $skip = $true
14 | $skipReason = " (skipping because we're not an admin)"
15 | }
16 | }
17 | Context "Assign values to DefaultRunspace" {
18 | BeforeEach {
19 | $origRS = [runspace]::DefaultRunspace
20 | }
21 | # pester requires the original runspace to be available, so we assign
22 | # and then retrieve. We can't leave the DefaultRunspace
23 | # in a different state when we call our assertions because
24 | # pester needs the environment set up in that runspace
25 | It "Null can be assigned to DefaultRunspace" {
26 | [Runspace]::DefaultRunspace = $null
27 | $newRs = [runspace]::DefaultRunspace
28 | [Runspace]::DefaultRunspace = $origRS
29 | $newRs | Should BeNullOrEmpty
30 | }
31 | It "A LocalRunspace can be assigned to DefaultRunspace" {
32 | $nrs = [runspacefactory]::CreateRunspace()
33 | $nrs.Open()
34 | [runspace]::DefaultRunspace = $nrs
35 | $newRS = [runspace]::DefaultRunspace
36 | [Runspace]::DefaultRunspace = $origRS
37 | $newRS.Name |Should Not Be $origRS.Name
38 |
39 | }
40 | It -skip:$skip "A RemoteRunspace fails to be assigned to DefaultRunspace.${skipReason}" {
41 | try
42 | {
43 | $s = New-PSSession localhost
44 | [runspace]::DefaultRunspace = $s.Runspace
45 | throw "Execution OK"
46 | }
47 | catch
48 | {
49 | $_.FullyQualifiedErrorId | Should be ExceptionWhenSetting
50 | $_.Exception.InnerException.GetType().Name |
51 | Should Be InvalidOperationException
52 | }
53 | finally
54 | {
55 | if ( $s ) { $s | Remove-PSSession }
56 | }
57 | }
58 | }
59 | Context "Retrieve the RunspaceIsRemote property and validate" {
60 | It "The default runspace is not Remote" {
61 | [Runspace]::DefaultRunspace.RunspaceIsRemote | should be $false
62 | }
63 | It "A runspace created by runspacefactory without arguments is not Remote" {
64 | [RunspaceFactory]::CreateRunspace().RunspaceIsRemote | should be $false
65 | }
66 | It -skip:$skip "A Runspace created as part of new-pssession is Remote.${skipReason}" {
67 | try
68 | {
69 | $s = new-PsSession localhost
70 | $s.Runspace.RunspaceIsRemote | Should be $true
71 | }
72 | finally
73 | {
74 | if ( $s ) { $s | Remove-PsSession }
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/provider/Providers/Pester.Get-ChildItem.Depth.Tests.ps1:
--------------------------------------------------------------------------------
1 | function CreateDirStructure
2 | {
3 | param(
4 | [string] $Dir,
5 | [int] $Width,
6 | [int] $Depth
7 | )
8 |
9 | 1..$Width | % {
10 | $newDirPath = Join-Path $Dir ("Level"+$Depth+$_)
11 | $newFilePath = $newDirPath + ".txt"
12 | new-item -type directory -Path $newDirPath -Force | Out-Null
13 | Get-Date | Out-File $newFilePath
14 | if ($Depth -gt 0) { CreateDirStructure $newDirPath $Width ($Depth - 1) }
15 | }
16 | }
17 |
18 | #Pester.psm1 does not currently implement BeforeAll / AfterAll for suite setup/cleanup.
19 | $testDir = "$env:TEMP\GetChildItemDepthTests"
20 | CreateDirStructure $testDir 2 2
21 |
22 | <# Above produces this structure:
23 | $env:Temp\GetChildItemDepthTests\Level21
24 | $env:Temp\GetChildItemDepthTests\Level21.txt
25 | $env:Temp\GetChildItemDepthTests\Level21\Level11
26 | $env:Temp\GetChildItemDepthTests\Level21\Level11.txt
27 | $env:Temp\GetChildItemDepthTests\Level21\Level11\Level01
28 | $env:Temp\GetChildItemDepthTests\Level21\Level11\Level01.txt
29 | $env:Temp\GetChildItemDepthTests\Level21\Level11\Level02
30 | $env:Temp\GetChildItemDepthTests\Level21\Level11\Level02.txt
31 | $env:Temp\GetChildItemDepthTests\Level21\Level12
32 | $env:Temp\GetChildItemDepthTests\Level21\Level12.txt
33 | $env:Temp\GetChildItemDepthTests\Level21\Level12\Level01
34 | $env:Temp\GetChildItemDepthTests\Level21\Level12\Level01.txt
35 | $env:Temp\GetChildItemDepthTests\Level21\Level12\Level02
36 | $env:Temp\GetChildItemDepthTests\Level21\Level12\Level02.txt
37 | $env:Temp\GetChildItemDepthTests\Level22
38 | $env:Temp\GetChildItemDepthTests\Level22.txt
39 | $env:Temp\GetChildItemDepthTests\Level22\Level11
40 | $env:Temp\GetChildItemDepthTests\Level22\Level11.txt
41 | $env:Temp\GetChildItemDepthTests\Level22\Level11\Level01
42 | $env:Temp\GetChildItemDepthTests\Level22\Level11\Level01.txt
43 | $env:Temp\GetChildItemDepthTests\Level22\Level11\Level02
44 | $env:Temp\GetChildItemDepthTests\Level22\Level11\Level02.txt
45 | $env:Temp\GetChildItemDepthTests\Level22\Level12
46 | $env:Temp\GetChildItemDepthTests\Level22\Level12.txt
47 | $env:Temp\GetChildItemDepthTests\Level22\Level12\Level01
48 | $env:Temp\GetChildItemDepthTests\Level22\Level12\Level01.txt
49 | $env:Temp\GetChildItemDepthTests\Level22\Level12\Level02
50 | $env:Temp\GetChildItemDepthTests\Level22\Level12\Level02.txt
51 | #>
52 |
53 | Describe "Tests for Depth parameter of Get-ChildItem" {
54 |
55 | It "Depth 0 for items" {
56 | (Get-ChildItem $testDir -Recurse -Depth 0).Count -eq (Get-ChildItem $testDir).Count | Should Be $true
57 | }
58 | It "Depth 0 for names" {
59 | (Get-ChildItem $testDir -Recurse -Depth 0 -Name).Count -eq (Get-ChildItem $testDir -Name).Count | Should Be $true
60 | }
61 | It "FileSystemProvider limited recursion for items" {
62 | (Get-ChildItem $testDir -Recurse -Depth 1).Count | Should Be 12
63 | }
64 | It "FileSystemProvider limited recursion for names" {
65 | (Get-ChildItem $testDir -Recurse -Depth 1 -Name).Count | Should Be 12
66 | }
67 | It "RegistryProvider limited recursion for items" {
68 | $topLevelOnlyCount = (Get-ChildItem "hklm:\SYSTEM\CurrentControlSet\Hardware Profiles").Count
69 | $depth1RecursionCount = (Get-ChildItem "hklm:\SYSTEM\CurrentControlSet\Hardware Profiles" -Recurse -Depth 1).Count
70 | $fullRecursionCount = (Get-ChildItem "hklm:\SYSTEM\CurrentControlSet\Hardware Profiles" -Recurse).Count
71 | ($depth1RecursionCount -gt $topLevelOnlyCount) -and ($depth1RecursionCount -lt $fullRecursionCount) | Should Be $true
72 | }
73 | It "RegistryProvider limited recursion for names" {
74 | $topLevelOnlyCount = (Get-ChildItem "hklm:\SYSTEM\CurrentControlSet\Hardware Profiles" -Name).Count
75 | $depth1RecursionCount = (Get-ChildItem "hklm:\SYSTEM\CurrentControlSet\Hardware Profiles" -Recurse -Depth 1 -Name).Count
76 | $fullRecursionCount = (Get-ChildItem "hklm:\SYSTEM\CurrentControlSet\Hardware Profiles" -Recurse -Name).Count
77 | ($depth1RecursionCount -gt $topLevelOnlyCount) -and ($depth1RecursionCount -lt $fullRecursionCount) | Should Be $true
78 | }
79 | It "Implicit recursion for FileSystemProvider" {
80 | (Get-ChildItem $testDir -Depth 1).Count -eq (Get-ChildItem -Recurse $testDir -Depth 1).Count | Should Be $true
81 | }
82 | It "Implicit recursion for RegistryProvider" {
83 | $explicitRecursionCount = (Get-ChildItem "hklm:\SYSTEM\CurrentControlSet\Hardware Profiles" -Recurse -Depth 0 -Name).Count
84 | $implicitRecursionCount = (Get-ChildItem "hklm:\SYSTEM\CurrentControlSet\Hardware Profiles" -Depth 0 -Name).Count
85 | $implicitRecursionCount | Should Be $explicitRecursionCount
86 | }
87 | }
88 |
89 | del $testDir -Recurse -Force
90 |
--------------------------------------------------------------------------------
/provider/Providers/Pester.Providers.DrivePersistence.Tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Tests to check persistence of providers drives" {
2 |
3 | # test for bug 2784052
4 | It "Get-PSDrive should not remove custom drives" {
5 | $newDrives = Get-ChildItem function:[e-z]: -Name | ?{ !(Test-Path $_) } | select -First 7
6 | $newDriveLetters = $newDrives -replace ".$"
7 | $originalDriveCount = (Get-PSDrive).Count
8 | new-psdrive $newDriveLetters[0] -psp FileSystem -root 'c:\'
9 | new-psdrive $newDriveLetters[1] -psp Registry -root 'hkcu:\'
10 | new-psdrive $newDriveLetters[2] -psp Environment -root ''
11 | new-psdrive $newDriveLetters[3] -psp Function -root ''
12 | new-psdrive $newDriveLetters[4] -psp Certificate -root '\'
13 | new-psdrive $newDriveLetters[5] -psp Variable -root ''
14 | new-psdrive $newDriveLetters[6] -psp Alias -root ''
15 |
16 | # run Get-PSDrive several times to check for bug 2784052 (Fixing regression in CL#498641)
17 | # bug in 'if' condition in get-psdrive resulted in custom non-filesystem provider drives being removed when get-psdrive was called.
18 | 1..3 | % {Get-PSDrive} | Out-Null
19 | $newDriveCount = (Get-PSDrive).Count
20 | $newDriveCount | Should Be ($originalDriveCount + 7)
21 | $newDrives | %{ Test-Path $_ | Should Be $true }
22 | Remove-PSDrive $newDriveLetters
23 | }
24 | }
--------------------------------------------------------------------------------
/provider/Providers/pester.management.junction.tests.ps1:
--------------------------------------------------------------------------------
1 | Describe "Junctions" -Tags "P1", "Innerloop" {
2 | Context "Cyclic Junctions" {
3 | BeforeAll {
4 | $junctionTarget = (New-Item -Path "TestDrive:\JunctionTarget" -ItemType Directory -Force).FullName
5 | $null = New-Item -Path "TestDrive:\JunctionTarget\file.txt"
6 | $cyclicJunction = (New-Item -Path "TestDrive:\JunctionTarget\Cyclic" -target $junctionTarget -ItemType junction -Force).fullName
7 | }
8 |
9 | It "copy junction with force gets an error" {
10 | Copy-Item $cyclicJunction -Recurse -Destination "TestDrive:\CopyDestination" -force -ErrorAction SilentlyContinue -ErrorVariable copyErrorDirectory
11 | $copyErrorDirectory.FullyQualifiedErrorId | Should Be "CopyDirectoryInfoItemIOError,Microsoft.PowerShell.Commands.CopyItemCommand"
12 | }
13 |
14 | It "cannot be deleted without Force" {
15 | Remove-Item $cyclicJunction -Recurse -ErrorVariable cyclicDeleteError -ErrorAction SilentlyContinue
16 | $cyclicDeleteError.FullyQualifiedErrorId | Should Be "DirectoryNotEmpty,Microsoft.PowerShell.Commands.RemoveItemCommand"
17 | }
18 |
19 | It "can be deleted" {
20 | Remove-Item $cyclicJunction -Force -Recurse
21 | $cyclicJunction | Should Not Exist
22 | }
23 | }
24 |
25 | Context "Junction operations" {
26 |
27 | BeforeAll {
28 | $junctionTarget = (New-Item -Path "TestDrive:\JunctionTarget" -ItemType Directory -Force).FullName
29 | $null = New-Item -Path "TestDrive:\JunctionTarget\file.txt"
30 | $junction = (New-Item -Path "TestDrive:\JunctionDestination" -target $junctionTarget -ItemType junction -Force).fullName
31 | }
32 |
33 | It "target can be deleted" {
34 | Remove-Item $junctionTarget -Recurse -Force
35 | Get-ChildItem $junction -ErrorVariable targetDelete -ErrorAction SilentlyContinue
36 | $targetDelete.FullyQualifiedErrorId | Should Be "DirIOError,Microsoft.PowerShell.Commands.GetChildItemCommand"
37 | }
38 |
39 | AfterAll {
40 | Remove-Item $junction -Force -ErrorAction SilentlyContinue
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/remoting/Cmdlets/NoReboot.tests.ps1:
--------------------------------------------------------------------------------
1 | #
2 | # Tests for PowerShell Remoting Cmdlets with regards to WSMan No-Reboot feature
3 | # 2015
4 | #
5 |
6 | function Get-PluginDetails([string]$name = $(throw "Endpoint name not provided."))
7 | {
8 | function Unescape-Xml($s) {
9 | if ($s) {
10 | $s = $s.Replace("<", "<");
11 | $s = $s.Replace(">", ">");
12 | $s = $s.Replace(""", '"');
13 | $s = $s.Replace(""", '"');
14 | $s = $s.Replace("'", "'");
15 | $s = $s.Replace("&", "&");
16 | }
17 |
18 | return $s;
19 | }
20 |
21 | $hashprovider = new-object system.collections.CaseInsensitiveHashCodeProvider
22 | $comparer=new-object system.collections.CaseInsensitiveComparer
23 | $h = new-object system.collections.hashtable([System.Collections.IHashCodeProvider]$hashprovider, [System.Collections.IComparer]$comparer)
24 | $wfendpoint = $false
25 |
26 | if (test-path wsman:\localhost\plugin\"$name") {
27 | function Get-Details([string]$path, [hashtable]$h) {
28 | foreach ($o in (get-childitem $path)) {
29 | if ($o.PSIsContainer) {
30 | Get-Details $o.PSPath $h
31 | } else {
32 | $h[$o.Name] = $o.Value
33 | }
34 | }
35 | }
36 |
37 | Get-Details wsman:\localhost\plugin\""$name"" $h
38 |
39 | $sddl = $h["Sddl"]
40 | if ($sddl) {
41 | $h.Remove("Sddl")
42 | $h["SecurityDescriptorSddl"] = $sddl
43 | }
44 |
45 | if ($h["PSSessionConfigurationTypeName"] -eq "Microsoft.PowerShell.Workflow.PSWorkflowSessionConfiguration") {
46 | import-module psworkflow -Scope local
47 | $wf = new-psworkflowexecutionoption
48 |
49 | foreach ($o in $wf.GetType().GetProperties()) {
50 | $h[$o.Name] = $o.GetValue($wf, $null)
51 | }
52 | }
53 |
54 | if (test-path wsman:\localhost\plugin\"$name"\InitializationParameters\SessionConfigurationData) {
55 | $xscd = [xml](Unescape-Xml (Unescape-Xml (get-item wsman:\localhost\plugin\"$name"\InitializationParameters\SessionConfigurationData).Value))
56 |
57 | foreach ($o in $xscd.SessionConfigurationData.Param) {
58 | if ($o.Name -eq "PrivateData") {
59 | foreach($wf in $o.PrivateData.Param) {
60 | $h[$wf.Name] = $wf.Value
61 | }
62 | } else {
63 | $h[$o.Name] = $o.Value
64 | }
65 | }
66 | }
67 | }
68 |
69 | return $h
70 | }
71 |
72 | Describe "Remoting Cmdlets WinRM Noreboot Tests" {
73 |
74 | BeforeAll {
75 | $testName = 'abc'
76 | $checkRebootSession = $null
77 | $sc = 'SilentlyContinue'
78 |
79 | if ((Get-Service -Name 'WinRM').Status -ne 'Running'){ Start-Service -Name 'WinRM' }
80 | Unregister-PSSessionConfiguration -Name abc -Force -ErrorAction $sc
81 |
82 | function Restart-WinRM
83 | {
84 | # This removes all of the output to the screen
85 | Restart-Service -Name WinRM -Force -Confirm:$false 3>$null
86 | }
87 |
88 | }
89 |
90 | Context "Register-PSSessionConfiguration" {
91 | BeforeEach{
92 | Restart-WinRM
93 | $checkRebootSession = New-PSSession -ComputerName localhost
94 | $checkRebootSession.State | Should be 'Opened'
95 | }
96 |
97 | AfterEach{
98 | Remove-PSSession $checkRebootSession -Confirm:$false
99 | Unregister-PSSessionConfiguration -Name abc -Force -ErrorAction $sc
100 | }
101 |
102 | It "Registering without a reboot" {
103 |
104 | $checkRebootSession.State | Should be 'Opened'
105 | $c = Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
106 | $checkRebootSession.State | Should be 'Opened'
107 |
108 | $h = Get-PluginDetails $testName
109 | $h["Enabled"] | Should Be "True"
110 | }
111 |
112 | It "Registering without a reboot with -Force" {
113 |
114 | $checkRebootSession.State | Should be 'Opened'
115 | $c = Register-PSSessionConfiguration -Force -Name $testName -WarningAction $sc -WarningVariable $null
116 | $checkRebootSession.State | Should be 'Opened'
117 |
118 | $h = Get-PluginDetails $testName
119 | $h["Enabled"] | Should Be "True"
120 | }
121 |
122 | It "Error on re-register" {
123 |
124 | $checkRebootSession.State | Should be 'Opened'
125 | $c = Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
126 | $checkRebootSession.State | Should be 'Opened'
127 |
128 | #now should fail while still not rebooting
129 | { Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null } | Should Throw
130 |
131 | $checkRebootSession.State | Should be 'Opened'
132 | }
133 |
134 | It "Re-register with -Force should reboot and work" {
135 |
136 | # first instance of register does not require a reboot
137 | $checkRebootSession.State | Should be 'Opened'
138 | $c = Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null -Force
139 | $checkRebootSession.State | Should be 'Opened'
140 |
141 | Unregister-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
142 |
143 | # Now reboot of WinRM is required with -Force, the cmdlet should reboot WinRM for us
144 | { Register-PSSessionConfiguration -Name $testName -Force 3>$null } | Should not Throw
145 |
146 | $checkRebootSession.State | Should not be 'Opened'
147 |
148 | $newTestSession = New-PSSession -ComputerName localhost -ConfigurationName $testName
149 | $newTestSession.State | Should be 'Opened'
150 | Remove-PSSession $newTestSession -Confirm:$false
151 | }
152 |
153 | It "Re-register WITHOUT -Force should not reboot and session won't work" {
154 |
155 | # first instance of register does not require a reboot
156 | $checkRebootSession.State | Should be 'Opened'
157 | $c = Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
158 | $checkRebootSession.State | Should be 'Opened'
159 |
160 | Unregister-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
161 |
162 | # Now reboot of WinRM is required with -Force, the cmdlet should reboot WinRM for us
163 | { Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null } | Should not Throw
164 |
165 | $checkRebootSession.State | Should be 'Opened'
166 |
167 | { $newTestSession = New-PSSession -ComputerName localhost -ConfigurationName $testName -ErrorAction Stop } | Should Throw
168 | $newTestSession.State | Should not be 'Opened'
169 | }
170 | }
171 |
172 | Context "Unregister-PSSessionConfiguration" {
173 | BeforeEach{
174 | Restart-WinRM
175 | $checkRebootSession = New-PSSession -ComputerName localhost
176 | $checkRebootSession.State | Should be 'Opened'
177 | }
178 |
179 | AfterEach{
180 | Remove-PSSession $checkRebootSession -Confirm:$false
181 | Unregister-PSSessionConfiguration -Name abc -Force -ErrorAction $sc
182 | }
183 |
184 | It "Unregistering without a reboot" {
185 |
186 | Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
187 |
188 | $checkRebootSession.State | Should be 'Opened'
189 | Unregister-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
190 | $checkRebootSession.State | Should be 'Opened'
191 | }
192 |
193 | It "Unregistering without a reboot with -Force" {
194 |
195 | Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
196 |
197 | $checkRebootSession.State | Should be 'Opened'
198 | Unregister-PSSessionConfiguration -Force -Name $testName -WarningAction $sc -WarningVariable $null
199 | $checkRebootSession.State | Should be 'Opened'
200 | }
201 |
202 | It "Error on Unregistering a non-existing plugin" {
203 |
204 | $checkRebootSession.State | Should be 'Opened'
205 | { Unregister-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null -ErrorAction Stop } | Should Throw
206 | $checkRebootSession.State | Should be 'Opened'
207 | }
208 | }
209 |
210 | Context "Disable-PSSessionConfiguration" {
211 | BeforeEach{
212 | Restart-WinRM
213 | $checkRebootSession = New-PSSession -ComputerName localhost
214 | $checkRebootSession.State | Should be 'Opened'
215 | }
216 |
217 | AfterEach{
218 | Remove-PSSession $checkRebootSession -Confirm:$false
219 | Unregister-PSSessionConfiguration -Name abc -Force -ErrorAction $sc
220 | }
221 |
222 | It "Disabling without a reboot" {
223 |
224 | Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
225 |
226 | $checkRebootSession.State | Should be 'Opened'
227 | Disable-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
228 | $checkRebootSession.State | Should be 'Opened'
229 |
230 | $h = Get-PluginDetails $testName
231 | $h["Enabled"] | Should Be "False"
232 | }
233 |
234 | It "Disabling without a reboot with -Force" {
235 |
236 | Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
237 |
238 | $checkRebootSession.State | Should be 'Opened'
239 | Disable-PSSessionConfiguration -Force -Name $testName -WarningAction $sc -WarningVariable $null
240 | $checkRebootSession.State | Should be 'Opened'
241 |
242 | $h = Get-PluginDetails $testName
243 | $h["Enabled"] | Should Be "False"
244 | }
245 | }
246 |
247 | Context "Enable-PSSessionConfiguration" {
248 | BeforeEach{
249 | Restart-WinRM
250 | $checkRebootSession = New-PSSession -ComputerName localhost
251 | $checkRebootSession.State | Should be 'Opened'
252 | }
253 |
254 | AfterEach{
255 | Remove-PSSession $checkRebootSession -Confirm:$false
256 | Unregister-PSSessionConfiguration -Name abc -Force -ErrorAction $sc
257 | }
258 |
259 | It "Enabling without a reboot" {
260 | # Ensure session configuration commands work in strict mode
261 | Set-StrictMode -Version 5.0
262 |
263 | Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
264 |
265 | $checkRebootSession.State | Should be 'Opened'
266 | Enable-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
267 | $checkRebootSession.State | Should be 'Opened'
268 |
269 | $h = Get-PluginDetails $testName
270 | $h["Enabled"] | Should Be "True"
271 | }
272 |
273 | It "Enabling without a reboot with -Force" {
274 | # Ensure session configuration commands work in strict mode
275 | Set-StrictMode -Version 5.0
276 |
277 | Register-PSSessionConfiguration -Name $testName -WarningAction $sc -WarningVariable $null
278 |
279 | $checkRebootSession.State | Should be 'Opened'
280 | Enable-PSSessionConfiguration -Force -Name $testName -WarningAction $sc -WarningVariable $null
281 | $checkRebootSession.State | Should be 'Opened'
282 |
283 | $h = Get-PluginDetails $testName
284 | $h["Enabled"] | Should Be "True"
285 | }
286 | }
287 | }
288 |
289 |
290 |
291 |
--------------------------------------------------------------------------------