f7beb89df5
Adding a dependency on a module with variants can be problematic if the code adding the dependency is not aware of every mutator that has created variants. Add an AliasVariations to BottomUpMutatorContext, which allows a mutator to alias the original variant of a module to one of the new variants of the module, which will allow future dependencies to be added using the original list of variations. The aliases are transient, and only exist until the next mutator that calls CreateVariations when visiting the module without also calling AliasVariations. Test: TestAlises Change-Id: Ieaa04b5a6bdcb5a1ff5114b1e03460de795d4479
197 lines
5.9 KiB
Go
197 lines
5.9 KiB
Go
// Copyright 2019 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 blueprint
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
type moduleCtxTestModule struct {
|
|
SimpleName
|
|
}
|
|
|
|
func newModuleCtxTestModule() (Module, []interface{}) {
|
|
m := &moduleCtxTestModule{}
|
|
return m, []interface{}{&m.SimpleName.Properties}
|
|
}
|
|
|
|
func (f *moduleCtxTestModule) GenerateBuildActions(ModuleContext) {
|
|
}
|
|
|
|
func noCreateAliasMutator(name string) func(ctx BottomUpMutatorContext) {
|
|
return func(ctx BottomUpMutatorContext) {
|
|
if ctx.ModuleName() == name {
|
|
ctx.CreateVariations("a", "b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func createAliasMutator(name string) func(ctx BottomUpMutatorContext) {
|
|
return func(ctx BottomUpMutatorContext) {
|
|
if ctx.ModuleName() == name {
|
|
ctx.CreateVariations("a", "b")
|
|
ctx.AliasVariation("b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func addVariantDepsMutator(variants []Variation, tag DependencyTag, from, to string) func(ctx BottomUpMutatorContext) {
|
|
return func(ctx BottomUpMutatorContext) {
|
|
if ctx.ModuleName() == from {
|
|
ctx.AddVariationDependencies(variants, tag, to)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAliases(t *testing.T) {
|
|
runWithFailures := func(ctx *Context, expectedErr string) {
|
|
t.Helper()
|
|
bp := `
|
|
test {
|
|
name: "foo",
|
|
}
|
|
|
|
test {
|
|
name: "bar",
|
|
}
|
|
`
|
|
|
|
mockFS := map[string][]byte{
|
|
"Blueprints": []byte(bp),
|
|
}
|
|
|
|
ctx.MockFileSystem(mockFS)
|
|
|
|
_, errs := ctx.ParseFileList(".", []string{"Blueprints"})
|
|
if len(errs) > 0 {
|
|
t.Errorf("unexpected parse errors:")
|
|
for _, err := range errs {
|
|
t.Errorf(" %s", err)
|
|
}
|
|
}
|
|
|
|
_, errs = ctx.ResolveDependencies(nil)
|
|
if len(errs) > 0 {
|
|
if expectedErr == "" {
|
|
t.Errorf("unexpected dep errors:")
|
|
for _, err := range errs {
|
|
t.Errorf(" %s", err)
|
|
}
|
|
} else {
|
|
for _, err := range errs {
|
|
if strings.Contains(err.Error(), expectedErr) {
|
|
continue
|
|
} else {
|
|
t.Errorf("unexpected dep error: %s", err)
|
|
}
|
|
}
|
|
}
|
|
} else if expectedErr != "" {
|
|
t.Errorf("missing dep error: %s", expectedErr)
|
|
}
|
|
}
|
|
|
|
run := func(ctx *Context) {
|
|
t.Helper()
|
|
runWithFailures(ctx, "")
|
|
}
|
|
|
|
t.Run("simple", func(t *testing.T) {
|
|
// Creates a module "bar" with variants "a" and "b" and alias "" -> "b".
|
|
// Tests a dependency from "foo" to "bar" variant "b" through alias "".
|
|
ctx := NewContext()
|
|
ctx.RegisterModuleType("test", newModuleCtxTestModule)
|
|
ctx.RegisterBottomUpMutator("1", createAliasMutator("bar"))
|
|
ctx.RegisterBottomUpMutator("2", addVariantDepsMutator(nil, nil, "foo", "bar"))
|
|
|
|
run(ctx)
|
|
|
|
foo := ctx.moduleGroupFromName("foo", nil).modules[0]
|
|
barB := ctx.moduleGroupFromName("bar", nil).modules[1]
|
|
|
|
if g, w := barB.variantName, "b"; g != w {
|
|
t.Fatalf("expected bar.modules[1] variant to be %q, got %q", w, g)
|
|
}
|
|
|
|
if g, w := foo.forwardDeps, []*moduleInfo{barB}; !reflect.DeepEqual(g, w) {
|
|
t.Fatalf("expected foo deps to be %q, got %q", w, g)
|
|
}
|
|
})
|
|
|
|
t.Run("chained", func(t *testing.T) {
|
|
// Creates a module "bar" with variants "a_a", "a_b", "b_a" and "b_b" and aliases "" -> "b_b",
|
|
// "a" -> "a_b", and "b" -> "b_b".
|
|
// Tests a dependency from "foo" to "bar" variant "b_b" through alias "".
|
|
ctx := NewContext()
|
|
ctx.RegisterModuleType("test", newModuleCtxTestModule)
|
|
ctx.RegisterBottomUpMutator("1", createAliasMutator("bar"))
|
|
ctx.RegisterBottomUpMutator("2", createAliasMutator("bar"))
|
|
ctx.RegisterBottomUpMutator("3", addVariantDepsMutator(nil, nil, "foo", "bar"))
|
|
|
|
run(ctx)
|
|
|
|
foo := ctx.moduleGroupFromName("foo", nil).modules[0]
|
|
barBB := ctx.moduleGroupFromName("bar", nil).modules[3]
|
|
|
|
if g, w := barBB.variantName, "b_b"; g != w {
|
|
t.Fatalf("expected bar.modules[3] variant to be %q, got %q", w, g)
|
|
}
|
|
|
|
if g, w := foo.forwardDeps, []*moduleInfo{barBB}; !reflect.DeepEqual(g, w) {
|
|
t.Fatalf("expected foo deps to be %q, got %q", w, g)
|
|
}
|
|
})
|
|
|
|
t.Run("chained2", func(t *testing.T) {
|
|
// Creates a module "bar" with variants "a_a", "a_b", "b_a" and "b_b" and aliases "" -> "b_b",
|
|
// "a" -> "a_b", and "b" -> "b_b".
|
|
// Tests a dependency from "foo" to "bar" variant "a_b" through alias "a".
|
|
ctx := NewContext()
|
|
ctx.RegisterModuleType("test", newModuleCtxTestModule)
|
|
ctx.RegisterBottomUpMutator("1", createAliasMutator("bar"))
|
|
ctx.RegisterBottomUpMutator("2", createAliasMutator("bar"))
|
|
ctx.RegisterBottomUpMutator("3", addVariantDepsMutator([]Variation{{"1", "a"}}, nil, "foo", "bar"))
|
|
|
|
run(ctx)
|
|
|
|
foo := ctx.moduleGroupFromName("foo", nil).modules[0]
|
|
barAB := ctx.moduleGroupFromName("bar", nil).modules[1]
|
|
|
|
if g, w := barAB.variantName, "a_b"; g != w {
|
|
t.Fatalf("expected bar.modules[1] variant to be %q, got %q", w, g)
|
|
}
|
|
|
|
if g, w := foo.forwardDeps, []*moduleInfo{barAB}; !reflect.DeepEqual(g, w) {
|
|
t.Fatalf("expected foo deps to be %q, got %q", w, g)
|
|
}
|
|
})
|
|
|
|
t.Run("removed dangling alias", func(t *testing.T) {
|
|
// Creates a module "bar" with variants "a" and "b" and aliases "" -> "b", then splits the variants into
|
|
// "a_a", "a_b", "b_a" and "b_b" without creating new aliases.
|
|
// Tests a dependency from "foo" to removed "bar" alias "" fails.
|
|
ctx := NewContext()
|
|
ctx.RegisterModuleType("test", newModuleCtxTestModule)
|
|
ctx.RegisterBottomUpMutator("1", createAliasMutator("bar"))
|
|
ctx.RegisterBottomUpMutator("2", noCreateAliasMutator("bar"))
|
|
ctx.RegisterBottomUpMutator("3", addVariantDepsMutator(nil, nil, "foo", "bar"))
|
|
|
|
runWithFailures(ctx, `dependency "bar" of "foo" missing variant:`+"\n \n"+
|
|
"available variants:"+
|
|
"\n 1:a, 2:a\n 1:a, 2:b\n 1:b, 2:a\n 1:b, 2:b")
|
|
})
|
|
}
|