1// Copyright 2020 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 blueprint 16 17import ( 18 "fmt" 19 "reflect" 20 "strings" 21 "testing" 22) 23 24type providerTestModule struct { 25 SimpleName 26 properties struct { 27 Deps []string 28 } 29 30 mutatorProviderValues []string 31 generateBuildActionsProviderValues []string 32} 33 34func newProviderTestModule() (Module, []interface{}) { 35 m := &providerTestModule{} 36 return m, []interface{}{&m.properties, &m.SimpleName.Properties} 37} 38 39type providerTestMutatorInfo struct { 40 Values []string 41} 42 43type providerTestGenerateBuildActionsInfo struct { 44 Value string 45} 46 47type providerTestUnsetInfo string 48 49var providerTestMutatorInfoProvider = NewMutatorProvider(&providerTestMutatorInfo{}, "provider_mutator") 50var providerTestGenerateBuildActionsInfoProvider = NewProvider(&providerTestGenerateBuildActionsInfo{}) 51var providerTestUnsetInfoProvider = NewMutatorProvider((providerTestUnsetInfo)(""), "provider_mutator") 52var providerTestUnusedMutatorProvider = NewMutatorProvider(&struct{ unused string }{}, "nonexistent_mutator") 53 54func (p *providerTestModule) GenerateBuildActions(ctx ModuleContext) { 55 unset := ctx.Provider(providerTestUnsetInfoProvider).(providerTestUnsetInfo) 56 if unset != "" { 57 panic(fmt.Sprintf("expected zero value for providerTestGenerateBuildActionsInfoProvider before it was set, got %q", 58 unset)) 59 } 60 61 _ = ctx.Provider(providerTestUnusedMutatorProvider) 62 63 ctx.SetProvider(providerTestGenerateBuildActionsInfoProvider, &providerTestGenerateBuildActionsInfo{ 64 Value: ctx.ModuleName(), 65 }) 66 67 mp := ctx.Provider(providerTestMutatorInfoProvider).(*providerTestMutatorInfo) 68 if mp != nil { 69 p.mutatorProviderValues = mp.Values 70 } 71 72 ctx.VisitDirectDeps(func(module Module) { 73 gbap := ctx.OtherModuleProvider(module, providerTestGenerateBuildActionsInfoProvider).(*providerTestGenerateBuildActionsInfo) 74 if gbap != nil { 75 p.generateBuildActionsProviderValues = append(p.generateBuildActionsProviderValues, gbap.Value) 76 } 77 }) 78} 79 80func providerTestDepsMutator(ctx BottomUpMutatorContext) { 81 if p, ok := ctx.Module().(*providerTestModule); ok { 82 ctx.AddDependency(ctx.Module(), nil, p.properties.Deps...) 83 } 84} 85 86func providerTestMutator(ctx BottomUpMutatorContext) { 87 values := []string{strings.ToLower(ctx.ModuleName())} 88 89 ctx.VisitDirectDeps(func(module Module) { 90 mp := ctx.OtherModuleProvider(module, providerTestMutatorInfoProvider).(*providerTestMutatorInfo) 91 if mp != nil { 92 values = append(values, mp.Values...) 93 } 94 }) 95 96 ctx.SetProvider(providerTestMutatorInfoProvider, &providerTestMutatorInfo{ 97 Values: values, 98 }) 99} 100 101func providerTestAfterMutator(ctx BottomUpMutatorContext) { 102 _ = ctx.Provider(providerTestMutatorInfoProvider) 103} 104 105func TestProviders(t *testing.T) { 106 ctx := NewContext() 107 ctx.RegisterModuleType("provider_module", newProviderTestModule) 108 ctx.RegisterBottomUpMutator("provider_deps_mutator", providerTestDepsMutator) 109 ctx.RegisterBottomUpMutator("provider_mutator", providerTestMutator) 110 ctx.RegisterBottomUpMutator("provider_after_mutator", providerTestAfterMutator) 111 112 ctx.MockFileSystem(map[string][]byte{ 113 "Android.bp": []byte(` 114 provider_module { 115 name: "A", 116 deps: ["B"], 117 } 118 119 provider_module { 120 name: "B", 121 deps: ["C", "D"], 122 } 123 124 provider_module { 125 name: "C", 126 deps: ["D"], 127 } 128 129 provider_module { 130 name: "D", 131 } 132 `), 133 }) 134 135 _, errs := ctx.ParseBlueprintsFiles("Android.bp", nil) 136 if len(errs) == 0 { 137 _, errs = ctx.ResolveDependencies(nil) 138 } 139 if len(errs) == 0 { 140 _, errs = ctx.PrepareBuildActions(nil) 141 } 142 if len(errs) > 0 { 143 t.Errorf("unexpected errors:") 144 for _, err := range errs { 145 t.Errorf(" %s", err) 146 } 147 t.FailNow() 148 } 149 150 aModule := ctx.moduleGroupFromName("A", nil).moduleByVariantName("").logicModule.(*providerTestModule) 151 if g, w := aModule.generateBuildActionsProviderValues, []string{"B"}; !reflect.DeepEqual(g, w) { 152 t.Errorf("expected A.generateBuildActionsProviderValues %q, got %q", w, g) 153 } 154 if g, w := aModule.mutatorProviderValues, []string{"a", "b", "c", "d", "d"}; !reflect.DeepEqual(g, w) { 155 t.Errorf("expected A.mutatorProviderValues %q, got %q", w, g) 156 } 157 158 bModule := ctx.moduleGroupFromName("B", nil).moduleByVariantName("").logicModule.(*providerTestModule) 159 if g, w := bModule.generateBuildActionsProviderValues, []string{"C", "D"}; !reflect.DeepEqual(g, w) { 160 t.Errorf("expected B.generateBuildActionsProviderValues %q, got %q", w, g) 161 } 162 if g, w := bModule.mutatorProviderValues, []string{"b", "c", "d", "d"}; !reflect.DeepEqual(g, w) { 163 t.Errorf("expected B.mutatorProviderValues %q, got %q", w, g) 164 } 165} 166 167type invalidProviderUsageMutatorInfo string 168type invalidProviderUsageGenerateBuildActionsInfo string 169 170var invalidProviderUsageMutatorInfoProvider = NewMutatorProvider(invalidProviderUsageMutatorInfo(""), "mutator_under_test") 171var invalidProviderUsageGenerateBuildActionsInfoProvider = NewProvider(invalidProviderUsageGenerateBuildActionsInfo("")) 172 173type invalidProviderUsageTestModule struct { 174 parent *invalidProviderUsageTestModule 175 176 SimpleName 177 properties struct { 178 Deps []string 179 180 Early_mutator_set_of_mutator_provider bool 181 Late_mutator_set_of_mutator_provider bool 182 Late_build_actions_set_of_mutator_provider bool 183 Early_mutator_set_of_build_actions_provider bool 184 185 Early_mutator_get_of_mutator_provider bool 186 Early_module_get_of_mutator_provider bool 187 Early_mutator_get_of_build_actions_provider bool 188 Early_module_get_of_build_actions_provider bool 189 190 Duplicate_set bool 191 } 192} 193 194func invalidProviderUsageDepsMutator(ctx BottomUpMutatorContext) { 195 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok { 196 ctx.AddDependency(ctx.Module(), nil, i.properties.Deps...) 197 } 198} 199 200func invalidProviderUsageParentMutator(ctx TopDownMutatorContext) { 201 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok { 202 ctx.VisitDirectDeps(func(module Module) { 203 module.(*invalidProviderUsageTestModule).parent = i 204 }) 205 } 206} 207 208func invalidProviderUsageBeforeMutator(ctx BottomUpMutatorContext) { 209 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok { 210 if i.properties.Early_mutator_set_of_mutator_provider { 211 // A mutator attempting to set the value of a provider associated with a later mutator. 212 ctx.SetProvider(invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) 213 } 214 if i.properties.Early_mutator_get_of_mutator_provider { 215 // A mutator attempting to get the value of a provider associated with a later mutator. 216 _ = ctx.Provider(invalidProviderUsageMutatorInfoProvider) 217 } 218 } 219} 220 221func invalidProviderUsageMutatorUnderTest(ctx TopDownMutatorContext) { 222 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok { 223 if i.properties.Early_mutator_set_of_build_actions_provider { 224 // A mutator attempting to set the value of a non-mutator provider. 225 ctx.SetProvider(invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) 226 } 227 if i.properties.Early_mutator_get_of_build_actions_provider { 228 // A mutator attempting to get the value of a non-mutator provider. 229 _ = ctx.Provider(invalidProviderUsageGenerateBuildActionsInfoProvider) 230 } 231 if i.properties.Early_module_get_of_mutator_provider { 232 // A mutator attempting to get the value of a provider associated with this mutator on 233 // a module for which this mutator hasn't run. This is a top down mutator so 234 // dependencies haven't run yet. 235 ctx.VisitDirectDeps(func(module Module) { 236 _ = ctx.OtherModuleProvider(module, invalidProviderUsageMutatorInfoProvider) 237 }) 238 } 239 } 240} 241 242func invalidProviderUsageAfterMutator(ctx BottomUpMutatorContext) { 243 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok { 244 if i.properties.Late_mutator_set_of_mutator_provider { 245 // A mutator trying to set the value of a provider associated with an earlier mutator. 246 ctx.SetProvider(invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) 247 } 248 if i.properties.Late_mutator_set_of_mutator_provider { 249 // A mutator trying to set the value of a provider associated with an earlier mutator. 250 ctx.SetProvider(invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) 251 } 252 } 253} 254 255func (i *invalidProviderUsageTestModule) GenerateBuildActions(ctx ModuleContext) { 256 if i.properties.Late_build_actions_set_of_mutator_provider { 257 // A GenerateBuildActions trying to set the value of a provider associated with a mutator. 258 ctx.SetProvider(invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo("")) 259 } 260 if i.properties.Early_module_get_of_build_actions_provider { 261 // A GenerateBuildActions trying to get the value of a provider on a module for which 262 // GenerateBuildActions hasn't run. 263 _ = ctx.OtherModuleProvider(i.parent, invalidProviderUsageGenerateBuildActionsInfoProvider) 264 } 265 if i.properties.Duplicate_set { 266 ctx.SetProvider(invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) 267 ctx.SetProvider(invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo("")) 268 } 269} 270 271func TestInvalidProvidersUsage(t *testing.T) { 272 run := func(t *testing.T, module string, prop string, panicMsg string) { 273 t.Helper() 274 ctx := NewContext() 275 ctx.RegisterModuleType("invalid_provider_usage_test_module", func() (Module, []interface{}) { 276 m := &invalidProviderUsageTestModule{} 277 return m, []interface{}{&m.properties, &m.SimpleName.Properties} 278 }) 279 ctx.RegisterBottomUpMutator("deps", invalidProviderUsageDepsMutator) 280 ctx.RegisterBottomUpMutator("before", invalidProviderUsageBeforeMutator) 281 ctx.RegisterTopDownMutator("mutator_under_test", invalidProviderUsageMutatorUnderTest) 282 ctx.RegisterBottomUpMutator("after", invalidProviderUsageAfterMutator) 283 ctx.RegisterTopDownMutator("parent", invalidProviderUsageParentMutator) 284 285 // Don't invalidate the parent pointer and before GenerateBuildActions. 286 ctx.skipCloneModulesAfterMutators = true 287 288 var parentBP, moduleUnderTestBP, childBP string 289 290 prop += ": true," 291 292 switch module { 293 case "parent": 294 parentBP = prop 295 case "module_under_test": 296 moduleUnderTestBP = prop 297 case "child": 298 childBP = prop 299 } 300 301 bp := fmt.Sprintf(` 302 invalid_provider_usage_test_module { 303 name: "parent", 304 deps: ["module_under_test"], 305 %s 306 } 307 308 invalid_provider_usage_test_module { 309 name: "module_under_test", 310 deps: ["child"], 311 %s 312 } 313 314 invalid_provider_usage_test_module { 315 name: "child", 316 %s 317 } 318 319 `, 320 parentBP, 321 moduleUnderTestBP, 322 childBP) 323 324 ctx.MockFileSystem(map[string][]byte{ 325 "Android.bp": []byte(bp), 326 }) 327 328 _, errs := ctx.ParseBlueprintsFiles("Android.bp", nil) 329 330 if len(errs) == 0 { 331 _, errs = ctx.ResolveDependencies(nil) 332 } 333 334 if len(errs) == 0 { 335 _, errs = ctx.PrepareBuildActions(nil) 336 } 337 338 if len(errs) == 0 { 339 t.Fatal("expected an error") 340 } 341 342 if len(errs) > 1 { 343 t.Errorf("expected a single error, got %d:", len(errs)) 344 for i, err := range errs { 345 t.Errorf("%d: %s", i, err) 346 } 347 t.FailNow() 348 } 349 350 if panicErr, ok := errs[0].(panicError); ok { 351 if panicErr.panic != panicMsg { 352 t.Fatalf("expected panic %q, got %q", panicMsg, panicErr.panic) 353 } 354 } else { 355 t.Fatalf("expected a panicError, got %T: %s", errs[0], errs[0].Error()) 356 } 357 358 } 359 360 tests := []struct { 361 prop string 362 module string 363 364 panicMsg string 365 skip string 366 }{ 367 { 368 prop: "early_mutator_set_of_mutator_provider", 369 module: "module_under_test", 370 panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test started", 371 }, 372 { 373 prop: "late_mutator_set_of_mutator_provider", 374 module: "module_under_test", 375 panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo after mutator mutator_under_test finished", 376 }, 377 { 378 prop: "late_build_actions_set_of_mutator_provider", 379 module: "module_under_test", 380 panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo after mutator mutator_under_test finished", 381 }, 382 { 383 prop: "early_mutator_set_of_build_actions_provider", 384 module: "module_under_test", 385 panicMsg: "Can't set value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions started", 386 }, 387 388 { 389 prop: "early_mutator_get_of_mutator_provider", 390 module: "module_under_test", 391 panicMsg: "Can't get value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test finished", 392 }, 393 { 394 prop: "early_module_get_of_mutator_provider", 395 module: "module_under_test", 396 panicMsg: "Can't get value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test finished", 397 }, 398 { 399 prop: "early_mutator_get_of_build_actions_provider", 400 module: "module_under_test", 401 panicMsg: "Can't get value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions finished", 402 }, 403 { 404 prop: "early_module_get_of_build_actions_provider", 405 module: "module_under_test", 406 panicMsg: "Can't get value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions finished", 407 }, 408 { 409 prop: "duplicate_set", 410 module: "module_under_test", 411 panicMsg: "Value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo is already set", 412 }, 413 } 414 415 for _, tt := range tests { 416 t.Run(tt.prop, func(t *testing.T) { 417 run(t, tt.module, tt.prop, tt.panicMsg) 418 }) 419 } 420} 421