1// Copyright 2021 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package bazel 16 17import ( 18 "reflect" 19 "strings" 20 "testing" 21 22 "github.com/google/blueprint/proptools" 23) 24 25func TestUniqueBazelLabels(t *testing.T) { 26 testCases := []struct { 27 originalLabels []Label 28 expectedUniqueLabels []Label 29 }{ 30 { 31 originalLabels: []Label{ 32 {Label: "a"}, 33 {Label: "b"}, 34 {Label: "a"}, 35 {Label: "c"}, 36 }, 37 expectedUniqueLabels: []Label{ 38 {Label: "a"}, 39 {Label: "b"}, 40 {Label: "c"}, 41 }, 42 }, 43 } 44 for _, tc := range testCases { 45 actualUniqueLabels := UniqueSortedBazelLabels(tc.originalLabels) 46 if !reflect.DeepEqual(tc.expectedUniqueLabels, actualUniqueLabels) { 47 t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabels, actualUniqueLabels) 48 } 49 } 50} 51 52func TestSubtractStrings(t *testing.T) { 53 testCases := []struct { 54 haystack []string 55 needle []string 56 expectedResult []string 57 }{ 58 { 59 haystack: []string{ 60 "a", 61 "b", 62 "c", 63 }, 64 needle: []string{ 65 "a", 66 }, 67 expectedResult: []string{ 68 "b", "c", 69 }, 70 }, 71 } 72 for _, tc := range testCases { 73 actualResult := SubtractStrings(tc.haystack, tc.needle) 74 if !reflect.DeepEqual(tc.expectedResult, actualResult) { 75 t.Fatalf("Expected %v, got %v", tc.expectedResult, actualResult) 76 } 77 } 78} 79 80func TestSubtractBazelLabelList(t *testing.T) { 81 testCases := []struct { 82 haystack LabelList 83 needle LabelList 84 expectedResult LabelList 85 }{ 86 { 87 haystack: LabelList{ 88 Includes: []Label{ 89 {Label: "a"}, 90 {Label: "b"}, 91 {Label: "c"}, 92 }, 93 Excludes: []Label{ 94 {Label: "x"}, 95 {Label: "y"}, 96 {Label: "z"}, 97 }, 98 }, 99 needle: LabelList{ 100 Includes: []Label{ 101 {Label: "a"}, 102 }, 103 Excludes: []Label{ 104 {Label: "z"}, 105 }, 106 }, 107 // NOTE: Excludes are intentionally not subtracted 108 expectedResult: LabelList{ 109 Includes: []Label{ 110 {Label: "b"}, 111 {Label: "c"}, 112 }, 113 Excludes: []Label{ 114 {Label: "x"}, 115 {Label: "y"}, 116 {Label: "z"}, 117 }, 118 }, 119 }, 120 } 121 for _, tc := range testCases { 122 actualResult := SubtractBazelLabelList(tc.haystack, tc.needle) 123 if !reflect.DeepEqual(tc.expectedResult, actualResult) { 124 t.Fatalf("Expected %v, got %v", tc.expectedResult, actualResult) 125 } 126 } 127} 128func TestFirstUniqueBazelLabelList(t *testing.T) { 129 testCases := []struct { 130 originalLabelList LabelList 131 expectedUniqueLabelList LabelList 132 }{ 133 { 134 originalLabelList: LabelList{ 135 Includes: []Label{ 136 {Label: "a"}, 137 {Label: "b"}, 138 {Label: "a"}, 139 {Label: "c"}, 140 }, 141 Excludes: []Label{ 142 {Label: "x"}, 143 {Label: "x"}, 144 {Label: "y"}, 145 {Label: "z"}, 146 }, 147 }, 148 expectedUniqueLabelList: LabelList{ 149 Includes: []Label{ 150 {Label: "a"}, 151 {Label: "b"}, 152 {Label: "c"}, 153 }, 154 Excludes: []Label{ 155 {Label: "x"}, 156 {Label: "y"}, 157 {Label: "z"}, 158 }, 159 }, 160 }, 161 } 162 for _, tc := range testCases { 163 actualUniqueLabelList := FirstUniqueBazelLabelList(tc.originalLabelList) 164 if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) { 165 t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList) 166 } 167 } 168} 169 170func TestUniqueSortedBazelLabelList(t *testing.T) { 171 testCases := []struct { 172 originalLabelList LabelList 173 expectedUniqueLabelList LabelList 174 }{ 175 { 176 originalLabelList: LabelList{ 177 Includes: []Label{ 178 {Label: "c"}, 179 {Label: "a"}, 180 {Label: "a"}, 181 {Label: "b"}, 182 }, 183 Excludes: []Label{ 184 {Label: "y"}, 185 {Label: "z"}, 186 {Label: "x"}, 187 {Label: "x"}, 188 }, 189 }, 190 expectedUniqueLabelList: LabelList{ 191 Includes: []Label{ 192 {Label: "a"}, 193 {Label: "b"}, 194 {Label: "c"}, 195 }, 196 Excludes: []Label{ 197 {Label: "x"}, 198 {Label: "y"}, 199 {Label: "z"}, 200 }, 201 }, 202 }, 203 } 204 for _, tc := range testCases { 205 actualUniqueLabelList := UniqueSortedBazelLabelList(tc.originalLabelList) 206 if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) { 207 t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList) 208 } 209 } 210} 211 212func makeLabels(labels ...string) []Label { 213 var ret []Label 214 for _, l := range labels { 215 ret = append(ret, Label{Label: l}) 216 } 217 return ret 218} 219 220func makeLabelList(includes, excludes []string) LabelList { 221 return LabelList{ 222 Includes: makeLabels(includes...), 223 Excludes: makeLabels(excludes...), 224 } 225} 226 227func TestResolveExcludes(t *testing.T) { 228 attr := LabelListAttribute{ 229 Value: makeLabelList( 230 []string{ 231 "all_include", 232 "arm_exclude", 233 "android_exclude", 234 "product_config_exclude", 235 }, 236 []string{"all_exclude"}, 237 ), 238 ConfigurableValues: configurableLabelLists{ 239 ArchConfigurationAxis: labelListSelectValues{ 240 "arm": makeLabelList([]string{}, []string{"arm_exclude"}), 241 "x86": makeLabelList([]string{"x86_include"}, []string{}), 242 ConditionsDefaultConfigKey: makeLabelList([]string{"default_include"}, []string{}), 243 }, 244 OsConfigurationAxis: labelListSelectValues{ 245 "android": makeLabelList([]string{}, []string{"android_exclude"}), 246 "linux": makeLabelList([]string{"linux_include"}, []string{}), 247 }, 248 OsArchConfigurationAxis: labelListSelectValues{ 249 "linux_x86": makeLabelList([]string{"linux_x86_include"}, []string{}), 250 }, 251 ProductVariableConfigurationAxis("product_with_defaults", NoConfigAxis): labelListSelectValues{ 252 "a": makeLabelList([]string{}, []string{"not_in_value"}), 253 "b": makeLabelList([]string{"b_val"}, []string{}), 254 "c": makeLabelList([]string{"c_val"}, []string{}), 255 ConditionsDefaultConfigKey: makeLabelList([]string{"c_val", "default", "default2", "all_exclude"}, []string{}), 256 }, 257 ProductVariableConfigurationAxis("product_only_with_excludes", NoConfigAxis): labelListSelectValues{ 258 "a": makeLabelList([]string{}, []string{"product_config_exclude"}), 259 }, 260 }, 261 } 262 263 attr.ResolveExcludes() 264 265 expectedBaseIncludes := []Label{{Label: "all_include"}} 266 if !reflect.DeepEqual(expectedBaseIncludes, attr.Value.Includes) { 267 t.Errorf("Expected Value includes %q, got %q", attr.Value.Includes, expectedBaseIncludes) 268 } 269 var nilLabels []Label 270 expectedConfiguredIncludes := map[ConfigurationAxis]map[string][]Label{ 271 ArchConfigurationAxis: { 272 "arm": nilLabels, 273 "x86": makeLabels("arm_exclude", "x86_include"), 274 ConditionsDefaultConfigKey: makeLabels("arm_exclude", "default_include"), 275 }, 276 OsConfigurationAxis: { 277 "android": nilLabels, 278 "linux": makeLabels("android_exclude", "linux_include"), 279 ConditionsDefaultConfigKey: makeLabels("android_exclude"), 280 }, 281 OsArchConfigurationAxis: { 282 "linux_x86": makeLabels("linux_x86_include"), 283 ConditionsDefaultConfigKey: nilLabels, 284 }, 285 ProductVariableConfigurationAxis("product_with_defaults", NoConfigAxis): { 286 "a": nilLabels, 287 "b": makeLabels("b_val"), 288 "c": makeLabels("c_val"), 289 ConditionsDefaultConfigKey: makeLabels("c_val", "default", "default2"), 290 }, 291 ProductVariableConfigurationAxis("product_only_with_excludes", NoConfigAxis): { 292 "a": nilLabels, 293 ConditionsDefaultConfigKey: makeLabels("product_config_exclude"), 294 }, 295 } 296 for _, axis := range attr.SortedConfigurationAxes() { 297 if _, ok := expectedConfiguredIncludes[axis]; !ok { 298 t.Errorf("Found unexpected axis %s", axis) 299 continue 300 } 301 expectedForAxis := expectedConfiguredIncludes[axis] 302 gotForAxis := attr.ConfigurableValues[axis] 303 if len(expectedForAxis) != len(gotForAxis) { 304 t.Errorf("Expected %d configs for %s, got %d: %s", len(expectedForAxis), axis, len(gotForAxis), gotForAxis) 305 } 306 for config, value := range gotForAxis { 307 if expected, ok := expectedForAxis[config]; ok { 308 if !reflect.DeepEqual(expected, value.Includes) { 309 t.Errorf("For %s,\nexpected: %#v\ngot %#v", axis, expected, value.Includes) 310 } 311 } else { 312 t.Errorf("Got unexpected config %q for %s", config, axis) 313 } 314 } 315 } 316} 317 318func TestLabelListAttributePartition(t *testing.T) { 319 testCases := []struct { 320 name string 321 input LabelListAttribute 322 predicated LabelListAttribute 323 unpredicated LabelListAttribute 324 predicate func(label Label) bool 325 }{ 326 { 327 name: "move all to predicated partition", 328 input: MakeLabelListAttribute(makeLabelList( 329 []string{"keep1", "throw1", "keep2", "throw2"}, 330 []string{"keep1", "throw1", "keep2", "throw2"}, 331 )), 332 predicated: MakeLabelListAttribute(makeLabelList( 333 []string{"keep1", "throw1", "keep2", "throw2"}, 334 []string{"keep1", "throw1", "keep2", "throw2"}, 335 )), 336 unpredicated: LabelListAttribute{}, 337 predicate: func(label Label) bool { 338 return true 339 }, 340 }, 341 { 342 name: "move all to unpredicated partition", 343 input: MakeLabelListAttribute(makeLabelList( 344 []string{"keep1", "throw1", "keep2", "throw2"}, 345 []string{"keep1", "throw1", "keep2", "throw2"}, 346 )), 347 predicated: LabelListAttribute{}, 348 unpredicated: MakeLabelListAttribute(makeLabelList( 349 []string{"keep1", "throw1", "keep2", "throw2"}, 350 []string{"keep1", "throw1", "keep2", "throw2"}, 351 )), 352 predicate: func(label Label) bool { 353 return false 354 }, 355 }, 356 { 357 name: "partition includes and excludes", 358 input: MakeLabelListAttribute(makeLabelList( 359 []string{"keep1", "throw1", "keep2", "throw2"}, 360 []string{"keep1", "throw1", "keep2", "throw2"}, 361 )), 362 predicated: MakeLabelListAttribute(makeLabelList( 363 []string{"keep1", "keep2"}, 364 []string{"keep1", "keep2"}, 365 )), 366 unpredicated: MakeLabelListAttribute(makeLabelList( 367 []string{"throw1", "throw2"}, 368 []string{"throw1", "throw2"}, 369 )), 370 predicate: func(label Label) bool { 371 return strings.HasPrefix(label.Label, "keep") 372 }, 373 }, 374 { 375 name: "partition excludes only", 376 input: MakeLabelListAttribute(makeLabelList( 377 []string{}, 378 []string{"keep1", "throw1", "keep2", "throw2"}, 379 )), 380 predicated: MakeLabelListAttribute(makeLabelList( 381 []string{}, 382 []string{"keep1", "keep2"}, 383 )), 384 unpredicated: MakeLabelListAttribute(makeLabelList( 385 []string{}, 386 []string{"throw1", "throw2"}, 387 )), 388 predicate: func(label Label) bool { 389 return strings.HasPrefix(label.Label, "keep") 390 }, 391 }, 392 { 393 name: "partition includes only", 394 input: MakeLabelListAttribute(makeLabelList( 395 []string{"keep1", "throw1", "keep2", "throw2"}, 396 []string{}, 397 )), 398 predicated: MakeLabelListAttribute(makeLabelList( 399 []string{"keep1", "keep2"}, 400 []string{}, 401 )), 402 unpredicated: MakeLabelListAttribute(makeLabelList( 403 []string{"throw1", "throw2"}, 404 []string{}, 405 )), 406 predicate: func(label Label) bool { 407 return strings.HasPrefix(label.Label, "keep") 408 }, 409 }, 410 { 411 name: "empty partition", 412 input: MakeLabelListAttribute(makeLabelList([]string{}, []string{})), 413 predicated: LabelListAttribute{}, 414 unpredicated: LabelListAttribute{}, 415 predicate: func(label Label) bool { 416 return true 417 }, 418 }, 419 } 420 421 for _, tc := range testCases { 422 t.Run(tc.name, func(t *testing.T) { 423 predicated, unpredicated := tc.input.Partition(tc.predicate) 424 if !predicated.Value.Equals(tc.predicated.Value) { 425 t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated) 426 } 427 for axis, configs := range predicated.ConfigurableValues { 428 tcConfigs, ok := tc.predicated.ConfigurableValues[axis] 429 if !ok || !reflect.DeepEqual(configs, tcConfigs) { 430 t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated) 431 } 432 } 433 if !unpredicated.Value.Equals(tc.unpredicated.Value) { 434 t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated) 435 } 436 for axis, configs := range unpredicated.ConfigurableValues { 437 tcConfigs, ok := tc.unpredicated.ConfigurableValues[axis] 438 if !ok || !reflect.DeepEqual(configs, tcConfigs) { 439 t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated) 440 } 441 } 442 }) 443 } 444} 445 446// labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of 447// typ 448func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper { 449 return func(omc OtherModuleContext, label Label) (string, bool) { 450 m, ok := omc.ModuleFromName(label.Label) 451 if !ok { 452 return label.Label, false 453 } 454 mTyp := omc.OtherModuleType(m) 455 if typ == mTyp { 456 return label.Label + suffix, true 457 } 458 return label.Label, false 459 } 460} 461 462func TestPartitionLabelListAttribute(t *testing.T) { 463 testCases := []struct { 464 name string 465 ctx *OtherModuleTestContext 466 labelList LabelListAttribute 467 filters LabelPartitions 468 expected PartitionToLabelListAttribute 469 expectedErrMsg *string 470 }{ 471 { 472 name: "no configurable values", 473 ctx: &OtherModuleTestContext{}, 474 labelList: LabelListAttribute{ 475 Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}), 476 }, 477 filters: LabelPartitions{ 478 "A": LabelPartition{Extensions: []string{".a"}}, 479 "B": LabelPartition{Extensions: []string{".b"}}, 480 "C": LabelPartition{Extensions: []string{".c"}}, 481 }, 482 expected: PartitionToLabelListAttribute{ 483 "A": LabelListAttribute{Value: makeLabelList([]string{"a.a"}, []string{})}, 484 "B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})}, 485 "C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})}, 486 }, 487 }, 488 { 489 name: "no configurable values, remainder partition", 490 ctx: &OtherModuleTestContext{}, 491 labelList: LabelListAttribute{ 492 Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}), 493 }, 494 filters: LabelPartitions{ 495 "A": LabelPartition{Extensions: []string{".a"}, Keep_remainder: true}, 496 "B": LabelPartition{Extensions: []string{".b"}}, 497 "C": LabelPartition{Extensions: []string{".c"}}, 498 }, 499 expected: PartitionToLabelListAttribute{ 500 "A": LabelListAttribute{Value: makeLabelList([]string{"a.a", "d.d", "e.e"}, []string{})}, 501 "B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})}, 502 "C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})}, 503 }, 504 }, 505 { 506 name: "no configurable values, empty partition", 507 ctx: &OtherModuleTestContext{}, 508 labelList: LabelListAttribute{ 509 Value: makeLabelList([]string{"a.a", "c.c"}, []string{}), 510 }, 511 filters: LabelPartitions{ 512 "A": LabelPartition{Extensions: []string{".a"}}, 513 "B": LabelPartition{Extensions: []string{".b"}}, 514 "C": LabelPartition{Extensions: []string{".c"}}, 515 }, 516 expected: PartitionToLabelListAttribute{ 517 "A": LabelListAttribute{Value: makeLabelList([]string{"a.a"}, []string{})}, 518 "C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})}, 519 }, 520 }, 521 { 522 name: "no configurable values, has map", 523 ctx: &OtherModuleTestContext{ 524 Modules: []TestModuleInfo{{ModuleName: "srcs", Typ: "fg", Dir: "dir"}}, 525 }, 526 labelList: LabelListAttribute{ 527 Value: makeLabelList([]string{"a.a", "srcs", "b.b", "c.c"}, []string{}), 528 }, 529 filters: LabelPartitions{ 530 "A": LabelPartition{Extensions: []string{".a"}, LabelMapper: labelAddSuffixForTypeMapper("_a", "fg")}, 531 "B": LabelPartition{Extensions: []string{".b"}}, 532 "C": LabelPartition{Extensions: []string{".c"}}, 533 }, 534 expected: PartitionToLabelListAttribute{ 535 "A": LabelListAttribute{Value: makeLabelList([]string{"a.a", "srcs_a"}, []string{})}, 536 "B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})}, 537 "C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})}, 538 }, 539 }, 540 { 541 name: "configurable values, keeps empty if excludes", 542 ctx: &OtherModuleTestContext{}, 543 labelList: LabelListAttribute{ 544 ConfigurableValues: configurableLabelLists{ 545 ArchConfigurationAxis: labelListSelectValues{ 546 "x86": makeLabelList([]string{"a.a", "c.c"}, []string{}), 547 "arm": makeLabelList([]string{"b.b"}, []string{}), 548 "x86_64": makeLabelList([]string{"b.b"}, []string{"d.d"}), 549 }, 550 }, 551 }, 552 filters: LabelPartitions{ 553 "A": LabelPartition{Extensions: []string{".a"}}, 554 "B": LabelPartition{Extensions: []string{".b"}}, 555 "C": LabelPartition{Extensions: []string{".c"}}, 556 }, 557 expected: PartitionToLabelListAttribute{ 558 "A": LabelListAttribute{ 559 ConfigurableValues: configurableLabelLists{ 560 ArchConfigurationAxis: labelListSelectValues{ 561 "x86": makeLabelList([]string{"a.a"}, []string{}), 562 "x86_64": makeLabelList([]string{}, []string{"c.c"}), 563 }, 564 }, 565 }, 566 "B": LabelListAttribute{ 567 ConfigurableValues: configurableLabelLists{ 568 ArchConfigurationAxis: labelListSelectValues{ 569 "arm": makeLabelList([]string{"b.b"}, []string{}), 570 "x86_64": makeLabelList([]string{"b.b"}, []string{"c.c"}), 571 }, 572 }, 573 }, 574 "C": LabelListAttribute{ 575 ConfigurableValues: configurableLabelLists{ 576 ArchConfigurationAxis: labelListSelectValues{ 577 "x86": makeLabelList([]string{"c.c"}, []string{}), 578 "x86_64": makeLabelList([]string{}, []string{"c.c"}), 579 }, 580 }, 581 }, 582 }, 583 }, 584 { 585 name: "error for multiple partitions same value", 586 ctx: &OtherModuleTestContext{}, 587 labelList: LabelListAttribute{ 588 Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}), 589 }, 590 filters: LabelPartitions{ 591 "A": LabelPartition{Extensions: []string{".a"}}, 592 "other A": LabelPartition{Extensions: []string{".a"}}, 593 }, 594 expected: PartitionToLabelListAttribute{}, 595 expectedErrMsg: proptools.StringPtr(`"a.a" was found in multiple partitions:`), 596 }, 597 } 598 599 for _, tc := range testCases { 600 t.Run(tc.name, func(t *testing.T) { 601 got := PartitionLabelListAttribute(tc.ctx, &tc.labelList, tc.filters) 602 603 if hasErrors, expectsErr := len(tc.ctx.errors) > 0, tc.expectedErrMsg != nil; hasErrors != expectsErr { 604 t.Errorf("Unexpected error(s): %q, expected: %q", tc.ctx.errors, *tc.expectedErrMsg) 605 } else if tc.expectedErrMsg != nil { 606 found := false 607 for _, err := range tc.ctx.errors { 608 if strings.Contains(err, *tc.expectedErrMsg) { 609 found = true 610 break 611 } 612 } 613 614 if !found { 615 t.Errorf("Expected error message: %q, got %q", *tc.expectedErrMsg, tc.ctx.errors) 616 } 617 return 618 } 619 620 if len(tc.expected) != len(got) { 621 t.Errorf("Expected %d partitions, got %d partitions", len(tc.expected), len(got)) 622 } 623 for partition, expectedLla := range tc.expected { 624 gotLla, ok := got[partition] 625 if !ok { 626 t.Errorf("Expected partition %q, but it was not found %v", partition, got) 627 continue 628 } 629 expectedLabelList := expectedLla.Value 630 gotLabelList := gotLla.Value 631 if !reflect.DeepEqual(expectedLabelList.Includes, gotLabelList.Includes) { 632 t.Errorf("Expected no config includes %v, got %v", expectedLabelList.Includes, gotLabelList.Includes) 633 } 634 expectedAxes := expectedLla.SortedConfigurationAxes() 635 gotAxes := gotLla.SortedConfigurationAxes() 636 if !reflect.DeepEqual(expectedAxes, gotAxes) { 637 t.Errorf("Expected axes %v, got %v (%#v)", expectedAxes, gotAxes, gotLla) 638 } 639 for _, axis := range expectedLla.SortedConfigurationAxes() { 640 if _, exists := gotLla.ConfigurableValues[axis]; !exists { 641 t.Errorf("Expected %s to be a supported axis, but it was not found", axis) 642 } 643 if expected, got := expectedLla.ConfigurableValues[axis], gotLla.ConfigurableValues[axis]; len(expected) != len(got) { 644 t.Errorf("For axis %q: expected configs %v, got %v", axis, expected, got) 645 } 646 for config, expectedLabelList := range expectedLla.ConfigurableValues[axis] { 647 gotLabelList, exists := gotLla.ConfigurableValues[axis][config] 648 if !exists { 649 t.Errorf("Expected %s to be a supported config, but config was not found", config) 650 continue 651 } 652 if !reflect.DeepEqual(expectedLabelList.Includes, gotLabelList.Includes) { 653 t.Errorf("Expected %s %s includes %v, got %v", axis, config, expectedLabelList.Includes, gotLabelList.Includes) 654 } 655 } 656 } 657 } 658 }) 659 } 660} 661 662func TestDeduplicateAxesFromBase(t *testing.T) { 663 attr := StringListAttribute{ 664 Value: []string{ 665 "all_include", 666 "arm_include", 667 "android_include", 668 "linux_x86_include", 669 }, 670 ConfigurableValues: configurableStringLists{ 671 ArchConfigurationAxis: stringListSelectValues{ 672 "arm": []string{"arm_include"}, 673 "x86": []string{"x86_include"}, 674 }, 675 OsConfigurationAxis: stringListSelectValues{ 676 "android": []string{"android_include"}, 677 "linux": []string{"linux_include"}, 678 }, 679 OsArchConfigurationAxis: stringListSelectValues{ 680 "linux_x86": {"linux_x86_include"}, 681 }, 682 ProductVariableConfigurationAxis("a", NoConfigAxis): stringListSelectValues{ 683 "a": []string{"not_in_value"}, 684 }, 685 }, 686 } 687 688 attr.DeduplicateAxesFromBase() 689 690 expectedBaseIncludes := []string{ 691 "all_include", 692 "arm_include", 693 "android_include", 694 "linux_x86_include", 695 } 696 if !reflect.DeepEqual(expectedBaseIncludes, attr.Value) { 697 t.Errorf("Expected Value includes %q, got %q", attr.Value, expectedBaseIncludes) 698 } 699 expectedConfiguredIncludes := configurableStringLists{ 700 ArchConfigurationAxis: stringListSelectValues{ 701 "x86": []string{"x86_include"}, 702 }, 703 OsConfigurationAxis: stringListSelectValues{ 704 "linux": []string{"linux_include"}, 705 }, 706 OsArchConfigurationAxis: stringListSelectValues{}, 707 ProductVariableConfigurationAxis("a", NoConfigAxis): stringListSelectValues{ 708 "a": []string{"not_in_value"}, 709 }, 710 } 711 for _, axis := range attr.SortedConfigurationAxes() { 712 if _, ok := expectedConfiguredIncludes[axis]; !ok { 713 t.Errorf("Found unexpected axis %s", axis) 714 continue 715 } 716 expectedForAxis := expectedConfiguredIncludes[axis] 717 gotForAxis := attr.ConfigurableValues[axis] 718 if len(expectedForAxis) != len(gotForAxis) { 719 t.Errorf("Expected %d configs for %s, got %d: %s", len(expectedForAxis), axis, len(gotForAxis), gotForAxis) 720 } 721 for config, value := range gotForAxis { 722 if expected, ok := expectedForAxis[config]; ok { 723 if !reflect.DeepEqual(expected, value) { 724 t.Errorf("For %s, expected: %#v, got %#v", axis, expected, value) 725 } 726 } else { 727 t.Errorf("Got unexpected config %q for %s", config, axis) 728 } 729 } 730 } 731} 732