Skip to content

Commit db56acc

Browse files
authored
Merge pull request #999 from Gijsreyn/comparison-function-coalesce
Comparison and object funcions coalesce, create_object and null
2 parents 499d554 + 9687a29 commit db56acc

File tree

6 files changed

+590
-154
lines changed

6 files changed

+590
-154
lines changed

dsc/tests/dsc_expressions.tests.ps1

Lines changed: 210 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -2,188 +2,244 @@
22
# Licensed under the MIT License.
33

44
Describe 'Expressions tests' {
5-
It 'Accessors work: <text>' -TestCases @(
6-
@{ text = "[parameters('test').hello]"; expected = '@{world=there}' }
7-
@{ text = "[parameters('test').hello.world]"; expected = 'there' }
8-
@{ text = "[parameters('test').array[0]]"; expected = 'one' }
9-
@{ text = "[parameters('test').array[1][1]]"; expected = 'three' }
10-
@{ text = "[parameters('test').objectArray[0].name]"; expected = 'one' }
11-
@{ text = "[parameters('test').objectArray[1].value[0]]"; expected = '2' }
12-
@{ text = "[parameters('test').objectArray[1].value[1].name]"; expected = 'three' }
13-
@{ text = "[parameters('test').index]"; expected = '1' }
14-
@{ text = "[parameters('test').objectArray[parameters('test').index].name]"; expected = 'two' }
15-
) {
16-
param($text, $expected)
17-
$yaml = @"
18-
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
19-
parameters:
20-
test:
21-
type: object
22-
defaultValue:
23-
index: 1
24-
hello:
25-
world: there
26-
array:
27-
- one
28-
- [ 'two', 'three' ]
29-
objectArray:
30-
- name: one
31-
value: 1
32-
- name: two
33-
value:
34-
- 2
35-
- nestedObject:
36-
name: three
37-
value: 3
38-
resources:
39-
- name: echo
40-
type: Microsoft.DSC.Debug/Echo
41-
properties:
42-
output: "$text"
5+
It 'Accessors work: <text>' -TestCases @(
6+
@{ text = "[parameters('test').hello]"; expected = '@{world=there}' }
7+
@{ text = "[parameters('test').hello.world]"; expected = 'there' }
8+
@{ text = "[parameters('test').array[0]]"; expected = 'one' }
9+
@{ text = "[parameters('test').array[1][1]]"; expected = 'three' }
10+
@{ text = "[parameters('test').objectArray[0].name]"; expected = 'one' }
11+
@{ text = "[parameters('test').objectArray[1].value[0]]"; expected = '2' }
12+
@{ text = "[parameters('test').objectArray[1].value[1].name]"; expected = 'three' }
13+
@{ text = "[parameters('test').index]"; expected = '1' }
14+
@{ text = "[parameters('test').objectArray[parameters('test').index].name]"; expected = 'two' }
15+
) {
16+
param($text, $expected)
17+
$yaml = @"
18+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
19+
parameters:
20+
test:
21+
type: object
22+
defaultValue:
23+
index: 1
24+
hello:
25+
world: there
26+
array:
27+
- one
28+
- [ 'two', 'three' ]
29+
objectArray:
30+
- name: one
31+
value: 1
32+
- name: two
33+
value:
34+
- 2
35+
- nestedObject:
36+
name: three
37+
value: 3
38+
resources:
39+
- name: echo
40+
type: Microsoft.DSC.Debug/Echo
41+
properties:
42+
output: "$text"
4343
"@
44-
$debug = $yaml | dsc -l trace config get -o yaml -f - 2>&1 | Out-String
45-
$out = $yaml | dsc config get -f - | ConvertFrom-Json
46-
$LASTEXITCODE | Should -Be 0 -Because $debug
47-
$out.results[0].result.actualState.output | Should -Be $expected -Because $debug
48-
}
44+
$debug = $yaml | dsc -l trace config get -o yaml -f - 2>&1 | Out-String
45+
$out = $yaml | dsc config get -f - | ConvertFrom-Json
46+
$LASTEXITCODE | Should -Be 0 -Because $debug
47+
$out.results[0].result.actualState.output | Should -Be $expected -Because $debug
48+
}
4949

50-
It 'Invalid expressions: <expression>' -TestCases @(
51-
@{ expression = "[concat('A','B')].hello" }
52-
@{ expression = "[concat('A','B')](0)" }
53-
@{ expression = "[concat('a','b').hello]" }
54-
@{ expression = "[concat('a','b')[0]]" }
55-
) {
56-
param($expression)
57-
$yaml = @"
58-
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
59-
resources:
60-
- name: echo
61-
type: Microsoft.DSC.Debug/Echo
62-
properties:
63-
output: "$expression"
50+
It 'Invalid expressions: <expression>' -TestCases @(
51+
@{ expression = "[concat('A','B')].hello" }
52+
@{ expression = "[concat('A','B')](0)" }
53+
@{ expression = "[concat('a','b').hello]" }
54+
@{ expression = "[concat('a','b')[0]]" }
55+
) {
56+
param($expression)
57+
$yaml = @"
58+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
59+
resources:
60+
- name: echo
61+
type: Microsoft.DSC.Debug/Echo
62+
properties:
63+
output: "$expression"
6464
"@
65-
$out = dsc config get -i $yaml 2>&1
66-
$LASTEXITCODE | Should -Be 2
67-
$out | Should -BeLike "*ERROR*"
68-
}
65+
$out = dsc config get -i $yaml 2>&1
66+
$LASTEXITCODE | Should -Be 2
67+
$out | Should -BeLike "*ERROR*"
68+
}
6969

70-
It 'Multi-line string literals work' {
71-
$yamlPath = "$PSScriptRoot/../examples/multiline.dsc.yaml"
72-
$out = dsc config get -f $yamlPath | ConvertFrom-Json
73-
$LASTEXITCODE | Should -Be 0
74-
$out.results[0].result.actualState.output | Should -BeExactly @"
70+
It 'Multi-line string literals work' {
71+
$yamlPath = "$PSScriptRoot/../examples/multiline.dsc.yaml"
72+
$out = dsc config get -f $yamlPath | ConvertFrom-Json
73+
$LASTEXITCODE | Should -Be 0
74+
$out.results[0].result.actualState.output | Should -BeExactly @"
7575
This is a
7676
'multi-line'
7777
string.
7878
7979
"@.Replace("`r", "")
80-
$out.results[1].result.actualState.output | Should -BeExactly "This is a single-quote: '"
81-
}
80+
$out.results[1].result.actualState.output | Should -BeExactly "This is a single-quote: '"
81+
}
8282

83-
It 'Nested Group resource does not invoke expressions' {
84-
$yaml = @'
85-
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
86-
resources:
87-
- name: Nested Group
88-
type: Microsoft.DSC/Group
89-
properties:
90-
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
91-
resources:
92-
- name: Deeply nested OSInfo
93-
type: Microsoft/OSInfo
94-
properties: {}
95-
- name: Deeply nested echo
96-
type: Microsoft.DSC.Debug/Echo
97-
properties:
98-
output: >-
99-
[reference(
100-
resourceId('Microsoft/OSInfo', 'Deeply nested OSInfo')
101-
)]
102-
dependsOn:
103-
- "[resourceId('Microsoft/OSInfo', 'Deeply nested OSInfo')]"
83+
It 'Nested Group resource does not invoke expressions' {
84+
$yaml = @'
85+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
86+
resources:
87+
- name: Nested Group
88+
type: Microsoft.DSC/Group
89+
properties:
90+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
91+
resources:
92+
- name: Deeply nested OSInfo
93+
type: Microsoft/OSInfo
94+
properties: {}
95+
- name: Deeply nested echo
96+
type: Microsoft.DSC.Debug/Echo
97+
properties:
98+
output: >-
99+
[reference(
100+
resourceId('Microsoft/OSInfo', 'Deeply nested OSInfo')
101+
)]
102+
dependsOn:
103+
- "[resourceId('Microsoft/OSInfo', 'Deeply nested OSInfo')]"
104104
'@
105105

106-
$out = dsc config get -i $yaml | ConvertFrom-Json
107-
$LASTEXITCODE | Should -Be 0
108-
$out.results[0].result[1].result.actualState.output.family | Should -BeExactly $out.results[0].result[0].result.actualState.family
109-
}
106+
$out = dsc config get -i $yaml | ConvertFrom-Json
107+
$LASTEXITCODE | Should -Be 0
108+
$out.results[0].result[1].result.actualState.output.family | Should -BeExactly $out.results[0].result[0].result.actualState.family
109+
}
110110

111-
It 'Logical functions work: <expression>' -TestCases @(
112-
@{ expression = "[equals('a', 'a')]"; expected = $true }
113-
@{ expression = "[equals('a', 'b')]"; expected = $false }
114-
@{ expression = "[not(equals('a', 'b'))]"; expected = $true }
115-
@{ expression = "[greater(5, 3)]"; expected = $true }
116-
@{ expression = "[greater(3, 5)]"; expected = $false }
117-
@{ expression = "[greater(5, 5)]"; expected = $false }
118-
@{ expression = "[greaterOrEquals(5, 3)]"; expected = $true }
119-
@{ expression = "[greaterOrEquals(3, 5)]"; expected = $false }
120-
@{ expression = "[greaterOrEquals(5, 5)]"; expected = $true }
121-
@{ expression = "[less(3, 5)]"; expected = $true }
122-
@{ expression = "[less(5, 3)]"; expected = $false }
123-
@{ expression = "[less(5, 5)]"; expected = $false }
124-
@{ expression = "[lessOrEquals(3, 5)]"; expected = $true }
125-
@{ expression = "[lessOrEquals(5, 3)]"; expected = $false }
126-
@{ expression = "[lessOrEquals(5, 5)]"; expected = $true }
127-
@{ expression = "[greater('b', 'a')]"; expected = $true }
128-
@{ expression = "[greater('a', 'b')]"; expected = $false }
129-
@{ expression = "[greater('A', 'a')]"; expected = $false }
130-
@{ expression = "[greaterOrEquals('b', 'a')]"; expected = $true }
131-
@{ expression = "[greaterOrEquals('a', 'b')]"; expected = $false }
132-
@{ expression = "[greaterOrEquals('a', 'a')]"; expected = $true }
133-
@{ expression = "[greaterOrEquals('Aa', 'aa')]"; expected = $false }
134-
@{ expression = "[less('a', 'b')]"; expected = $true }
135-
@{ expression = "[less('b', 'a')]"; expected = $false }
136-
@{ expression = "[less('A', 'a')]"; expected = $true }
137-
@{ expression = "[lessOrEquals('a', 'b')]"; expected = $true }
138-
@{ expression = "[lessOrEquals('b', 'a')]"; expected = $false }
139-
@{ expression = "[lessOrEquals('a', 'a')]"; expected = $true }
140-
@{ expression = "[lessOrEquals('aa', 'Aa')]"; expected = $false }
141-
@{ expression = "[and(true, true)]"; expected = $true }
142-
@{ expression = "[and(true, false)]"; expected = $false }
143-
@{ expression = "[or(false, true)]"; expected = $true }
144-
@{ expression = "[or(false, false)]"; expected = $false }
145-
@{ expression = "[not(true)]"; expected = $false }
146-
@{ expression = "[not(or(true, false))]"; expected = $false }
147-
@{ expression = "[bool('TRUE')]" ; expected = $true }
148-
@{ expression = "[bool('False')]" ; expected = $false }
149-
@{ expression = "[bool(1)]" ; expected = $true }
150-
@{ expression = "[not(bool(0))]" ; expected = $true }
151-
@{ expression = "[true()]" ; expected = $true }
152-
@{ expression = "[false()]" ; expected = $false }
153-
) {
154-
param($expression, $expected)
155-
$yaml = @"
111+
It 'Comparison functions work: <expression>' -TestCases @(
112+
@{ expression = "[greater(5, 3)]"; expected = $true }
113+
@{ expression = "[greater(3, 5)]"; expected = $false }
114+
@{ expression = "[greater(5, 5)]"; expected = $false }
115+
@{ expression = "[greaterOrEquals(5, 3)]"; expected = $true }
116+
@{ expression = "[greaterOrEquals(3, 5)]"; expected = $false }
117+
@{ expression = "[greaterOrEquals(5, 5)]"; expected = $true }
118+
@{ expression = "[less(3, 5)]"; expected = $true }
119+
@{ expression = "[less(5, 3)]"; expected = $false }
120+
@{ expression = "[less(5, 5)]"; expected = $false }
121+
@{ expression = "[lessOrEquals(3, 5)]"; expected = $true }
122+
@{ expression = "[lessOrEquals(5, 3)]"; expected = $false }
123+
@{ expression = "[lessOrEquals(5, 5)]"; expected = $true }
124+
@{ expression = "[greater('b', 'a')]"; expected = $true }
125+
@{ expression = "[greater('a', 'b')]"; expected = $false }
126+
@{ expression = "[greater('A', 'a')]"; expected = $false }
127+
@{ expression = "[greaterOrEquals('b', 'a')]"; expected = $true }
128+
@{ expression = "[greaterOrEquals('a', 'b')]"; expected = $false }
129+
@{ expression = "[greaterOrEquals('a', 'a')]"; expected = $true }
130+
@{ expression = "[greaterOrEquals('Aa', 'aa')]"; expected = $false }
131+
@{ expression = "[less('a', 'b')]"; expected = $true }
132+
@{ expression = "[less('b', 'a')]"; expected = $false }
133+
@{ expression = "[less('A', 'a')]"; expected = $true }
134+
@{ expression = "[lessOrEquals('a', 'b')]"; expected = $true }
135+
@{ expression = "[lessOrEquals('b', 'a')]"; expected = $false }
136+
@{ expression = "[lessOrEquals('a', 'a')]"; expected = $true }
137+
@{ expression = "[lessOrEquals('aa', 'Aa')]"; expected = $false }
138+
@{ expression = "[coalesce('DSC', 'World')]" ; expected = 'DSC' }
139+
@{ expression = "[coalesce(42, 'fallback')]" ; expected = 42 }
140+
@{ expression = "[coalesce(true, false)]" ; expected = $true }
141+
@{ expression = "[coalesce('first', 'second')]" ; expected = 'first' }
142+
@{ expression = "[coalesce(createArray('a', 'b'), createArray('c', 'd'))]" ; expected = @('a', 'b') }
143+
@{ expression = "[coalesce(null(), 'fallback')]" ; expected = 'fallback' }
144+
145+
@{ expression = "[coalesce(null(), createArray(1, 2, 3))]" ; expected = @(1, 2, 3) }
146+
@{ expression = "[coalesce(null(), null(), null(), 'finalValue')]" ; expected = 'finalValue' }
147+
@{ expression = "[coalesce(null(), 42, 'not-reached')]" ; expected = 42 }
148+
@{ expression = "[coalesce(null(), true, false)]" ; expected = $true }
149+
) {
150+
param($expression, $expected)
151+
$yaml = @"
152+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
153+
resources:
154+
- name: echo
155+
type: Microsoft.DSC.Debug/Echo
156+
properties:
157+
output: "$expression"
158+
"@
159+
$out = dsc config get -i $yaml 2>$TestDrive/error.log | ConvertFrom-Json
160+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw | Out-String)
161+
$out.results[0].result.actualState.output | Should -Be $expected -Because ($out | ConvertTo-Json -Depth 10| Out-String)
162+
}
163+
164+
It 'Object functions work: <expression>' -TestCases @(
165+
@{ expression = "[createObject('name', 'test')]" ; expected = @{name = 'test' } }
166+
@{ expression = "[createObject('key1', 'value1', 'key2', 42)]" ; expected = @{key1 = 'value1'; key2 = 42 } }
167+
@{ expression = "[createObject()]" ; expected = @{} }
168+
@{ expression = "[null()]" ; expected = $null }
169+
@{ expression = "[createObject('key', null())]" ; expected = @{key = $null } }
170+
@{ expression = "[createObject('result', coalesce(null(), 'fallback'))]" ; expected = @{result = 'fallback' } }
171+
@{ expression = "[createObject('obj', coalesce(null(), createObject('name', 'test')))]" ; expected = @{obj = @{name = 'test' } } }
172+
) {
173+
param($expression, $expected)
174+
$yaml = @"
156175
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
157176
resources:
158177
- name: echo
159178
type: Microsoft.DSC.Debug/Echo
160179
properties:
161180
output: "$expression"
162181
"@
163-
$out = dsc config get -i $yaml 2>$TestDrive/error.log | ConvertFrom-Json
164-
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw | Out-String)
165-
$out.results[0].result.actualState.output | Should -Be $expected -Because ($out | ConvertTo-Json -Depth 10| Out-String)
182+
$out = dsc config get -i $yaml 2>$TestDrive/error.log | ConvertFrom-Json
183+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw | Out-String)
184+
foreach ($key in $out.results[0].result.actualState.output.psobject.properties.Name) {
185+
if ($out.results[0].result.actualState.output.$key -is [psobject]) {
186+
$out.results[0].result.actualState.output.$key.psobject.properties.value | Should -Be $expected.$key.values -Because ($out | ConvertTo-Json -Depth 10 | Out-String)
187+
} else {
188+
$out.results[0].result.actualState.output.$key | Should -Be $expected.$key -Because ($out | ConvertTo-Json -Depth 10 | Out-String)
189+
}
166190
}
191+
}
192+
193+
It 'Logical functions work: <expression>' -TestCases @(
194+
@{ expression = "[equals('a', 'a')]"; expected = $true }
195+
@{ expression = "[equals('a', 'b')]"; expected = $false }
196+
@{ expression = "[not(equals('a', 'b'))]"; expected = $true }
197+
@{ expression = "[and(true, true)]"; expected = $true }
198+
@{ expression = "[and(true, false)]"; expected = $false }
199+
@{ expression = "[or(false, true)]"; expected = $true }
200+
@{ expression = "[or(false, false)]"; expected = $false }
201+
@{ expression = "[not(true)]"; expected = $false }
202+
@{ expression = "[not(or(true, false))]"; expected = $false }
203+
@{ expression = "[bool('TRUE')]" ; expected = $true }
204+
@{ expression = "[bool('False')]" ; expected = $false }
205+
@{ expression = "[bool(1)]" ; expected = $true }
206+
@{ expression = "[not(bool(0))]" ; expected = $true }
207+
@{ expression = "[true()]" ; expected = $true }
208+
@{ expression = "[false()]" ; expected = $false }
209+
) {
210+
param($expression, $expected)
211+
$yaml = @"
212+
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
213+
resources:
214+
- name: echo
215+
type: Microsoft.DSC.Debug/Echo
216+
properties:
217+
output: "$expression"
218+
"@
219+
$out = dsc config get -i $yaml 2>$TestDrive/error.log | ConvertFrom-Json
220+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.log -Raw | Out-String)
221+
$out.results[0].result.actualState.output | Should -Be $expected -Because ($out | ConvertTo-Json -Depth 10 | Out-String)
222+
}
167223

168-
It 'Comparison functions handle type mismatches: <expression>' -TestCases @(
169-
@{ expression = "[greater('a', 1)]" }
170-
@{ expression = "[greaterOrEquals('5', 3)]" }
171-
@{ expression = "[less(1, 'b')]" }
172-
@{ expression = "[lessOrEquals(5, 'a')]" }
173-
) {
174-
param($expression)
175-
$yaml = @"
224+
It 'Comparison functions handle type mismatches: <expression>' -TestCases @(
225+
@{ expression = "[greater('a', 1)]" }
226+
@{ expression = "[greaterOrEquals('5', 3)]" }
227+
@{ expression = "[less(1, 'b')]" }
228+
@{ expression = "[lessOrEquals(5, 'a')]" }
229+
) {
230+
param($expression)
231+
$yaml = @"
176232
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
177233
resources:
178234
- name: echo
179235
type: Microsoft.DSC.Debug/Echo
180236
properties:
181237
output: "$expression"
182238
"@
183-
$out = dsc config get -i $yaml 2>$TestDrive/error.log
184-
$LASTEXITCODE | Should -Be 2
185-
$log = Get-Content -Path $TestDrive/error.log -Raw
186-
$log | Should -BeLike "*ERROR* Arguments must be of the same type*"
239+
$out = dsc config get -i $yaml 2>$TestDrive/error.log
240+
$LASTEXITCODE | Should -Be 2
241+
$log = Get-Content -Path $TestDrive/error.log -Raw
242+
$log | Should -BeLike "*ERROR* Arguments must be of the same type*"
187243

188-
}
244+
}
189245
}

0 commit comments

Comments
 (0)