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