• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 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	"path/filepath"
20	"testing"
21
22	"android/soong/android"
23
24	"github.com/google/blueprint/proptools"
25)
26
27// TODO(b/177892522): Move these tests into a more appropriate place.
28
29func fixtureSetPrebuiltHiddenApiDirProductVariable(prebuiltHiddenApiDir *string) android.FixturePreparer {
30	return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
31		variables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir
32	})
33}
34
35var prepareForTestWithDefaultPlatformBootclasspath = android.FixtureAddTextFile("frameworks/base/boot/Android.bp", `
36	platform_bootclasspath {
37		name: "platform-bootclasspath",
38	}
39`)
40
41var hiddenApiFixtureFactory = android.GroupFixturePreparers(
42	PrepareForTestWithJavaDefaultModules,
43	PrepareForTestWithHiddenApiBuildComponents,
44)
45
46func TestHiddenAPISingleton(t *testing.T) {
47	t.Parallel()
48	result := android.GroupFixturePreparers(
49		hiddenApiFixtureFactory,
50		FixtureConfigureBootJars("platform:foo"),
51		prepareForTestWithDefaultPlatformBootclasspath,
52	).RunTestWithBp(t, `
53		java_library {
54			name: "foo",
55			srcs: ["a.java"],
56			compile_dex: true,
57		}
58	`)
59
60	hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
61	hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
62	want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
63	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
64}
65
66func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) {
67	t.Parallel()
68	expectedErrorMessage := "module prebuilt_foo{os:android,arch:common} does not provide a dex jar"
69
70	android.GroupFixturePreparers(
71		hiddenApiFixtureFactory,
72		FixtureConfigureBootJars("platform:foo"),
73		prepareForTestWithDefaultPlatformBootclasspath,
74	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorMessage)).
75		RunTestWithBp(t, `
76		java_library {
77			name: "foo",
78			srcs: ["a.java"],
79			compile_dex: true,
80		}
81
82		java_import {
83			name: "foo",
84			jars: ["a.jar"],
85			prefer: true,
86		}
87	`)
88}
89
90func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
91	t.Parallel()
92	result := android.GroupFixturePreparers(
93		hiddenApiFixtureFactory,
94		FixtureConfigureBootJars("platform:foo"),
95		prepareForTestWithDefaultPlatformBootclasspath,
96	).RunTestWithBp(t, `
97		java_import {
98			name: "foo",
99			jars: ["a.jar"],
100			compile_dex: true,
101	}
102	`)
103
104	hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
105	hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
106	want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
107	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
108}
109
110func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
111	t.Parallel()
112	result := android.GroupFixturePreparers(
113		hiddenApiFixtureFactory,
114		FixtureConfigureBootJars("platform:foo"),
115		prepareForTestWithDefaultPlatformBootclasspath,
116	).RunTestWithBp(t, `
117		java_library {
118			name: "foo",
119			srcs: ["a.java"],
120			compile_dex: true,
121		}
122
123		java_import {
124			name: "foo",
125			jars: ["a.jar"],
126			compile_dex: true,
127			prefer: false,
128		}
129	`)
130
131	hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
132	hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
133	fromSourceJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
134	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, fromSourceJarArg)
135
136	prebuiltJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/dex/foo.jar"
137	android.AssertStringDoesNotContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, prebuiltJarArg)
138}
139
140func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
141	t.Parallel()
142	result := android.GroupFixturePreparers(
143		hiddenApiFixtureFactory,
144		FixtureConfigureBootJars("platform:foo"),
145		prepareForTestWithDefaultPlatformBootclasspath,
146	).RunTestWithBp(t, `
147		java_library {
148			name: "foo",
149			srcs: ["a.java"],
150			compile_dex: true,
151		}
152
153		java_import {
154			name: "foo",
155			jars: ["a.jar"],
156			compile_dex: true,
157			prefer: true,
158		}
159	`)
160
161	hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
162	hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
163	prebuiltJarArg := "--boot-dex=out/soong/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
164	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, prebuiltJarArg)
165
166	fromSourceJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
167	android.AssertStringDoesNotContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, fromSourceJarArg)
168}
169
170func TestHiddenAPISingletonSdks(t *testing.T) {
171	t.Parallel()
172	testCases := []struct {
173		name             string
174		unbundledBuild   bool
175		publicStub       string
176		systemStub       string
177		testStub         string
178		corePlatformStub string
179
180		// Additional test preparer
181		preparer android.FixturePreparer
182	}{
183		{
184			name:             "testBundled",
185			unbundledBuild:   false,
186			publicStub:       "android_stubs_current_exportable",
187			systemStub:       "android_system_stubs_current_exportable",
188			testStub:         "android_test_stubs_current_exportable",
189			corePlatformStub: "legacy.core.platform.api.stubs.exportable",
190			preparer:         android.GroupFixturePreparers(),
191		}, {
192			name:             "testUnbundled",
193			unbundledBuild:   true,
194			publicStub:       "sdk_public_current_android",
195			systemStub:       "sdk_system_current_android",
196			testStub:         "sdk_test_current_android",
197			corePlatformStub: "legacy.core.platform.api.stubs.exportable",
198			preparer:         PrepareForTestWithPrebuiltsOfCurrentApi,
199		},
200	}
201	for _, tc := range testCases {
202		t.Run(tc.name, func(t *testing.T) {
203			result := android.GroupFixturePreparers(
204				hiddenApiFixtureFactory,
205				tc.preparer,
206				prepareForTestWithDefaultPlatformBootclasspath,
207				// Make sure that we have atleast one platform library so that we can check the monolithic hiddenapi
208				// file creation.
209				FixtureConfigureBootJars("platform:foo"),
210				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
211					variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild)
212				}),
213				android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
214			).RunTestWithBp(t, `
215		java_library {
216			name: "foo",
217			srcs: ["a.java"],
218			compile_dex: true,
219		}
220		`)
221
222			hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
223			hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
224			wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild)
225			android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantPublicStubs)
226
227			wantSystemStubs := "--system-stub-classpath=" + generateSdkDexPath(tc.systemStub, tc.unbundledBuild)
228			android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantSystemStubs)
229
230			wantTestStubs := "--test-stub-classpath=" + generateSdkDexPath(tc.testStub, tc.unbundledBuild)
231			android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantTestStubs)
232
233			wantCorePlatformStubs := "--core-platform-stub-classpath=" + generateDexPath(defaultJavaDir, tc.corePlatformStub)
234			android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantCorePlatformStubs)
235		})
236	}
237}
238
239func generateDexedPath(subDir, dex, module string) string {
240	return fmt.Sprintf("out/soong/.intermediates/%s/android_common/%s/%s.jar", subDir, dex, module)
241}
242
243func generateDexPath(moduleDir string, module string) string {
244	return generateDexedPath(filepath.Join(moduleDir, module), "dex", module)
245}
246
247func generateSdkDexPath(module string, unbundled bool) string {
248	if unbundled {
249		return generateDexedPath("prebuilts/sdk/"+module, "dex", module)
250	}
251	return generateDexPath(defaultJavaDir, module)
252}
253
254func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) {
255	t.Parallel()
256
257	// The idea behind this test is to ensure that when the build is
258	// confugured with a PrebuiltHiddenApiDir that the rules for the
259	// hiddenapi singleton copy the prebuilts to the typical output
260	// location, and then use that output location for the hiddenapi encode
261	// dex step.
262
263	// Where to find the prebuilt hiddenapi files:
264	prebuiltHiddenApiDir := "path/to/prebuilt/hiddenapi"
265
266	result := android.GroupFixturePreparers(
267		hiddenApiFixtureFactory,
268		FixtureConfigureBootJars("platform:foo"),
269		fixtureSetPrebuiltHiddenApiDirProductVariable(&prebuiltHiddenApiDir),
270	).RunTestWithBp(t, `
271		java_import {
272			name: "foo",
273			jars: ["a.jar"],
274			compile_dex: true,
275	}
276	`)
277
278	expectedCpInput := prebuiltHiddenApiDir + "/hiddenapi-flags.csv"
279	expectedCpOutput := "out/soong/hiddenapi/hiddenapi-flags.csv"
280	expectedFlagsCsv := "out/soong/hiddenapi/hiddenapi-flags.csv"
281
282	foo := result.ModuleForTests(t, "foo", "android_common")
283
284	hiddenAPI := result.SingletonForTests(t, "hiddenapi")
285	cpRule := hiddenAPI.Rule("Cp")
286	actualCpInput := cpRule.BuildParams.Input
287	actualCpOutput := cpRule.BuildParams.Output
288	encodeDexRule := foo.Rule("hiddenAPIEncodeDex")
289	actualFlagsCsv := encodeDexRule.BuildParams.Args["flagsCsv"]
290
291	android.AssertPathRelativeToTopEquals(t, "hiddenapi cp rule input", expectedCpInput, actualCpInput)
292
293	android.AssertPathRelativeToTopEquals(t, "hiddenapi cp rule output", expectedCpOutput, actualCpOutput)
294
295	android.AssertStringEquals(t, "hiddenapi encode dex rule flags csv", expectedFlagsCsv, actualFlagsCsv)
296}
297
298func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) {
299	t.Parallel()
300
301	result := android.GroupFixturePreparers(
302		hiddenApiFixtureFactory,
303		FixtureConfigureBootJars("platform:foo"),
304		PrepareForTestWithJavaSdkLibraryFiles,
305		FixtureWithLastReleaseApis("foo"),
306
307		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
308		// is disabled.
309		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
310	).RunTestWithBp(t, `
311		java_sdk_library {
312			name: "foo",
313			srcs: ["a.java"],
314			shared_library: false,
315			compile_dex: true,
316			public: {enabled: true},
317		}
318	`)
319
320	checkDexEncoded := func(t *testing.T, name, unencodedDexJar, encodedDexJar string) {
321		moduleForTests := result.ModuleForTests(t, name+".impl", "android_common")
322
323		encodeDexRule := moduleForTests.Rule("hiddenAPIEncodeDex")
324		actualUnencodedDexJar := encodeDexRule.Input
325
326		// Make sure that the module has its dex jar encoded.
327		android.AssertStringEquals(t, "encode embedded java_library", unencodedDexJar, actualUnencodedDexJar.String())
328
329		// Make sure that the encoded dex jar is the exported one.
330		errCtx := moduleErrorfTestCtx{}
331		exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath(errCtx).Path()
332		android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar)
333	}
334
335	expectedUnencodedDexJar := "out/soong/.intermediates/foo.impl/android_common/aligned/foo.jar"
336	expectedEncodedDexJar := "out/soong/.intermediates/foo.impl/android_common/hiddenapi/foo.jar"
337	checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar)
338}
339