Add CreateAliasVariation
CreateAliasVariation creates a new variation for the current mutator that is an alias to a variation that was created with CreateVarations by the same mutator. It is similar to AliasVariation, except that AliasVariation creates an alias from the pre-mutated variant to one of the new variations, while CreateAliasVariation creates an alias from a new post-mutated variation to one of the new variations. Bug: 164216768 Test: TestCreateAliasVariation Change-Id: I8847b8d6fc1d3248abc910b2fe2399881f9bdaee
This commit is contained in:
parent
edc41769fe
commit
279489c017
3 changed files with 236 additions and 32 deletions
61
context.go
61
context.go
|
@ -201,8 +201,8 @@ type moduleInfo struct {
|
|||
waitingCount int
|
||||
|
||||
// set during each runMutator
|
||||
splitModules []*moduleInfo
|
||||
aliasTarget *moduleInfo
|
||||
splitModules []*moduleInfo
|
||||
pendingAliases []pendingAlias
|
||||
|
||||
// set during PrepareBuildActions
|
||||
actionDefs localBuildActions
|
||||
|
@ -1317,6 +1317,15 @@ func (c *Context) convertDepsToVariation(module *moduleInfo,
|
|||
break
|
||||
}
|
||||
}
|
||||
if newDep == nil {
|
||||
// check aliases against variationNam
|
||||
for _, a := range dep.module.pendingAliases {
|
||||
if a.fromVariant.variations[mutatorName] == variationName {
|
||||
newDep = a.target
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if newDep == nil && defaultVariationName != nil {
|
||||
// give it a second chance; match with defaultVariationName
|
||||
for _, m := range dep.module.splitModules {
|
||||
|
@ -1325,6 +1334,15 @@ func (c *Context) convertDepsToVariation(module *moduleInfo,
|
|||
break
|
||||
}
|
||||
}
|
||||
if newDep == nil {
|
||||
// check aliases against defaultVariationName
|
||||
for _, a := range dep.module.pendingAliases {
|
||||
if a.fromVariant.variations[mutatorName] == *defaultVariationName {
|
||||
newDep = a.target
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if newDep == nil {
|
||||
errs = append(errs, &BlueprintError{
|
||||
|
@ -2221,6 +2239,8 @@ func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
|
|||
panic("split module found in sorted module list")
|
||||
}
|
||||
|
||||
module.pendingAliases = nil
|
||||
|
||||
mctx := &mutatorContext{
|
||||
baseModuleContext: baseModuleContext{
|
||||
context: c,
|
||||
|
@ -2315,10 +2335,10 @@ func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
|
|||
}
|
||||
|
||||
// Create any new aliases.
|
||||
if module.aliasTarget != nil {
|
||||
for _, alias := range module.pendingAliases {
|
||||
group.aliases = append(group.aliases, &moduleAlias{
|
||||
variant: module.variant,
|
||||
target: module.aliasTarget,
|
||||
variant: alias.fromVariant,
|
||||
target: alias.target,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -2339,13 +2359,23 @@ func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
|
|||
module.newDirectDeps = nil
|
||||
}
|
||||
|
||||
findAliasTarget := func(variant variant) *moduleInfo {
|
||||
for _, alias := range group.aliases {
|
||||
if alias.variant.variations.equal(variant.variations) {
|
||||
return alias.target
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Forward or delete any dangling aliases.
|
||||
for i := 0; i < len(group.aliases); i++ {
|
||||
alias := group.aliases[i]
|
||||
|
||||
if alias.target.logicModule == nil {
|
||||
if alias.target.aliasTarget != nil {
|
||||
alias.target = alias.target.aliasTarget
|
||||
newTarget := findAliasTarget(alias.target.variant)
|
||||
if newTarget != nil {
|
||||
alias.target = newTarget
|
||||
} else {
|
||||
// The alias was left dangling, remove it.
|
||||
group.aliases = append(group.aliases[:i], group.aliases[i+1:]...)
|
||||
|
@ -3538,14 +3568,17 @@ func (s moduleSorter) Less(i, j int) bool {
|
|||
iName := s.nameInterface.UniqueName(newNamespaceContext(iMod), iMod.group.name)
|
||||
jName := s.nameInterface.UniqueName(newNamespaceContext(jMod), jMod.group.name)
|
||||
if iName == jName {
|
||||
iName = s.modules[i].variant.name
|
||||
jName = s.modules[j].variant.name
|
||||
iVariantName := s.modules[i].variant.name
|
||||
jVariantName := s.modules[j].variant.name
|
||||
if iVariantName == jVariantName {
|
||||
panic(fmt.Sprintf("duplicate module name: %s %s: %#v and %#v\n",
|
||||
iName, iVariantName, iMod.variant.variations, jMod.variant.variations))
|
||||
} else {
|
||||
return iVariantName < jVariantName
|
||||
}
|
||||
} else {
|
||||
return iName < jName
|
||||
}
|
||||
|
||||
if iName == jName {
|
||||
panic(fmt.Sprintf("duplicate module name: %s: %#v and %#v\n", iName, iMod, jMod))
|
||||
}
|
||||
return iName < jName
|
||||
}
|
||||
|
||||
func (s moduleSorter) Swap(i, j int) {
|
||||
|
|
|
@ -850,12 +850,21 @@ type BottomUpMutatorContext interface {
|
|||
// Replacements don't take effect until after the mutator pass is finished.
|
||||
ReplaceDependenciesIf(string, ReplaceDependencyPredicate)
|
||||
|
||||
// AliasVariation takes a variationName that was passed to CreateVariations for this module, and creates an
|
||||
// alias from the current variant to the new variant. The alias will be valid until the next time a mutator
|
||||
// calls CreateVariations or CreateLocalVariations on this module without also calling AliasVariation. The
|
||||
// alias can be used to add dependencies on the newly created variant using the variant map from before
|
||||
// CreateVariations was run.
|
||||
// AliasVariation takes a variationName that was passed to CreateVariations for this module,
|
||||
// and creates an alias from the current variant (before the mutator has run) to the new
|
||||
// variant. The alias will be valid until the next time a mutator calls CreateVariations or
|
||||
// CreateLocalVariations on this module without also calling AliasVariation. The alias can
|
||||
// be used to add dependencies on the newly created variant using the variant map from
|
||||
// before CreateVariations was run.
|
||||
AliasVariation(variationName string)
|
||||
|
||||
// CreateAliasVariation takes a toVariationName that was passed to CreateVariations for this
|
||||
// module, and creates an alias from a new fromVariationName variant the toVariationName
|
||||
// variant. The alias will be valid until the next time a mutator calls CreateVariations or
|
||||
// CreateLocalVariations on this module without also calling AliasVariation. The alias can
|
||||
// be used to add dependencies on the toVariationName variant using the fromVariationName
|
||||
// variant.
|
||||
CreateAliasVariation(fromVariationName, toVariationName string)
|
||||
}
|
||||
|
||||
// A Mutator function is called for each Module, and can use
|
||||
|
@ -899,6 +908,11 @@ func (mctx *mutatorContext) CreateLocalVariations(variationNames ...string) []Mo
|
|||
return mctx.createVariations(variationNames, true)
|
||||
}
|
||||
|
||||
type pendingAlias struct {
|
||||
fromVariant variant
|
||||
target *moduleInfo
|
||||
}
|
||||
|
||||
func (mctx *mutatorContext) createVariations(variationNames []string, local bool) []Module {
|
||||
ret := []Module{}
|
||||
modules, errs := mctx.context.createVariations(mctx.module, mctx.name, mctx.defaultVariation, variationNames, local)
|
||||
|
@ -923,13 +937,18 @@ func (mctx *mutatorContext) createVariations(variationNames []string, local bool
|
|||
}
|
||||
|
||||
func (mctx *mutatorContext) AliasVariation(variationName string) {
|
||||
if mctx.module.aliasTarget != nil {
|
||||
panic(fmt.Errorf("AliasVariation already called"))
|
||||
for _, alias := range mctx.module.pendingAliases {
|
||||
if alias.fromVariant.variations.equal(mctx.module.variant.variations) {
|
||||
panic(fmt.Errorf("AliasVariation already called"))
|
||||
}
|
||||
}
|
||||
|
||||
for _, variant := range mctx.newVariations {
|
||||
if variant.variant.variations[mctx.name] == variationName {
|
||||
mctx.module.aliasTarget = variant
|
||||
mctx.module.pendingAliases = append(mctx.module.pendingAliases, pendingAlias{
|
||||
fromVariant: mctx.module.variant,
|
||||
target: variant,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -941,6 +960,32 @@ func (mctx *mutatorContext) AliasVariation(variationName string) {
|
|||
panic(fmt.Errorf("no %q variation in module variations %q", variationName, foundVariations))
|
||||
}
|
||||
|
||||
func (mctx *mutatorContext) CreateAliasVariation(aliasVariationName, targetVariationName string) {
|
||||
newVariant := newVariant(mctx.module, mctx.name, aliasVariationName, false)
|
||||
|
||||
for _, alias := range mctx.module.pendingAliases {
|
||||
if alias.fromVariant.variations.equal(newVariant.variations) {
|
||||
panic(fmt.Errorf("can't alias %q to %q, already aliased to %q", aliasVariationName, targetVariationName, alias.target.variant.name))
|
||||
}
|
||||
}
|
||||
|
||||
for _, variant := range mctx.newVariations {
|
||||
if variant.variant.variations[mctx.name] == targetVariationName {
|
||||
mctx.module.pendingAliases = append(mctx.module.pendingAliases, pendingAlias{
|
||||
fromVariant: newVariant,
|
||||
target: variant,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var foundVariations []string
|
||||
for _, variant := range mctx.newVariations {
|
||||
foundVariations = append(foundVariations, variant.variant.variations[mctx.name])
|
||||
}
|
||||
panic(fmt.Errorf("no %q variation in module variations %q", targetVariationName, foundVariations))
|
||||
}
|
||||
|
||||
func (mctx *mutatorContext) SetDependencyVariation(variationName string) {
|
||||
mctx.context.convertDepsToVariation(mctx.module, mctx.name, variationName, nil)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ func newModuleCtxTestModule() (Module, []interface{}) {
|
|||
func (f *moduleCtxTestModule) GenerateBuildActions(ModuleContext) {
|
||||
}
|
||||
|
||||
func noCreateAliasMutator(name string) func(ctx BottomUpMutatorContext) {
|
||||
func noAliasMutator(name string) func(ctx BottomUpMutatorContext) {
|
||||
return func(ctx BottomUpMutatorContext) {
|
||||
if ctx.ModuleName() == name {
|
||||
ctx.CreateVariations("a", "b")
|
||||
|
@ -40,11 +40,22 @@ func noCreateAliasMutator(name string) func(ctx BottomUpMutatorContext) {
|
|||
}
|
||||
}
|
||||
|
||||
func aliasMutator(name string) func(ctx BottomUpMutatorContext) {
|
||||
return func(ctx BottomUpMutatorContext) {
|
||||
if ctx.ModuleName() == name {
|
||||
ctx.CreateVariations("a", "b")
|
||||
ctx.AliasVariation("b")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createAliasMutator(name string) func(ctx BottomUpMutatorContext) {
|
||||
return func(ctx BottomUpMutatorContext) {
|
||||
if ctx.ModuleName() == name {
|
||||
ctx.CreateVariations("a", "b")
|
||||
ctx.AliasVariation("b")
|
||||
ctx.CreateAliasVariation("c", "a")
|
||||
ctx.CreateAliasVariation("d", "b")
|
||||
ctx.CreateAliasVariation("e", "a")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +68,7 @@ func addVariantDepsMutator(variants []Variation, tag DependencyTag, from, to str
|
|||
}
|
||||
}
|
||||
|
||||
func TestAliases(t *testing.T) {
|
||||
func TestAliasVariation(t *testing.T) {
|
||||
runWithFailures := func(ctx *Context, expectedErr string) {
|
||||
t.Helper()
|
||||
bp := `
|
||||
|
@ -115,7 +126,7 @@ func TestAliases(t *testing.T) {
|
|||
// Tests a dependency from "foo" to "bar" variant "b" through alias "".
|
||||
ctx := NewContext()
|
||||
ctx.RegisterModuleType("test", newModuleCtxTestModule)
|
||||
ctx.RegisterBottomUpMutator("1", createAliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("1", aliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("2", addVariantDepsMutator(nil, nil, "foo", "bar"))
|
||||
|
||||
run(ctx)
|
||||
|
@ -138,8 +149,8 @@ func TestAliases(t *testing.T) {
|
|||
// 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("1", aliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("2", aliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("3", addVariantDepsMutator(nil, nil, "foo", "bar"))
|
||||
|
||||
run(ctx)
|
||||
|
@ -162,8 +173,8 @@ func TestAliases(t *testing.T) {
|
|||
// 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("1", aliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("2", aliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("3", addVariantDepsMutator([]Variation{{"1", "a"}}, nil, "foo", "bar"))
|
||||
|
||||
run(ctx)
|
||||
|
@ -186,8 +197,8 @@ func TestAliases(t *testing.T) {
|
|||
// 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("1", aliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("2", noAliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("3", addVariantDepsMutator(nil, nil, "foo", "bar"))
|
||||
|
||||
runWithFailures(ctx, `dependency "bar" of "foo" missing variant:`+"\n \n"+
|
||||
|
@ -196,6 +207,121 @@ func TestAliases(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestCreateAliasVariations(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"}, nil)
|
||||
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 "c" -> "a", "d" -> "b", and "e" -> "a".
|
||||
// Tests a dependency from "foo" to "bar" variant "b" through alias "d".
|
||||
ctx := NewContext()
|
||||
ctx.RegisterModuleType("test", newModuleCtxTestModule)
|
||||
ctx.RegisterBottomUpMutator("1", createAliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("2", addVariantDepsMutator([]Variation{{"1", "d"}}, nil, "foo", "bar"))
|
||||
|
||||
run(ctx)
|
||||
|
||||
foo := ctx.moduleGroupFromName("foo", nil).modules[0]
|
||||
barB := ctx.moduleGroupFromName("bar", nil).modules[1]
|
||||
|
||||
if g, w := barB.variant.name, "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 "c" -> "a_b",
|
||||
// "d" -> "b_b", and "d" -> "a_b".
|
||||
// Tests a dependency from "foo" to "bar" variant "b_b" through alias "d".
|
||||
ctx := NewContext()
|
||||
ctx.RegisterModuleType("test", newModuleCtxTestModule)
|
||||
ctx.RegisterBottomUpMutator("1", createAliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("2", aliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("3", addVariantDepsMutator([]Variation{{"1", "d"}}, nil, "foo", "bar"))
|
||||
|
||||
run(ctx)
|
||||
|
||||
foo := ctx.moduleGroupFromName("foo", nil).modules[0]
|
||||
barBB := ctx.moduleGroupFromName("bar", nil).modules[3]
|
||||
|
||||
if g, w := barBB.variant.name, "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("removed dangling alias", func(t *testing.T) {
|
||||
// Creates a module "bar" with variants "a" and "b" and alias "c" -> "a", "d" -> "b", and "e" -> "a",
|
||||
// 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 "d" fails.
|
||||
ctx := NewContext()
|
||||
ctx.RegisterModuleType("test", newModuleCtxTestModule)
|
||||
ctx.RegisterBottomUpMutator("1", createAliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("2", noAliasMutator("bar"))
|
||||
ctx.RegisterBottomUpMutator("3", addVariantDepsMutator([]Variation{{"1", "d"}}, nil, "foo", "bar"))
|
||||
|
||||
runWithFailures(ctx, `dependency "bar" of "foo" missing variant:`+"\n 1:d\n"+
|
||||
"available variants:"+
|
||||
"\n 1:a, 2:a\n 1:a, 2:b\n 1:b, 2:a\n 1:b, 2:b")
|
||||
})
|
||||
}
|
||||
|
||||
func expectedErrors(t *testing.T, errs []error, expectedMessages ...string) {
|
||||
t.Helper()
|
||||
if len(errs) != len(expectedMessages) {
|
||||
|
|
Loading…
Reference in a new issue