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