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	}.AddToFixture(),
58)
59
60// Test fixture preparer that will define all default java modules except the
61// fake_tool_binary for dex2oatd.
62var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers(
63	// Make sure that all the module types used in the defaults are registered.
64	PrepareForTestWithJavaBuildComponents,
65	// Additional files needed when test disallows non-existent source.
66	android.MockFS{
67		// Needed for framework-res
68		defaultJavaDir + "/AndroidManifest.xml": nil,
69		// Needed for framework
70		defaultJavaDir + "/framework/aidl": nil,
71		// Needed for various deps defined in GatherRequiredDepsForTest()
72		defaultJavaDir + "/a.java": nil,
73	}.AddToFixture(),
74	// The java default module definitions.
75	android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()),
76	// Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module.
77	dexpreopt.PrepareForTestWithDexpreoptCompatLibs,
78)
79
80// Test fixture preparer that will define default java modules, e.g. standard prebuilt modules.
81var PrepareForTestWithJavaDefaultModules = android.GroupFixturePreparers(
82	PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd,
83	dexpreopt.PrepareForTestWithFakeDex2oatd,
84)
85
86// Provides everything needed by dexpreopt.
87var PrepareForTestWithDexpreopt = android.GroupFixturePreparers(
88	PrepareForTestWithJavaDefaultModules,
89	dexpreopt.PrepareForTestByEnablingDexpreopt,
90)
91
92var PrepareForTestWithOverlayBuildComponents = android.FixtureRegisterWithContext(registerOverlayBuildComponents)
93
94// Prepare a fixture to use all java module types, mutators and singletons fully.
95//
96// This should only be used by tests that want to run with as much of the build enabled as possible.
97var PrepareForIntegrationTestWithJava = android.GroupFixturePreparers(
98	cc.PrepareForIntegrationTestWithCc,
99	PrepareForTestWithJavaDefaultModules,
100)
101
102// Prepare a fixture with the standard files required by a java_sdk_library module.
103var PrepareForTestWithJavaSdkLibraryFiles = android.FixtureMergeMockFs(android.MockFS{
104	"api/current.txt":               nil,
105	"api/removed.txt":               nil,
106	"api/system-current.txt":        nil,
107	"api/system-removed.txt":        nil,
108	"api/test-current.txt":          nil,
109	"api/test-removed.txt":          nil,
110	"api/module-lib-current.txt":    nil,
111	"api/module-lib-removed.txt":    nil,
112	"api/system-server-current.txt": nil,
113	"api/system-server-removed.txt": nil,
114})
115
116// FixtureWithLastReleaseApis creates a preparer that creates prebuilt versions of the specified
117// modules for the `last` API release. By `last` it just means last in the list of supplied versions
118// and as this only provides one version it can be any value.
119//
120// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this.
121func FixtureWithLastReleaseApis(moduleNames ...string) android.FixturePreparer {
122	return FixtureWithPrebuiltApis(map[string][]string{
123		"30": moduleNames,
124	})
125}
126
127// PrepareForTestWithPrebuiltsOfCurrentApi is a preparer that creates prebuilt versions of the
128// standard modules for the current version.
129//
130// This uses FixtureWithPrebuiltApis under the covers so the limitations of that apply to this.
131var PrepareForTestWithPrebuiltsOfCurrentApi = FixtureWithPrebuiltApis(map[string][]string{
132	"current": {},
133	// Can't have current on its own as it adds a prebuilt_apis module but doesn't add any
134	// .txt files which causes the prebuilt_apis module to fail.
135	"30": {},
136})
137
138// FixtureWithPrebuiltApis creates a preparer that will define prebuilt api modules for the
139// specified releases and modules.
140//
141// The supplied map keys are the releases, e.g. current, 29, 30, etc. The values are a list of
142// modules for that release. Due to limitations in the prebuilt_apis module which this preparer
143// uses the set of releases must include at least one numbered release, i.e. it cannot just include
144// "current".
145//
146// This defines a file in the mock file system in a predefined location (prebuilts/sdk/Android.bp)
147// and so only one instance of this can be used in each fixture.
148func FixtureWithPrebuiltApis(release2Modules map[string][]string) android.FixturePreparer {
149	mockFS := android.MockFS{}
150	path := "prebuilts/sdk/Android.bp"
151
152	bp := fmt.Sprintf(`
153			prebuilt_apis {
154				name: "sdk",
155				api_dirs: ["%s"],
156				imports_sdk_version: "none",
157				imports_compile_dex: true,
158			}
159		`, strings.Join(android.SortedStringKeys(release2Modules), `", "`))
160
161	for release, modules := range release2Modules {
162		libs := append([]string{"android", "core-for-system-modules"}, modules...)
163		mockFS.Merge(prebuiltApisFilesForLibs([]string{release}, libs))
164	}
165	return android.GroupFixturePreparers(
166		android.FixtureAddTextFile(path, bp),
167		android.FixtureMergeMockFs(mockFS),
168	)
169}
170
171func prebuiltApisFilesForLibs(apiLevels []string, sdkLibs []string) map[string][]byte {
172	fs := make(map[string][]byte)
173	for _, level := range apiLevels {
174		for _, lib := range sdkLibs {
175			for _, scope := range []string{"public", "system", "module-lib", "system-server", "test"} {
176				fs[fmt.Sprintf("prebuilts/sdk/%s/%s/%s.jar", level, scope, lib)] = nil
177				// No finalized API files for "current"
178				if level != "current" {
179					fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s.txt", level, scope, lib)] = nil
180					fs[fmt.Sprintf("prebuilts/sdk/%s/%s/api/%s-removed.txt", level, scope, lib)] = nil
181				}
182			}
183		}
184		fs[fmt.Sprintf("prebuilts/sdk/%s/public/framework.aidl", level)] = nil
185	}
186	return fs
187}
188
189// FixtureConfigureBootJars configures the boot jars in both the dexpreopt.GlobalConfig and
190// Config.productVariables structs. As a side effect that enables dexpreopt.
191func FixtureConfigureBootJars(bootJars ...string) android.FixturePreparer {
192	artBootJars := []string{}
193	for _, j := range bootJars {
194		artApex := false
195		for _, artApexName := range artApexNames {
196			if strings.HasPrefix(j, artApexName+":") {
197				artApex = true
198				break
199			}
200		}
201		if artApex {
202			artBootJars = append(artBootJars, j)
203		}
204	}
205	return android.GroupFixturePreparers(
206		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
207			variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
208		}),
209		dexpreopt.FixtureSetBootJars(bootJars...),
210		dexpreopt.FixtureSetArtBootJars(artBootJars...),
211
212		// Add a fake dex2oatd module.
213		dexpreopt.PrepareForTestWithFakeDex2oatd,
214	)
215}
216
217// FixtureConfigureUpdatableBootJars configures the updatable boot jars in both the
218// dexpreopt.GlobalConfig and Config.productVariables structs. As a side effect that enables
219// dexpreopt.
220func FixtureConfigureUpdatableBootJars(bootJars ...string) android.FixturePreparer {
221	return android.GroupFixturePreparers(
222		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
223			variables.UpdatableBootJars = android.CreateTestConfiguredJarList(bootJars)
224		}),
225		dexpreopt.FixtureSetUpdatableBootJars(bootJars...),
226
227		// Add a fake dex2oatd module.
228		dexpreopt.PrepareForTestWithFakeDex2oatd,
229	)
230}
231
232// registerRequiredBuildComponentsForTest registers the build components used by
233// PrepareForTestWithJavaDefaultModules.
234//
235// As functionality is moved out of here into separate FixturePreparer instances they should also
236// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test
237// fixtures.
238func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
239	RegisterAARBuildComponents(ctx)
240	RegisterAppBuildComponents(ctx)
241	RegisterAppImportBuildComponents(ctx)
242	RegisterAppSetBuildComponents(ctx)
243	registerBootclasspathBuildComponents(ctx)
244	registerBootclasspathFragmentBuildComponents(ctx)
245	RegisterDexpreoptBootJarsComponents(ctx)
246	RegisterDocsBuildComponents(ctx)
247	RegisterGenRuleBuildComponents(ctx)
248	registerJavaBuildComponents(ctx)
249	registerPlatformBootclasspathBuildComponents(ctx)
250	RegisterPrebuiltApisBuildComponents(ctx)
251	RegisterRuntimeResourceOverlayBuildComponents(ctx)
252	RegisterSdkLibraryBuildComponents(ctx)
253	RegisterStubsBuildComponents(ctx)
254	RegisterSystemModulesBuildComponents(ctx)
255	registerSystemserverClasspathBuildComponents(ctx)
256	registerLintBuildComponents(ctx)
257}
258
259// gatherRequiredDepsForTest gathers the module definitions used by
260// PrepareForTestWithJavaDefaultModules.
261//
262// As functionality is moved out of here into separate FixturePreparer instances they should also
263// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test
264// fixtures.
265func gatherRequiredDepsForTest() string {
266	var bp string
267
268	extraModules := []string{
269		"core-lambda-stubs",
270		"ext",
271		"android_stubs_current",
272		"android_system_stubs_current",
273		"android_test_stubs_current",
274		"android_module_lib_stubs_current",
275		"android_system_server_stubs_current",
276		"core.current.stubs",
277		"legacy.core.platform.api.stubs",
278		"stable.core.platform.api.stubs",
279		"kotlin-stdlib",
280		"kotlin-stdlib-jdk7",
281		"kotlin-stdlib-jdk8",
282		"kotlin-annotations",
283	}
284
285	for _, extra := range extraModules {
286		bp += fmt.Sprintf(`
287			java_library {
288				name: "%s",
289				srcs: ["a.java"],
290				sdk_version: "none",
291				system_modules: "stable-core-platform-api-stubs-system-modules",
292				compile_dex: true,
293			}
294		`, extra)
295	}
296
297	bp += `
298		java_library {
299			name: "framework",
300			srcs: ["a.java"],
301			sdk_version: "none",
302			system_modules: "stable-core-platform-api-stubs-system-modules",
303			aidl: {
304				export_include_dirs: ["framework/aidl"],
305			},
306		}
307
308		android_app {
309			name: "framework-res",
310			sdk_version: "core_platform",
311		}`
312
313	systemModules := []string{
314		"core-current-stubs-system-modules",
315		"core-module-lib-stubs-system-modules",
316		"legacy-core-platform-api-stubs-system-modules",
317		"stable-core-platform-api-stubs-system-modules",
318	}
319
320	for _, extra := range systemModules {
321		bp += fmt.Sprintf(`
322			java_system_modules {
323				name: "%[1]s",
324				libs: ["%[1]s-lib"],
325			}
326			java_library {
327				name: "%[1]s-lib",
328				sdk_version: "none",
329				system_modules: "none",
330			}
331		`, extra)
332	}
333
334	// Make sure that the dex_bootjars singleton module is instantiated for the tests.
335	bp += `
336		dex_bootjars {
337			name: "dex_bootjars",
338		}
339`
340
341	return bp
342}
343
344func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
345	t.Helper()
346	module := ctx.ModuleForTests(name, variant).Module()
347	deps := []string{}
348	ctx.VisitDirectDeps(module, func(m blueprint.Module) {
349		deps = append(deps, m.Name())
350	})
351	sort.Strings(deps)
352
353	if actual := deps; !reflect.DeepEqual(expected, actual) {
354		t.Errorf("expected %#q, found %#q", expected, actual)
355	}
356}
357
358// CheckPlatformBootclasspathModules returns the apex:module pair for the modules depended upon by
359// the platform-bootclasspath module.
360func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
361	t.Helper()
362	platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
363	pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules)
364	android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs)
365}
366
367// ApexNamePairsFromModules returns the apex:module pair for the supplied modules.
368func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module) []string {
369	pairs := []string{}
370	for _, module := range modules {
371		pairs = append(pairs, apexNamePairFromModule(ctx, module))
372	}
373	return pairs
374}
375
376func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string {
377	name := module.Name()
378	var apex string
379	apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
380	if apexInfo.IsForPlatform() {
381		apex = "platform"
382	} else {
383		apex = apexInfo.InApexVariants[0]
384	}
385
386	return fmt.Sprintf("%s:%s", apex, name)
387}
388
389// CheckPlatformBootclasspathFragments returns the apex:module pair for the fragments depended upon
390// by the platform-bootclasspath module.
391func CheckPlatformBootclasspathFragments(t *testing.T, result *android.TestResult, name string, expected []string) {
392	t.Helper()
393	platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
394	pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.fragments)
395	android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs)
396}
397
398func CheckHiddenAPIRuleInputs(t *testing.T, message string, expected string, hiddenAPIRule android.TestingBuildParams) {
399	t.Helper()
400	inputs := android.Paths{}
401	if hiddenAPIRule.Input != nil {
402		inputs = append(inputs, hiddenAPIRule.Input)
403	}
404	inputs = append(inputs, hiddenAPIRule.Inputs...)
405	inputs = append(inputs, hiddenAPIRule.Implicits...)
406	inputs = android.SortedUniquePaths(inputs)
407	actual := strings.TrimSpace(strings.Join(inputs.RelativeToTop().Strings(), "\n"))
408	re := regexp.MustCompile(`\n\s+`)
409	expected = strings.TrimSpace(re.ReplaceAllString(expected, "\n"))
410	if actual != expected {
411		t.Errorf("Expected hiddenapi rule inputs - %s:\n%s\nactual inputs:\n%s", message, expected, actual)
412	}
413}
414
415// Check that the merged file create by platform_compat_config_singleton has the correct inputs.
416func CheckMergedCompatConfigInputs(t *testing.T, result *android.TestResult, message string, expectedPaths ...string) {
417	sourceGlobalCompatConfig := result.SingletonForTests("platform_compat_config_singleton")
418	allOutputs := sourceGlobalCompatConfig.AllOutputs()
419	android.AssertIntEquals(t, message+": output len", 1, len(allOutputs))
420	output := sourceGlobalCompatConfig.Output(allOutputs[0])
421	android.AssertPathsRelativeToTopEquals(t, message+": inputs", expectedPaths, output.Implicits)
422}
423