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 "strings" 22 "testing" 23 24 "android/soong/android" 25 "android/soong/cc" 26 "android/soong/dexpreopt" 27 28 "github.com/google/blueprint" 29) 30 31const defaultJavaDir = "default/java" 32const testDefaultUpdatableModuleVersion = "340090000" 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 java components that invoke Metalava. 56 "build/soong/java/metalava/Android.bp": []byte(`filegroup {name: "metalava-config-files"}`), 57 // Needed for apps that do not provide their own. 58 "build/make/target/product/security": nil, 59 // Required to generate Java used-by API coverage 60 "build/soong/scripts/gen_java_usedby_apex.sh": nil, 61 // Needed for the global lint checks provided from frameworks/base 62 "prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar": nil, 63 }.AddToFixture(), 64 android.PrepareForTestWithBuildFlag("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION", testDefaultUpdatableModuleVersion), 65) 66 67var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers( 68 // The java default module definitions. 69 android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()), 70 // Additional files needed when test disallows non-existent source. 71 android.MockFS{ 72 // Needed for framework-res 73 defaultJavaDir + "/AndroidManifest.xml": nil, 74 // Needed for framework 75 defaultJavaDir + "/framework/aidl": nil, 76 // Needed for various deps defined in GatherRequiredDepsForTest() 77 defaultJavaDir + "/a.java": nil, 78 defaultJavaDir + "/api/current.txt": nil, 79 defaultJavaDir + "/api/removed.txt": nil, 80 defaultJavaDir + "/api/system-current.txt": nil, 81 defaultJavaDir + "/api/system-removed.txt": nil, 82 defaultJavaDir + "/api/test-current.txt": nil, 83 defaultJavaDir + "/api/test-removed.txt": nil, 84 defaultJavaDir + "/api/module-lib-current.txt": nil, 85 defaultJavaDir + "/api/module-lib-removed.txt": nil, 86 defaultJavaDir + "/api/system-server-current.txt": nil, 87 defaultJavaDir + "/api/system-server-removed.txt": nil, 88 89 // Needed for R8 rules on apps 90 "build/make/core/proguard.flags": nil, 91 "build/make/core/proguard_basic_keeps.flags": nil, 92 "prebuilts/cmdline-tools/shrinker.xml": nil, 93 }.AddToFixture(), 94) 95 96var prepareForTestWithJavaDefaultModulesBase = android.GroupFixturePreparers( 97 // Make sure that all the module types used in the defaults are registered. 98 PrepareForTestWithJavaBuildComponents, 99 prepareForTestWithFrameworkDeps, 100 // Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module. 101 dexpreopt.PrepareForTestWithDexpreoptCompatLibs, 102) 103 104// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules. 105var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers( 106 prepareForTestWithJavaDefaultModulesBase, 107 dexpreopt.FixtureDisableDexpreoptBootImages(true), 108 dexpreopt.FixtureDisableDexpreopt(true), 109) 110 111// Provides everything needed by dexpreopt. 112var PrepareForTestWithDexpreopt = android.GroupFixturePreparers( 113 prepareForTestWithJavaDefaultModulesBase, 114 dexpreopt.PrepareForTestWithFakeDex2oatd, 115 dexpreopt.PrepareForTestByEnablingDexpreopt, 116) 117 118// Provides everything needed by dexpreopt except the fake_tool_binary for dex2oatd. 119var PrepareForTestWithDexpreoptWithoutFakeDex2oatd = android.GroupFixturePreparers( 120 prepareForTestWithJavaDefaultModulesBase, 121 dexpreopt.PrepareForTestByEnablingDexpreopt, 122) 123 124// Prepare a fixture to use all java module types, mutators and singletons fully. 125// 126// This should only be used by tests that want to run with as much of the build enabled as possible. 127var PrepareForIntegrationTestWithJava = android.GroupFixturePreparers( 128 cc.PrepareForIntegrationTestWithCc, 129 PrepareForTestWithJavaDefaultModules, 130) 131 132// Prepare a fixture with the standard files required by a java_sdk_library module. 133var PrepareForTestWithJavaSdkLibraryFiles = android.FixtureMergeMockFs(android.MockFS{ 134 "api/current.txt": nil, 135 "api/removed.txt": nil, 136 "api/system-current.txt": nil, 137 "api/system-removed.txt": nil, 138 "api/test-current.txt": nil, 139 "api/test-removed.txt": nil, 140 "api/module-lib-current.txt": nil, 141 "api/module-lib-removed.txt": nil, 142 "api/system-server-current.txt": nil, 143 "api/system-server-removed.txt": nil, 144}) 145 146// FixtureWithLastReleaseApis creates a preparer that creates prebuilt versions of the specified 147// modules for the `last` API release. By `last` it just means last in the list of supplied versions 148// and as this only provides one version it can be any value. 149// 150// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this. 151func FixtureWithLastReleaseApis(moduleNames ...string) android.FixturePreparer { 152 return FixtureWithPrebuiltApis(map[string][]string{ 153 "30": moduleNames, 154 }) 155} 156 157// PrepareForTestWithPrebuiltsOfCurrentApi is a preparer that creates prebuilt versions of the 158// standard modules for the current version. 159// 160// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this. 161var PrepareForTestWithPrebuiltsOfCurrentApi = FixtureWithPrebuiltApis(map[string][]string{ 162 "current": {}, 163 // Can't have current on its own as it adds a prebuilt_apis module but doesn't add any 164 // .txt files which causes the prebuilt_apis module to fail. 165 "30": {}, 166}) 167 168var prepareForTestWithFrameworkJacocoInstrumentation = android.GroupFixturePreparers( 169 android.FixtureMergeEnv(map[string]string{ 170 "EMMA_INSTRUMENT_FRAMEWORK": "true", 171 }), 172 PrepareForTestWithJacocoInstrumentation, 173) 174 175// PrepareForTestWithJacocoInstrumentation creates a mock jacocoagent library that can be 176// depended on as part of the build process for instrumented Java modules. 177var PrepareForTestWithJacocoInstrumentation = android.GroupFixturePreparers( 178 android.FixtureMergeEnv(map[string]string{ 179 "EMMA_INSTRUMENT": "true", 180 }), 181 android.FixtureAddFile("jacocoagent/Test.java", nil), 182 android.FixtureAddFile("jacocoagent/Android.bp", []byte(` 183 java_library { 184 name: "jacocoagent", 185 host_supported: true, 186 srcs: ["Test.java"], 187 sdk_version: "current", 188 apex_available: [ 189 "//apex_available:anyapex", 190 "//apex_available:platform", 191 ], 192 compile_dex: true, 193 } 194 `)), 195) 196 197// FixtureWithPrebuiltApis creates a preparer that will define prebuilt api modules for the 198// specified releases and modules. 199// 200// The supplied map keys are the releases, e.g. current, 29, 30, etc. The values are a list of 201// modules for that release. Due to limitations in the prebuilt_apis module which this preparer 202// uses the set of releases must include at least one numbered release, i.e. it cannot just include 203// "current". 204// 205// This defines a file in the mock file system in a predefined location (prebuilts/sdk/Android.bp) 206// and so only one instance of this can be used in each fixture. 207func FixtureWithPrebuiltApis(release2Modules map[string][]string) android.FixturePreparer { 208 return FixtureWithPrebuiltApisAndExtensions(release2Modules, nil) 209} 210 211func FixtureWithPrebuiltApisAndExtensions(apiLevel2Modules map[string][]string, extensionLevel2Modules map[string][]string) android.FixturePreparer { 212 mockFS := android.MockFS{} 213 path := "prebuilts/sdk/Android.bp" 214 215 bp := fmt.Sprintf(` 216 prebuilt_apis { 217 name: "sdk", 218 api_dirs: ["%s"], 219 extensions_dir: "extensions", 220 imports_sdk_version: "none", 221 imports_compile_dex: true, 222 } 223 `, strings.Join(android.SortedKeys(apiLevel2Modules), `", "`)) 224 225 for release, modules := range apiLevel2Modules { 226 mockFS.Merge(prebuiltApisFilesForModules([]string{release}, modules)) 227 } 228 if extensionLevel2Modules != nil { 229 for release, modules := range extensionLevel2Modules { 230 mockFS.Merge(prebuiltExtensionApiFiles([]string{release}, modules)) 231 } 232 } 233 return android.GroupFixturePreparers( 234 android.FixtureAddTextFile(path, bp), 235 android.FixtureMergeMockFs(mockFS), 236 ) 237} 238 239func prebuiltApisFilesForModules(apiLevels []string, modules []string) map[string][]byte { 240 libs := append([]string{"android"}, modules...) 241 242 fs := make(map[string][]byte) 243 for _, level := range apiLevels { 244 apiLevel := android.ApiLevelForTest(level) 245 for _, sdkKind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkModule, android.SdkSystemServer, android.SdkTest} { 246 // A core-for-system-modules file must only be created for the sdk kind that supports it. 247 if sdkKind == systemModuleKind(sdkKind, apiLevel) { 248 fs[fmt.Sprintf("prebuilts/sdk/%s/%s/core-for-system-modules.jar", level, sdkKind)] = nil 249 } 250 251 for _, lib := range libs { 252 // Create a jar file for every library. 253 fs[fmt.Sprintf("prebuilts/sdk/%s/%s/%s.jar", level, sdkKind, lib)] = nil 254 255 // No finalized API files for "current" 256 if level != "current" { 257 fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s.txt", level, sdkKind, lib)] = nil 258 fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s-removed.txt", level, sdkKind, lib)] = nil 259 } 260 } 261 } 262 if level == "current" { 263 fs["prebuilts/sdk/current/core/android.jar"] = nil 264 } 265 fs[fmt.Sprintf("prebuilts/sdk/%s/public/framework.aidl", level)] = nil 266 } 267 return fs 268} 269 270func prebuiltExtensionApiFiles(extensionLevels []string, modules []string) map[string][]byte { 271 fs := make(map[string][]byte) 272 for _, level := range extensionLevels { 273 for _, sdkKind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkModule, android.SdkSystemServer} { 274 for _, lib := range modules { 275 fs[fmt.Sprintf("prebuilts/sdk/extensions/%s/%s/api/%s.txt", level, sdkKind, lib)] = nil 276 fs[fmt.Sprintf("prebuilts/sdk/extensions/%s/%s/api/%s-removed.txt", level, sdkKind, lib)] = nil 277 } 278 } 279 } 280 return fs 281} 282 283// FixtureConfigureBootJars configures the boot jars in both the dexpreopt.GlobalConfig and 284// Config.productVariables structs. As a side effect that enables dexpreopt. 285func FixtureConfigureBootJars(bootJars ...string) android.FixturePreparer { 286 artBootJars := []string{} 287 for _, j := range bootJars { 288 artApex := false 289 for _, artApexName := range artApexNames { 290 if strings.HasPrefix(j, artApexName+":") { 291 artApex = true 292 break 293 } 294 } 295 if artApex { 296 artBootJars = append(artBootJars, j) 297 } 298 } 299 return android.GroupFixturePreparers( 300 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 301 variables.BootJars = android.CreateTestConfiguredJarList(bootJars) 302 }), 303 dexpreopt.FixtureSetBootJars(bootJars...), 304 dexpreopt.FixtureSetArtBootJars(artBootJars...), 305 306 // Add a fake dex2oatd module. 307 dexpreopt.PrepareForTestWithFakeDex2oatd, 308 ) 309} 310 311// FixtureConfigureApexBootJars configures the apex boot jars in both the 312// dexpreopt.GlobalConfig and Config.productVariables structs. As a side effect that enables 313// dexpreopt. 314func FixtureConfigureApexBootJars(bootJars ...string) android.FixturePreparer { 315 return android.GroupFixturePreparers( 316 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { 317 variables.ApexBootJars = android.CreateTestConfiguredJarList(bootJars) 318 }), 319 dexpreopt.FixtureSetApexBootJars(bootJars...), 320 321 // Add a fake dex2oatd module. 322 dexpreopt.PrepareForTestWithFakeDex2oatd, 323 ) 324} 325 326// FixtureUseLegacyCorePlatformApi prepares the fixture by setting the exception list of those 327// modules that are allowed to use the legacy core platform API to be the ones supplied. 328func FixtureUseLegacyCorePlatformApi(moduleNames ...string) android.FixturePreparer { 329 lookup := make(map[string]struct{}) 330 for _, moduleName := range moduleNames { 331 lookup[moduleName] = struct{}{} 332 } 333 return android.FixtureModifyConfig(func(config android.Config) { 334 // Try and set the legacyCorePlatformApiLookup in the config, the returned value will be the 335 // actual value that is set. 336 cached := config.Once(legacyCorePlatformApiLookupKey, func() interface{} { 337 return lookup 338 }) 339 // Make sure that the cached value is the one we need. 340 if !reflect.DeepEqual(cached, lookup) { 341 panic(fmt.Errorf("attempting to set legacyCorePlatformApiLookupKey to %q but it has already been set to %q", lookup, cached)) 342 } 343 }) 344} 345 346// registerRequiredBuildComponentsForTest registers the build components used by 347// PrepareForTestWithJavaDefaultModules. 348// 349// As functionality is moved out of here into separate FixturePreparer instances they should also 350// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test 351// fixtures. 352func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) { 353 RegisterAARBuildComponents(ctx) 354 RegisterAppBuildComponents(ctx) 355 RegisterAppImportBuildComponents(ctx) 356 RegisterAppSetBuildComponents(ctx) 357 registerBootclasspathFragmentBuildComponents(ctx) 358 RegisterDexpreoptBootJarsComponents(ctx) 359 RegisterDocsBuildComponents(ctx) 360 RegisterGenRuleBuildComponents(ctx) 361 registerJavaBuildComponents(ctx) 362 registerPlatformBootclasspathBuildComponents(ctx) 363 RegisterPrebuiltApisBuildComponents(ctx) 364 RegisterRuntimeResourceOverlayBuildComponents(ctx) 365 RegisterSdkLibraryBuildComponents(ctx) 366 RegisterStubsBuildComponents(ctx) 367 RegisterSystemModulesBuildComponents(ctx) 368 registerSystemserverClasspathBuildComponents(ctx) 369 android.RegisterApexContributionsBuildComponents(ctx) 370} 371 372// gatherRequiredDepsForTest gathers the module definitions used by 373// PrepareForTestWithJavaDefaultModules. 374// 375// As functionality is moved out of here into separate FixturePreparer instances they should also 376// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test 377// fixtures. 378func gatherRequiredDepsForTest() string { 379 var bp string 380 381 extraModules := []string{ 382 "core-lambda-stubs", 383 "ext", 384 "android_stubs_current", 385 "android_system_stubs_current", 386 "android_test_stubs_current", 387 "android_module_lib_stubs_current", 388 "android_system_server_stubs_current", 389 "core.current.stubs", 390 "legacy.core.platform.api.stubs", 391 "stable.core.platform.api.stubs", 392 "android_stubs_current_exportable", 393 "android_system_stubs_current_exportable", 394 "android_test_stubs_current_exportable", 395 "android_module_lib_stubs_current_exportable", 396 "android_system_server_stubs_current_exportable", 397 "core.current.stubs.exportable", 398 "legacy.core.platform.api.stubs.exportable", 399 "kotlin-stdlib", 400 "kotlin-stdlib-jdk7", 401 "kotlin-stdlib-jdk8", 402 "kotlin-annotations", 403 "stub-annotations", 404 "aconfig-annotations-lib", 405 "aconfig_storage_stub", 406 "unsupportedappusage", 407 } 408 409 for _, extra := range extraModules { 410 bp += fmt.Sprintf(` 411 java_library { 412 name: "%s", 413 srcs: ["a.java"], 414 sdk_version: "none", 415 system_modules: "stable-core-platform-api-stubs-system-modules", 416 compile_dex: true, 417 is_stubs_module: true, 418 } 419 `, extra) 420 } 421 422 type droidstubsStruct struct { 423 name string 424 apiSurface string 425 apiFile string 426 removedFile string 427 } 428 429 var publicDroidstubs = droidstubsStruct{ 430 name: "api-stubs-docs-non-updatable", 431 apiSurface: "public", 432 apiFile: "api/current.txt", 433 removedFile: "api/removed.txt", 434 } 435 var systemDroidstubs = droidstubsStruct{ 436 name: "system-api-stubs-docs-non-updatable", 437 apiSurface: "system", 438 apiFile: "api/system-current.txt", 439 removedFile: "api/system-removed.txt", 440 } 441 var testDroidstubs = droidstubsStruct{ 442 name: "test-api-stubs-docs-non-updatable", 443 apiSurface: "test", 444 apiFile: "api/test-current.txt", 445 removedFile: "api/test-removed.txt", 446 } 447 var moduleLibDroidstubs = droidstubsStruct{ 448 name: "module-lib-api-stubs-docs-non-updatable", 449 apiSurface: "module-lib", 450 apiFile: "api/module-lib-current.txt", 451 removedFile: "api/module-lib-removed.txt", 452 } 453 var systemServerDroidstubs = droidstubsStruct{ 454 // This module does not exist but is named this way for consistency 455 name: "system-server-api-stubs-docs-non-updatable", 456 apiSurface: "system-server", 457 apiFile: "api/system-server-current.txt", 458 removedFile: "api/system-server-removed.txt", 459 } 460 var droidstubsStructs = []droidstubsStruct{ 461 publicDroidstubs, 462 systemDroidstubs, 463 testDroidstubs, 464 moduleLibDroidstubs, 465 systemServerDroidstubs, 466 } 467 468 extraApiLibraryModules := map[string]droidstubsStruct{ 469 "android_stubs_current.from-text": publicDroidstubs, 470 "android_system_stubs_current.from-text": systemDroidstubs, 471 "android_test_stubs_current.from-text": testDroidstubs, 472 "android_module_lib_stubs_current.from-text": moduleLibDroidstubs, 473 "android_module_lib_stubs_current_full.from-text": moduleLibDroidstubs, 474 "android_system_server_stubs_current.from-text": systemServerDroidstubs, 475 "core.current.stubs.from-text": publicDroidstubs, 476 "legacy.core.platform.api.stubs.from-text": publicDroidstubs, 477 "stable.core.platform.api.stubs.from-text": publicDroidstubs, 478 "core-lambda-stubs.from-text": publicDroidstubs, 479 "android-non-updatable.stubs.test_module_lib": moduleLibDroidstubs, 480 } 481 482 for _, droidstubs := range droidstubsStructs { 483 bp += fmt.Sprintf(` 484 droidstubs { 485 name: "%s", 486 api_surface: "%s", 487 check_api: { 488 current: { 489 api_file: "%s", 490 removed_api_file: "%s", 491 } 492 } 493 } 494 `, 495 droidstubs.name, 496 droidstubs.apiSurface, 497 droidstubs.apiFile, 498 droidstubs.removedFile, 499 ) 500 } 501 502 for libName, droidstubs := range extraApiLibraryModules { 503 bp += fmt.Sprintf(` 504 java_api_library { 505 name: "%s", 506 api_contributions: ["%s"], 507 stubs_type: "everything", 508 sdk_version: "none", 509 system_modules: "none", 510 } 511 `, libName, droidstubs.name+".api.contribution") 512 } 513 514 bp += ` 515 java_library { 516 name: "framework", 517 srcs: ["a.java"], 518 sdk_version: "none", 519 system_modules: "stable-core-platform-api-stubs-system-modules", 520 aidl: { 521 export_include_dirs: ["framework/aidl"], 522 }, 523 compile_dex: true, 524 } 525 java_library { 526 name: "framework-minus-apex", 527 srcs: ["a.java"], 528 sdk_version: "none", 529 system_modules: "stable-core-platform-api-stubs-system-modules", 530 aidl: { 531 export_include_dirs: ["framework/aidl"], 532 }, 533 compile_dex: true, 534 } 535 536 android_app { 537 name: "framework-res", 538 sdk_version: "core_platform", 539 }` 540 541 systemModules := []string{ 542 "core-public-stubs-system-modules", 543 "core-module-lib-stubs-system-modules", 544 "legacy-core-platform-api-stubs-system-modules", 545 "stable-core-platform-api-stubs-system-modules", 546 "core-public-stubs-system-modules.from-text", 547 "core-module-lib-stubs-system-modules.from-text", 548 "legacy-core-platform-api-stubs-system-modules.from-text", 549 "stable-core-platform-api-stubs-system-modules.from-text", 550 } 551 552 for _, extra := range systemModules { 553 bp += fmt.Sprintf(` 554 java_system_modules { 555 name: "%[1]s", 556 libs: ["%[1]s-lib"], 557 } 558 java_library { 559 name: "%[1]s-lib", 560 sdk_version: "none", 561 system_modules: "none", 562 srcs: ["a.java"], 563 } 564 `, extra) 565 } 566 567 // Make sure that the dex_bootjars singleton module is instantiated for the tests. 568 bp += ` 569 dex_bootjars { 570 name: "dex_bootjars", 571 } 572` 573 574 bp += ` 575 all_apex_contributions { 576 name: "all_apex_contributions", 577 } 578` 579 return bp 580} 581 582func getModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string) []string { 583 t.Helper() 584 module := ctx.ModuleForTests(t, name, variant).Module() 585 deps := []string{} 586 ctx.VisitDirectDeps(module, func(m blueprint.Module) { 587 deps = append(deps, m.Name()) 588 }) 589 return android.SortedUniqueStrings(deps) 590} 591 592// CheckModuleDependencies checks if the expected dependencies of the module are 593// identical to the actual dependencies. 594func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) { 595 t.Helper() 596 deps := getModuleDependencies(t, ctx, name, variant) 597 598 if actual := deps; !reflect.DeepEqual(expected, actual) { 599 t.Errorf("expected %#q, found %#q", expected, actual) 600 } 601} 602 603// CheckModuleHasDependency returns true if the module depends on the expected dependency. 604func CheckModuleHasDependency(t *testing.T, ctx *android.TestContext, name, variant string, expected string) bool { 605 for _, dep := range getModuleDependencies(t, ctx, name, variant) { 606 if dep == expected { 607 return true 608 } 609 } 610 return false 611} 612 613// CheckModuleHasDependency returns true if the module depends on the expected dependency. 614func CheckModuleHasDependencyWithTag(t *testing.T, ctx *android.TestContext, name, variant string, desiredTag blueprint.DependencyTag, expected string) bool { 615 module := ctx.ModuleForTests(t, name, variant).Module() 616 found := false 617 ctx.VisitDirectDepsWithTags(module, func(m blueprint.Module, tag blueprint.DependencyTag) { 618 if tag == desiredTag && m.Name() == expected { 619 found = true 620 } 621 }) 622 return found 623} 624 625// CheckPlatformBootclasspathModules returns the apex:module pair for the modules depended upon by 626// the platform-bootclasspath module. 627func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) { 628 t.Helper() 629 platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule) 630 pairs := apexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules, platformBootclasspath.libraryToApex) 631 android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs) 632} 633 634func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *android.TestResult, generated bool, contents, outputFilename, installDir string) { 635 t.Helper() 636 p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) 637 info, _ := android.OtherModuleProvider(result, p, ClasspathFragmentProtoContentInfoProvider) 638 639 android.AssertBoolEquals(t, "classpath proto generated", generated, info.ClasspathFragmentProtoGenerated) 640 android.AssertStringEquals(t, "classpath proto contents", contents, info.ClasspathFragmentProtoContents.String()) 641 android.AssertStringEquals(t, "output filepath", outputFilename, info.ClasspathFragmentProtoOutput.Base()) 642 android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir) 643} 644 645// CheckPlatformBootclasspathDependencies checks the dependencies of the selected module against the expected list. 646// 647// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the 648// name of the apex, or platform is it is not part of an apex and <module> is the module name. 649func CheckPlatformBootclasspathDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) { 650 t.Helper() 651 platformBootclasspath := ctx.ModuleForTests(t, name, variant).Module().(*platformBootclasspathModule) 652 modules := []android.Module{} 653 ctx.VisitDirectDeps(platformBootclasspath, func(m blueprint.Module) { 654 modules = append(modules, m.(android.Module)) 655 }) 656 657 pairs := apexNamePairsFromModules(ctx, modules, platformBootclasspath.libraryToApex) 658 android.AssertDeepEquals(t, "module dependencies", expected, pairs) 659} 660 661// apexNamePairsFromModules returns the apex:module pair for the supplied modules. 662func apexNamePairsFromModules(ctx *android.TestContext, modules []android.Module, modulesToApex map[android.Module]string) []string { 663 pairs := []string{} 664 for _, module := range modules { 665 pairs = append(pairs, apexNamePairFromModule(ctx, module, modulesToApex)) 666 } 667 return pairs 668} 669 670// ApexFragmentPairsFromModules returns the apex:fragment pair for the supplied fragments. 671func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.Module, apexNameToFragment map[string]android.Module) []string { 672 pairs := []string{} 673 for _, fragment := range fragments { 674 found := false 675 for apex, apexFragment := range apexNameToFragment { 676 if apexFragment == fragment { 677 pairs = append(pairs, apex+":"+ctx.ModuleName(fragment)) 678 found = true 679 } 680 } 681 if !found { 682 pairs = append(pairs, "platform:"+ctx.ModuleName(fragment)) 683 } 684 } 685 return pairs 686} 687 688func apexNamePairFromModule(ctx *android.TestContext, module android.Module, modulesToApex map[android.Module]string) string { 689 name := module.Name() 690 apex := modulesToApex[module] 691 if apex == "" { 692 apex = "platform" 693 } 694 695 return fmt.Sprintf("%s:%s", apex, name) 696} 697 698// CheckPlatformBootclasspathFragments returns the apex:module pair for the fragments depended upon 699// by the platform-bootclasspath module. 700func CheckPlatformBootclasspathFragments(t *testing.T, result *android.TestResult, name string, expected []string) { 701 t.Helper() 702 platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule) 703 pairs := ApexFragmentPairsFromModules(result.TestContext, platformBootclasspath.fragments, platformBootclasspath.apexNameToFragment) 704 android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs) 705} 706 707func CheckHiddenAPIRuleInputs(t *testing.T, message string, expected string, hiddenAPIRule android.TestingBuildParams) { 708 t.Helper() 709 inputs := android.Paths{} 710 if hiddenAPIRule.Input != nil { 711 inputs = append(inputs, hiddenAPIRule.Input) 712 } 713 inputs = append(inputs, hiddenAPIRule.Inputs...) 714 inputs = append(inputs, hiddenAPIRule.Implicits...) 715 inputs = android.SortedUniquePaths(inputs) 716 actual := strings.TrimSpace(strings.Join(inputs.RelativeToTop().Strings(), "\n")) 717 re := regexp.MustCompile(`\n\s+`) 718 expected = strings.TrimSpace(re.ReplaceAllString(expected, "\n")) 719 if actual != expected { 720 t.Errorf("Expected hiddenapi rule inputs - %s:\n%s\nactual inputs:\n%s", message, expected, actual) 721 } 722} 723 724// Check that the merged file create by platform_compat_config_singleton has the correct inputs. 725func CheckMergedCompatConfigInputs(t *testing.T, result *android.TestResult, message string, expectedPaths ...string) { 726 sourceGlobalCompatConfig := result.SingletonForTests(t, "platform_compat_config_singleton") 727 allOutputs := sourceGlobalCompatConfig.AllOutputs() 728 android.AssertIntEquals(t, message+": output len", 1, len(allOutputs)) 729 output := sourceGlobalCompatConfig.Output(allOutputs[0]) 730 android.AssertPathsRelativeToTopEquals(t, message+": inputs", expectedPaths, output.Implicits) 731} 732 733// Register the fake APEX mutator to `android.InitRegistrationContext` as if the real mutator exists 734// at runtime. This must be called in `init()` of a test if the test is going to use the fake APEX 735// mutator. Otherwise, we will be missing the runtime mutator because "soong-apex" is not a 736// dependency, which will cause an inconsistency between testing and runtime mutators. 737func RegisterFakeRuntimeApexMutator() { 738 registerFakeApexMutator(android.InitRegistrationContext) 739} 740 741var PrepareForTestWithFakeApexMutator = android.GroupFixturePreparers( 742 android.FixtureRegisterWithContext(registerFakeApexMutator), 743) 744 745func registerFakeApexMutator(ctx android.RegistrationContext) { 746 ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 747 ctx.Transition("apex", &fakeApexMutator{}) 748 }) 749} 750 751type apexModuleBase interface { 752 ApexAvailable() []string 753} 754 755var _ apexModuleBase = (*Library)(nil) 756var _ apexModuleBase = (*SdkLibrary)(nil) 757 758// A fake APEX mutator that creates a platform variant and an APEX variant for modules with 759// `apex_available`. It helps us avoid a dependency on the real mutator defined in "soong-apex", 760// which will cause a cyclic dependency, and it provides an easy way to create an APEX variant for 761// testing without dealing with all the complexities in the real mutator. 762type fakeApexMutator struct{} 763 764func (f *fakeApexMutator) Split(ctx android.BaseModuleContext) []string { 765 switch ctx.Module().(type) { 766 case *Library, *SdkLibrary: 767 return []string{"", "apex1000"} 768 } 769 return []string{""} 770} 771 772func (f *fakeApexMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { 773 return sourceVariation 774} 775 776func (f *fakeApexMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { 777 return incomingVariation 778} 779 780func (f *fakeApexMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { 781 if variation != "" { 782 apexInfo := android.ApexInfo{ 783 ApexVariationName: "apex1000", 784 } 785 android.SetProvider(ctx, android.ApexInfoProvider, apexInfo) 786 } 787} 788 789// Applies the given modifier on the boot image config with the given name. 790func FixtureModifyBootImageConfig(name string, configModifier func(*bootImageConfig)) android.FixturePreparer { 791 return android.FixtureModifyConfig(func(androidConfig android.Config) { 792 pathCtx := android.PathContextForTesting(androidConfig) 793 config := genBootImageConfigRaw(pathCtx) 794 configModifier(config[name]) 795 }) 796} 797 798// Sets the value of `installDir` of the boot image config with the given name. 799func FixtureSetBootImageInstallDirOnDevice(name string, installDir string) android.FixturePreparer { 800 return FixtureModifyBootImageConfig(name, func(config *bootImageConfig) { 801 config.installDir = installDir 802 }) 803} 804