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 TopDownMutatorContext) { 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.TopDown("add_missing_dependencies", addMissingDependenciesMutator) 76 }) 77 }), 78 FixtureWithRootAndroidBp(bp), 79 ).RunTest(t) 80 81 foo := result.ModuleForTests("foo", "").Module().(*mutatorTestModule) 82 83 AssertDeepEquals(t, "foo missing deps", []string{"added_missing_dep", "regular_missing_dep"}, foo.missingDeps) 84} 85 86type testTransitionMutator struct { 87 split func(ctx BaseModuleContext) []string 88 outgoingTransition func(ctx OutgoingTransitionContext, sourceVariation string) string 89 incomingTransition func(ctx IncomingTransitionContext, incomingVariation string) string 90 mutate func(ctx BottomUpMutatorContext, variation string) 91} 92 93func (t *testTransitionMutator) Split(ctx BaseModuleContext) []string { 94 if t.split != nil { 95 return t.split(ctx) 96 } 97 return []string{""} 98} 99 100func (t *testTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string { 101 if t.outgoingTransition != nil { 102 return t.outgoingTransition(ctx, sourceVariation) 103 } 104 return sourceVariation 105} 106 107func (t *testTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string { 108 if t.incomingTransition != nil { 109 return t.incomingTransition(ctx, incomingVariation) 110 } 111 return incomingVariation 112} 113 114func (t *testTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) { 115 if t.mutate != nil { 116 t.mutate(ctx, variation) 117 } 118} 119 120func TestModuleString(t *testing.T) { 121 bp := ` 122 test { 123 name: "foo", 124 } 125 ` 126 127 var moduleStrings []string 128 129 GroupFixturePreparers( 130 FixtureRegisterWithContext(func(ctx RegistrationContext) { 131 132 ctx.PreArchMutators(func(ctx RegisterMutatorsContext) { 133 ctx.Transition("pre_arch", &testTransitionMutator{ 134 split: func(ctx BaseModuleContext) []string { 135 moduleStrings = append(moduleStrings, ctx.Module().String()) 136 return []string{"a", "b"} 137 }, 138 }) 139 }) 140 141 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { 142 ctx.Transition("pre_deps", &testTransitionMutator{ 143 split: func(ctx BaseModuleContext) []string { 144 moduleStrings = append(moduleStrings, ctx.Module().String()) 145 return []string{"c", "d"} 146 }, 147 }) 148 }) 149 150 ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) { 151 ctx.Transition("post_deps", &testTransitionMutator{ 152 split: func(ctx BaseModuleContext) []string { 153 moduleStrings = append(moduleStrings, ctx.Module().String()) 154 return []string{"e", "f"} 155 }, 156 outgoingTransition: func(ctx OutgoingTransitionContext, sourceVariation string) string { 157 return "" 158 }, 159 }) 160 ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) { 161 moduleStrings = append(moduleStrings, ctx.Module().String()) 162 ctx.Rename(ctx.Module().base().Name() + "_renamed1") 163 }).UsesRename() 164 ctx.BottomUp("final", func(ctx BottomUpMutatorContext) { 165 moduleStrings = append(moduleStrings, ctx.Module().String()) 166 }) 167 }) 168 169 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 170 }), 171 FixtureWithRootAndroidBp(bp), 172 ).RunTest(t) 173 174 want := []string{ 175 // Initial name. 176 "foo{}", 177 178 // After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order). 179 "foo{pre_arch:b}", 180 "foo{pre_arch:a}", 181 182 // After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown). 183 "foo{pre_arch:b,pre_deps:d}", 184 "foo{pre_arch:b,pre_deps:c}", 185 "foo{pre_arch:a,pre_deps:d}", 186 "foo{pre_arch:a,pre_deps:c}", 187 188 // After post_deps. 189 "foo{pre_arch:a,pre_deps:c,post_deps:e}", 190 "foo{pre_arch:a,pre_deps:c,post_deps:f}", 191 "foo{pre_arch:a,pre_deps:d,post_deps:e}", 192 "foo{pre_arch:a,pre_deps:d,post_deps:f}", 193 "foo{pre_arch:b,pre_deps:c,post_deps:e}", 194 "foo{pre_arch:b,pre_deps:c,post_deps:f}", 195 "foo{pre_arch:b,pre_deps:d,post_deps:e}", 196 "foo{pre_arch:b,pre_deps:d,post_deps:f}", 197 198 // After rename_bottom_up. 199 "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}", 200 "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}", 201 "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}", 202 "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}", 203 "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}", 204 "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}", 205 "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}", 206 "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}", 207 } 208 209 AssertDeepEquals(t, "module String() values", want, moduleStrings) 210} 211 212func TestFinalDepsPhase(t *testing.T) { 213 bp := ` 214 test { 215 name: "common_dep_1", 216 } 217 test { 218 name: "common_dep_2", 219 } 220 test { 221 name: "foo", 222 } 223 ` 224 225 finalGot := sync.Map{} 226 227 GroupFixturePreparers( 228 FixtureRegisterWithContext(func(ctx RegistrationContext) { 229 dep1Tag := struct { 230 blueprint.BaseDependencyTag 231 }{} 232 dep2Tag := struct { 233 blueprint.BaseDependencyTag 234 }{} 235 236 ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) { 237 ctx.BottomUp("far_deps_1", func(ctx BottomUpMutatorContext) { 238 if !strings.HasPrefix(ctx.ModuleName(), "common_dep") { 239 ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1") 240 } 241 }) 242 ctx.Transition("variant", &testTransitionMutator{ 243 split: func(ctx BaseModuleContext) []string { 244 return []string{"a", "b"} 245 }, 246 }) 247 }) 248 249 ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) { 250 ctx.BottomUp("far_deps_2", func(ctx BottomUpMutatorContext) { 251 if !strings.HasPrefix(ctx.ModuleName(), "common_dep") { 252 ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep2Tag, "common_dep_2") 253 } 254 }) 255 ctx.BottomUp("final", func(ctx BottomUpMutatorContext) { 256 counter, _ := finalGot.LoadOrStore(ctx.Module().String(), &atomic.Int64{}) 257 counter.(*atomic.Int64).Add(1) 258 ctx.VisitDirectDeps(func(mod Module) { 259 counter, _ := finalGot.LoadOrStore(fmt.Sprintf("%s -> %s", ctx.Module().String(), mod), &atomic.Int64{}) 260 counter.(*atomic.Int64).Add(1) 261 }) 262 }) 263 }) 264 265 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 266 }), 267 FixtureWithRootAndroidBp(bp), 268 ).RunTest(t) 269 270 finalWant := map[string]int{ 271 "common_dep_1{variant:a}": 1, 272 "common_dep_1{variant:b}": 1, 273 "common_dep_2{variant:a}": 1, 274 "common_dep_2{variant:b}": 1, 275 "foo{variant:a}": 1, 276 "foo{variant:a} -> common_dep_1{variant:a}": 1, 277 "foo{variant:a} -> common_dep_2{variant:a}": 1, 278 "foo{variant:b}": 1, 279 "foo{variant:b} -> common_dep_1{variant:b}": 1, 280 "foo{variant:b} -> common_dep_2{variant:a}": 1, 281 } 282 283 finalGotMap := make(map[string]int) 284 finalGot.Range(func(k, v any) bool { 285 finalGotMap[k.(string)] = int(v.(*atomic.Int64).Load()) 286 return true 287 }) 288 289 AssertDeepEquals(t, "final", finalWant, finalGotMap) 290} 291 292func TestTransitionMutatorInFinalDeps(t *testing.T) { 293 GroupFixturePreparers( 294 FixtureRegisterWithContext(func(ctx RegistrationContext) { 295 ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) { 296 ctx.Transition("vars", &testTransitionMutator{ 297 split: func(ctx BaseModuleContext) []string { 298 return []string{"a", "b"} 299 }, 300 }) 301 }) 302 303 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 304 }), 305 FixtureWithRootAndroidBp(`test {name: "foo"}`), 306 ). 307 ExtendWithErrorHandler(FixtureExpectsOneErrorPattern("not allowed in FinalDepsMutators")). 308 RunTest(t) 309} 310