xref: /aosp_15_r20/build/soong/java/platform_bootclasspath_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright (C) 2021 The Android Open Source Project
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	"testing"
19
20	"android/soong/android"
21)
22
23// Contains some simple tests for platform_bootclasspath.
24
25var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers(
26	PrepareForTestWithJavaDefaultModules,
27)
28
29func TestPlatformBootclasspath(t *testing.T) {
30	preparer := android.GroupFixturePreparers(
31		prepareForTestWithPlatformBootclasspath,
32		FixtureConfigureBootJars("platform:foo", "system_ext:bar"),
33		android.FixtureWithRootAndroidBp(`
34			platform_bootclasspath {
35				name: "platform-bootclasspath",
36			}
37
38			java_library {
39				name: "bar",
40				srcs: ["a.java"],
41				system_modules: "none",
42				sdk_version: "none",
43				compile_dex: true,
44				system_ext_specific: true,
45			}
46		`),
47	)
48
49	var addSourceBootclassPathModule = android.FixtureAddTextFile("source/Android.bp", `
50		java_library {
51			name: "foo",
52			host_supported: true, // verify that b/232106778 is fixed
53			srcs: ["a.java"],
54			system_modules: "none",
55			sdk_version: "none",
56			compile_dex: true,
57		}
58	`)
59
60	var addPrebuiltBootclassPathModule = android.FixtureAddTextFile("prebuilt/Android.bp", `
61		java_import {
62			name: "foo",
63			jars: ["a.jar"],
64			compile_dex: true,
65			prefer: false,
66		}
67	`)
68
69	var addPrebuiltPreferredBootclassPathModule = android.FixtureAddTextFile("prebuilt/Android.bp", `
70		java_import {
71			name: "foo",
72			jars: ["a.jar"],
73			compile_dex: true,
74			prefer: true,
75		}
76	`)
77
78	t.Run("missing", func(t *testing.T) {
79		preparer.
80			ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"platform-bootclasspath" depends on undefined module "foo"`)).
81			RunTest(t)
82	})
83
84	fooSourceSrc := "source/a.java"
85	barSrc := "a.java"
86
87	checkSrcJarInputs := func(t *testing.T, result *android.TestResult, name string, expected []string) {
88		t.Helper()
89		srcjar := result.ModuleForTests(name, "android_common").Output(name + "-transitive.srcjar")
90		android.AssertStringDoesContain(t, "srcjar arg", srcjar.Args["jarArgs"], "-srcjar")
91		android.AssertArrayString(t, "srcjar inputs", expected, srcjar.Implicits.Strings())
92	}
93	t.Run("source", func(t *testing.T) {
94		result := android.GroupFixturePreparers(
95			preparer,
96			addSourceBootclassPathModule,
97		).RunTest(t)
98
99		CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{
100			"platform:foo",
101			"platform:bar",
102		})
103		checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
104			fooSourceSrc,
105			barSrc,
106		})
107	})
108
109	t.Run("prebuilt", func(t *testing.T) {
110		result := android.GroupFixturePreparers(
111			preparer,
112			addPrebuiltBootclassPathModule,
113		).RunTest(t)
114
115		CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{
116			"platform:prebuilt_foo",
117			"platform:bar",
118		})
119		checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
120			// TODO(b/151360309): This should also have the srcs for prebuilt_foo
121			barSrc,
122		})
123	})
124
125	t.Run("source+prebuilt - source preferred", func(t *testing.T) {
126		result := android.GroupFixturePreparers(
127			preparer,
128			addSourceBootclassPathModule,
129			addPrebuiltBootclassPathModule,
130		).RunTest(t)
131
132		CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{
133			"platform:foo",
134			"platform:bar",
135		})
136		checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
137			fooSourceSrc,
138			barSrc,
139		})
140	})
141
142	t.Run("source+prebuilt - prebuilt preferred", func(t *testing.T) {
143		result := android.GroupFixturePreparers(
144			preparer,
145			addSourceBootclassPathModule,
146			addPrebuiltPreferredBootclassPathModule,
147		).RunTest(t)
148
149		CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{
150			"platform:prebuilt_foo",
151			"platform:bar",
152		})
153		checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
154			// TODO(b/151360309): This should also have the srcs for prebuilt_foo
155			barSrc,
156		})
157	})
158
159	t.Run("dex import", func(t *testing.T) {
160		result := android.GroupFixturePreparers(
161			preparer,
162			android.FixtureAddTextFile("deximport/Android.bp", `
163				dex_import {
164					name: "foo",
165					jars: ["a.jar"],
166				}
167			`),
168		).RunTest(t)
169
170		CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{
171			"platform:prebuilt_foo",
172			"platform:bar",
173		})
174		checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
175			// TODO(b/151360309): This should also have the srcs for prebuilt_foo
176			barSrc,
177		})
178	})
179}
180
181func TestPlatformBootclasspathVariant(t *testing.T) {
182	result := android.GroupFixturePreparers(
183		prepareForTestWithPlatformBootclasspath,
184		android.FixtureWithRootAndroidBp(`
185			platform_bootclasspath {
186				name: "platform-bootclasspath",
187			}
188		`),
189	).RunTest(t)
190
191	variants := result.ModuleVariantsForTests("platform-bootclasspath")
192	android.AssertIntEquals(t, "expect 1 variant", 1, len(variants))
193}
194
195func TestPlatformBootclasspath_ClasspathFragmentPaths(t *testing.T) {
196	result := android.GroupFixturePreparers(
197		prepareForTestWithPlatformBootclasspath,
198		android.FixtureWithRootAndroidBp(`
199			platform_bootclasspath {
200				name: "platform-bootclasspath",
201			}
202		`),
203	).RunTest(t)
204
205	p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
206	android.AssertStringEquals(t, "output filepath", "bootclasspath.pb", p.ClasspathFragmentBase.outputFilepath.Base())
207	android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath)
208}
209
210func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) {
211	preparer := android.GroupFixturePreparers(
212		prepareForTestWithPlatformBootclasspath,
213		android.FixtureWithRootAndroidBp(`
214			platform_bootclasspath {
215				name: "platform-bootclasspath",
216			}
217		`),
218	)
219
220	t.Run("AndroidMkEntries", func(t *testing.T) {
221		result := preparer.RunTest(t)
222
223		p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
224
225		entries := android.AndroidMkEntriesForTest(t, result.TestContext, p)
226		android.AssertIntEquals(t, "AndroidMkEntries count", 2, len(entries))
227	})
228
229	t.Run("hiddenapi-flags-entry", func(t *testing.T) {
230		result := preparer.RunTest(t)
231
232		p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
233
234		entries := android.AndroidMkEntriesForTest(t, result.TestContext, p)
235		got := entries[0].OutputFile
236		android.AssertBoolEquals(t, "valid output path", true, got.Valid())
237		android.AssertSame(t, "output filepath", p.hiddenAPIFlagsCSV, got.Path())
238	})
239
240	t.Run("classpath-fragment-entry", func(t *testing.T) {
241		result := preparer.RunTest(t)
242
243		want := map[string][]string{
244			"LOCAL_MODULE":                {"platform-bootclasspath"},
245			"LOCAL_MODULE_CLASS":          {"ETC"},
246			"LOCAL_INSTALLED_MODULE_STEM": {"bootclasspath.pb"},
247			// Output and Install paths are tested separately in TestPlatformBootclasspath_ClasspathFragmentPaths
248		}
249
250		p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
251
252		entries := android.AndroidMkEntriesForTest(t, result.TestContext, p)
253		got := entries[1]
254		for k, expectedValue := range want {
255			if value, ok := got.EntryMap[k]; ok {
256				android.AssertDeepEquals(t, k, expectedValue, value)
257			} else {
258				t.Errorf("No %s defined, saw %q", k, got.EntryMap)
259			}
260		}
261	})
262}
263
264func TestPlatformBootclasspath_Dist(t *testing.T) {
265	result := android.GroupFixturePreparers(
266		prepareForTestWithPlatformBootclasspath,
267		FixtureConfigureBootJars("platform:foo", "platform:bar"),
268		android.PrepareForTestWithAndroidMk,
269		android.FixtureWithRootAndroidBp(`
270			platform_bootclasspath {
271				name: "platform-bootclasspath",
272				dists: [
273					{
274						targets: ["droidcore"],
275						tag: "hiddenapi-flags.csv",
276					},
277				],
278			}
279
280			java_library {
281				name: "bar",
282				srcs: ["a.java"],
283				system_modules: "none",
284				sdk_version: "none",
285				compile_dex: true,
286			}
287
288			java_library {
289				name: "foo",
290				srcs: ["a.java"],
291				system_modules: "none",
292				sdk_version: "none",
293				compile_dex: true,
294			}
295		`),
296	).RunTest(t)
297
298	platformBootclasspath := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
299	entries := android.AndroidMkEntriesForTest(t, result.TestContext, platformBootclasspath)
300	goals := entries[0].GetDistForGoals(platformBootclasspath)
301	android.AssertStringEquals(t, "platform dist goals phony", ".PHONY: droidcore", goals[0])
302	android.AssertStringDoesContain(t, "platform dist goals meta check", goals[1], "$(if $(strip $(ALL_TARGETS.")
303	android.AssertStringDoesContain(t, "platform dist goals meta assign", goals[1], "),,$(eval ALL_TARGETS.")
304	android.AssertStringEquals(t, "platform dist goals call", "$(call dist-for-goals,droidcore,out/soong/hiddenapi/hiddenapi-flags.csv:hiddenapi-flags.csv)", android.StringRelativeToTop(result.Config, goals[2]))
305}
306
307func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) {
308	result := android.GroupFixturePreparers(
309		hiddenApiFixtureFactory,
310		PrepareForTestWithJavaSdkLibraryFiles,
311		FixtureWithLastReleaseApis("bar"),
312		FixtureConfigureBootJars("platform:foo", "platform:bar"),
313	).RunTestWithBp(t, `
314		java_library {
315			name: "foo",
316			srcs: ["a.java"],
317			compile_dex: true,
318
319			hiddenapi_additional_annotations: [
320				"foo-hiddenapi-annotations",
321			],
322		}
323
324		java_library {
325			name: "foo-hiddenapi-annotations",
326			srcs: ["a.java"],
327			compile_dex: true,
328		}
329
330		java_import {
331			name: "foo",
332			jars: ["a.jar"],
333			compile_dex: true,
334			prefer: false,
335		}
336
337		java_sdk_library {
338			name: "bar",
339			srcs: ["a.java"],
340			compile_dex: true,
341		}
342
343		platform_bootclasspath {
344			name: "myplatform-bootclasspath",
345		}
346	`)
347
348	// Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that
349	// creates the index.csv file.
350	platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common")
351
352	var rule android.TestingBuildParams
353
354	// All the intermediate rules use the same inputs.
355	expectedIntermediateInputs := `
356		out/soong/.intermediates/bar.impl/android_common/javac/bar.jar
357		out/soong/.intermediates/foo-hiddenapi-annotations/android_common/javac/foo-hiddenapi-annotations.jar
358		out/soong/.intermediates/foo/android_common/javac/foo.jar
359	`
360
361	// Check flags output.
362	rule = platformBootclasspath.Output("hiddenapi-monolithic/annotation-flags-from-classes.csv")
363	CheckHiddenAPIRuleInputs(t, "intermediate flags", expectedIntermediateInputs, rule)
364
365	rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-flags.csv")
366	CheckHiddenAPIRuleInputs(t, "monolithic flags", `
367		out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/annotation-flags-from-classes.csv
368		out/soong/hiddenapi/hiddenapi-stub-flags.txt
369	`, rule)
370
371	// Check metadata output.
372	rule = platformBootclasspath.Output("hiddenapi-monolithic/metadata-from-classes.csv")
373	CheckHiddenAPIRuleInputs(t, "intermediate metadata", expectedIntermediateInputs, rule)
374
375	rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-unsupported.csv")
376	CheckHiddenAPIRuleInputs(t, "monolithic metadata", `
377		out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/metadata-from-classes.csv
378	`, rule)
379
380	// Check index output.
381	rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv")
382	CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule)
383
384	rule = platformBootclasspath.Output("out/soong/hiddenapi/hiddenapi-index.csv")
385	CheckHiddenAPIRuleInputs(t, "monolithic index", `
386		out/soong/.intermediates/myplatform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
387	`, rule)
388}
389