• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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