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