Call TransitionMutator.IncomingTransition when adding dependencies later
Adding a dependency on a module that has already had a TransitionMutator run on it may require adjusting the variation name based on the results of IncomingTranstion. Store the variants that existed before the TransitionMutator ran, find one that is a subset of the requested variant, and call TranstionMutator.IncomingTransition to update the value. Bug: 319288033 Test: TestPostTransitionDeps Change-Id: I690357f9792401a3edbc5ae9fdcb666495954fbc
This commit is contained in:
parent
6ed94b7f85
commit
d7474dd743
5 changed files with 279 additions and 114 deletions
92
context.go
92
context.go
|
@ -91,6 +91,8 @@ type Context struct {
|
|||
mutatorInfo []*mutatorInfo
|
||||
variantMutatorNames []string
|
||||
|
||||
transitionMutators []*transitionMutatorImpl
|
||||
|
||||
depsModified uint32 // positive if a mutator modified the dependencies
|
||||
|
||||
dependenciesReady bool // set to true on a successful ResolveDependencies
|
||||
|
@ -455,10 +457,11 @@ type singletonInfo struct {
|
|||
|
||||
type mutatorInfo struct {
|
||||
// set during RegisterMutator
|
||||
topDownMutator TopDownMutator
|
||||
bottomUpMutator BottomUpMutator
|
||||
name string
|
||||
parallel bool
|
||||
topDownMutator TopDownMutator
|
||||
bottomUpMutator BottomUpMutator
|
||||
name string
|
||||
parallel bool
|
||||
transitionMutator *transitionMutatorImpl
|
||||
}
|
||||
|
||||
func newContext() *Context {
|
||||
|
@ -686,6 +689,8 @@ type MutatorHandle interface {
|
|||
// method on the mutator context is thread-safe, but the mutator must handle synchronization
|
||||
// for any modifications to global state or any modules outside the one it was invoked on.
|
||||
Parallel() MutatorHandle
|
||||
|
||||
setTransitionMutator(impl *transitionMutatorImpl) MutatorHandle
|
||||
}
|
||||
|
||||
func (mutator *mutatorInfo) Parallel() MutatorHandle {
|
||||
|
@ -693,6 +698,11 @@ func (mutator *mutatorInfo) Parallel() MutatorHandle {
|
|||
return mutator
|
||||
}
|
||||
|
||||
func (mutator *mutatorInfo) setTransitionMutator(impl *transitionMutatorImpl) MutatorHandle {
|
||||
mutator.transitionMutator = impl
|
||||
return mutator
|
||||
}
|
||||
|
||||
// SetIgnoreUnknownModuleTypes sets the behavior of the context in the case
|
||||
// where it encounters an unknown module type while parsing Blueprints files. By
|
||||
// default, the context will report unknown module types as an error. If this
|
||||
|
@ -1489,7 +1499,7 @@ func (c *Context) createVariations(origModule *moduleInfo, mutator *mutatorInfo,
|
|||
var newLogicModule Module
|
||||
var newProperties []interface{}
|
||||
|
||||
if i == 0 {
|
||||
if i == 0 && mutator.transitionMutator == nil {
|
||||
// Reuse the existing module for the first new variant
|
||||
// This both saves creating a new module, and causes the insertion in c.moduleInfo below
|
||||
// with logicModule as the key to replace the original entry in c.moduleInfo
|
||||
|
@ -1736,6 +1746,8 @@ func (c *Context) resolveDependencies(ctx context.Context, config interface{}) (
|
|||
}
|
||||
defer c.EndEvent("clone_modules")
|
||||
|
||||
c.clearTransitionMutatorInputVariants()
|
||||
|
||||
c.dependenciesReady = true
|
||||
})
|
||||
|
||||
|
@ -1772,8 +1784,8 @@ func blueprintDepsMutator(ctx BottomUpMutatorContext) {
|
|||
// findExactVariantOrSingle searches the moduleGroup for a module with the same variant as module,
|
||||
// and returns the matching module, or nil if one is not found. A group with exactly one module
|
||||
// is always considered matching.
|
||||
func findExactVariantOrSingle(module *moduleInfo, possible *moduleGroup, reverse bool) *moduleInfo {
|
||||
found, _ := findVariant(module, possible, nil, false, reverse)
|
||||
func (c *Context) findExactVariantOrSingle(module *moduleInfo, config any, possible *moduleGroup, reverse bool) *moduleInfo {
|
||||
found, _ := c.findVariant(module, config, possible, nil, false, reverse)
|
||||
if found == nil {
|
||||
for _, moduleOrAlias := range possible.modules {
|
||||
if m := moduleOrAlias.module(); m != nil {
|
||||
|
@ -1788,7 +1800,7 @@ func findExactVariantOrSingle(module *moduleInfo, possible *moduleGroup, reverse
|
|||
return found
|
||||
}
|
||||
|
||||
func (c *Context) addDependency(module *moduleInfo, tag DependencyTag, depName string) (*moduleInfo, []error) {
|
||||
func (c *Context) addDependency(module *moduleInfo, config any, tag DependencyTag, depName string) (*moduleInfo, []error) {
|
||||
if _, ok := tag.(BaseDependencyTag); ok {
|
||||
panic("BaseDependencyTag is not allowed to be used directly!")
|
||||
}
|
||||
|
@ -1805,7 +1817,7 @@ func (c *Context) addDependency(module *moduleInfo, tag DependencyTag, depName s
|
|||
return nil, c.discoveredMissingDependencies(module, depName, nil)
|
||||
}
|
||||
|
||||
if m := findExactVariantOrSingle(module, possibleDeps, false); m != nil {
|
||||
if m := c.findExactVariantOrSingle(module, config, possibleDeps, false); m != nil {
|
||||
module.newDirectDeps = append(module.newDirectDeps, depInfo{m, tag})
|
||||
atomic.AddUint32(&c.depsModified, 1)
|
||||
return m, nil
|
||||
|
@ -1825,7 +1837,7 @@ func (c *Context) addDependency(module *moduleInfo, tag DependencyTag, depName s
|
|||
}}
|
||||
}
|
||||
|
||||
func (c *Context) findReverseDependency(module *moduleInfo, destName string) (*moduleInfo, []error) {
|
||||
func (c *Context) findReverseDependency(module *moduleInfo, config any, destName string) (*moduleInfo, []error) {
|
||||
if destName == module.Name() {
|
||||
return nil, []error{&BlueprintError{
|
||||
Err: fmt.Errorf("%q depends on itself", destName),
|
||||
|
@ -1842,7 +1854,7 @@ func (c *Context) findReverseDependency(module *moduleInfo, destName string) (*m
|
|||
}}
|
||||
}
|
||||
|
||||
if m := findExactVariantOrSingle(module, possibleDeps, true); m != nil {
|
||||
if m := c.findExactVariantOrSingle(module, config, possibleDeps, true); m != nil {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
|
@ -1860,7 +1872,33 @@ func (c *Context) findReverseDependency(module *moduleInfo, destName string) (*m
|
|||
}}
|
||||
}
|
||||
|
||||
func findVariant(module *moduleInfo, possibleDeps *moduleGroup, variations []Variation, far bool, reverse bool) (*moduleInfo, variationMap) {
|
||||
// applyIncomingTransitions takes a variationMap being used to add a dependency on a module in a moduleGroup
|
||||
// and applies the IncomingTransition method of each completed TransitionMutator to modify the requested variation.
|
||||
// It finds a variant that existed before the TransitionMutator ran that is a subset of the requested variant to
|
||||
// use as the module context for IncomingTransition.
|
||||
func (c *Context) applyIncomingTransitions(config any, group *moduleGroup, variant variationMap) {
|
||||
for _, transitionMutator := range c.transitionMutators {
|
||||
for _, inputVariant := range transitionMutator.inputVariants[group] {
|
||||
if inputVariant.variant.variations.subsetOf(variant) {
|
||||
sourceVariation := variant[transitionMutator.name]
|
||||
|
||||
ctx := &incomingTransitionContextImpl{
|
||||
transitionContextImpl{context: c, source: nil, dep: inputVariant,
|
||||
depTag: nil, config: config},
|
||||
}
|
||||
|
||||
outgoingVariation := transitionMutator.mutator.IncomingTransition(ctx, sourceVariation)
|
||||
variant[transitionMutator.name] = outgoingVariation
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *Context) findVariant(module *moduleInfo, config any,
|
||||
possibleDeps *moduleGroup, variations []Variation, far bool, reverse bool) (*moduleInfo, variationMap) {
|
||||
|
||||
// We can't just append variant.Variant to module.dependencyVariant.variantName and
|
||||
// compare the strings because the result won't be in mutator registration order.
|
||||
// Create a new map instead, and then deep compare the maps.
|
||||
|
@ -1882,6 +1920,8 @@ func findVariant(module *moduleInfo, possibleDeps *moduleGroup, variations []Var
|
|||
newVariant[v.Mutator] = v.Variation
|
||||
}
|
||||
|
||||
c.applyIncomingTransitions(config, possibleDeps, newVariant)
|
||||
|
||||
check := func(variant variationMap) bool {
|
||||
if far {
|
||||
return newVariant.subsetOf(variant)
|
||||
|
@ -1901,7 +1941,7 @@ func findVariant(module *moduleInfo, possibleDeps *moduleGroup, variations []Var
|
|||
return foundDep, newVariant
|
||||
}
|
||||
|
||||
func (c *Context) addVariationDependency(module *moduleInfo, variations []Variation,
|
||||
func (c *Context) addVariationDependency(module *moduleInfo, config any, variations []Variation,
|
||||
tag DependencyTag, depName string, far bool) (*moduleInfo, []error) {
|
||||
if _, ok := tag.(BaseDependencyTag); ok {
|
||||
panic("BaseDependencyTag is not allowed to be used directly!")
|
||||
|
@ -1912,7 +1952,7 @@ func (c *Context) addVariationDependency(module *moduleInfo, variations []Variat
|
|||
return nil, c.discoveredMissingDependencies(module, depName, nil)
|
||||
}
|
||||
|
||||
foundDep, newVariant := findVariant(module, possibleDeps, variations, far, false)
|
||||
foundDep, newVariant := c.findVariant(module, config, possibleDeps, variations, far, false)
|
||||
|
||||
if foundDep == nil {
|
||||
if c.allowMissingDependencies {
|
||||
|
@ -2936,6 +2976,13 @@ func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
|
|||
|
||||
c.moduleInfo = newModuleInfo
|
||||
|
||||
isTransitionMutator := mutator.transitionMutator != nil
|
||||
|
||||
var transitionMutatorInputVariants map[*moduleGroup][]*moduleInfo
|
||||
if isTransitionMutator {
|
||||
transitionMutatorInputVariants = make(map[*moduleGroup][]*moduleInfo)
|
||||
}
|
||||
|
||||
for _, group := range c.moduleGroups {
|
||||
for i := 0; i < len(group.modules); i++ {
|
||||
module := group.modules[i].module()
|
||||
|
@ -2946,6 +2993,10 @@ func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
|
|||
|
||||
// Update module group to contain newly split variants
|
||||
if module.splitModules != nil {
|
||||
if isTransitionMutator {
|
||||
// For transition mutators, save the pre-split variant for reusing later in applyIncomingTransitions.
|
||||
transitionMutatorInputVariants[group] = append(transitionMutatorInputVariants[group], module)
|
||||
}
|
||||
group.modules, i = spliceModules(group.modules, i, module.splitModules)
|
||||
}
|
||||
|
||||
|
@ -2996,6 +3047,11 @@ func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
|
|||
}
|
||||
}
|
||||
|
||||
if isTransitionMutator {
|
||||
mutator.transitionMutator.inputVariants = transitionMutatorInputVariants
|
||||
c.transitionMutators = append(c.transitionMutators, mutator.transitionMutator)
|
||||
}
|
||||
|
||||
// Add in any new reverse dependencies that were added by the mutator
|
||||
for module, deps := range reverseDeps {
|
||||
sort.Sort(depSorter(deps))
|
||||
|
@ -3031,6 +3087,14 @@ func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
|
|||
return deps, errs
|
||||
}
|
||||
|
||||
// clearTransitionMutatorInputVariants removes the inputVariants field from every
|
||||
// TransitionMutator now that all dependencies have been resolved.
|
||||
func (c *Context) clearTransitionMutatorInputVariants() {
|
||||
for _, mutator := range c.transitionMutators {
|
||||
mutator.inputVariants = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Replaces every build logic module with a clone of itself. Prevents introducing problems where
|
||||
// a mutator sets a non-property member variable on a module, which works until a later mutator
|
||||
// creates variants of that module.
|
||||
|
|
|
@ -829,7 +829,8 @@ func Test_findVariant(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, _ := findVariant(module, tt.possibleDeps, tt.variations, tt.far, tt.reverse)
|
||||
ctx := NewContext()
|
||||
got, _ := ctx.findVariant(module, nil, tt.possibleDeps, tt.variations, tt.far, tt.reverse)
|
||||
if g, w := got == nil, tt.want == "nil"; g != w {
|
||||
t.Fatalf("findVariant() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
|
|
@ -575,7 +575,7 @@ func (m *baseModuleContext) OtherModuleDependencyVariantExists(variations []Vari
|
|||
if possibleDeps == nil {
|
||||
return false
|
||||
}
|
||||
found, _ := findVariant(m.module, possibleDeps, variations, false, false)
|
||||
found, _ := m.context.findVariant(m.module, m.config, possibleDeps, variations, false, false)
|
||||
return found != nil
|
||||
}
|
||||
|
||||
|
@ -584,7 +584,7 @@ func (m *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []V
|
|||
if possibleDeps == nil {
|
||||
return false
|
||||
}
|
||||
found, _ := findVariant(m.module, possibleDeps, variations, true, false)
|
||||
found, _ := m.context.findVariant(m.module, m.config, possibleDeps, variations, true, false)
|
||||
return found != nil
|
||||
}
|
||||
|
||||
|
@ -593,7 +593,7 @@ func (m *baseModuleContext) OtherModuleReverseDependencyVariantExists(name strin
|
|||
if possibleDeps == nil {
|
||||
return false
|
||||
}
|
||||
found, _ := findVariant(m.module, possibleDeps, nil, false, true)
|
||||
found, _ := m.context.findVariant(m.module, m.config, possibleDeps, nil, false, true)
|
||||
return found != nil
|
||||
}
|
||||
|
||||
|
@ -1117,7 +1117,7 @@ func (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps
|
|||
depInfos := make([]Module, 0, len(deps))
|
||||
for _, dep := range deps {
|
||||
modInfo := mctx.context.moduleInfo[module]
|
||||
depInfo, errs := mctx.context.addDependency(modInfo, tag, dep)
|
||||
depInfo, errs := mctx.context.addDependency(modInfo, mctx.config, tag, dep)
|
||||
if len(errs) > 0 {
|
||||
mctx.errs = append(mctx.errs, errs...)
|
||||
}
|
||||
|
@ -1135,7 +1135,7 @@ func (mctx *mutatorContext) AddReverseDependency(module Module, tag DependencyTa
|
|||
panic("BaseDependencyTag is not allowed to be used directly!")
|
||||
}
|
||||
|
||||
destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], destName)
|
||||
destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], mctx.config, destName)
|
||||
if len(errs) > 0 {
|
||||
mctx.errs = append(mctx.errs, errs...)
|
||||
return
|
||||
|
@ -1152,7 +1152,7 @@ func (mctx *mutatorContext) AddVariationDependencies(variations []Variation, tag
|
|||
|
||||
depInfos := make([]Module, 0, len(deps))
|
||||
for _, dep := range deps {
|
||||
depInfo, errs := mctx.context.addVariationDependency(mctx.module, variations, tag, dep, false)
|
||||
depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.config, variations, tag, dep, false)
|
||||
if len(errs) > 0 {
|
||||
mctx.errs = append(mctx.errs, errs...)
|
||||
}
|
||||
|
@ -1170,7 +1170,7 @@ func (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation,
|
|||
|
||||
depInfos := make([]Module, 0, len(deps))
|
||||
for _, dep := range deps {
|
||||
depInfo, errs := mctx.context.addVariationDependency(mctx.module, variations, tag, dep, true)
|
||||
depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.config, variations, tag, dep, true)
|
||||
if len(errs) > 0 {
|
||||
mctx.errs = append(mctx.errs, errs...)
|
||||
}
|
||||
|
|
|
@ -144,8 +144,9 @@ type OutgoingTransitionContext interface {
|
|||
}
|
||||
|
||||
type transitionMutatorImpl struct {
|
||||
name string
|
||||
mutator TransitionMutator
|
||||
name string
|
||||
mutator TransitionMutator
|
||||
inputVariants map[*moduleGroup][]*moduleInfo
|
||||
}
|
||||
|
||||
// Adds each argument in items to l if it's not already there.
|
||||
|
@ -294,7 +295,7 @@ func (c *Context) RegisterTransitionMutator(name string, mutator TransitionMutat
|
|||
impl := &transitionMutatorImpl{name: name, mutator: mutator}
|
||||
|
||||
c.RegisterTopDownMutator(name+"_deps", impl.topDownMutator).Parallel()
|
||||
c.RegisterBottomUpMutator(name, impl.bottomUpMutator).Parallel()
|
||||
c.RegisterBottomUpMutator(name, impl.bottomUpMutator).Parallel().setTransitionMutator(impl)
|
||||
c.RegisterBottomUpMutator(name+"_mutate", impl.mutateMutator).Parallel()
|
||||
}
|
||||
|
||||
|
|
|
@ -15,14 +15,48 @@
|
|||
package blueprint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTransition(t *testing.T) {
|
||||
func testTransition(bp string) (*Context, []error) {
|
||||
ctx := newContext()
|
||||
ctx.MockFileSystem(map[string][]byte{
|
||||
"Android.bp": []byte(`
|
||||
"Android.bp": []byte(bp),
|
||||
})
|
||||
|
||||
ctx.RegisterBottomUpMutator("deps", depsMutator)
|
||||
ctx.RegisterTransitionMutator("transition", transitionTestMutator{})
|
||||
ctx.RegisterBottomUpMutator("post_transition_deps", postTransitionDepsMutator)
|
||||
|
||||
ctx.RegisterModuleType("transition_module", newTransitionModule)
|
||||
_, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)
|
||||
if len(errs) > 0 {
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
_, errs = ctx.ResolveDependencies(nil)
|
||||
if len(errs) > 0 {
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func assertNoErrors(t *testing.T, errs []error) {
|
||||
t.Helper()
|
||||
if len(errs) > 0 {
|
||||
t.Errorf("unexpected errors:")
|
||||
for _, err := range errs {
|
||||
t.Errorf(" %s", err)
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
const testTransitionBp = `
|
||||
transition_module {
|
||||
name: "A",
|
||||
deps: ["B", "C"],
|
||||
|
@ -33,6 +67,7 @@ func TestTransition(t *testing.T) {
|
|||
name: "B",
|
||||
deps: ["C"],
|
||||
outgoing: "c",
|
||||
%s
|
||||
}
|
||||
|
||||
transition_module {
|
||||
|
@ -43,103 +78,156 @@ func TestTransition(t *testing.T) {
|
|||
transition_module {
|
||||
name: "D",
|
||||
incoming: "d",
|
||||
deps: ["E"],
|
||||
}
|
||||
`),
|
||||
|
||||
transition_module {
|
||||
name: "E",
|
||||
}
|
||||
`
|
||||
|
||||
func getTransitionModule(ctx *Context, name, variant string) *transitionModule {
|
||||
group := ctx.moduleGroupFromName(name, nil)
|
||||
module := group.moduleOrAliasByVariantName(variant).module()
|
||||
return module.logicModule.(*transitionModule)
|
||||
}
|
||||
|
||||
func checkTransitionVariants(t *testing.T, ctx *Context, name string, expectedVariants []string) {
|
||||
t.Helper()
|
||||
group := ctx.moduleGroupFromName(name, nil)
|
||||
var gotVariants []string
|
||||
for _, variant := range group.modules {
|
||||
gotVariants = append(gotVariants, variant.moduleOrAliasVariant().variations["transition"])
|
||||
}
|
||||
if !slices.Equal(expectedVariants, gotVariants) {
|
||||
t.Errorf("expected variants of %q to be %q, got %q", name, expectedVariants, gotVariants)
|
||||
}
|
||||
}
|
||||
|
||||
func checkTransitionDeps(t *testing.T, ctx *Context, m Module, expected ...string) {
|
||||
t.Helper()
|
||||
var got []string
|
||||
ctx.VisitDirectDeps(m, func(m Module) {
|
||||
got = append(got, ctx.ModuleName(m)+"("+ctx.ModuleSubDir(m)+")")
|
||||
})
|
||||
|
||||
ctx.RegisterBottomUpMutator("deps", depsMutator)
|
||||
ctx.RegisterTransitionMutator("transition", transitionTestMutator{})
|
||||
|
||||
ctx.RegisterModuleType("transition_module", newTransitionModule)
|
||||
_, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)
|
||||
if len(errs) > 0 {
|
||||
t.Errorf("unexpected parse errors:")
|
||||
for _, err := range errs {
|
||||
t.Errorf(" %s", err)
|
||||
}
|
||||
t.FailNow()
|
||||
if !slices.Equal(got, expected) {
|
||||
t.Errorf("unexpected %q dependencies, got %q expected %q",
|
||||
ctx.ModuleName(m), got, expected)
|
||||
}
|
||||
}
|
||||
|
||||
_, errs = ctx.ResolveDependencies(nil)
|
||||
if len(errs) > 0 {
|
||||
t.Errorf("unexpected dep errors:")
|
||||
for _, err := range errs {
|
||||
t.Errorf(" %s", err)
|
||||
}
|
||||
t.FailNow()
|
||||
func checkTransitionMutate(t *testing.T, m *transitionModule, variant string) {
|
||||
t.Helper()
|
||||
if m.properties.Mutated != variant {
|
||||
t.Errorf("unexpected mutated property in %q, expected %q got %q", m.Name(), variant, m.properties.Mutated)
|
||||
}
|
||||
}
|
||||
|
||||
getModule := func(name, variant string) *transitionModule {
|
||||
group := ctx.moduleGroupFromName(name, nil)
|
||||
module := group.moduleOrAliasByVariantName(variant).module()
|
||||
return module.logicModule.(*transitionModule)
|
||||
}
|
||||
|
||||
checkVariants := func(name string, expectedVariants []string) {
|
||||
t.Helper()
|
||||
group := ctx.moduleGroupFromName(name, nil)
|
||||
var gotVariants []string
|
||||
for _, variant := range group.modules {
|
||||
gotVariants = append(gotVariants, variant.moduleOrAliasVariant().variations["transition"])
|
||||
}
|
||||
if !slices.Equal(expectedVariants, gotVariants) {
|
||||
t.Errorf("expected variants of %q to be %q, got %q", name, expectedVariants, gotVariants)
|
||||
}
|
||||
}
|
||||
func TestTransition(t *testing.T) {
|
||||
ctx, errs := testTransition(fmt.Sprintf(testTransitionBp, ""))
|
||||
assertNoErrors(t, errs)
|
||||
|
||||
// Module A uses Split to create a and b variants
|
||||
checkVariants("A", []string{"a", "b"})
|
||||
checkTransitionVariants(t, ctx, "A", []string{"a", "b"})
|
||||
// Module B inherits a and b variants from A
|
||||
checkVariants("B", []string{"", "a", "b"})
|
||||
checkTransitionVariants(t, ctx, "B", []string{"", "a", "b"})
|
||||
// Module C inherits a and b variants from A, but gets an outgoing c variant from B
|
||||
checkVariants("C", []string{"", "a", "b", "c"})
|
||||
checkTransitionVariants(t, ctx, "C", []string{"", "a", "b", "c"})
|
||||
// Module D always has incoming variant d
|
||||
checkVariants("D", []string{"", "d"})
|
||||
checkTransitionVariants(t, ctx, "D", []string{"", "d"})
|
||||
// Module E inherits d from D
|
||||
checkTransitionVariants(t, ctx, "E", []string{"", "d"})
|
||||
|
||||
A_a := getModule("A", "a")
|
||||
A_b := getModule("A", "b")
|
||||
B_a := getModule("B", "a")
|
||||
B_b := getModule("B", "b")
|
||||
C_a := getModule("C", "a")
|
||||
C_b := getModule("C", "b")
|
||||
C_c := getModule("C", "c")
|
||||
D_d := getModule("D", "d")
|
||||
A_a := getTransitionModule(ctx, "A", "a")
|
||||
A_b := getTransitionModule(ctx, "A", "b")
|
||||
B_a := getTransitionModule(ctx, "B", "a")
|
||||
B_b := getTransitionModule(ctx, "B", "b")
|
||||
C_a := getTransitionModule(ctx, "C", "a")
|
||||
C_b := getTransitionModule(ctx, "C", "b")
|
||||
C_c := getTransitionModule(ctx, "C", "c")
|
||||
D_d := getTransitionModule(ctx, "D", "d")
|
||||
E_d := getTransitionModule(ctx, "E", "d")
|
||||
|
||||
checkDeps := func(m Module, expected ...string) {
|
||||
var got []string
|
||||
ctx.VisitDirectDeps(m, func(m Module) {
|
||||
got = append(got, ctx.ModuleName(m)+"("+ctx.ModuleSubDir(m)+")")
|
||||
})
|
||||
if !slices.Equal(got, expected) {
|
||||
t.Errorf("unexpected %q dependencies, got %q expected %q",
|
||||
ctx.ModuleName(m), got, expected)
|
||||
}
|
||||
checkTransitionDeps(t, ctx, A_a, "B(a)", "C(a)")
|
||||
checkTransitionDeps(t, ctx, A_b, "B(b)", "C(b)")
|
||||
checkTransitionDeps(t, ctx, B_a, "C(c)")
|
||||
checkTransitionDeps(t, ctx, B_b, "C(c)")
|
||||
checkTransitionDeps(t, ctx, C_a, "D(d)")
|
||||
checkTransitionDeps(t, ctx, C_b, "D(d)")
|
||||
checkTransitionDeps(t, ctx, C_c, "D(d)")
|
||||
checkTransitionDeps(t, ctx, D_d, "E(d)")
|
||||
checkTransitionDeps(t, ctx, E_d)
|
||||
|
||||
checkTransitionMutate(t, A_a, "a")
|
||||
checkTransitionMutate(t, A_b, "b")
|
||||
checkTransitionMutate(t, B_a, "a")
|
||||
checkTransitionMutate(t, B_b, "b")
|
||||
checkTransitionMutate(t, C_a, "a")
|
||||
checkTransitionMutate(t, C_b, "b")
|
||||
checkTransitionMutate(t, C_c, "c")
|
||||
checkTransitionMutate(t, D_d, "d")
|
||||
checkTransitionMutate(t, E_d, "d")
|
||||
}
|
||||
|
||||
func TestPostTransitionDeps(t *testing.T) {
|
||||
ctx, errs := testTransition(fmt.Sprintf(testTransitionBp,
|
||||
`post_transition_deps: ["D:late", "E:d"],`))
|
||||
assertNoErrors(t, errs)
|
||||
|
||||
// Module A uses Split to create a and b variants
|
||||
checkTransitionVariants(t, ctx, "A", []string{"a", "b"})
|
||||
// Module B inherits a and b variants from A
|
||||
checkTransitionVariants(t, ctx, "B", []string{"", "a", "b"})
|
||||
// Module C inherits a and b variants from A, but gets an outgoing c variant from B
|
||||
checkTransitionVariants(t, ctx, "C", []string{"", "a", "b", "c"})
|
||||
// Module D always has incoming variant d
|
||||
checkTransitionVariants(t, ctx, "D", []string{"", "d"})
|
||||
// Module E inherits d from D
|
||||
checkTransitionVariants(t, ctx, "E", []string{"", "d"})
|
||||
|
||||
A_a := getTransitionModule(ctx, "A", "a")
|
||||
A_b := getTransitionModule(ctx, "A", "b")
|
||||
B_a := getTransitionModule(ctx, "B", "a")
|
||||
B_b := getTransitionModule(ctx, "B", "b")
|
||||
C_a := getTransitionModule(ctx, "C", "a")
|
||||
C_b := getTransitionModule(ctx, "C", "b")
|
||||
C_c := getTransitionModule(ctx, "C", "c")
|
||||
D_d := getTransitionModule(ctx, "D", "d")
|
||||
E_d := getTransitionModule(ctx, "E", "d")
|
||||
|
||||
checkTransitionDeps(t, ctx, A_a, "B(a)", "C(a)")
|
||||
checkTransitionDeps(t, ctx, A_b, "B(b)", "C(b)")
|
||||
checkTransitionDeps(t, ctx, B_a, "C(c)", "D(d)", "E(d)")
|
||||
checkTransitionDeps(t, ctx, B_b, "C(c)", "D(d)", "E(d)")
|
||||
checkTransitionDeps(t, ctx, C_a, "D(d)")
|
||||
checkTransitionDeps(t, ctx, C_b, "D(d)")
|
||||
checkTransitionDeps(t, ctx, C_c, "D(d)")
|
||||
checkTransitionDeps(t, ctx, D_d, "E(d)")
|
||||
checkTransitionDeps(t, ctx, E_d)
|
||||
|
||||
checkTransitionMutate(t, A_a, "a")
|
||||
checkTransitionMutate(t, A_b, "b")
|
||||
checkTransitionMutate(t, B_a, "a")
|
||||
checkTransitionMutate(t, B_b, "b")
|
||||
checkTransitionMutate(t, C_a, "a")
|
||||
checkTransitionMutate(t, C_b, "b")
|
||||
checkTransitionMutate(t, C_c, "c")
|
||||
checkTransitionMutate(t, D_d, "d")
|
||||
checkTransitionMutate(t, E_d, "d")
|
||||
}
|
||||
|
||||
func TestPostTransitionDepsMissingVariant(t *testing.T) {
|
||||
// TODO: eventually this will create the missing variant on demand
|
||||
_, errs := testTransition(fmt.Sprintf(testTransitionBp,
|
||||
`post_transition_deps: ["E:missing"],`))
|
||||
expectedError := `Android.bp:8:4: dependency "E" of "B" missing variant:
|
||||
transition:missing
|
||||
available variants:
|
||||
transition:
|
||||
transition:d`
|
||||
if len(errs) != 1 || errs[0].Error() != expectedError {
|
||||
t.Errorf("expected error %q, got %q", expectedError, errs)
|
||||
}
|
||||
|
||||
checkDeps(A_a, "B(a)", "C(a)")
|
||||
checkDeps(A_b, "B(b)", "C(b)")
|
||||
checkDeps(B_a, "C(c)")
|
||||
checkDeps(B_b, "C(c)")
|
||||
checkDeps(C_a, "D(d)")
|
||||
checkDeps(C_b, "D(d)")
|
||||
checkDeps(C_c, "D(d)")
|
||||
checkDeps(D_d)
|
||||
|
||||
checkMutate := func(m *transitionModule, variant string) {
|
||||
t.Helper()
|
||||
if m.properties.Mutated != variant {
|
||||
t.Errorf("unexpected mutated property in %q, expected %q got %q", m.Name(), variant, m.properties.Mutated)
|
||||
}
|
||||
}
|
||||
|
||||
checkMutate(A_a, "a")
|
||||
checkMutate(A_b, "b")
|
||||
checkMutate(B_a, "a")
|
||||
checkMutate(B_b, "b")
|
||||
checkMutate(C_a, "a")
|
||||
checkMutate(C_b, "b")
|
||||
checkMutate(C_c, "c")
|
||||
checkMutate(D_d, "d")
|
||||
}
|
||||
|
||||
type transitionTestMutator struct{}
|
||||
|
@ -172,10 +260,11 @@ func (transitionTestMutator) Mutate(ctx BottomUpMutatorContext, variation string
|
|||
type transitionModule struct {
|
||||
SimpleName
|
||||
properties struct {
|
||||
Deps []string
|
||||
Split []string
|
||||
Outgoing *string
|
||||
Incoming *string
|
||||
Deps []string
|
||||
Post_transition_deps []string
|
||||
Split []string
|
||||
Outgoing *string
|
||||
Incoming *string
|
||||
|
||||
Mutated string `blueprint:"mutated"`
|
||||
}
|
||||
|
@ -196,3 +285,13 @@ func (f *transitionModule) Deps() []string {
|
|||
func (f *transitionModule) IgnoreDeps() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func postTransitionDepsMutator(mctx BottomUpMutatorContext) {
|
||||
if m, ok := mctx.Module().(*transitionModule); ok {
|
||||
for _, dep := range m.properties.Post_transition_deps {
|
||||
module, variation, _ := strings.Cut(dep, ":")
|
||||
variations := []Variation{{"transition", variation}}
|
||||
mctx.AddVariationDependencies(variations, walkerDepsTag{follow: true}, module)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue