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