1// Copyright 2015 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 android 16 17import ( 18 "fmt" 19 "strings" 20 "sync" 21 "sync/atomic" 22 "testing" 23 24 "github.com/google/blueprint" 25) 26 27type mutatorTestModule struct { 28 ModuleBase 29 props struct { 30 Deps_missing_deps []string 31 Mutator_missing_deps []string 32 } 33 34 missingDeps []string 35} 36 37func mutatorTestModuleFactory() Module { 38 module := &mutatorTestModule{} 39 module.AddProperties(&module.props) 40 InitAndroidModule(module) 41 return module 42} 43 44func (m *mutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { 45 ctx.Build(pctx, BuildParams{ 46 Rule: Touch, 47 Output: PathForModuleOut(ctx, "output"), 48 }) 49 50 m.missingDeps = ctx.GetMissingDependencies() 51} 52 53func (m *mutatorTestModule) DepsMutator(ctx BottomUpMutatorContext) { 54 ctx.AddDependency(ctx.Module(), nil, m.props.Deps_missing_deps...) 55} 56 57func addMissingDependenciesMutator(ctx BottomUpMutatorContext) { 58 ctx.AddMissingDependencies(ctx.Module().(*mutatorTestModule).props.Mutator_missing_deps) 59} 60 61func TestMutatorAddMissingDependencies(t *testing.T) { 62 bp := ` 63 test { 64 name: "foo", 65 deps_missing_deps: ["regular_missing_dep"], 66 mutator_missing_deps: ["added_missing_dep"], 67 } 68 ` 69 70 result := GroupFixturePreparers( 71 PrepareForTestWithAllowMissingDependencies, 72 FixtureRegisterWithContext(func(ctx RegistrationContext) { 73 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 74 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { 75 ctx.BottomUp("add_missing_dependencies", addMissingDependenciesMutator) 76 }) 77 }), 78 FixtureWithRootAndroidBp(bp), 79 ).RunTest(t) 80 81 foo := result.ModuleForTests(t, "foo", "").Module().(*mutatorTestModule) 82 83 AssertDeepEquals(t, "foo missing deps", []string{"added_missing_dep", "regular_missing_dep"}, foo.missingDeps) 84} 85 86func TestFinalDepsPhase(t *testing.T) { 87 bp := ` 88 test { 89 name: "common_dep_1", 90 } 91 test { 92 name: "common_dep_2", 93 } 94 test { 95 name: "foo", 96 } 97 ` 98 99 finalGot := sync.Map{} 100 101 GroupFixturePreparers( 102 FixtureRegisterWithContext(func(ctx RegistrationContext) { 103 dep1Tag := struct { 104 blueprint.BaseDependencyTag 105 }{} 106 dep2Tag := struct { 107 blueprint.BaseDependencyTag 108 }{} 109 110 ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) { 111 ctx.BottomUp("far_deps_1", func(ctx BottomUpMutatorContext) { 112 if !strings.HasPrefix(ctx.ModuleName(), "common_dep") { 113 ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1") 114 } 115 }) 116 ctx.Transition("variant", &testTransitionMutator{ 117 split: func(ctx BaseModuleContext) []string { 118 return []string{"a", "b"} 119 }, 120 }) 121 }) 122 123 ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) { 124 ctx.BottomUp("far_deps_2", func(ctx BottomUpMutatorContext) { 125 if !strings.HasPrefix(ctx.ModuleName(), "common_dep") { 126 ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep2Tag, "common_dep_2") 127 } 128 }) 129 ctx.BottomUp("final", func(ctx BottomUpMutatorContext) { 130 counter, _ := finalGot.LoadOrStore(ctx.Module().String(), &atomic.Int64{}) 131 counter.(*atomic.Int64).Add(1) 132 ctx.VisitDirectDeps(func(mod Module) { 133 counter, _ := finalGot.LoadOrStore(fmt.Sprintf("%s -> %s", ctx.Module().String(), mod), &atomic.Int64{}) 134 counter.(*atomic.Int64).Add(1) 135 }) 136 }) 137 }) 138 139 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 140 }), 141 FixtureWithRootAndroidBp(bp), 142 ).RunTest(t) 143 144 finalWant := map[string]int{ 145 "common_dep_1{variant:a}": 1, 146 "common_dep_1{variant:b}": 1, 147 "common_dep_2{variant:a}": 1, 148 "common_dep_2{variant:b}": 1, 149 "foo{variant:a}": 1, 150 "foo{variant:a} -> common_dep_1{variant:a}": 1, 151 "foo{variant:a} -> common_dep_2{variant:a}": 1, 152 "foo{variant:b}": 1, 153 "foo{variant:b} -> common_dep_1{variant:b}": 1, 154 "foo{variant:b} -> common_dep_2{variant:a}": 1, 155 } 156 157 finalGotMap := make(map[string]int) 158 finalGot.Range(func(k, v any) bool { 159 finalGotMap[k.(string)] = int(v.(*atomic.Int64).Load()) 160 return true 161 }) 162 163 AssertDeepEquals(t, "final", finalWant, finalGotMap) 164} 165