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 "reflect" 20 "strings" 21 "testing" 22 23 "github.com/google/blueprint" 24 "github.com/google/blueprint/proptools" 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 config := TestConfig(buildDir, nil, bp, nil) 71 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true) 72 73 ctx := NewTestContext() 74 ctx.SetAllowMissingDependencies(true) 75 76 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 77 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { 78 ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator) 79 }) 80 81 ctx.Register(config) 82 _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) 83 FailIfErrored(t, errs) 84 _, errs = ctx.PrepareBuildActions(config) 85 FailIfErrored(t, errs) 86 87 foo := ctx.ModuleForTests("foo", "").Module().(*mutatorTestModule) 88 89 if g, w := foo.missingDeps, []string{"added_missing_dep", "regular_missing_dep"}; !reflect.DeepEqual(g, w) { 90 t.Errorf("want foo missing deps %q, got %q", w, g) 91 } 92} 93 94func TestModuleString(t *testing.T) { 95 ctx := NewTestContext() 96 97 var moduleStrings []string 98 99 ctx.PreArchMutators(func(ctx RegisterMutatorsContext) { 100 ctx.BottomUp("pre_arch", func(ctx BottomUpMutatorContext) { 101 moduleStrings = append(moduleStrings, ctx.Module().String()) 102 ctx.CreateVariations("a", "b") 103 }) 104 ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) { 105 moduleStrings = append(moduleStrings, ctx.Module().String()) 106 ctx.Rename(ctx.Module().base().Name() + "_renamed1") 107 }) 108 }) 109 110 ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) { 111 ctx.BottomUp("pre_deps", func(ctx BottomUpMutatorContext) { 112 moduleStrings = append(moduleStrings, ctx.Module().String()) 113 ctx.CreateVariations("c", "d") 114 }) 115 }) 116 117 ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) { 118 ctx.BottomUp("post_deps", func(ctx BottomUpMutatorContext) { 119 moduleStrings = append(moduleStrings, ctx.Module().String()) 120 ctx.CreateLocalVariations("e", "f") 121 }) 122 ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) { 123 moduleStrings = append(moduleStrings, ctx.Module().String()) 124 ctx.Rename(ctx.Module().base().Name() + "_renamed2") 125 }) 126 ctx.BottomUp("final", func(ctx BottomUpMutatorContext) { 127 moduleStrings = append(moduleStrings, ctx.Module().String()) 128 }) 129 }) 130 131 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 132 133 bp := ` 134 test { 135 name: "foo", 136 } 137 ` 138 139 config := TestConfig(buildDir, nil, bp, nil) 140 141 ctx.Register(config) 142 143 _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) 144 FailIfErrored(t, errs) 145 _, errs = ctx.PrepareBuildActions(config) 146 FailIfErrored(t, errs) 147 148 want := []string{ 149 // Initial name. 150 "foo{}", 151 152 // After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order). 153 "foo{pre_arch:b}", 154 "foo{pre_arch:a}", 155 156 // After rename_top_down. 157 "foo_renamed1{pre_arch:a}", 158 "foo_renamed1{pre_arch:b}", 159 160 // After pre_deps. 161 "foo_renamed1{pre_arch:a,pre_deps:c}", 162 "foo_renamed1{pre_arch:a,pre_deps:d}", 163 "foo_renamed1{pre_arch:b,pre_deps:c}", 164 "foo_renamed1{pre_arch:b,pre_deps:d}", 165 166 // After post_deps. 167 "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}", 168 "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}", 169 "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}", 170 "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}", 171 "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}", 172 "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}", 173 "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}", 174 "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}", 175 176 // After rename_bottom_up. 177 "foo_renamed2{pre_arch:a,pre_deps:c,post_deps:e}", 178 "foo_renamed2{pre_arch:a,pre_deps:c,post_deps:f}", 179 "foo_renamed2{pre_arch:a,pre_deps:d,post_deps:e}", 180 "foo_renamed2{pre_arch:a,pre_deps:d,post_deps:f}", 181 "foo_renamed2{pre_arch:b,pre_deps:c,post_deps:e}", 182 "foo_renamed2{pre_arch:b,pre_deps:c,post_deps:f}", 183 "foo_renamed2{pre_arch:b,pre_deps:d,post_deps:e}", 184 "foo_renamed2{pre_arch:b,pre_deps:d,post_deps:f}", 185 } 186 187 if !reflect.DeepEqual(moduleStrings, want) { 188 t.Errorf("want module String() values:\n%q\ngot:\n%q", want, moduleStrings) 189 } 190} 191 192func TestFinalDepsPhase(t *testing.T) { 193 ctx := NewTestContext() 194 195 finalGot := map[string]int{} 196 197 dep1Tag := struct { 198 blueprint.BaseDependencyTag 199 }{} 200 dep2Tag := struct { 201 blueprint.BaseDependencyTag 202 }{} 203 204 ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) { 205 ctx.BottomUp("far_deps_1", func(ctx BottomUpMutatorContext) { 206 if !strings.HasPrefix(ctx.ModuleName(), "common_dep") { 207 ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1") 208 } 209 }) 210 ctx.BottomUp("variant", func(ctx BottomUpMutatorContext) { 211 ctx.CreateLocalVariations("a", "b") 212 }) 213 }) 214 215 ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) { 216 ctx.BottomUp("far_deps_2", func(ctx BottomUpMutatorContext) { 217 if !strings.HasPrefix(ctx.ModuleName(), "common_dep") { 218 ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep2Tag, "common_dep_2") 219 } 220 }) 221 ctx.BottomUp("final", func(ctx BottomUpMutatorContext) { 222 finalGot[ctx.Module().String()] += 1 223 ctx.VisitDirectDeps(func(mod Module) { 224 finalGot[fmt.Sprintf("%s -> %s", ctx.Module().String(), mod)] += 1 225 }) 226 }) 227 }) 228 229 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 230 231 bp := ` 232 test { 233 name: "common_dep_1", 234 } 235 test { 236 name: "common_dep_2", 237 } 238 test { 239 name: "foo", 240 } 241 ` 242 243 config := TestConfig(buildDir, nil, bp, nil) 244 ctx.Register(config) 245 246 _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) 247 FailIfErrored(t, errs) 248 _, errs = ctx.PrepareBuildActions(config) 249 FailIfErrored(t, errs) 250 251 finalWant := map[string]int{ 252 "common_dep_1{variant:a}": 1, 253 "common_dep_1{variant:b}": 1, 254 "common_dep_2{variant:a}": 1, 255 "common_dep_2{variant:b}": 1, 256 "foo{variant:a}": 1, 257 "foo{variant:a} -> common_dep_1{variant:a}": 1, 258 "foo{variant:a} -> common_dep_2{variant:a}": 1, 259 "foo{variant:b}": 1, 260 "foo{variant:b} -> common_dep_1{variant:b}": 1, 261 "foo{variant:b} -> common_dep_2{variant:a}": 1, 262 } 263 264 if !reflect.DeepEqual(finalWant, finalGot) { 265 t.Errorf("want:\n%q\ngot:\n%q", finalWant, finalGot) 266 } 267} 268 269func TestNoCreateVariationsInFinalDeps(t *testing.T) { 270 ctx := NewTestContext() 271 272 checkErr := func() { 273 if err := recover(); err == nil || !strings.Contains(fmt.Sprintf("%s", err), "not allowed in FinalDepsMutators") { 274 panic("Expected FinalDepsMutators consistency check to fail") 275 } 276 } 277 278 ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) { 279 ctx.BottomUp("vars", func(ctx BottomUpMutatorContext) { 280 defer checkErr() 281 ctx.CreateVariations("a", "b") 282 }) 283 ctx.BottomUp("local_vars", func(ctx BottomUpMutatorContext) { 284 defer checkErr() 285 ctx.CreateLocalVariations("a", "b") 286 }) 287 }) 288 289 ctx.RegisterModuleType("test", mutatorTestModuleFactory) 290 config := TestConfig(buildDir, nil, `test {name: "foo"}`, nil) 291 ctx.Register(config) 292 293 _, errs := ctx.ParseFileList(".", []string{"Android.bp"}) 294 FailIfErrored(t, errs) 295 _, errs = ctx.PrepareBuildActions(config) 296 FailIfErrored(t, errs) 297} 298