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