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