blob: 0724556c0e12bbeff550eb8a2ef00bba458c196d [file] [log] [blame]
Paul Duffinb432df92021-03-22 22:09:42 +00001// 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 apex
16
17import (
Paul Duffinffa83752021-06-09 14:32:53 +010018 "fmt"
19 "strings"
Paul Duffinb432df92021-03-22 22:09:42 +000020 "testing"
21
22 "android/soong/android"
Paul Duffinb432df92021-03-22 22:09:42 +000023 "android/soong/java"
24 "github.com/google/blueprint"
Paul Duffin7487a7a2021-05-19 09:36:09 +010025 "github.com/google/blueprint/proptools"
Paul Duffinb432df92021-03-22 22:09:42 +000026)
27
28// Contains tests for platform_bootclasspath logic from java/platform_bootclasspath.go that requires
29// apexes.
30
31var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers(
32 java.PrepareForTestWithDexpreopt,
33 PrepareForTestWithApexBuildComponents,
34)
35
Paul Duffinffa83752021-06-09 14:32:53 +010036func TestPlatformBootclasspath_Fragments(t *testing.T) {
37 result := android.GroupFixturePreparers(
38 prepareForTestWithPlatformBootclasspath,
39 java.PrepareForTestWithJavaSdkLibraryFiles,
40 java.FixtureWithLastReleaseApis("foo"),
41 android.FixtureWithRootAndroidBp(`
42 platform_bootclasspath {
43 name: "platform-bootclasspath",
44 fragments: [
45 {module:"bar-fragment"},
46 ],
47 hidden_api: {
48 unsupported: [
49 "unsupported.txt",
50 ],
51 removed: [
52 "removed.txt",
53 ],
54 max_target_r_low_priority: [
55 "max-target-r-low-priority.txt",
56 ],
57 max_target_q: [
58 "max-target-q.txt",
59 ],
60 max_target_p: [
61 "max-target-p.txt",
62 ],
63 max_target_o_low_priority: [
64 "max-target-o-low-priority.txt",
65 ],
66 blocked: [
67 "blocked.txt",
68 ],
69 unsupported_packages: [
70 "unsupported-packages.txt",
71 ],
72 },
73 }
74
75 bootclasspath_fragment {
76 name: "bar-fragment",
77 contents: ["bar"],
78 api: {
79 stub_libs: ["foo"],
80 },
81 hidden_api: {
82 unsupported: [
83 "bar-unsupported.txt",
84 ],
85 removed: [
86 "bar-removed.txt",
87 ],
88 max_target_r_low_priority: [
89 "bar-max-target-r-low-priority.txt",
90 ],
91 max_target_q: [
92 "bar-max-target-q.txt",
93 ],
94 max_target_p: [
95 "bar-max-target-p.txt",
96 ],
97 max_target_o_low_priority: [
98 "bar-max-target-o-low-priority.txt",
99 ],
100 blocked: [
101 "bar-blocked.txt",
102 ],
103 unsupported_packages: [
104 "bar-unsupported-packages.txt",
105 ],
106 },
107 }
108
109 java_library {
110 name: "bar",
111 srcs: ["a.java"],
112 system_modules: "none",
113 sdk_version: "none",
114 compile_dex: true,
115 }
116
117 java_sdk_library {
118 name: "foo",
119 srcs: ["a.java"],
120 public: {
121 enabled: true,
122 },
123 compile_dex: true,
124 }
125 `),
126 ).RunTest(t)
127
128 pbcp := result.Module("platform-bootclasspath", "android_common")
129 info := result.ModuleProvider(pbcp, java.MonolithicHiddenAPIInfoProvider).(java.MonolithicHiddenAPIInfo)
130
131 for _, category := range java.HiddenAPIFlagFileCategories {
132 name := category.PropertyName
133 message := fmt.Sprintf("category %s", name)
134 filename := strings.ReplaceAll(name, "_", "-")
135 expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
136 android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category])
137 }
138
139 android.AssertPathsRelativeToTopEquals(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/stub-flags.csv"}, info.StubFlagsPaths)
140 android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
141 android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
142 android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/index.csv"}, info.IndexPaths)
143 android.AssertPathsRelativeToTopEquals(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/all-flags.csv"}, info.AllFlagsPaths)
144}
145
Paul Duffinb432df92021-03-22 22:09:42 +0000146func TestPlatformBootclasspathDependencies(t *testing.T) {
147 result := android.GroupFixturePreparers(
148 prepareForTestWithPlatformBootclasspath,
149 prepareForTestWithArtApex,
150 prepareForTestWithMyapex,
151 // Configure some libraries in the art and framework boot images.
Paul Duffin60264a02021-04-12 20:02:36 +0100152 java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo"),
153 java.FixtureConfigureUpdatableBootJars("myapex:bar"),
Paul Duffinb432df92021-03-22 22:09:42 +0000154 java.PrepareForTestWithJavaSdkLibraryFiles,
155 java.FixtureWithLastReleaseApis("foo"),
156 ).RunTestWithBp(t, `
157 apex {
158 name: "com.android.art",
159 key: "com.android.art.key",
160 bootclasspath_fragments: [
161 "art-bootclasspath-fragment",
162 ],
163 updatable: false,
164 }
165
166 apex_key {
167 name: "com.android.art.key",
168 public_key: "com.android.art.avbpubkey",
169 private_key: "com.android.art.pem",
170 }
171
172 bootclasspath_fragment {
173 name: "art-bootclasspath-fragment",
174 apex_available: [
175 "com.android.art",
176 ],
177 contents: [
178 "baz",
179 "quuz",
180 ],
181 }
182
183 java_library {
184 name: "baz",
185 apex_available: [
186 "com.android.art",
187 ],
188 srcs: ["b.java"],
189 installable: true,
190 }
191
192 // Add a java_import that is not preferred and so won't have an appropriate apex variant created
193 // for it to make sure that the platform_bootclasspath doesn't try and add a dependency onto it.
194 java_import {
195 name: "baz",
196 apex_available: [
197 "com.android.art",
198 ],
199 jars: ["b.jar"],
200 }
201
202 java_library {
203 name: "quuz",
204 apex_available: [
205 "com.android.art",
206 ],
207 srcs: ["b.java"],
208 installable: true,
209 }
210
211 apex {
212 name: "myapex",
213 key: "myapex.key",
214 java_libs: [
215 "bar",
216 ],
217 updatable: false,
218 }
219
220 apex_key {
221 name: "myapex.key",
222 public_key: "testkey.avbpubkey",
223 private_key: "testkey.pem",
224 }
225
226 java_sdk_library {
227 name: "foo",
228 srcs: ["b.java"],
229 }
230
231 java_library {
232 name: "bar",
233 srcs: ["b.java"],
234 installable: true,
235 apex_available: ["myapex"],
236 permitted_packages: ["bar"],
237 }
238
239 platform_bootclasspath {
240 name: "myplatform-bootclasspath",
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100241
242 fragments: [
243 {
244 apex: "com.android.art",
245 module: "art-bootclasspath-fragment",
246 },
247 ],
Paul Duffinb432df92021-03-22 22:09:42 +0000248 }
249`,
250 )
251
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100252 java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
Paul Duffin74431d52021-04-21 14:10:42 +0100253 // The configured contents of BootJars.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100254 "com.android.art:baz",
255 "com.android.art:quuz",
256 "platform:foo",
Paul Duffin74431d52021-04-21 14:10:42 +0100257
258 // The configured contents of UpdatableBootJars.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100259 "myapex:bar",
260 })
261
262 java.CheckPlatformBootclasspathFragments(t, result, "myplatform-bootclasspath", []string{
263 `com.android.art:art-bootclasspath-fragment`,
264 })
265
Paul Duffinb432df92021-03-22 22:09:42 +0000266 // Make sure that the myplatform-bootclasspath has the correct dependencies.
267 CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
Paul Duffin74431d52021-04-21 14:10:42 +0100268 // The following are stubs.
269 `platform:android_stubs_current`,
270 `platform:android_system_stubs_current`,
271 `platform:android_test_stubs_current`,
272 `platform:legacy.core.platform.api.stubs`,
273
274 // Needed for generating the boot image.
Paul Duffinb432df92021-03-22 22:09:42 +0000275 `platform:dex2oatd`,
Paul Duffin74431d52021-04-21 14:10:42 +0100276
277 // The configured contents of BootJars.
Paul Duffinb432df92021-03-22 22:09:42 +0000278 `com.android.art:baz`,
279 `com.android.art:quuz`,
280 `platform:foo`,
Paul Duffin74431d52021-04-21 14:10:42 +0100281
282 // The configured contents of UpdatableBootJars.
Paul Duffinb432df92021-03-22 22:09:42 +0000283 `myapex:bar`,
Paul Duffin74431d52021-04-21 14:10:42 +0100284
285 // The fragments.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100286 `com.android.art:art-bootclasspath-fragment`,
Paul Duffinb432df92021-03-22 22:09:42 +0000287 })
288}
289
Paul Duffin7487a7a2021-05-19 09:36:09 +0100290// TestPlatformBootclasspath_AlwaysUsePrebuiltSdks verifies that the build does not fail when
291// AlwaysUsePrebuiltSdk() returns true. The structure of the modules in this test matches what
292// currently exists in some places in the Android build but it is not the intended structure. It is
293// in fact an invalid structure that should cause build failures. However, fixing that structure
294// will take too long so in the meantime this tests the workarounds to avoid build breakages.
295//
296// The main issues with this structure are:
297// 1. There is no prebuilt_bootclasspath_fragment referencing the "foo" java_sdk_library_import.
298// 2. There is no prebuilt_apex/apex_set which makes the dex implementation jar available to the
299// prebuilt_bootclasspath_fragment and the "foo" java_sdk_library_import.
300//
301// Together these cause the following symptoms:
302// 1. The "foo" java_sdk_library_import does not have a dex implementation jar.
303// 2. The "foo" java_sdk_library_import does not have a myapex variant.
304//
305// TODO(b/179354495): Fix the structure in this test once the main Android build has been fixed.
306func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
307 result := android.GroupFixturePreparers(
308 prepareForTestWithPlatformBootclasspath,
309 prepareForTestWithMyapex,
310 // Configure two libraries, the first is a java_sdk_library whose prebuilt will be used because
311 // of AlwaysUsePrebuiltsSdk() but does not have an appropriate apex variant and does not provide
312 // a boot dex jar. The second is a normal library that is unaffected. The order matters because
313 // if the dependency on myapex:foo is filtered out because of either of those conditions then
314 // the dependencies resolved by the platform_bootclasspath will not match the configured list
315 // and so will fail the test.
316 java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"),
317 java.PrepareForTestWithJavaSdkLibraryFiles,
318 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
319 variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
320 }),
321 java.FixtureWithPrebuiltApis(map[string][]string{
322 "current": {},
323 "30": {"foo"},
324 }),
325 ).RunTestWithBp(t, `
326 apex {
327 name: "myapex",
328 key: "myapex.key",
329 bootclasspath_fragments: [
330 "mybootclasspath-fragment",
331 ],
332 updatable: false,
333 }
334
335 apex_key {
336 name: "myapex.key",
337 public_key: "testkey.avbpubkey",
338 private_key: "testkey.pem",
339 }
340
341 java_library {
342 name: "bar",
343 srcs: ["b.java"],
344 installable: true,
345 apex_available: ["myapex"],
346 permitted_packages: ["bar"],
347 }
348
349 java_sdk_library {
350 name: "foo",
351 srcs: ["b.java"],
352 shared_library: false,
353 public: {
354 enabled: true,
355 },
356 apex_available: ["myapex"],
357 permitted_packages: ["foo"],
358 }
359
360 // A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
361 // because AlwaysUsePrebuiltSdks() is true.
362 java_sdk_library_import {
363 name: "foo",
364 prefer: false,
365 shared_library: false,
366 public: {
367 jars: ["sdk_library/public/foo-stubs.jar"],
368 stub_srcs: ["sdk_library/public/foo_stub_sources"],
369 current_api: "sdk_library/public/foo.txt",
370 removed_api: "sdk_library/public/foo-removed.txt",
371 sdk_version: "current",
372 },
373 apex_available: ["myapex"],
374 }
375
376 // This always depends on the source foo module, its dependencies are not affected by the
377 // AlwaysUsePrebuiltSdks().
378 bootclasspath_fragment {
379 name: "mybootclasspath-fragment",
380 apex_available: [
381 "myapex",
382 ],
383 contents: [
384 "foo", "bar",
385 ],
386 }
387
388 platform_bootclasspath {
389 name: "myplatform-bootclasspath",
390 }
391`,
392 )
393
394 java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
395 // The configured contents of BootJars.
396 "platform:prebuilt_foo", // Note: This is the platform not myapex variant.
397 "myapex:bar",
398 })
399
400 // Make sure that the myplatform-bootclasspath has the correct dependencies.
401 CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
402 // The following are stubs.
403 "platform:prebuilt_sdk_public_current_android",
404 "platform:prebuilt_sdk_system_current_android",
405 "platform:prebuilt_sdk_test_current_android",
406
407 // Not a prebuilt as no prebuilt existed when it was added.
408 "platform:legacy.core.platform.api.stubs",
409
410 // Needed for generating the boot image.
411 `platform:dex2oatd`,
412
413 // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
414 // modules when available as it does not know which one will be preferred.
415 //
416 // The source module has an APEX variant but the prebuilt does not.
417 "myapex:foo",
418 "platform:prebuilt_foo",
419
420 // Only a source module exists.
421 "myapex:bar",
422 })
423}
424
Paul Duffinb432df92021-03-22 22:09:42 +0000425// CheckModuleDependencies checks the dependencies of the selected module against the expected list.
426//
427// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
428// name of the apex, or platform is it is not part of an apex and <module> is the module name.
429func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
430 t.Helper()
431 module := ctx.ModuleForTests(name, variant).Module()
432 modules := []android.Module{}
433 ctx.VisitDirectDeps(module, func(m blueprint.Module) {
434 modules = append(modules, m.(android.Module))
435 })
436
437 pairs := java.ApexNamePairsFromModules(ctx, modules)
438 android.AssertDeepEquals(t, "module dependencies", expected, pairs)
439}