forked from PowerShell/PowerShell
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLanguageAndParser.TestFollowup.Tests.ps1
More file actions
192 lines (164 loc) · 6.5 KB
/
Copy pathLanguageAndParser.TestFollowup.Tests.ps1
File metadata and controls
192 lines (164 loc) · 6.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
$powershellexe = (get-process -id $PID).mainmodule.filename
Describe "Clone array" -Tags "CI" {
It "Cast in target expr" {
(([int[]](42)).clone()) | Should Be 42
(([int[]](1..5)).clone()).Length | Should Be 5
(([int[]](1..5)).clone()).GetType() | Should Be ([int[]])
}
It "Cast not in target expr" {
$e = [int[]](42)
$e.Clone() | Should Be 42
$e = [int[]](1..5)
$e.Clone().Length | Should Be 5
$e.Clone().GetType() | Should Be ([int[]])
}
}
Describe "Set fields through PSMemberInfo" -Tags "CI" {
Add-Type @"
public struct AStruct { public string s; }
"@
It "via cast" {
([AStruct]@{s = "abc" }).s | Should Be "abc"
}
It "via new-object" {
(new-object AStruct -prop @{s="abc"}).s | Should Be "abc"
}
It "via PSObject" {
$x = [AStruct]::new()
$x.psobject.properties['s'].Value = 'abc'
$x.s | Should Be "abc"
}
}
Describe "MSFT:3309783" -Tags "CI" {
It "Run in another process" {
# For a reliable test, we must run this in a new process because an earlier binding in this process
# could mask the bug/fix.
& $powershellexe -noprofile -command "[psobject] | % FullName" | Should Be System.Management.Automation.PSObject
}
It "Run in current process" {
# For good measure, do the same thing in this process
[psobject] | % FullName | Should Be System.Management.Automation.PSObject
}
It "Pipe objects derived from PSObject" {
# Related - make sure we can still pipe objects derived from PSObject
class MyPsObj : PSObject
{
MyPsObj($obj) : base($obj) { }
[string] ToString() {
# Don't change access via .psobject, that was also a bug.
return "MyObj: " + $this.psobject.BaseObject
}
}
[MyPsObj]::new("abc").psobject.ToString() | Should Be "MyObj: abc"
[MyPsObj]::new("def") | Out-String | % Trim | Should Be "MyObj: def"
}
}
Describe "ScriptBlockAst.GetScriptBlock throws on error" -Tags "CI" {
$e = $null
It "with parse error" {
$ast = [System.Management.Automation.Language.Parser]::ParseInput('function ', [ref]$null, [ref]$e)
{ $ast.GetScriptBlock() } | Should Throw
}
It "with semantic errors" {
$ast = [System.Management.Automation.Language.Parser]::ParseInput('function foo{param()begin{}end{[ref][ref]1}dynamicparam{}}', [ref]$null, [ref]$e)
{ $ast.GetScriptBlock() } | Should Throw
{ $ast.EndBlock.Statements[0].Body.GetScriptBlock() } | Should Throw
}
}
Describe "Hashtable key property syntax" -Tags "CI" {
$script = @'
# First create a hashtable wrapped in PSObject
$hash = New-Object hashtable
$key = [ConsoleColor]::Red
$null = $hash.$key
$hash = @{}
$hash.$key = 'Hello'
# works in PS 2,3,4. Fails in PS 5:
$hash.$key
'@
It "In current process" {
# Run in current process, but something that ran earlier could influence
# the result
Invoke-Expression $script | Should Be Hello
}
It "In different process" {
# So also run in a fresh process
$bytes = [System.Text.Encoding]::Unicode.GetBytes($script)
& $powershellexe -noprofile -encodedCommand ([Convert]::ToBase64String($bytes)) | Should Be Hello
}
}
Describe "Assign automatic variables" -Tags "CI" {
$autos = '_', 'args', 'this', 'input', 'pscmdlet', 'psboundparameters', 'myinvocation', 'psscriptroot', 'pscommandpath'
foreach ($auto in $autos)
{
It "Assign auto w/ invalid type constraint - $auto" {
{ & ([ScriptBlock]::Create("[datetime]`$$auto = 1")) } | Should Throw $auto
{ . ([ScriptBlock]::Create("[datetime]`$$auto = 1")) } | Should Throw $auto
{ & ([ScriptBlock]::Create("[runspace]`$$auto = 1")) } | Should Throw $auto
{ . ([ScriptBlock]::Create("[runspace]`$$auto = 1")) } | Should Throw $auto
{ & ([ScriptBlock]::Create("[notexist]`$$auto = 1")) } | Should Throw $auto
{ . ([ScriptBlock]::Create("[notexist]`$$auto = 1")) } | Should Throw $auto
}
}
foreach ($auto in $autos)
{
It "Assign auto w/o type constraint - $auto" {
& ([ScriptBlock]::Create("`$$auto = 1; `$$auto")) | Should Be 1
. ([ScriptBlock]::Create("`$$auto = 1; `$$auto")) | Should Be 1
}
}
It "Assign auto w/ correct type constraint" {
& { [object]$_ = 1; $_ } | Should Be 1
& { [object[]]$args = 1; $args } | Should Be 1
& { [object]$this = 1; $this } | Should Be 1
& { [object]$input = 1; $input } | Should Be 1
# Can't test PSCmdlet or PSBoundParameters, they use an internal type
& { [System.Management.Automation.InvocationInfo]$myInvocation = $myInvocation; $myInvocation.Line } | Should Match Automation.InvocationInfo
& { [string]$PSScriptRoot = 'abc'; $PSScriptRoot } | Should Be abc
& { [string]$PSCommandPath = 'abc'; $PSCommandPath } | Should Be abc
}
}
Describe "Attribute error position" -Tags "CI" {
It "Ambiguous overloads" {
try
{
& {
param(
[ValidateNotNull(1,2,3,4)]
$param
)
}
throw "Should have thrown"
}
catch
{
$_.InvocationInfo.Line | Should Match ValidateNotNull
$_.FullyQualifiedErrorId | Should Be MethodCountCouldNotFindBest
}
}
}
Describe "Multiple alias attributes" -Tags "CI" {
It "basic test" {
function foo {
param(
[alias('aa')]
[alias('bb')]
$cc
)
$cc
}
foo -aa 1 | Should Be 1
foo -bb 2 | Should Be 2
foo -cc 3 | Should Be 3
}
}
Describe "Members of System.Type" -Tags "CI" {
It "Members in public classes derived from System.Type should be found" {
class MyType : System.Collections.IEnumerable
{
[System.Collections.IEnumerator] GetEnumerator() { return $null }
}
[type] | Get-Member ImplementedInterfaces | Should Be 'System.Collections.Generic.IEnumerable[type] ImplementedInterfaces {get;}'
[MyType].ImplementedInterfaces | Should Be System.Collections.IEnumerable
}
}