• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	"strings"
19	"testing"
20
21	"android/soong/android"
22	"android/soong/dexpreopt"
23)
24
25// Contains some simple tests for bootclasspath_fragment logic, additional tests can be found in
26// apex/bootclasspath_fragment_test.go as the ART boot image requires modules from the ART apex.
27
28var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers(
29	PrepareForTestWithJavaDefaultModules,
30	dexpreopt.PrepareForTestByEnablingDexpreopt,
31)
32
33func TestBootclasspathFragment_UnknownImageName(t *testing.T) {
34	prepareForTestWithBootclasspathFragment.
35		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
36			`\Qimage_name: unknown image name "unknown", expected "art"\E`)).
37		RunTestWithBp(t, `
38			bootclasspath_fragment {
39				name: "unknown-bootclasspath-fragment",
40				image_name: "unknown",
41				contents: ["foo"],
42			}
43		`)
44}
45
46func TestPrebuiltBootclasspathFragment_UnknownImageName(t *testing.T) {
47	prepareForTestWithBootclasspathFragment.
48		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
49			`\Qimage_name: unknown image name "unknown", expected "art"\E`)).
50		RunTestWithBp(t, `
51			prebuilt_bootclasspath_fragment {
52				name: "unknown-bootclasspath-fragment",
53				image_name: "unknown",
54				contents: ["foo"],
55			}
56		`)
57}
58
59func TestBootclasspathFragmentInconsistentArtConfiguration_Platform(t *testing.T) {
60	android.GroupFixturePreparers(
61		prepareForTestWithBootclasspathFragment,
62		dexpreopt.FixtureSetArtBootJars("platform:foo", "apex:bar"),
63	).
64		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
65			`\QArtApexJars is invalid as it requests a platform variant of "foo"\E`)).
66		RunTestWithBp(t, `
67			bootclasspath_fragment {
68				name: "bootclasspath-fragment",
69				image_name: "art",
70				contents: ["foo", "bar"],
71				apex_available: [
72					"apex",
73				],
74			}
75		`)
76}
77
78func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testing.T) {
79	android.GroupFixturePreparers(
80		prepareForTestWithBootclasspathFragment,
81		dexpreopt.FixtureSetArtBootJars("apex1:foo", "apex2:bar"),
82	).
83		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
84			`\QArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex "apex1" and "apex2"\E`)).
85		RunTestWithBp(t, `
86			bootclasspath_fragment {
87				name: "bootclasspath-fragment",
88				image_name: "art",
89				contents: ["foo", "bar"],
90				apex_available: [
91					"apex1",
92					"apex2",
93				],
94			}
95		`)
96}
97
98func TestBootclasspathFragment_Coverage(t *testing.T) {
99	prepareWithBp := android.FixtureWithRootAndroidBp(`
100		bootclasspath_fragment {
101			name: "myfragment",
102			contents: [
103				"mybootlib",
104			],
105			api: {
106				stub_libs: [
107					"mysdklibrary",
108				],
109			},
110			coverage: {
111				contents: [
112					"coveragelib",
113				],
114				api: {
115					stub_libs: [
116						"mycoveragestubs",
117					],
118				},
119			},
120			hidden_api: {
121				split_packages: ["*"],
122			},
123		}
124
125		java_library {
126			name: "mybootlib",
127			srcs: ["Test.java"],
128			system_modules: "none",
129			sdk_version: "none",
130			compile_dex: true,
131		}
132
133		java_library {
134			name: "coveragelib",
135			srcs: ["Test.java"],
136			system_modules: "none",
137			sdk_version: "none",
138			compile_dex: true,
139		}
140
141		java_sdk_library {
142			name: "mysdklibrary",
143			srcs: ["Test.java"],
144			compile_dex: true,
145			public: {enabled: true},
146			system: {enabled: true},
147		}
148
149		java_sdk_library {
150			name: "mycoveragestubs",
151			srcs: ["Test.java"],
152			compile_dex: true,
153			public: {enabled: true},
154		}
155	`)
156
157	checkContents := func(t *testing.T, result *android.TestResult, expected ...string) {
158		module := result.Module("myfragment", "android_common").(*BootclasspathFragmentModule)
159		android.AssertArrayString(t, "contents property", expected, module.properties.Contents)
160	}
161
162	preparer := android.GroupFixturePreparers(
163		prepareForTestWithBootclasspathFragment,
164		PrepareForTestWithJavaSdkLibraryFiles,
165		FixtureWithLastReleaseApis("mysdklibrary", "mycoveragestubs"),
166		FixtureConfigureApexBootJars("someapex:mybootlib"),
167		prepareWithBp,
168	)
169
170	t.Run("without coverage", func(t *testing.T) {
171		result := preparer.RunTest(t)
172		checkContents(t, result, "mybootlib")
173	})
174
175	t.Run("with coverage", func(t *testing.T) {
176		result := android.GroupFixturePreparers(
177			prepareForTestWithFrameworkJacocoInstrumentation,
178			preparer,
179		).RunTest(t)
180		checkContents(t, result, "mybootlib", "coveragelib")
181	})
182}
183
184func TestBootclasspathFragment_StubLibs(t *testing.T) {
185	result := android.GroupFixturePreparers(
186		prepareForTestWithBootclasspathFragment,
187		PrepareForTestWithJavaSdkLibraryFiles,
188		FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
189		FixtureConfigureApexBootJars("someapex:mysdklibrary"),
190	).RunTestWithBp(t, `
191		bootclasspath_fragment {
192			name: "myfragment",
193			contents: ["mysdklibrary"],
194			api: {
195				stub_libs: [
196					"mystublib",
197					"myothersdklibrary",
198				],
199			},
200			core_platform_api: {
201				stub_libs: ["mycoreplatform.stubs"],
202			},
203			hidden_api: {
204				split_packages: ["*"],
205			},
206		}
207
208		java_library {
209			name: "mystublib",
210			srcs: ["Test.java"],
211			system_modules: "none",
212			sdk_version: "none",
213			compile_dex: true,
214		}
215
216		java_sdk_library {
217			name: "mysdklibrary",
218			srcs: ["a.java"],
219			shared_library: false,
220			public: {enabled: true},
221			system: {enabled: true},
222		}
223
224		java_sdk_library {
225			name: "myothersdklibrary",
226			srcs: ["a.java"],
227			shared_library: false,
228			public: {enabled: true},
229		}
230
231		java_sdk_library {
232			name: "mycoreplatform",
233			srcs: ["a.java"],
234			shared_library: false,
235			public: {enabled: true},
236		}
237	`)
238
239	fragment := result.Module("myfragment", "android_common")
240	info := result.ModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
241
242	stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
243
244	// Stubs jars for mysdklibrary
245	publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar"
246	systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.system/android_common/dex/mysdklibrary.stubs.system.jar"
247
248	// Stubs jars for myothersdklibrary
249	otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs/android_common/dex/myothersdklibrary.stubs.jar"
250
251	// Check that SdkPublic uses public stubs for all sdk libraries.
252	android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(PublicHiddenAPIScope))
253
254	// Check that SdkSystem uses system stubs for mysdklibrary and public stubs for myothersdklibrary
255	// as it does not provide system stubs.
256	android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(SystemHiddenAPIScope))
257
258	// Check that SdkTest also uses system stubs for mysdklibrary as it does not provide test stubs
259	// and public stubs for myothersdklibrary as it does not provide test stubs either.
260	android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(TestHiddenAPIScope))
261
262	// Check that SdkCorePlatform uses public stubs from the mycoreplatform library.
263	corePlatformStubsJar := "out/soong/.intermediates/mycoreplatform.stubs/android_common/dex/mycoreplatform.stubs.jar"
264	android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(CorePlatformHiddenAPIScope))
265
266	// Check the widest stubs.. The list contains the widest stub dex jar provided by each module.
267	expectedWidestPaths := []string{
268		// mycoreplatform's widest API is core platform.
269		corePlatformStubsJar,
270
271		// myothersdklibrary's widest API is public.
272		otherPublicStubsJar,
273
274		// sdklibrary's widest API is system.
275		systemStubsJar,
276
277		// mystublib's only provides one API and so it must be the widest.
278		stubsJar,
279	}
280
281	android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope())
282}
283
284func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
285	result := android.GroupFixturePreparers(
286		prepareForTestWithBootclasspathFragment,
287		PrepareForTestWithJavaSdkLibraryFiles,
288		FixtureWithLastReleaseApis("mysdklibrary", "mynewlibrary"),
289		FixtureConfigureApexBootJars("myapex:mybootlib", "myapex:mynewlibrary"),
290		android.MockFS{
291			"my-blocked.txt":                   nil,
292			"my-max-target-o-low-priority.txt": nil,
293			"my-max-target-p.txt":              nil,
294			"my-max-target-q.txt":              nil,
295			"my-max-target-r-low-priority.txt": nil,
296			"my-removed.txt":                   nil,
297			"my-unsupported-packages.txt":      nil,
298			"my-unsupported.txt":               nil,
299			"my-new-max-target-q.txt":          nil,
300		}.AddToFixture(),
301		android.FixtureWithRootAndroidBp(`
302			bootclasspath_fragment {
303				name: "mybootclasspathfragment",
304				apex_available: ["myapex"],
305				contents: ["mybootlib", "mynewlibrary"],
306				hidden_api: {
307					unsupported: [
308							"my-unsupported.txt",
309					],
310					removed: [
311							"my-removed.txt",
312					],
313					max_target_r_low_priority: [
314							"my-max-target-r-low-priority.txt",
315					],
316					max_target_q: [
317							"my-max-target-q.txt",
318					],
319					max_target_p: [
320							"my-max-target-p.txt",
321					],
322					max_target_o_low_priority: [
323							"my-max-target-o-low-priority.txt",
324					],
325					blocked: [
326							"my-blocked.txt",
327					],
328					unsupported_packages: [
329							"my-unsupported-packages.txt",
330					],
331					split_packages: ["sdklibrary"],
332					package_prefixes: ["sdklibrary.all.mine"],
333					single_packages: ["sdklibrary.mine"],
334				},
335			}
336
337			java_library {
338				name: "mybootlib",
339				apex_available: ["myapex"],
340				srcs: ["Test.java"],
341				system_modules: "none",
342				sdk_version: "none",
343				min_sdk_version: "1",
344				compile_dex: true,
345				permitted_packages: ["mybootlib"],
346			}
347
348			java_sdk_library {
349				name: "mynewlibrary",
350				apex_available: ["myapex"],
351				srcs: ["Test.java"],
352				min_sdk_version: "10",
353				compile_dex: true,
354				public: {enabled: true},
355				permitted_packages: ["mysdklibrary"],
356				hidden_api: {
357					max_target_q: [
358							"my-new-max-target-q.txt",
359					],
360					split_packages: ["sdklibrary", "newlibrary"],
361					package_prefixes: ["newlibrary.all.mine"],
362					single_packages: ["newlibrary.mine"],
363				},
364			}
365		`),
366	).RunTest(t)
367
368	// Make sure that the library exports hidden API properties for use by the bootclasspath_fragment.
369	library := result.Module("mynewlibrary", "android_common")
370	info := result.ModuleProvider(library, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
371	android.AssertArrayString(t, "split packages", []string{"sdklibrary", "newlibrary"}, info.SplitPackages)
372	android.AssertArrayString(t, "package prefixes", []string{"newlibrary.all.mine"}, info.PackagePrefixes)
373	android.AssertArrayString(t, "single packages", []string{"newlibrary.mine"}, info.SinglePackages)
374	for _, c := range HiddenAPIFlagFileCategories {
375		expectedMaxTargetQPaths := []string(nil)
376		if c.PropertyName == "max_target_q" {
377			expectedMaxTargetQPaths = []string{"my-new-max-target-q.txt"}
378		}
379		android.AssertPathsRelativeToTopEquals(t, c.PropertyName, expectedMaxTargetQPaths, info.FlagFilesByCategory[c])
380	}
381
382	// Make sure that the signature-patterns.csv is passed all the appropriate package properties
383	// from the bootclasspath_fragment and its contents.
384	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common")
385	rule := fragment.Output("modular-hiddenapi/signature-patterns.csv")
386	expectedCommand := strings.Join([]string{
387		"--split-package newlibrary",
388		"--split-package sdklibrary",
389		"--package-prefix newlibrary.all.mine",
390		"--package-prefix sdklibrary.all.mine",
391		"--single-package newlibrary.mine",
392		"--single-package sdklibrary",
393	}, " ")
394	android.AssertStringDoesContain(t, "signature patterns command", rule.RuleParams.Command, expectedCommand)
395}
396
397func TestBootclasspathFragment_Test(t *testing.T) {
398	result := android.GroupFixturePreparers(
399		prepareForTestWithBootclasspathFragment,
400		PrepareForTestWithJavaSdkLibraryFiles,
401		FixtureWithLastReleaseApis("mysdklibrary"),
402	).RunTestWithBp(t, `
403		bootclasspath_fragment {
404			name: "myfragment",
405			contents: ["mysdklibrary"],
406			hidden_api: {
407				split_packages: [],
408			},
409		}
410
411		bootclasspath_fragment_test {
412			name: "a_test_fragment",
413			contents: ["mysdklibrary"],
414			hidden_api: {
415				split_packages: [],
416			},
417		}
418
419
420		java_sdk_library {
421			name: "mysdklibrary",
422			srcs: ["a.java"],
423			shared_library: false,
424			public: {enabled: true},
425			system: {enabled: true},
426		}
427	`)
428
429	fragment := result.Module("myfragment", "android_common").(*BootclasspathFragmentModule)
430	android.AssertBoolEquals(t, "not a test fragment", false, fragment.isTestFragment())
431
432	fragment = result.Module("a_test_fragment", "android_common").(*BootclasspathFragmentModule)
433	android.AssertBoolEquals(t, "is a test fragment by type", true, fragment.isTestFragment())
434}
435