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