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