1 Import-Module Pester
2 
3 
4 BeforeAll {
5     . $PSScriptRoot/../job-matrix-functions.ps1
6 
CompareMatrices([Array] $matrix, [Array] $expected)7     function CompareMatrices([Array]$matrix, [Array]$expected) {
8         $matrix.Length | Should -Be $expected.Length
9 
10         for ($i = 0; $i -lt $matrix.Length; $i++) {
11             foreach ($entry in $matrix[$i]) {
12                 $entry.name | Should -Be $expected[$i].name
13                 foreach ($param in $entry.parameters.GetEnumerator()) {
14                     $param.Value | Should -Be $expected[$i].parameters[$param.Name]
15                 }
16             }
17         }
18     }
19 }
20 
21 Describe "Platform Matrix nonSparse" -Tag "nonsparse" {
22     BeforeEach {
23         $matrixJson = @'
24 {
25     "matrix": {
26         "testField1": [ 1, 2 ],
27         "testField2": [ 1, 2, 3 ],
28         "testField3": [ 1, 2, 3, 4 ],
29     }
30 }
31 '@
32         $config = GetMatrixConfigFromJson $matrixJson
33     }
34 
35     It "Should process nonSparse parameters" {
36         $parameters, $nonSparse = ProcessNonSparseParameters $config.matrixParameters "testField1","testField3"
37 
38         $parameters.Count | Should -Be 1
39         $parameters[0].Name | Should -Be "testField2"
40         $parameters[0].Value | Should -Be 1,2,3
41 
42         $nonSparse.Count | Should -Be 2
43         $nonSparse[0].Name | Should -Be "testField1"
44         $nonSparse[0].Value | Should -Be 1,2
45         $nonSparse[1].Name | Should -Be "testField3"
46         $nonSparse[1].Value | Should -Be 1,2,3,4
47 
48         $parameters, $nonSparse = ProcessNonSparseParameters $config.matrixParameters "testField3"
49         $parameters.Count | Should -Be 2
50         ($parameters).Name -match "testField3" | Should -Be $null
51 
52         $nonSparse.Count | Should -Be 1
53         $nonSparse[0].Name | Should -Be "testField3"
54         $nonSparse[0].Value | Should -Be 1,2,3,4
55     }
56 
57     It "Should ignore nonSparse with all selection" {
58         $matrix = GenerateMatrix $config "all" -nonSparseParameters "testField3"
59         $matrix.Length | Should -Be 24
60     }
61 
62     It "Should combine sparse matrix with nonSparse parameters" {
63         $matrix = GenerateMatrix $config "sparse" -nonSparseParameters "testField3"
64         $matrix.Length | Should -Be 12
65     }
66 
67     It "Should combine with multiple nonSparse fields" {
68         $matrixJson = @'
69 {
70     "matrix": {
71         "testField1": [ 1, 2 ],
72         "testField2": [ 1, 2 ],
73         "testField3": [ 31, 32 ],
74         "testField4": [ 41, 42 ]
75     }
76 }
77 '@
78         $config = GetMatrixConfigFromJson $matrixJson
79 
80         $matrix = GenerateMatrix $config "all" -nonSparseParameters "testField3","testField4"
81         $matrix.Length | Should -Be 16
82 
83         $matrix = GenerateMatrix $config "sparse" -nonSparseParameters "testField3","testField4"
84         $matrix.Length | Should -Be 8
85     }
86 }
87 
88 Describe "Platform Matrix Import" -Tag "import" {
89     It "Should generate a matrix with nonSparseParameters and an imported sparse matrix" {
90         $matrixJson = @'
91 {
92     "matrix": {
93         "$IMPORT": "./test-import-matrix.json",
94         "testField": [ "test1", "test2" ]
95     }
96 }
97 '@
98         $importConfig = GetMatrixConfigFromJson $matrixJson
99         $matrix = GenerateMatrix $importConfig "sparse" -nonSparseParameters "testField"
100 
101         $matrix.Length | Should -Be 6
102 
103         $matrix[0].name | Should -Be test1_foo1_bar1
104         $matrix[0].parameters.testField | Should -Be "test1"
105         $matrix[0].parameters.Foo | Should -Be "foo1"
106         $matrix[2].name | Should -Be test1_importedBazName
107         $matrix[2].parameters.testField | Should -Be "test1"
108         $matrix[2].parameters.Baz | Should -Be "importedBaz"
109         $matrix[4].name | Should -Be test2_foo2_bar2
110         $matrix[4].parameters.testField | Should -Be "test2"
111         $matrix[4].parameters.Foo | Should -Be "foo2"
112     }
113 
114     It "Should source imported display name lookups" {
115         $matrixJson = @'
116 {
117     "displayNames": {
118         "test1": "test1DisplayName",
119         "importedBaz": "importedBazNameOverride"
120     },
121     "matrix": {
122         "$IMPORT": "./test-import-matrix.json",
123         "testField": [ "test1", "test2" ]
124     }
125 }
126 '@
127         $importConfig = GetMatrixConfigFromJson $matrixJson
128         $matrix = GenerateMatrix $importConfig "sparse" -nonSparseParameters "testField"
129 
130         $matrix[0].name | Should -Be test1DisplayName_foo1_bar1
131         $matrix[2].name | Should -Be test1DisplayName_importedBazNameOverride
132     }
133 
134     It "Should generate a sparse matrix with an imported sparse matrix" {
135         $matrixJson = @'
136 {
137     "matrix": {
138         "$IMPORT": "./test-import-matrix.json",
139         "testField1": [ "test11", "test12" ],
140         "testField2": [ "test21", "test22" ]
141     }
142 }
143 '@
144 
145         $expectedMatrix = @'
146 [
147   {
148     "parameters": { "testField1": "test11", "testField2": "test21", "Foo": "foo1", "Bar": "bar1" },
149     "name": "test11_test21_foo1_bar1"
150   },
151   {
152     "parameters": { "testField1": "test11", "testField2": "test21", "Foo": "foo2", "Bar": "bar2" },
153     "name": "test11_test21_foo2_bar2"
154   },
155   {
156     "parameters": { "testField1": "test11", "testField2": "test21", "Baz": "importedBaz" },
157     "name": "test11_test21_importedBazName"
158   },
159   {
160     "parameters": { "testField1": "test12", "testField2": "test22", "Foo": "foo1", "Bar": "bar1" },
161     "name": "test12_test22_foo1_bar1"
162   },
163   {
164     "parameters": { "testField1": "test12", "testField2": "test22", "Foo": "foo2", "Bar": "bar2" },
165     "name": "test12_test22_foo2_bar2"
166   },
167   {
168     "parameters": { "testField1": "test12", "testField2": "test22", "Baz": "importedBaz" },
169     "name": "test12_test22_importedBazName"
170   }
171 ]
172 '@
173 
174         $importConfig = GetMatrixConfigFromJson $matrixJson
175         $matrix = GenerateMatrix $importConfig "sparse"
176         $expected = $expectedMatrix | ConvertFrom-Json -AsHashtable
177 
178         $matrix.Length | Should -Be 6
179         CompareMatrices $matrix $expected
180     }
181 
182     It "Should import a sparse matrix with import, include, and exclude" {
183         $matrixJson = @'
184 {
185     "matrix": {
186         "$IMPORT": "./test-import-matrix.json",
187         "testField": [ "test1", "test2", "test3" ],
188     },
189     "include": [
190       {
191         "testImportIncludeName": [ "testInclude1", "testInclude2" ]
192       }
193     ],
194     "exclude": [
195       {
196         "testField": "test1"
197       },
198       {
199         "testField": "test3",
200         "Baz": "importedBaz"
201       }
202     ]
203 }
204 '@
205 
206         $expectedMatrix = @'
207 [
208   {
209     "parameters": { "testField": "test2", "Foo": "foo1", "Bar": "bar1" },
210     "name": "test2_foo1_bar1"
211   },
212   {
213     "parameters": { "testField": "test2", "Foo": "foo2", "Bar": "bar2" },
214     "name": "test2_foo2_bar2"
215   },
216   {
217     "parameters": { "testField": "test2", "Baz": "importedBaz" },
218     "name": "test2_importedBazName"
219   },
220   {
221     "parameters": { "testField": "test3", "Foo": "foo1", "Bar": "bar1" },
222     "name": "test3_foo1_bar1"
223   },
224   {
225     "parameters": { "testField": "test3", "Foo": "foo2", "Bar": "bar2" },
226     "name": "test3_foo2_bar2"
227   },
228   {
229     "parameters": { "testImportIncludeName": "testInclude1" },
230     "name": "testInclude1"
231   },
232   {
233     "parameters": { "testImportIncludeName": "testInclude2" },
234     "name": "testInclude2"
235   }
236 ]
237 '@
238 
239         $importConfig = GetMatrixConfigFromJson $matrixJson
240         $matrix = GenerateMatrix $importConfig "sparse"
241         $expected = $expectedMatrix | ConvertFrom-Json -AsHashtable
242 
243         $matrix.Length | Should -Be 7
244         CompareMatrices $matrix $expected
245     }
246 
247     It "Should not combine matrices with duplicate keys" {
248         $matrixJson = @'
249 {
250     "matrix": {
251         "$IMPORT": "./test-import-matrix.json",
252         "Foo": [ "fooOverride1", "fooOverride2" ],
253     }
254 }
255 '@
256 
257         $importConfig = GetMatrixConfigFromJson $matrixJson
258         { GenerateMatrix $importConfig "sparse" } | Should -Throw
259     }
260 
261 }
262 
263 Describe "Platform Matrix Replace" -Tag "replace" {
264     It "Should parse replacement syntax" -TestCases @(
265          @{ query = 'foo=bar/baz'; key = '^foo$'; value = '^bar$'; replace = 'baz' },
266          @{ query = 'foo=\/p:bar/\/p:baz'; key = '^foo$'; value = '^\/p:bar$'; replace = '/p:baz' },
267          @{ query = 'f\=o\/o=\/p:b\=ar/\/p:b\=az'; key = '^f\=o\/o$'; value = '^\/p:b\=ar$'; replace = '/p:b=az' },
268          @{ query = 'foo=bar/'; key = '^foo$'; value = '^bar$'; replace = '' },
269          @{ query = 'foo=/baz'; key = '^foo$'; value = '^$'; replace = 'baz' }
270     ) {
271         $parsed = ParseReplacement $query
272         $parsed.key | Should -Be $key
273         $parsed.value | Should -Be $value
274         $parsed.replace | Should -Be $replace
275     }
276 
277     It "Should fail for invalid replacement syntax" -TestCases @(
278         @{ query = '' },
279         @{ query = 'asdf' },
280         @{ query = 'asdf=foo/bar/baz' },
281         @{ query = 'asdf=foo=bar/baz' },
282         @{ query = 'asdf=foo' }
283     ) {
284         { $parsed = ParseReplacement $query } | Should -Throw
285         { $parsed = ParseReplacement $query } | Should -Throw
286         { $parsed = ParseReplacement $query } | Should -Throw
287         { $parsed = ParseReplacement $query } | Should -Throw
288         { $parsed = ParseReplacement $query } | Should -Throw
289     }
290 
291     It "Should replace values in a matrix" {
292         $matrixJson = @'
293 {
294     "matrix": {
295         "Foo": [ "foo1", "foo2" ],
296         "Bar": [ "bar1", "bar2" ]
297     },
298     "include": [ { "Baz": "baz1" } ]
299 }
300 '@
301 
302         $expectedMatrix = @'
303 [
304   {
305     "parameters": { "Foo": "foo1Replaced", "Bar": "bar1" },
306     "name": "foo1Replaced_bar1"
307   },
308   {
309     "parameters": { "Foo": "fooDefaultReplaced", "Bar": "bar2" },
310     "name": "fooDefaultReplaced_bar2"
311   },
312   {
313     "parameters": { "Baz": "bazReplaced" },
314     "name": "bazReplaced"
315   }
316 ]
317 '@
318 
319         $replace = @(
320             "Foo=foo1/foo1Replaced",
321             "Foo=foo.*/fooDefaultReplaced",
322             ".*=B.z\d/bazReplaced"
323         )
324 
325         $importConfig = GetMatrixConfigFromJson $matrixJson
326         $matrix = GenerateMatrix -config $importConfig -selectFromMatrixType "sparse" -replace $replace
327         $expected = $expectedMatrix | ConvertFrom-Json -AsHashtable
328 
329         $matrix.Length | Should -Be 3
330         CompareMatrices $matrix $expected
331     }
332 
333     It "Should replace values in a matrix with import and nonSparseParameters" {
334         $matrixJson = @'
335 {
336     "matrix": {
337         "$IMPORT": "./test-import-matrix.json",
338         "testField": [ "test1", "test2" ]
339     }
340 }
341 '@
342         $importConfig = GetMatrixConfigFromJson $matrixJson
343         $matrix = GenerateMatrix $importConfig "sparse" -nonSparseParameters "testField" -replace @("testField=test1/testReplaced", "Baz=.*/bazReplaced")
344 
345         $matrix.Length | Should -Be 6
346 
347         $matrix[0].name | Should -Be testReplaced_foo1_bar1
348         $matrix[0].parameters.testField | Should -Be "testReplaced"
349         $matrix[0].parameters.Foo | Should -Be "foo1"
350         $matrix[2].name | Should -Be testReplaced_bazReplaced
351         $matrix[2].parameters.testField | Should -Be "testReplaced"
352         $matrix[2].parameters.Baz | Should -Be "bazReplaced"
353         $matrix[4].name | Should -Be test2_foo2_bar2
354         $matrix[4].parameters.testField | Should -Be "test2"
355         $matrix[4].parameters.Foo | Should -Be "foo2"
356     }
357 
358     It "Should replace values in groupings" {
359         $matrixJson = @'
360 {
361   "matrix": {
362     "Agent": {
363       "ubuntu-1804": { "OSVmImage": "MMSUbuntu18.04", "Pool": "azsdk-pool-mms-ubuntu-1804-general" }
364     },
365     "JavaTestVersion": [ "1.8", "1.11" ]
366   }
367 }
368 '@
369         $importConfig = GetMatrixConfigFromJson $matrixJson
370         $matrix = GenerateMatrix $importConfig "all" -replace @("JavaTestVersion=1.8/2.0", "Pool=.*ubuntu.*/custom-ubuntu-pool")
371 
372         $matrix.Length | Should -Be 2
373         # Replacements of inner values will preserve the grouping name
374         $matrix[0].name | Should -Be "ubuntu1804_20"
375         $matrix[0].parameters.JavaTestVersion | Should -Be "2.0"
376         $matrix[0].parameters.Pool | Should -Be "custom-ubuntu-pool"
377         $matrix[0].parameters.OSVmImage | Should -Be "MMSUbuntu18.04"
378 
379         # Make sure non-literal keys still replace under the hood
380         $matrix = GenerateMatrix $importConfig "all" -replace ".*=.*ubuntu.*/custom-ubuntu-pool"
381 
382         $matrix.Length | Should -Be 2
383         $matrix[0].name | Should -Be "ubuntu1804_18"
384         $matrix[0].parameters.Pool | Should -Be "custom-ubuntu-pool"
385     }
386 
387     It "Should replace values and apply regex capture groups" {
388         $matrixJson = @'
389 {
390   "matrix": {
391     "Foo": [ "foo1", "foo2" ],
392     "Bar": [ "bar1", "bar2" ]
393   }
394 }
395 '@
396         $importConfig = GetMatrixConfigFromJson $matrixJson
397         $replace = 'Foo=(foo)1/$1ReplacedFoo1', 'B.*=(.*)2/$1ReplacedBar2'
398         $matrix = GenerateMatrix $importConfig "sparse" -replace $replace
399 
400         $matrix.Length | Should -Be 2
401         $matrix[0].name | Should -Be "fooReplacedFoo1_bar1"
402         $matrix[0].parameters.Foo | Should -Be "fooReplacedFoo1"
403 
404         $matrix[1].name | Should -Be "foo2_barReplacedBar2"
405         $matrix[1].parameters.Bar | Should -Be "barReplacedBar2"
406     }
407 }
408