5e04d4884a
Using Label struct as the map key causes issues because it contains OriginalModuleName. The same module will have a different value for this property when called from inside a soong namespace vs from outside. If there are dups, we can just choose the first one. OriginalModuleName is often used with ModuleFromName, and that function panics if there are modules with the same name in two separate soong namespaces Test: go test ./bp2build ./bazel Change-Id: I2ee33efab03016a72f1eea99cb958b6198baeca2
836 lines
26 KiB
Go
836 lines
26 KiB
Go
// Copyright 2021 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package bazel
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/blueprint/proptools"
|
|
)
|
|
|
|
func TestUniqueBazelLabels(t *testing.T) {
|
|
testCases := []struct {
|
|
originalLabels []Label
|
|
expectedUniqueLabels []Label
|
|
}{
|
|
{
|
|
originalLabels: []Label{
|
|
{Label: "a"},
|
|
{Label: "b"},
|
|
{Label: "a"},
|
|
{Label: "c"},
|
|
// namespaces
|
|
{Label: "//foo:bar", OriginalModuleName: "bar"}, // when referenced from foo namespace
|
|
{Label: "//foo:bar", OriginalModuleName: "//foo:bar"}, // when reference from root namespace
|
|
},
|
|
expectedUniqueLabels: []Label{
|
|
{Label: "//foo:bar", OriginalModuleName: "bar"},
|
|
{Label: "a"},
|
|
{Label: "b"},
|
|
{Label: "c"},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
actualUniqueLabels := UniqueSortedBazelLabels(tc.originalLabels)
|
|
if !reflect.DeepEqual(tc.expectedUniqueLabels, actualUniqueLabels) {
|
|
t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabels, actualUniqueLabels)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSubtractStrings(t *testing.T) {
|
|
testCases := []struct {
|
|
haystack []string
|
|
needle []string
|
|
expectedResult []string
|
|
}{
|
|
{
|
|
haystack: []string{
|
|
"a",
|
|
"b",
|
|
"c",
|
|
},
|
|
needle: []string{
|
|
"a",
|
|
},
|
|
expectedResult: []string{
|
|
"b", "c",
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
actualResult := SubtractStrings(tc.haystack, tc.needle)
|
|
if !reflect.DeepEqual(tc.expectedResult, actualResult) {
|
|
t.Fatalf("Expected %v, got %v", tc.expectedResult, actualResult)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSubtractBazelLabelList(t *testing.T) {
|
|
testCases := []struct {
|
|
haystack LabelList
|
|
needle LabelList
|
|
expectedResult LabelList
|
|
}{
|
|
{
|
|
haystack: LabelList{
|
|
Includes: []Label{
|
|
{Label: "a"},
|
|
{Label: "b"},
|
|
{Label: "c"},
|
|
},
|
|
Excludes: []Label{
|
|
{Label: "x"},
|
|
{Label: "y"},
|
|
{Label: "z"},
|
|
},
|
|
},
|
|
needle: LabelList{
|
|
Includes: []Label{
|
|
{Label: "a"},
|
|
},
|
|
Excludes: []Label{
|
|
{Label: "z"},
|
|
},
|
|
},
|
|
// NOTE: Excludes are intentionally not subtracted
|
|
expectedResult: LabelList{
|
|
Includes: []Label{
|
|
{Label: "b"},
|
|
{Label: "c"},
|
|
},
|
|
Excludes: []Label{
|
|
{Label: "x"},
|
|
{Label: "y"},
|
|
{Label: "z"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
actualResult := SubtractBazelLabelList(tc.haystack, tc.needle)
|
|
if !reflect.DeepEqual(tc.expectedResult, actualResult) {
|
|
t.Fatalf("Expected %v, got %v", tc.expectedResult, actualResult)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSubtractBazelLabelListAttribute(t *testing.T) {
|
|
testCases := []struct {
|
|
haystack LabelListAttribute
|
|
needle LabelListAttribute
|
|
expected LabelListAttribute
|
|
}{
|
|
{
|
|
haystack: LabelListAttribute{
|
|
Value: makeLabelList(
|
|
[]string{"a", "b", "a", "c"},
|
|
[]string{"x", "x", "y", "z"},
|
|
),
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"arm": makeLabelList([]string{"arm_1", "arm_2"}, []string{}),
|
|
"x86": makeLabelList([]string{"x86_3", "x86_4", "x86_5"}, []string{"x86_5"}),
|
|
},
|
|
},
|
|
},
|
|
needle: LabelListAttribute{
|
|
Value: makeLabelList(
|
|
[]string{"d", "a"},
|
|
[]string{"x", "y2", "z2"},
|
|
),
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"arm": makeLabelList([]string{"arm_1", "arm_3"}, []string{}),
|
|
"x86": makeLabelList([]string{"x86_3", "x86_4"}, []string{"x86_6"}),
|
|
},
|
|
},
|
|
},
|
|
expected: LabelListAttribute{
|
|
Value: makeLabelList(
|
|
[]string{"b", "c"},
|
|
[]string{"x", "x", "y", "z"},
|
|
),
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"arm": makeLabelList([]string{"arm_2"}, []string{}),
|
|
"x86": makeLabelList([]string{"x86_5"}, []string{"x86_5"}),
|
|
},
|
|
},
|
|
ForceSpecifyEmptyList: false,
|
|
EmitEmptyList: false,
|
|
Prepend: false,
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
got := SubtractBazelLabelListAttribute(tc.haystack, tc.needle)
|
|
if !reflect.DeepEqual(tc.expected, got) {
|
|
t.Fatalf("Expected\n%v, but got\n%v", tc.expected, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFirstUniqueBazelLabelList(t *testing.T) {
|
|
testCases := []struct {
|
|
originalLabelList LabelList
|
|
expectedUniqueLabelList LabelList
|
|
}{
|
|
{
|
|
originalLabelList: LabelList{
|
|
Includes: []Label{
|
|
{Label: "a"},
|
|
{Label: "b"},
|
|
{Label: "a"},
|
|
{Label: "c"},
|
|
// namespaces
|
|
{Label: "//foo:bar", OriginalModuleName: "bar"}, // when referenced from foo namespace
|
|
{Label: "//foo:bar", OriginalModuleName: "//foo:bar"}, // when referenced from root namespace
|
|
},
|
|
Excludes: []Label{
|
|
{Label: "x"},
|
|
{Label: "x"},
|
|
{Label: "y"},
|
|
{Label: "z"},
|
|
},
|
|
},
|
|
expectedUniqueLabelList: LabelList{
|
|
Includes: []Label{
|
|
{Label: "a"},
|
|
{Label: "b"},
|
|
{Label: "c"},
|
|
{Label: "//foo:bar", OriginalModuleName: "bar"},
|
|
},
|
|
Excludes: []Label{
|
|
{Label: "x"},
|
|
{Label: "y"},
|
|
{Label: "z"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
actualUniqueLabelList := FirstUniqueBazelLabelList(tc.originalLabelList)
|
|
if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
|
|
t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFirstUniqueBazelLabelListAttribute(t *testing.T) {
|
|
testCases := []struct {
|
|
originalLabelList LabelListAttribute
|
|
expectedUniqueLabelList LabelListAttribute
|
|
}{
|
|
{
|
|
originalLabelList: LabelListAttribute{
|
|
Value: makeLabelList(
|
|
[]string{"a", "b", "a", "c"},
|
|
[]string{"x", "x", "y", "z"},
|
|
),
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"arm": makeLabelList([]string{"1", "2", "1"}, []string{}),
|
|
"x86": makeLabelList([]string{"3", "4", "4"}, []string{"5", "5"}),
|
|
},
|
|
},
|
|
},
|
|
expectedUniqueLabelList: LabelListAttribute{
|
|
Value: makeLabelList(
|
|
[]string{"a", "b", "c"},
|
|
[]string{"x", "y", "z"},
|
|
),
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"arm": makeLabelList([]string{"1", "2"}, []string{}),
|
|
"x86": makeLabelList([]string{"3", "4"}, []string{"5"}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
actualUniqueLabelList := FirstUniqueBazelLabelListAttribute(tc.originalLabelList)
|
|
if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
|
|
t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUniqueSortedBazelLabelList(t *testing.T) {
|
|
testCases := []struct {
|
|
originalLabelList LabelList
|
|
expectedUniqueLabelList LabelList
|
|
}{
|
|
{
|
|
originalLabelList: LabelList{
|
|
Includes: []Label{
|
|
{Label: "c"},
|
|
{Label: "a"},
|
|
{Label: "a"},
|
|
{Label: "b"},
|
|
},
|
|
Excludes: []Label{
|
|
{Label: "y"},
|
|
{Label: "z"},
|
|
{Label: "x"},
|
|
{Label: "x"},
|
|
},
|
|
},
|
|
expectedUniqueLabelList: LabelList{
|
|
Includes: []Label{
|
|
{Label: "a"},
|
|
{Label: "b"},
|
|
{Label: "c"},
|
|
},
|
|
Excludes: []Label{
|
|
{Label: "x"},
|
|
{Label: "y"},
|
|
{Label: "z"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
actualUniqueLabelList := UniqueSortedBazelLabelList(tc.originalLabelList)
|
|
if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
|
|
t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
|
|
}
|
|
}
|
|
}
|
|
|
|
func makeLabels(labels ...string) []Label {
|
|
var ret []Label
|
|
for _, l := range labels {
|
|
ret = append(ret, Label{Label: l})
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func makeLabelList(includes, excludes []string) LabelList {
|
|
return LabelList{
|
|
Includes: makeLabels(includes...),
|
|
Excludes: makeLabels(excludes...),
|
|
}
|
|
}
|
|
|
|
func TestResolveExcludes(t *testing.T) {
|
|
attr := LabelListAttribute{
|
|
Value: makeLabelList(
|
|
[]string{
|
|
"all_include",
|
|
"arm_exclude",
|
|
"android_exclude",
|
|
"product_config_exclude",
|
|
},
|
|
[]string{"all_exclude"},
|
|
),
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"arm": makeLabelList([]string{}, []string{"arm_exclude"}),
|
|
"x86": makeLabelList([]string{"x86_include"}, []string{}),
|
|
ConditionsDefaultConfigKey: makeLabelList([]string{"default_include"}, []string{}),
|
|
},
|
|
OsConfigurationAxis: labelListSelectValues{
|
|
"android": makeLabelList([]string{}, []string{"android_exclude"}),
|
|
"linux": makeLabelList([]string{"linux_include"}, []string{}),
|
|
},
|
|
OsArchConfigurationAxis: labelListSelectValues{
|
|
"linux_x86": makeLabelList([]string{"linux_x86_include"}, []string{}),
|
|
},
|
|
ProductVariableConfigurationAxis(false, "product_with_defaults"): labelListSelectValues{
|
|
"a": makeLabelList([]string{}, []string{"not_in_value"}),
|
|
"b": makeLabelList([]string{"b_val"}, []string{}),
|
|
"c": makeLabelList([]string{"c_val"}, []string{}),
|
|
ConditionsDefaultConfigKey: makeLabelList([]string{"c_val", "default", "default2", "all_exclude"}, []string{}),
|
|
},
|
|
ProductVariableConfigurationAxis(false, "product_only_with_excludes"): labelListSelectValues{
|
|
"a": makeLabelList([]string{}, []string{"product_config_exclude"}),
|
|
},
|
|
},
|
|
}
|
|
|
|
attr.ResolveExcludes()
|
|
|
|
expectedBaseIncludes := []Label{{Label: "all_include"}}
|
|
if !reflect.DeepEqual(expectedBaseIncludes, attr.Value.Includes) {
|
|
t.Errorf("Expected Value includes %q, got %q", attr.Value.Includes, expectedBaseIncludes)
|
|
}
|
|
var nilLabels []Label
|
|
expectedConfiguredIncludes := map[ConfigurationAxis]map[string][]Label{
|
|
ArchConfigurationAxis: {
|
|
"arm": nilLabels,
|
|
"x86": makeLabels("arm_exclude", "x86_include"),
|
|
ConditionsDefaultConfigKey: makeLabels("arm_exclude", "default_include"),
|
|
},
|
|
OsConfigurationAxis: {
|
|
"android": nilLabels,
|
|
"linux": makeLabels("android_exclude", "linux_include"),
|
|
ConditionsDefaultConfigKey: makeLabels("android_exclude"),
|
|
},
|
|
OsArchConfigurationAxis: {
|
|
"linux_x86": makeLabels("linux_x86_include"),
|
|
ConditionsDefaultConfigKey: nilLabels,
|
|
},
|
|
ProductVariableConfigurationAxis(false, "product_with_defaults"): {
|
|
"a": nilLabels,
|
|
"b": makeLabels("b_val"),
|
|
"c": makeLabels("c_val"),
|
|
ConditionsDefaultConfigKey: makeLabels("c_val", "default", "default2"),
|
|
},
|
|
ProductVariableConfigurationAxis(false, "product_only_with_excludes"): {
|
|
"a": nilLabels,
|
|
ConditionsDefaultConfigKey: makeLabels("product_config_exclude"),
|
|
},
|
|
}
|
|
for _, axis := range attr.SortedConfigurationAxes() {
|
|
if _, ok := expectedConfiguredIncludes[axis]; !ok {
|
|
t.Errorf("Found unexpected axis %s", axis)
|
|
continue
|
|
}
|
|
expectedForAxis := expectedConfiguredIncludes[axis]
|
|
gotForAxis := attr.ConfigurableValues[axis]
|
|
if len(expectedForAxis) != len(gotForAxis) {
|
|
t.Errorf("Expected %d configs for %s, got %d: %s", len(expectedForAxis), axis, len(gotForAxis), gotForAxis)
|
|
}
|
|
for config, value := range gotForAxis {
|
|
if expected, ok := expectedForAxis[config]; ok {
|
|
if !reflect.DeepEqual(expected, value.Includes) {
|
|
t.Errorf("For %s,\nexpected: %#v\ngot %#v", axis, expected, value.Includes)
|
|
}
|
|
} else {
|
|
t.Errorf("Got unexpected config %q for %s", config, axis)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLabelListAttributePartition(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
input LabelListAttribute
|
|
predicated LabelListAttribute
|
|
unpredicated LabelListAttribute
|
|
predicate func(label Label) bool
|
|
}{
|
|
{
|
|
name: "move all to predicated partition",
|
|
input: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
)),
|
|
predicated: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
)),
|
|
unpredicated: LabelListAttribute{},
|
|
predicate: func(label Label) bool {
|
|
return true
|
|
},
|
|
},
|
|
{
|
|
name: "move all to unpredicated partition",
|
|
input: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
)),
|
|
predicated: LabelListAttribute{},
|
|
unpredicated: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
)),
|
|
predicate: func(label Label) bool {
|
|
return false
|
|
},
|
|
},
|
|
{
|
|
name: "partition includes and excludes",
|
|
input: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
)),
|
|
predicated: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"keep1", "keep2"},
|
|
[]string{"keep1", "keep2"},
|
|
)),
|
|
unpredicated: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"throw1", "throw2"},
|
|
[]string{"throw1", "throw2"},
|
|
)),
|
|
predicate: func(label Label) bool {
|
|
return strings.HasPrefix(label.Label, "keep")
|
|
},
|
|
},
|
|
{
|
|
name: "partition excludes only",
|
|
input: MakeLabelListAttribute(makeLabelList(
|
|
[]string{},
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
)),
|
|
predicated: MakeLabelListAttribute(makeLabelList(
|
|
[]string{},
|
|
[]string{"keep1", "keep2"},
|
|
)),
|
|
unpredicated: MakeLabelListAttribute(makeLabelList(
|
|
[]string{},
|
|
[]string{"throw1", "throw2"},
|
|
)),
|
|
predicate: func(label Label) bool {
|
|
return strings.HasPrefix(label.Label, "keep")
|
|
},
|
|
},
|
|
{
|
|
name: "partition includes only",
|
|
input: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"keep1", "throw1", "keep2", "throw2"},
|
|
[]string{},
|
|
)),
|
|
predicated: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"keep1", "keep2"},
|
|
[]string{},
|
|
)),
|
|
unpredicated: MakeLabelListAttribute(makeLabelList(
|
|
[]string{"throw1", "throw2"},
|
|
[]string{},
|
|
)),
|
|
predicate: func(label Label) bool {
|
|
return strings.HasPrefix(label.Label, "keep")
|
|
},
|
|
},
|
|
{
|
|
name: "empty partition",
|
|
input: MakeLabelListAttribute(makeLabelList([]string{}, []string{})),
|
|
predicated: LabelListAttribute{},
|
|
unpredicated: LabelListAttribute{},
|
|
predicate: func(label Label) bool {
|
|
return true
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
predicated, unpredicated := tc.input.Partition(tc.predicate)
|
|
if !predicated.Value.Equals(tc.predicated.Value) {
|
|
t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated)
|
|
}
|
|
for axis, configs := range predicated.ConfigurableValues {
|
|
tcConfigs, ok := tc.predicated.ConfigurableValues[axis]
|
|
if !ok || !reflect.DeepEqual(configs, tcConfigs) {
|
|
t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated)
|
|
}
|
|
}
|
|
if !unpredicated.Value.Equals(tc.unpredicated.Value) {
|
|
t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated)
|
|
}
|
|
for axis, configs := range unpredicated.ConfigurableValues {
|
|
tcConfigs, ok := tc.unpredicated.ConfigurableValues[axis]
|
|
if !ok || !reflect.DeepEqual(configs, tcConfigs) {
|
|
t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of
|
|
// typ
|
|
func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper {
|
|
return func(omc OtherModuleContext, label Label) (string, bool) {
|
|
m, ok := omc.ModuleFromName(label.Label)
|
|
if !ok {
|
|
return label.Label, false
|
|
}
|
|
mTyp := omc.OtherModuleType(m)
|
|
if typ == mTyp {
|
|
return label.Label + suffix, true
|
|
}
|
|
return label.Label, false
|
|
}
|
|
}
|
|
|
|
func TestPartitionLabelListAttribute(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
ctx *OtherModuleTestContext
|
|
labelList LabelListAttribute
|
|
filters LabelPartitions
|
|
expected PartitionToLabelListAttribute
|
|
expectedErrMsg *string
|
|
}{
|
|
{
|
|
name: "no configurable values",
|
|
ctx: &OtherModuleTestContext{},
|
|
labelList: LabelListAttribute{
|
|
Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
|
|
},
|
|
filters: LabelPartitions{
|
|
"A": LabelPartition{Extensions: []string{".a"}},
|
|
"B": LabelPartition{Extensions: []string{".b"}},
|
|
"C": LabelPartition{Extensions: []string{".c"}},
|
|
},
|
|
expected: PartitionToLabelListAttribute{
|
|
"A": LabelListAttribute{Value: makeLabelList([]string{"a.a"}, []string{})},
|
|
"B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})},
|
|
"C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})},
|
|
},
|
|
},
|
|
{
|
|
name: "no configurable values, remainder partition",
|
|
ctx: &OtherModuleTestContext{},
|
|
labelList: LabelListAttribute{
|
|
Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
|
|
},
|
|
filters: LabelPartitions{
|
|
"A": LabelPartition{Extensions: []string{".a"}, Keep_remainder: true},
|
|
"B": LabelPartition{Extensions: []string{".b"}},
|
|
"C": LabelPartition{Extensions: []string{".c"}},
|
|
},
|
|
expected: PartitionToLabelListAttribute{
|
|
"A": LabelListAttribute{Value: makeLabelList([]string{"a.a", "d.d", "e.e"}, []string{})},
|
|
"B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})},
|
|
"C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})},
|
|
},
|
|
},
|
|
{
|
|
name: "no configurable values, empty partition",
|
|
ctx: &OtherModuleTestContext{},
|
|
labelList: LabelListAttribute{
|
|
Value: makeLabelList([]string{"a.a", "c.c"}, []string{}),
|
|
},
|
|
filters: LabelPartitions{
|
|
"A": LabelPartition{Extensions: []string{".a"}},
|
|
"B": LabelPartition{Extensions: []string{".b"}},
|
|
"C": LabelPartition{Extensions: []string{".c"}},
|
|
},
|
|
expected: PartitionToLabelListAttribute{
|
|
"A": LabelListAttribute{Value: makeLabelList([]string{"a.a"}, []string{})},
|
|
"C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})},
|
|
},
|
|
},
|
|
{
|
|
name: "no configurable values, has map",
|
|
ctx: &OtherModuleTestContext{
|
|
Modules: []TestModuleInfo{{ModuleName: "srcs", Typ: "fg", Dir: "dir"}},
|
|
},
|
|
labelList: LabelListAttribute{
|
|
Value: makeLabelList([]string{"a.a", "srcs", "b.b", "c.c"}, []string{}),
|
|
},
|
|
filters: LabelPartitions{
|
|
"A": LabelPartition{Extensions: []string{".a"}, LabelMapper: labelAddSuffixForTypeMapper("_a", "fg")},
|
|
"B": LabelPartition{Extensions: []string{".b"}},
|
|
"C": LabelPartition{Extensions: []string{".c"}},
|
|
},
|
|
expected: PartitionToLabelListAttribute{
|
|
"A": LabelListAttribute{Value: makeLabelList([]string{"a.a", "srcs_a"}, []string{})},
|
|
"B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})},
|
|
"C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})},
|
|
},
|
|
},
|
|
{
|
|
name: "configurable values, keeps empty if excludes",
|
|
ctx: &OtherModuleTestContext{},
|
|
labelList: LabelListAttribute{
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"x86": makeLabelList([]string{"a.a", "c.c"}, []string{}),
|
|
"arm": makeLabelList([]string{"b.b"}, []string{}),
|
|
"x86_64": makeLabelList([]string{"b.b"}, []string{"d.d"}),
|
|
},
|
|
},
|
|
},
|
|
filters: LabelPartitions{
|
|
"A": LabelPartition{Extensions: []string{".a"}},
|
|
"B": LabelPartition{Extensions: []string{".b"}},
|
|
"C": LabelPartition{Extensions: []string{".c"}},
|
|
},
|
|
expected: PartitionToLabelListAttribute{
|
|
"A": LabelListAttribute{
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"x86": makeLabelList([]string{"a.a"}, []string{}),
|
|
"x86_64": makeLabelList([]string{}, []string{"c.c"}),
|
|
},
|
|
},
|
|
},
|
|
"B": LabelListAttribute{
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"arm": makeLabelList([]string{"b.b"}, []string{}),
|
|
"x86_64": makeLabelList([]string{"b.b"}, []string{"c.c"}),
|
|
},
|
|
},
|
|
},
|
|
"C": LabelListAttribute{
|
|
ConfigurableValues: configurableLabelLists{
|
|
ArchConfigurationAxis: labelListSelectValues{
|
|
"x86": makeLabelList([]string{"c.c"}, []string{}),
|
|
"x86_64": makeLabelList([]string{}, []string{"c.c"}),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "error for multiple partitions same value",
|
|
ctx: &OtherModuleTestContext{},
|
|
labelList: LabelListAttribute{
|
|
Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
|
|
},
|
|
filters: LabelPartitions{
|
|
"A": LabelPartition{Extensions: []string{".a"}},
|
|
"other A": LabelPartition{Extensions: []string{".a"}},
|
|
},
|
|
expected: PartitionToLabelListAttribute{},
|
|
expectedErrMsg: proptools.StringPtr(`"a.a" was found in multiple partitions:`),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := PartitionLabelListAttribute(tc.ctx, &tc.labelList, tc.filters)
|
|
|
|
if hasErrors, expectsErr := len(tc.ctx.errors) > 0, tc.expectedErrMsg != nil; hasErrors != expectsErr {
|
|
t.Errorf("Unexpected error(s): %q, expected: %q", tc.ctx.errors, *tc.expectedErrMsg)
|
|
} else if tc.expectedErrMsg != nil {
|
|
found := false
|
|
for _, err := range tc.ctx.errors {
|
|
if strings.Contains(err, *tc.expectedErrMsg) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Errorf("Expected error message: %q, got %q", *tc.expectedErrMsg, tc.ctx.errors)
|
|
}
|
|
return
|
|
}
|
|
|
|
if len(tc.expected) != len(got) {
|
|
t.Errorf("Expected %d partitions, got %d partitions", len(tc.expected), len(got))
|
|
}
|
|
for partition, expectedLla := range tc.expected {
|
|
gotLla, ok := got[partition]
|
|
if !ok {
|
|
t.Errorf("Expected partition %q, but it was not found %v", partition, got)
|
|
continue
|
|
}
|
|
expectedLabelList := expectedLla.Value
|
|
gotLabelList := gotLla.Value
|
|
if !reflect.DeepEqual(expectedLabelList.Includes, gotLabelList.Includes) {
|
|
t.Errorf("Expected no config includes %v, got %v", expectedLabelList.Includes, gotLabelList.Includes)
|
|
}
|
|
expectedAxes := expectedLla.SortedConfigurationAxes()
|
|
gotAxes := gotLla.SortedConfigurationAxes()
|
|
if !reflect.DeepEqual(expectedAxes, gotAxes) {
|
|
t.Errorf("Expected axes %v, got %v (%#v)", expectedAxes, gotAxes, gotLla)
|
|
}
|
|
for _, axis := range expectedLla.SortedConfigurationAxes() {
|
|
if _, exists := gotLla.ConfigurableValues[axis]; !exists {
|
|
t.Errorf("Expected %s to be a supported axis, but it was not found", axis)
|
|
}
|
|
if expected, got := expectedLla.ConfigurableValues[axis], gotLla.ConfigurableValues[axis]; len(expected) != len(got) {
|
|
t.Errorf("For axis %q: expected configs %v, got %v", axis, expected, got)
|
|
}
|
|
for config, expectedLabelList := range expectedLla.ConfigurableValues[axis] {
|
|
gotLabelList, exists := gotLla.ConfigurableValues[axis][config]
|
|
if !exists {
|
|
t.Errorf("Expected %s to be a supported config, but config was not found", config)
|
|
continue
|
|
}
|
|
if !reflect.DeepEqual(expectedLabelList.Includes, gotLabelList.Includes) {
|
|
t.Errorf("Expected %s %s includes %v, got %v", axis, config, expectedLabelList.Includes, gotLabelList.Includes)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeduplicateAxesFromBase(t *testing.T) {
|
|
attr := StringListAttribute{
|
|
Value: []string{
|
|
"all_include",
|
|
"arm_include",
|
|
"android_include",
|
|
"linux_x86_include",
|
|
},
|
|
ConfigurableValues: configurableStringLists{
|
|
ArchConfigurationAxis: stringListSelectValues{
|
|
"arm": []string{"arm_include"},
|
|
"x86": []string{"x86_include"},
|
|
},
|
|
OsConfigurationAxis: stringListSelectValues{
|
|
"android": []string{"android_include"},
|
|
"linux": []string{"linux_include"},
|
|
},
|
|
OsArchConfigurationAxis: stringListSelectValues{
|
|
"linux_x86": {"linux_x86_include"},
|
|
},
|
|
ProductVariableConfigurationAxis(false, "a"): stringListSelectValues{
|
|
"a": []string{"not_in_value"},
|
|
},
|
|
},
|
|
}
|
|
|
|
attr.DeduplicateAxesFromBase()
|
|
|
|
expectedBaseIncludes := []string{
|
|
"all_include",
|
|
"arm_include",
|
|
"android_include",
|
|
"linux_x86_include",
|
|
}
|
|
if !reflect.DeepEqual(expectedBaseIncludes, attr.Value) {
|
|
t.Errorf("Expected Value includes %q, got %q", attr.Value, expectedBaseIncludes)
|
|
}
|
|
expectedConfiguredIncludes := configurableStringLists{
|
|
ArchConfigurationAxis: stringListSelectValues{
|
|
"x86": []string{"x86_include"},
|
|
},
|
|
OsConfigurationAxis: stringListSelectValues{
|
|
"linux": []string{"linux_include"},
|
|
},
|
|
OsArchConfigurationAxis: stringListSelectValues{},
|
|
ProductVariableConfigurationAxis(false, "a"): stringListSelectValues{
|
|
"a": []string{"not_in_value"},
|
|
},
|
|
}
|
|
for _, axis := range attr.SortedConfigurationAxes() {
|
|
if _, ok := expectedConfiguredIncludes[axis]; !ok {
|
|
t.Errorf("Found unexpected axis %s", axis)
|
|
continue
|
|
}
|
|
expectedForAxis := expectedConfiguredIncludes[axis]
|
|
gotForAxis := attr.ConfigurableValues[axis]
|
|
if len(expectedForAxis) != len(gotForAxis) {
|
|
t.Errorf("Expected %d configs for %s, got %d: %s", len(expectedForAxis), axis, len(gotForAxis), gotForAxis)
|
|
}
|
|
for config, value := range gotForAxis {
|
|
if expected, ok := expectedForAxis[config]; ok {
|
|
if !reflect.DeepEqual(expected, value) {
|
|
t.Errorf("For %s, expected: %#v, got %#v", axis, expected, value)
|
|
}
|
|
} else {
|
|
t.Errorf("Got unexpected config %q for %s", config, axis)
|
|
}
|
|
}
|
|
}
|
|
}
|