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