1// Copyright 2016 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 "testing" 19 20 "github.com/google/blueprint" 21) 22 23func TestPrebuilts(t *testing.T) { 24 buildOS := TestArchConfig(t.TempDir(), nil, "", nil).BuildOS 25 26 var prebuiltsTests = []struct { 27 name string 28 replaceBp bool // modules is added to default bp boilerplate if false. 29 modules string 30 prebuilt []OsType 31 preparer FixturePreparer 32 }{ 33 { 34 name: "no prebuilt", 35 modules: ` 36 source { 37 name: "bar", 38 }`, 39 prebuilt: nil, 40 }, 41 { 42 name: "no source prebuilt not preferred", 43 modules: ` 44 prebuilt { 45 name: "bar", 46 prefer: false, 47 srcs: ["prebuilt_file"], 48 }`, 49 prebuilt: []OsType{Android, buildOS}, 50 }, 51 { 52 name: "no source prebuilt preferred", 53 modules: ` 54 prebuilt { 55 name: "bar", 56 prefer: true, 57 srcs: ["prebuilt_file"], 58 }`, 59 prebuilt: []OsType{Android, buildOS}, 60 }, 61 { 62 name: "prebuilt not preferred", 63 modules: ` 64 source { 65 name: "bar", 66 } 67 68 prebuilt { 69 name: "bar", 70 prefer: false, 71 srcs: ["prebuilt_file"], 72 }`, 73 prebuilt: nil, 74 }, 75 { 76 name: "prebuilt preferred", 77 modules: ` 78 source { 79 name: "bar", 80 } 81 82 prebuilt { 83 name: "bar", 84 prefer: true, 85 srcs: ["prebuilt_file"], 86 }`, 87 prebuilt: []OsType{Android, buildOS}, 88 }, 89 { 90 name: "prebuilt no file not preferred", 91 modules: ` 92 source { 93 name: "bar", 94 } 95 96 prebuilt { 97 name: "bar", 98 prefer: false, 99 }`, 100 prebuilt: nil, 101 }, 102 { 103 name: "prebuilt no file preferred", 104 modules: ` 105 source { 106 name: "bar", 107 } 108 109 prebuilt { 110 name: "bar", 111 prefer: true, 112 }`, 113 prebuilt: nil, 114 }, 115 { 116 name: "prebuilt file from filegroup preferred", 117 modules: ` 118 filegroup { 119 name: "fg", 120 srcs: ["prebuilt_file"], 121 } 122 prebuilt { 123 name: "bar", 124 prefer: true, 125 srcs: [":fg"], 126 }`, 127 prebuilt: []OsType{Android, buildOS}, 128 }, 129 { 130 name: "prebuilt module for device only", 131 modules: ` 132 source { 133 name: "bar", 134 } 135 136 prebuilt { 137 name: "bar", 138 host_supported: false, 139 prefer: true, 140 srcs: ["prebuilt_file"], 141 }`, 142 prebuilt: []OsType{Android}, 143 }, 144 { 145 name: "prebuilt file for host only", 146 modules: ` 147 source { 148 name: "bar", 149 } 150 151 prebuilt { 152 name: "bar", 153 prefer: true, 154 target: { 155 host: { 156 srcs: ["prebuilt_file"], 157 }, 158 }, 159 }`, 160 prebuilt: []OsType{buildOS}, 161 }, 162 { 163 name: "prebuilt override not preferred", 164 modules: ` 165 source { 166 name: "baz", 167 } 168 169 override_source { 170 name: "bar", 171 base: "baz", 172 } 173 174 prebuilt { 175 name: "bar", 176 prefer: false, 177 srcs: ["prebuilt_file"], 178 }`, 179 prebuilt: nil, 180 }, 181 { 182 name: "prebuilt override preferred", 183 modules: ` 184 source { 185 name: "baz", 186 } 187 188 override_source { 189 name: "bar", 190 base: "baz", 191 } 192 193 prebuilt { 194 name: "bar", 195 prefer: true, 196 srcs: ["prebuilt_file"], 197 }`, 198 prebuilt: []OsType{Android, buildOS}, 199 }, 200 { 201 name: "prebuilt including default-disabled OS", 202 replaceBp: true, 203 modules: ` 204 source { 205 name: "foo", 206 deps: [":bar"], 207 target: { 208 windows: { 209 enabled: true, 210 }, 211 }, 212 } 213 214 source { 215 name: "bar", 216 target: { 217 windows: { 218 enabled: true, 219 }, 220 }, 221 } 222 223 prebuilt { 224 name: "bar", 225 prefer: true, 226 srcs: ["prebuilt_file"], 227 target: { 228 windows: { 229 enabled: true, 230 }, 231 }, 232 }`, 233 prebuilt: []OsType{Android, buildOS, Windows}, 234 }, 235 { 236 name: "fall back to source for default-disabled OS", 237 replaceBp: true, 238 modules: ` 239 source { 240 name: "foo", 241 deps: [":bar"], 242 target: { 243 windows: { 244 enabled: true, 245 }, 246 }, 247 } 248 249 source { 250 name: "bar", 251 target: { 252 windows: { 253 enabled: true, 254 }, 255 }, 256 } 257 258 prebuilt { 259 name: "bar", 260 prefer: true, 261 srcs: ["prebuilt_file"], 262 }`, 263 prebuilt: []OsType{Android, buildOS}, 264 }, 265 { 266 name: "prebuilt properties customizable", 267 replaceBp: true, 268 modules: ` 269 source { 270 name: "foo", 271 deps: [":bar"], 272 } 273 274 soong_config_module_type { 275 name: "prebuilt_with_config", 276 module_type: "prebuilt", 277 config_namespace: "any_namespace", 278 bool_variables: ["bool_var"], 279 properties: ["prefer"], 280 } 281 282 prebuilt_with_config { 283 name: "bar", 284 prefer: true, 285 srcs: ["prebuilt_file"], 286 soong_config_variables: { 287 bool_var: { 288 prefer: false, 289 conditions_default: { 290 prefer: true, 291 }, 292 }, 293 }, 294 }`, 295 prebuilt: []OsType{Android, buildOS}, 296 }, 297 } 298 299 fs := MockFS{ 300 "prebuilt_file": nil, 301 "source_file": nil, 302 } 303 304 for _, test := range prebuiltsTests { 305 t.Run(test.name, func(t *testing.T) { 306 bp := test.modules 307 if !test.replaceBp { 308 bp = bp + ` 309 source { 310 name: "foo", 311 deps: [":bar"], 312 }` 313 } 314 315 // Add windows to the target list to test the logic when a variant is 316 // disabled by default. 317 if !Windows.DefaultDisabled { 318 t.Errorf("windows is assumed to be disabled by default") 319 } 320 321 result := GroupFixturePreparers( 322 PrepareForTestWithArchMutator, 323 PrepareForTestWithPrebuilts, 324 PrepareForTestWithOverrides, 325 PrepareForTestWithFilegroup, 326 // Add a Windows target to the configuration. 327 FixtureModifyConfig(func(config Config) { 328 config.Targets[Windows] = []Target{ 329 {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true}, 330 } 331 }), 332 fs.AddToFixture(), 333 FixtureRegisterWithContext(registerTestPrebuiltModules), 334 OptionalFixturePreparer(test.preparer), 335 ).RunTestWithBp(t, bp) 336 337 for _, variant := range result.ModuleVariantsForTests("foo") { 338 foo := result.ModuleForTests("foo", variant) 339 t.Run(foo.Module().Target().Os.String(), func(t *testing.T) { 340 var dependsOnSourceModule, dependsOnPrebuiltModule bool 341 result.VisitDirectDeps(foo.Module(), func(m blueprint.Module) { 342 if _, ok := m.(*sourceModule); ok { 343 dependsOnSourceModule = true 344 } 345 if p, ok := m.(*prebuiltModule); ok { 346 dependsOnPrebuiltModule = true 347 if !p.Prebuilt().properties.UsePrebuilt { 348 t.Errorf("dependency on prebuilt module not marked used") 349 } 350 } 351 }) 352 353 moduleIsDisabled := !foo.Module().Enabled(PanickingConfigAndErrorContext(result.TestContext)) 354 deps := foo.Module().(*sourceModule).deps 355 if moduleIsDisabled { 356 if len(deps) > 0 { 357 t.Errorf("disabled module got deps: %v", deps) 358 } 359 } else { 360 if len(deps) != 1 { 361 t.Errorf("deps does not have single path, but is %v", deps) 362 } 363 } 364 365 var usingSourceFile, usingPrebuiltFile bool 366 if len(deps) > 0 && deps[0].String() == "source_file" { 367 usingSourceFile = true 368 } 369 if len(deps) > 0 && deps[0].String() == "prebuilt_file" { 370 usingPrebuiltFile = true 371 } 372 373 prebuilt := false 374 for _, os := range test.prebuilt { 375 if os == foo.Module().Target().Os { 376 prebuilt = true 377 } 378 } 379 380 if prebuilt { 381 if moduleIsDisabled { 382 t.Errorf("dependent module for prebuilt is disabled") 383 } 384 385 if !dependsOnPrebuiltModule { 386 t.Errorf("doesn't depend on prebuilt module") 387 } 388 if !usingPrebuiltFile { 389 t.Errorf("doesn't use prebuilt_file") 390 } 391 392 if dependsOnSourceModule { 393 t.Errorf("depends on source module") 394 } 395 if usingSourceFile { 396 t.Errorf("using source_file") 397 } 398 } else if !moduleIsDisabled { 399 if dependsOnPrebuiltModule { 400 t.Errorf("depends on prebuilt module") 401 } 402 if usingPrebuiltFile { 403 t.Errorf("using prebuilt_file") 404 } 405 406 if !dependsOnSourceModule { 407 t.Errorf("doesn't depend on source module") 408 } 409 if !usingSourceFile { 410 t.Errorf("doesn't use source_file") 411 } 412 } 413 }) 414 } 415 }) 416 } 417} 418 419func testPrebuiltErrorWithFixture(t *testing.T, expectedError, bp string, fixture FixturePreparer) { 420 t.Helper() 421 fs := MockFS{ 422 "prebuilt_file": nil, 423 } 424 GroupFixturePreparers( 425 PrepareForTestWithArchMutator, 426 PrepareForTestWithPrebuilts, 427 PrepareForTestWithOverrides, 428 fs.AddToFixture(), 429 FixtureRegisterWithContext(registerTestPrebuiltModules), 430 OptionalFixturePreparer(fixture), 431 ). 432 ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(expectedError)). 433 RunTestWithBp(t, bp) 434 435} 436 437func testPrebuiltError(t *testing.T, expectedError, bp string) { 438 testPrebuiltErrorWithFixture(t, expectedError, bp, nil) 439} 440 441func TestPrebuiltShouldNotChangePartition(t *testing.T) { 442 testPrebuiltError(t, `partition is different`, ` 443 source { 444 name: "foo", 445 vendor: true, 446 } 447 prebuilt { 448 name: "foo", 449 prefer: true, 450 srcs: ["prebuilt_file"], 451 }`) 452} 453 454func TestPrebuiltShouldNotChangePartition_WithOverride(t *testing.T) { 455 testPrebuiltError(t, `partition is different`, ` 456 source { 457 name: "foo", 458 vendor: true, 459 } 460 override_source { 461 name: "bar", 462 base: "foo", 463 } 464 prebuilt { 465 name: "bar", 466 prefer: true, 467 srcs: ["prebuilt_file"], 468 }`) 469} 470 471func registerTestPrebuiltBuildComponents(ctx RegistrationContext) { 472 registerTestPrebuiltModules(ctx) 473 474 RegisterPrebuiltMutators(ctx) 475 ctx.PostDepsMutators(RegisterOverridePostDepsMutators) 476} 477 478var prepareForTestWithFakePrebuiltModules = FixtureRegisterWithContext(registerTestPrebuiltModules) 479 480func registerTestPrebuiltModules(ctx RegistrationContext) { 481 ctx.RegisterModuleType("prebuilt", newPrebuiltModule) 482 ctx.RegisterModuleType("source", newSourceModule) 483 ctx.RegisterModuleType("override_source", newOverrideSourceModule) 484 ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory) 485 ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory) 486 ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory) 487 RegisterApexContributionsBuildComponents(ctx) 488} 489 490type prebuiltModule struct { 491 ModuleBase 492 prebuilt Prebuilt 493 properties struct { 494 Srcs []string `android:"path,arch_variant"` 495 } 496} 497 498func newPrebuiltModule() Module { 499 m := &prebuiltModule{} 500 m.AddProperties(&m.properties) 501 InitPrebuiltModule(m, &m.properties.Srcs) 502 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 503 return m 504} 505 506func (p *prebuiltModule) Name() string { 507 return p.prebuilt.Name(p.ModuleBase.Name()) 508} 509 510func (p *prebuiltModule) GenerateAndroidBuildActions(ctx ModuleContext) { 511 if len(p.properties.Srcs) >= 1 { 512 src := p.prebuilt.SingleSourcePath(ctx) 513 ctx.SetOutputFiles(Paths{src}, "") 514 } 515} 516 517func (p *prebuiltModule) Prebuilt() *Prebuilt { 518 return &p.prebuilt 519} 520 521type sourceModuleProperties struct { 522 Deps []string `android:"path,arch_variant"` 523} 524 525type sourceModule struct { 526 ModuleBase 527 OverridableModuleBase 528 529 properties sourceModuleProperties 530 dependsOnSourceModule, dependsOnPrebuiltModule bool 531 deps Paths 532 src Path 533} 534 535func newSourceModule() Module { 536 m := &sourceModule{} 537 m.AddProperties(&m.properties) 538 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 539 InitOverridableModule(m, nil) 540 return m 541} 542 543func (s *sourceModule) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) { 544 // s.properties.Deps are annotated with android:path, so they are 545 // automatically added to the dependency by pathDeps mutator 546} 547 548func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) { 549 s.deps = PathsForModuleSrc(ctx, s.properties.Deps) 550 s.src = PathForModuleSrc(ctx, "source_file") 551} 552 553func (s *sourceModule) Srcs() Paths { 554 return Paths{s.src} 555} 556 557type overrideSourceModule struct { 558 ModuleBase 559 OverrideModuleBase 560} 561 562func (o *overrideSourceModule) GenerateAndroidBuildActions(_ ModuleContext) { 563} 564 565func newOverrideSourceModule() Module { 566 m := &overrideSourceModule{} 567 m.AddProperties(&sourceModuleProperties{}) 568 569 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 570 InitOverrideModule(m) 571 return m 572} 573 574func TestPrebuiltErrorCannotListBothSourceAndPrebuiltInContributions(t *testing.T) { 575 selectMainlineModuleContritbutions := GroupFixturePreparers( 576 PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "my_apex_contributions"), 577 ) 578 testPrebuiltErrorWithFixture(t, `Found duplicate variations of the same module in apex_contributions: foo and prebuilt_foo. Please remove one of these`, ` 579 source { 580 name: "foo", 581 } 582 prebuilt { 583 name: "foo", 584 srcs: ["prebuilt_file"], 585 } 586 apex_contributions { 587 name: "my_apex_contributions", 588 api_domain: "my_mainline_module", 589 contents: [ 590 "foo", 591 "prebuilt_foo", 592 ], 593 } 594 all_apex_contributions { 595 name: "all_apex_contributions", 596 } 597 `, selectMainlineModuleContritbutions) 598} 599