1// Copyright 2019 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 java 16 17import ( 18 "fmt" 19 "reflect" 20 "regexp" 21 "sort" 22 "strings" 23 "testing" 24 25 "android/soong/android" 26 "android/soong/cc" 27 "android/soong/dexpreopt" 28 29 "github.com/google/blueprint" 30) 31 32const defaultJavaDir = "default/java" 33 34// Test fixture preparer that will register most java build components. 35// 36// Singletons and mutators should only be added here if they are needed for a majority of java 37// module types, otherwise they should be added under a separate preparer to allow them to be 38// selected only when needed to reduce test execution time. 39// 40// Module types do not have much of an overhead unless they are used so this should include as many 41// module types as possible. The exceptions are those module types that require mutators and/or 42// singletons in order to function in which case they should be kept together in a separate 43// preparer. 44var PrepareForTestWithJavaBuildComponents = android.GroupFixturePreparers( 45 // Make sure that mutators and module types, e.g. prebuilt mutators available. 46 android.PrepareForTestWithAndroidBuildComponents, 47 // Make java build components available to the test. 48 android.FixtureRegisterWithContext(registerRequiredBuildComponentsForTest), 49 android.FixtureRegisterWithContext(registerJavaPluginBuildComponents), 50 // Additional files needed in tests that disallow non-existent source files. 51 // This includes files that are needed by all, or at least most, instances of a java module type. 52 android.MockFS{ 53 // Needed for linter used by java_library. 54 "build/soong/java/lint_defaults.txt": nil, 55 // Needed for apps that do not provide their own. 56 "build/make/target/product/security": nil, 57 // Required to generate Java used-by API coverage 58 "build/soong/scripts/gen_java_usedby_apex.sh": nil, 59 // Needed for the global lint checks provided from frameworks/base 60 "prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar": nil, 61 }.AddToFixture(), 62) 63 64var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers( 65 // The java default module definitions. 66 android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()), 67 // Additional files needed when test disallows non-existent source. 68 android.MockFS{ 69 // Needed for framework-res 70 defaultJavaDir + "/AndroidManifest.xml": nil, 71 // Needed for framework 72 defaultJavaDir + "/framework/aidl": nil, 73 // Needed for various deps defined in GatherRequiredDepsForTest() 74 defaultJavaDir + "/a.java": nil, 75 76 // Needed for R8 rules on apps 77 "build/make/core/proguard.flags": nil, 78 "build/make/core/proguard_basic_keeps.flags": nil, 79 "prebuilts/cmdline-tools/shrinker.xml": nil, 80 }.AddToFixture(), 81) 82 83var prepareForTestWithJavaDefaultModulesBase = android.GroupFixturePreparers( 84 // Make sure that all the module types used in the defaults are registered. 85 PrepareForTestWithJavaBuildComponents, 86 prepareForTestWithFrameworkDeps, 87 // Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module. 88 dexpreopt.PrepareForTestWithDexpreoptCompatLibs, 89) 90 91// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules. 92var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers( 93 prepareForTestWithJavaDefaultModulesBase, 94 dexpreopt.FixtureDisableDexpreoptBootImages(true), 95 dexpreopt.FixtureDisableDexpreopt(true), 96) 97 98// Provides everything needed by dexpreopt. 99var PrepareForTestWithDexpreopt = android.GroupFixturePreparers( 100 prepareForTestWithJavaDefaultModulesBase, 101 dexpreopt.PrepareForTestWithFakeDex2oatd, 102 dexpreopt.PrepareForTestByEnablingDexpreopt, 103) 104 105// Provides everything needed by dexpreopt except the fake_tool_binary for dex2oatd. 106var PrepareForTestWithDexpreoptWithoutFakeDex2oatd = android.GroupFixturePreparers( 107 prepareForTestWithJavaDefaultModulesBase, 108 dexpreopt.PrepareForTestByEnablingDexpreopt, 109) 110 111var PrepareForTestWithOverlayBuildComponents = android.FixtureRegisterWithContext(registerOverlayBuildComponents) 112 113// Prepare a fixture to use all java module types, mutators and singletons fully. 114// 115// This should only be used by tests that want to run with as much of the build enabled as possible. 116var PrepareForIntegrationTestWithJava = android.GroupFixturePreparers( 117 cc.PrepareForIntegrationTestWithCc, 118 PrepareForTestWithJavaDefaultModules, 119) 120 121// Prepare a fixture with the standard files required by a java_sdk_library module. 122var PrepareForTestWithJavaSdkLibraryFiles = android.FixtureMergeMockFs(android.MockFS{ 123 "api/current.txt": nil, 124 "api/removed.txt": nil, 125 "api/system-current.txt": nil, 126 "api/system-removed.txt": nil, 127 "api/test-current.txt": nil, 128 "api/test-removed.txt": nil, 129 "api/module-lib-current.txt": nil, 130 "api/module-lib-removed.txt": nil, 131 "api/system-server-current.txt": nil, 132 "api/system-server-removed.txt": nil, 133}) 134 135// FixtureWithLastReleaseApis creates a preparer that creates prebuilt versions of the specified 136// modules for the `last` API release. By `last` it just means last in the list of supplied versions 137// and as this only provides one version it can be any value. 138// 139// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this. 140func FixtureWithLastReleaseApis(moduleNames ...string) android.FixturePreparer { 141 return FixtureWithPrebuiltApis(map[string][]string{ 142 "30": moduleNames, 143 }) 144} 145 146// PrepareForTestWithPrebuiltsOfCurrentApi is a preparer that creates prebuilt versions of the 147// standard modules for the current version. 148// 149// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this. 150var PrepareForTestWithPrebuiltsOfCurrentApi = FixtureWithPrebuiltApis(map[string][]string{ 151 "current": {}, 152 // Can't have current on its own as it adds a prebuilt_apis module but doesn't add any 153 // .txt files which causes the prebuilt_apis module to fail. 154 "30": {}, 155}) 156 157var prepareForTestWithFrameworkJacocoInstrumentation = android.GroupFixturePreparers( 158 android.FixtureMergeEnv(map[string]string{ 159 "EMMA_INSTRUMENT_FRAMEWORK": "true", 160 }), 161 PrepareForTestWithJacocoInstrumentation, 162) 163 164// PrepareForTestWithJacocoInstrumentation creates a mock jacocoagent library that can be 165// depended on as part of the build process for instrumented Java modules. 166var PrepareForTestWithJacocoInstrumentation = android.GroupFixturePreparers( 167 android.FixtureMergeEnv(map[string]string{ 168 "EMMA_INSTRUMENT": "true", 169 }), 170 android.FixtureAddFile("jacocoagent/Test.java", nil), 171 android.FixtureAddFile("jacocoagent/Android.bp", []byte(` 172 java_library { 173 name: "jacocoagent", 174 host_supported: true, 175 srcs: ["Test.java"], 176 sdk_version: "current", 177 } 178 `)), 179) 180 181// FixtureWithPrebuiltApis creates a preparer that will define prebuilt api modules for the 182// specified releases and modules. 183// 184// The supplied map keys are the releases, e.g. current, 29, 30, etc. The values are a list of 185// modules for that release. Due to limitations in the prebuilt_apis module which this preparer 186// uses the set of releases must include at least one numbered release, i.e. it cannot just include 187// "current". 188// 189// This defines a file in the mock file system in a predefined location (prebuilts/sdk/Android.bp) 190// and so only one instance of this can be used in each fixture. 191func FixtureWithPrebuiltApis(release2Modules map[string][]string) android.FixturePreparer { 192 return FixtureWithPrebuiltApisAndExtensions(release2Modules, nil) 193} 194 195func FixtureWithPrebuiltApisAndExtensions(apiLevel2Modules map[string][]string, extensionLevel2Modules map[string][]string) android.FixturePreparer { 196 mockFS := android.MockFS{} 197 path := "prebuilts/sdk/Android.bp" 198 199 bp := fmt.Sprintf(` 200 prebuilt_apis { 201 name: "sdk", 202 api_dirs: ["%s"], 203 extensions_dir: "extensions", 204 imports_sdk_version: "none", 205 imports_compile_dex: true, 206 } 207 `, strings.Join(android.SortedKeys(apiLevel2Modules), `", "`)) 208 209 for release, modules := range apiLevel2Modules { 210 mockFS.Merge(prebuiltApisFilesForModules([]string{release}, modules)) 211 } 212 if extensionLevel2Modules != nil { 213 for release, modules := range extensionLevel2Modules { 214 mockFS.Merge(prebuiltExtensionApiFiles([]string{release}, modules)) 215 } 216 } 217 return android.GroupFixturePreparers( 218 android.FixtureAddTextFile(path, bp), 219 android.FixtureMergeMockFs(mockFS), 220 ) 221} 222 223func prebuiltApisFilesForModules(apiLevels []string, modules []string) map[string][]byte { 224 libs := append([]string{"android"}, modules...) 225 226 fs := make(map[string][]byte) 227 for _, level := range apiLevels { 228 apiLevel := android.ApiLevelForTest(level) 229 for _, sdkKind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkModule, android.SdkSystemServer, android.SdkTest} { 230 // A core-for-system-modules file must only be created for the sdk kind that supports it. 231 if sdkKind == systemModuleKind(sdkKind, apiLevel) { 232 fs[fmt.Sprintf("prebuilts/sdk/%s/%s/core-for-system-modules.jar", level, sdkKind)] = nil 233 } 234 235 for _, lib := range libs { 236 // Create a jar file for every library. 237 fs[fmt.Sprintf("prebuilts/sdk/%s/%s/%s.jar", level, sdkKind, lib)] = nil 238 239 // No finalized API files for "current" 240 if level != "current" { 241 fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s.txt", level, sdkKind, lib)] = nil 242 fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s-removed.txt", level, sdkKind, lib)] = nil 243 } 244 } 245 } 246 if level == "current" { 247 fs["prebuilts/sdk/current/core/android.jar"] = nil 248 } 249 fs[fmt.Sprintf("prebuilts/sdk/%s/public/framework.aidl", level)] = nil 250 } 251 return fs 252} 253 254func prebuiltExtensionApiFiles(extensionLevels []string, modules []string) map[string][]byte { 255 fs := make(map[string][]byte) 256 for _, level := range extensionLevels { 257 for _, sdkKind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkModule, android.SdkSystemServer} { 258 for _, lib := range modules { 259 fs[fmt.Sprintf("prebuilts/sdk/extensions/%s/%s/api/%s.txt", level, sdkKind, lib)] = nil 260 fs[fmt.Sprintf("prebuilts/sdk/extensions/%s/%s/api/%s-removed.txt", level, sdkKind, lib)] = nil 261 } 262 } 263 } 264 return fs 265} 266 267// FixtureConfigureBootJars configures the boot jars in both the dexpreopt.GlobalConfig and 268// Config.productVariables structs. As a side effect that enables dexpreopt. 269func FixtureConfigureBootJars(bootJars ...string) android.FixturePreparer { 270 artBootJars := []string{} 271 for _, j := range bootJars { 272 artApex := false 273 for _, artApexName := range artApexNames { 274 if strings.HasPrefix(j, artApexName+":") { 275 artApex = true 276 break 277 } 278 } 279 if artApex { 280 artBootJars = append(artBootJars, j) 281 } 282 } 283 return android.GroupFixturePreparers( 284 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 285 variables.BootJars = android.CreateTestConfiguredJarList(bootJars) 286 }), 287 dexpreopt.FixtureSetBootJars(bootJars...), 288 dexpreopt.FixtureSetArtBootJars(artBootJars...), 289 290 // Add a fake dex2oatd module. 291 dexpreopt.PrepareForTestWithFakeDex2oatd, 292 ) 293} 294 295// FixtureConfigureApexBootJars configures the apex boot jars in both the 296// dexpreopt.GlobalConfig and Config.productVariables structs. As a side effect that enables 297// dexpreopt. 298func FixtureConfigureApexBootJars(bootJars ...string) android.FixturePreparer { 299 return android.GroupFixturePreparers( 300 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 301 variables.ApexBootJars = android.CreateTestConfiguredJarList(bootJars) 302 }), 303 dexpreopt.FixtureSetApexBootJars(bootJars...), 304 305 // Add a fake dex2oatd module. 306 dexpreopt.PrepareForTestWithFakeDex2oatd, 307 ) 308} 309 310// FixtureUseLegacyCorePlatformApi prepares the fixture by setting the exception list of those 311// modules that are allowed to use the legacy core platform API to be the ones supplied. 312func FixtureUseLegacyCorePlatformApi(moduleNames ...string) android.FixturePreparer { 313 lookup := make(map[string]struct{}) 314 for _, moduleName := range moduleNames { 315 lookup[moduleName] = struct{}{} 316 } 317 return android.FixtureModifyConfig(func(config android.Config) { 318 // Try and set the legacyCorePlatformApiLookup in the config, the returned value will be the 319 // actual value that is set. 320 cached := config.Once(legacyCorePlatformApiLookupKey, func() interface{} { 321 return lookup 322 }) 323 // Make sure that the cached value is the one we need. 324 if !reflect.DeepEqual(cached, lookup) { 325 panic(fmt.Errorf("attempting to set legacyCorePlatformApiLookupKey to %q but it has already been set to %q", lookup, cached)) 326 } 327 }) 328} 329 330// registerRequiredBuildComponentsForTest registers the build components used by 331// PrepareForTestWithJavaDefaultModules. 332// 333// As functionality is moved out of here into separate FixturePreparer instances they should also 334// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test 335// fixtures. 336func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { 337 RegisterAARBuildComponents(ctx) 338 RegisterAppBuildComponents(ctx) 339 RegisterAppImportBuildComponents(ctx) 340 RegisterAppSetBuildComponents(ctx) 341 registerBootclasspathBuildComponents(ctx) 342 registerBootclasspathFragmentBuildComponents(ctx) 343 RegisterDexpreoptBootJarsComponents(ctx) 344 RegisterDocsBuildComponents(ctx) 345 RegisterGenRuleBuildComponents(ctx) 346 registerJavaBuildComponents(ctx) 347 registerPlatformBootclasspathBuildComponents(ctx) 348 RegisterPrebuiltApisBuildComponents(ctx) 349 RegisterRuntimeResourceOverlayBuildComponents(ctx) 350 RegisterSdkLibraryBuildComponents(ctx) 351 RegisterStubsBuildComponents(ctx) 352 RegisterSystemModulesBuildComponents(ctx) 353 registerSystemserverClasspathBuildComponents(ctx) 354 registerLintBuildComponents(ctx) 355} 356 357// gatherRequiredDepsForTest gathers the module definitions used by 358// PrepareForTestWithJavaDefaultModules. 359// 360// As functionality is moved out of here into separate FixturePreparer instances they should also 361// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test 362// fixtures. 363func gatherRequiredDepsForTest() string { 364 var bp string 365 366 extraModules := []string{ 367 "core-lambda-stubs", 368 "ext", 369 "android_stubs_current", 370 "android_system_stubs_current", 371 "android_test_stubs_current", 372 "android_module_lib_stubs_current", 373 "android_system_server_stubs_current", 374 "core.current.stubs", 375 "legacy.core.platform.api.stubs", 376 "stable.core.platform.api.stubs", 377 378 "kotlin-stdlib", 379 "kotlin-stdlib-jdk7", 380 "kotlin-stdlib-jdk8", 381 "kotlin-annotations", 382 "stub-annotations", 383 } 384 385 for _, extra := range extraModules { 386 bp += fmt.Sprintf(` 387 java_library { 388 name: "%s", 389 srcs: ["a.java"], 390 sdk_version: "none", 391 system_modules: "stable-core-platform-api-stubs-system-modules", 392 compile_dex: true, 393 } 394 `, extra) 395 } 396 397 extraApiLibraryModules := map[string]string{ 398 "android_stubs_current.from-text": "api/current.txt", 399 "android_system_stubs_current.from-text": "api/system-current.txt", 400 "android_test_stubs_current.from-text": "api/test-current.txt", 401 "android_module_lib_stubs_current.from-text": "api/module-lib-current.txt", 402 "android_module_lib_stubs_current_full.from-text": "api/module-lib-current.txt", 403 "android_system_server_stubs_current.from-text": "api/system-server-current.txt", 404 "core.current.stubs.from-text": "api/current.txt", 405 "legacy.core.platform.api.stubs.from-text": "api/current.txt", 406 "stable.core.platform.api.stubs.from-text": "api/current.txt", 407 "core-lambda-stubs.from-text": "api/current.txt", 408 } 409 410 for libName, apiFile := range extraApiLibraryModules { 411 bp += fmt.Sprintf(` 412 java_api_library { 413 name: "%s", 414 api_files: ["%s"], 415 } 416 `, libName, apiFile) 417 } 418 419 bp += ` 420 java_library { 421 name: "framework", 422 srcs: ["a.java"], 423 sdk_version: "none", 424 system_modules: "stable-core-platform-api-stubs-system-modules", 425 aidl: { 426 export_include_dirs: ["framework/aidl"], 427 }, 428 compile_dex: true, 429 } 430 431 android_app { 432 name: "framework-res", 433 sdk_version: "core_platform", 434 }` 435 436 systemModules := []string{ 437 "core-public-stubs-system-modules", 438 "core-module-lib-stubs-system-modules", 439 "legacy-core-platform-api-stubs-system-modules", 440 "stable-core-platform-api-stubs-system-modules", 441 "core-public-stubs-system-modules.from-text", 442 "core-module-lib-stubs-system-modules.from-text", 443 "legacy-core-platform-api-stubs-system-modules.from-text", 444 "stable-core-platform-api-stubs-system-modules.from-text", 445 } 446 447 for _, extra := range systemModules { 448 bp += fmt.Sprintf(` 449 java_system_modules { 450 name: "%[1]s", 451 libs: ["%[1]s-lib"], 452 } 453 java_library { 454 name: "%[1]s-lib", 455 sdk_version: "none", 456 system_modules: "none", 457 } 458 `, extra) 459 } 460 461 // Make sure that the dex_bootjars singleton module is instantiated for the tests. 462 bp += ` 463 dex_bootjars { 464 name: "dex_bootjars", 465 } 466` 467 468 return bp 469} 470 471func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) { 472 t.Helper() 473 module := ctx.ModuleForTests(name, variant).Module() 474 deps := []string{} 475 ctx.VisitDirectDeps(module, func(m blueprint.Module) { 476 deps = append(deps, m.Name()) 477 }) 478 sort.Strings(deps) 479 480 if actual := deps; !reflect.DeepEqual(expected, actual) { 481 t.Errorf("expected %#q, found %#q", expected, actual) 482 } 483} 484 485// CheckPlatformBootclasspathModules returns the apex:module pair for the modules depended upon by 486// the platform-bootclasspath module. 487func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) { 488 t.Helper() 489 platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule) 490 pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules) 491 android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs) 492} 493 494func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *android.TestResult, generated bool, contents, outputFilename, installDir string) { 495 t.Helper() 496 p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) 497 info := result.ModuleProvider(p, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo) 498 499 android.AssertBoolEquals(t, "classpath proto generated", generated, info.ClasspathFragmentProtoGenerated) 500 android.AssertStringEquals(t, "classpath proto contents", contents, info.ClasspathFragmentProtoContents.String()) 501 android.AssertStringEquals(t, "output filepath", outputFilename, info.ClasspathFragmentProtoOutput.Base()) 502 android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir) 503} 504 505// ApexNamePairsFromModules returns the apex:module pair for the supplied modules. 506func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module) []string { 507 pairs := []string{} 508 for _, module := range modules { 509 pairs = append(pairs, apexNamePairFromModule(ctx, module)) 510 } 511 return pairs 512} 513 514func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string { 515 name := module.Name() 516 var apex string 517 apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) 518 if apexInfo.IsForPlatform() { 519 apex = "platform" 520 } else { 521 apex = apexInfo.InApexVariants[0] 522 } 523 524 return fmt.Sprintf("%s:%s", apex, name) 525} 526 527// CheckPlatformBootclasspathFragments returns the apex:module pair for the fragments depended upon 528// by the platform-bootclasspath module. 529func CheckPlatformBootclasspathFragments(t *testing.T, result *android.TestResult, name string, expected []string) { 530 t.Helper() 531 platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule) 532 pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.fragments) 533 android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs) 534} 535 536func CheckHiddenAPIRuleInputs(t *testing.T, message string, expected string, hiddenAPIRule android.TestingBuildParams) { 537 t.Helper() 538 inputs := android.Paths{} 539 if hiddenAPIRule.Input != nil { 540 inputs = append(inputs, hiddenAPIRule.Input) 541 } 542 inputs = append(inputs, hiddenAPIRule.Inputs...) 543 inputs = append(inputs, hiddenAPIRule.Implicits...) 544 inputs = android.SortedUniquePaths(inputs) 545 actual := strings.TrimSpace(strings.Join(inputs.RelativeToTop().Strings(), "\n")) 546 re := regexp.MustCompile(`\n\s+`) 547 expected = strings.TrimSpace(re.ReplaceAllString(expected, "\n")) 548 if actual != expected { 549 t.Errorf("Expected hiddenapi rule inputs - %s:\n%s\nactual inputs:\n%s", message, expected, actual) 550 } 551} 552 553// Check that the merged file create by platform_compat_config_singleton has the correct inputs. 554func CheckMergedCompatConfigInputs(t *testing.T, result *android.TestResult, message string, expectedPaths ...string) { 555 sourceGlobalCompatConfig := result.SingletonForTests("platform_compat_config_singleton") 556 allOutputs := sourceGlobalCompatConfig.AllOutputs() 557 android.AssertIntEquals(t, message+": output len", 1, len(allOutputs)) 558 output := sourceGlobalCompatConfig.Output(allOutputs[0]) 559 android.AssertPathsRelativeToTopEquals(t, message+": inputs", expectedPaths, output.Implicits) 560} 561 562// Register the fake APEX mutator to `android.InitRegistrationContext` as if the real mutator exists 563// at runtime. This must be called in `init()` of a test if the test is going to use the fake APEX 564// mutator. Otherwise, we will be missing the runtime mutator because "soong-apex" is not a 565// dependency, which will cause an inconsistency between testing and runtime mutators. 566func RegisterFakeRuntimeApexMutator() { 567 registerFakeApexMutator(android.InitRegistrationContext) 568} 569 570var PrepareForTestWithFakeApexMutator = android.GroupFixturePreparers( 571 android.FixtureRegisterWithContext(registerFakeApexMutator), 572) 573 574func registerFakeApexMutator(ctx android.RegistrationContext) { 575 ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 576 ctx.BottomUp("apex", fakeApexMutator).Parallel() 577 }) 578} 579 580type apexModuleBase interface { 581 ApexAvailable() []string 582} 583 584var _ apexModuleBase = (*Library)(nil) 585var _ apexModuleBase = (*SdkLibrary)(nil) 586 587// A fake APEX mutator that creates a platform variant and an APEX variant for modules with 588// `apex_available`. It helps us avoid a dependency on the real mutator defined in "soong-apex", 589// which will cause a cyclic dependency, and it provides an easy way to create an APEX variant for 590// testing without dealing with all the complexities in the real mutator. 591func fakeApexMutator(mctx android.BottomUpMutatorContext) { 592 switch mctx.Module().(type) { 593 case *Library, *SdkLibrary: 594 if len(mctx.Module().(apexModuleBase).ApexAvailable()) > 0 { 595 modules := mctx.CreateVariations("", "apex1000") 596 apexInfo := android.ApexInfo{ 597 ApexVariationName: "apex1000", 598 } 599 mctx.SetVariationProvider(modules[1], android.ApexInfoProvider, apexInfo) 600 } 601 } 602} 603 604// Applies the given modifier on the boot image config with the given name. 605func FixtureModifyBootImageConfig(name string, configModifier func(*bootImageConfig)) android.FixturePreparer { 606 return android.FixtureModifyConfig(func(androidConfig android.Config) { 607 pathCtx := android.PathContextForTesting(androidConfig) 608 config := genBootImageConfigRaw(pathCtx) 609 configModifier(config[name]) 610 }) 611} 612 613// Sets the value of `installDir` of the boot image config with the given name. 614func FixtureSetBootImageInstallDirOnDevice(name string, installDir string) android.FixturePreparer { 615 return FixtureModifyBootImageConfig(name, func(config *bootImageConfig) { 616 config.installDir = installDir 617 }) 618} 619