blob: 8cc83700386ae17e77fd1b9ef8628bff1d1e435a [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,
Paul Duffindc3f9562021-06-09 15:31:05 +010039 prepareForTestWithMyapex,
Paul Duffinffa83752021-06-09 14:32:53 +010040 java.PrepareForTestWithJavaSdkLibraryFiles,
41 java.FixtureWithLastReleaseApis("foo"),
Paul Duffindc3f9562021-06-09 15:31:05 +010042 java.FixtureConfigureBootJars("myapex:bar"),
Paul Duffinffa83752021-06-09 14:32:53 +010043 android.FixtureWithRootAndroidBp(`
44 platform_bootclasspath {
45 name: "platform-bootclasspath",
46 fragments: [
Paul Duffindc3f9562021-06-09 15:31:05 +010047 {
48 apex: "myapex",
49 module:"bar-fragment",
50 },
Paul Duffinffa83752021-06-09 14:32:53 +010051 ],
52 hidden_api: {
53 unsupported: [
54 "unsupported.txt",
55 ],
56 removed: [
57 "removed.txt",
58 ],
59 max_target_r_low_priority: [
60 "max-target-r-low-priority.txt",
61 ],
62 max_target_q: [
63 "max-target-q.txt",
64 ],
65 max_target_p: [
66 "max-target-p.txt",
67 ],
68 max_target_o_low_priority: [
69 "max-target-o-low-priority.txt",
70 ],
71 blocked: [
72 "blocked.txt",
73 ],
74 unsupported_packages: [
75 "unsupported-packages.txt",
76 ],
77 },
78 }
79
Paul Duffindc3f9562021-06-09 15:31:05 +010080 apex {
81 name: "myapex",
82 key: "myapex.key",
83 bootclasspath_fragments: [
84 "bar-fragment",
85 ],
86 updatable: false,
87 }
88
89 apex_key {
90 name: "myapex.key",
91 public_key: "testkey.avbpubkey",
92 private_key: "testkey.pem",
93 }
94
Paul Duffinffa83752021-06-09 14:32:53 +010095 bootclasspath_fragment {
96 name: "bar-fragment",
97 contents: ["bar"],
Paul Duffindc3f9562021-06-09 15:31:05 +010098 apex_available: ["myapex"],
Paul Duffinffa83752021-06-09 14:32:53 +010099 api: {
100 stub_libs: ["foo"],
101 },
102 hidden_api: {
103 unsupported: [
104 "bar-unsupported.txt",
105 ],
106 removed: [
107 "bar-removed.txt",
108 ],
109 max_target_r_low_priority: [
110 "bar-max-target-r-low-priority.txt",
111 ],
112 max_target_q: [
113 "bar-max-target-q.txt",
114 ],
115 max_target_p: [
116 "bar-max-target-p.txt",
117 ],
118 max_target_o_low_priority: [
119 "bar-max-target-o-low-priority.txt",
120 ],
121 blocked: [
122 "bar-blocked.txt",
123 ],
124 unsupported_packages: [
125 "bar-unsupported-packages.txt",
126 ],
127 },
128 }
129
130 java_library {
131 name: "bar",
Paul Duffindc3f9562021-06-09 15:31:05 +0100132 apex_available: ["myapex"],
Paul Duffinffa83752021-06-09 14:32:53 +0100133 srcs: ["a.java"],
134 system_modules: "none",
135 sdk_version: "none",
136 compile_dex: true,
Paul Duffindc3f9562021-06-09 15:31:05 +0100137 permitted_packages: ["bar"],
Paul Duffinffa83752021-06-09 14:32:53 +0100138 }
139
140 java_sdk_library {
141 name: "foo",
142 srcs: ["a.java"],
143 public: {
144 enabled: true,
145 },
146 compile_dex: true,
147 }
148 `),
149 ).RunTest(t)
150
151 pbcp := result.Module("platform-bootclasspath", "android_common")
152 info := result.ModuleProvider(pbcp, java.MonolithicHiddenAPIInfoProvider).(java.MonolithicHiddenAPIInfo)
153
154 for _, category := range java.HiddenAPIFlagFileCategories {
155 name := category.PropertyName
156 message := fmt.Sprintf("category %s", name)
157 filename := strings.ReplaceAll(name, "_", "-")
158 expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
159 android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category])
160 }
161
Paul Duffindc3f9562021-06-09 15:31:05 +0100162 android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
163 android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
164 android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/index.csv"}, info.IndexPaths)
Paul Duffin67b9d612021-07-21 17:38:47 +0100165
Paul Duffin280bae62021-07-20 18:03:53 +0100166 android.AssertArrayString(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/filtered-stub-flags.csv:out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
167 android.AssertArrayString(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/filtered-flags.csv:out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
Paul Duffinffa83752021-06-09 14:32:53 +0100168}
169
Paul Duffinb432df92021-03-22 22:09:42 +0000170func TestPlatformBootclasspathDependencies(t *testing.T) {
171 result := android.GroupFixturePreparers(
172 prepareForTestWithPlatformBootclasspath,
173 prepareForTestWithArtApex,
174 prepareForTestWithMyapex,
175 // Configure some libraries in the art and framework boot images.
Paul Duffin60264a02021-04-12 20:02:36 +0100176 java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo"),
satayevd604b212021-07-21 14:23:52 +0100177 java.FixtureConfigureApexBootJars("myapex:bar"),
Paul Duffinb432df92021-03-22 22:09:42 +0000178 java.PrepareForTestWithJavaSdkLibraryFiles,
179 java.FixtureWithLastReleaseApis("foo"),
180 ).RunTestWithBp(t, `
181 apex {
182 name: "com.android.art",
183 key: "com.android.art.key",
184 bootclasspath_fragments: [
185 "art-bootclasspath-fragment",
186 ],
187 updatable: false,
188 }
189
190 apex_key {
191 name: "com.android.art.key",
192 public_key: "com.android.art.avbpubkey",
193 private_key: "com.android.art.pem",
194 }
195
196 bootclasspath_fragment {
197 name: "art-bootclasspath-fragment",
198 apex_available: [
199 "com.android.art",
200 ],
201 contents: [
202 "baz",
203 "quuz",
204 ],
205 }
206
207 java_library {
208 name: "baz",
209 apex_available: [
210 "com.android.art",
211 ],
212 srcs: ["b.java"],
213 installable: true,
214 }
215
216 // Add a java_import that is not preferred and so won't have an appropriate apex variant created
217 // for it to make sure that the platform_bootclasspath doesn't try and add a dependency onto it.
218 java_import {
219 name: "baz",
220 apex_available: [
221 "com.android.art",
222 ],
223 jars: ["b.jar"],
224 }
225
226 java_library {
227 name: "quuz",
228 apex_available: [
229 "com.android.art",
230 ],
231 srcs: ["b.java"],
232 installable: true,
233 }
234
235 apex {
236 name: "myapex",
237 key: "myapex.key",
Paul Duffin89f570a2021-06-16 01:42:33 +0100238 bootclasspath_fragments: [
239 "my-bootclasspath-fragment",
Paul Duffinb432df92021-03-22 22:09:42 +0000240 ],
241 updatable: false,
242 }
243
Paul Duffin89f570a2021-06-16 01:42:33 +0100244 bootclasspath_fragment {
245 name: "my-bootclasspath-fragment",
246 contents: ["bar"],
247 apex_available: ["myapex"],
248 }
249
Paul Duffinb432df92021-03-22 22:09:42 +0000250 apex_key {
251 name: "myapex.key",
252 public_key: "testkey.avbpubkey",
253 private_key: "testkey.pem",
254 }
255
256 java_sdk_library {
257 name: "foo",
258 srcs: ["b.java"],
259 }
260
261 java_library {
262 name: "bar",
263 srcs: ["b.java"],
264 installable: true,
265 apex_available: ["myapex"],
266 permitted_packages: ["bar"],
267 }
268
269 platform_bootclasspath {
270 name: "myplatform-bootclasspath",
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100271
272 fragments: [
273 {
274 apex: "com.android.art",
275 module: "art-bootclasspath-fragment",
276 },
Paul Duffin89f570a2021-06-16 01:42:33 +0100277 {
278 apex: "myapex",
279 module: "my-bootclasspath-fragment",
280 },
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100281 ],
Paul Duffinb432df92021-03-22 22:09:42 +0000282 }
283`,
284 )
285
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100286 java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
Paul Duffin74431d52021-04-21 14:10:42 +0100287 // The configured contents of BootJars.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100288 "com.android.art:baz",
289 "com.android.art:quuz",
290 "platform:foo",
Paul Duffin74431d52021-04-21 14:10:42 +0100291
satayevd604b212021-07-21 14:23:52 +0100292 // The configured contents of ApexBootJars.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100293 "myapex:bar",
294 })
295
296 java.CheckPlatformBootclasspathFragments(t, result, "myplatform-bootclasspath", []string{
Paul Duffin89f570a2021-06-16 01:42:33 +0100297 "com.android.art:art-bootclasspath-fragment",
298 "myapex:my-bootclasspath-fragment",
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100299 })
300
Paul Duffinb432df92021-03-22 22:09:42 +0000301 // Make sure that the myplatform-bootclasspath has the correct dependencies.
302 CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
Paul Duffin74431d52021-04-21 14:10:42 +0100303 // The following are stubs.
304 `platform:android_stubs_current`,
305 `platform:android_system_stubs_current`,
306 `platform:android_test_stubs_current`,
307 `platform:legacy.core.platform.api.stubs`,
308
309 // Needed for generating the boot image.
Paul Duffinb432df92021-03-22 22:09:42 +0000310 `platform:dex2oatd`,
Paul Duffin74431d52021-04-21 14:10:42 +0100311
312 // The configured contents of BootJars.
Paul Duffinb432df92021-03-22 22:09:42 +0000313 `com.android.art:baz`,
314 `com.android.art:quuz`,
315 `platform:foo`,
Paul Duffin74431d52021-04-21 14:10:42 +0100316
satayevd604b212021-07-21 14:23:52 +0100317 // The configured contents of ApexBootJars.
Paul Duffinb432df92021-03-22 22:09:42 +0000318 `myapex:bar`,
Paul Duffin74431d52021-04-21 14:10:42 +0100319
320 // The fragments.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100321 `com.android.art:art-bootclasspath-fragment`,
Paul Duffin89f570a2021-06-16 01:42:33 +0100322 `myapex:my-bootclasspath-fragment`,
Paul Duffinb432df92021-03-22 22:09:42 +0000323 })
324}
325
Paul Duffin7487a7a2021-05-19 09:36:09 +0100326// TestPlatformBootclasspath_AlwaysUsePrebuiltSdks verifies that the build does not fail when
327// AlwaysUsePrebuiltSdk() returns true. The structure of the modules in this test matches what
328// currently exists in some places in the Android build but it is not the intended structure. It is
329// in fact an invalid structure that should cause build failures. However, fixing that structure
330// will take too long so in the meantime this tests the workarounds to avoid build breakages.
331//
332// The main issues with this structure are:
333// 1. There is no prebuilt_bootclasspath_fragment referencing the "foo" java_sdk_library_import.
334// 2. There is no prebuilt_apex/apex_set which makes the dex implementation jar available to the
335// prebuilt_bootclasspath_fragment and the "foo" java_sdk_library_import.
336//
337// Together these cause the following symptoms:
338// 1. The "foo" java_sdk_library_import does not have a dex implementation jar.
339// 2. The "foo" java_sdk_library_import does not have a myapex variant.
340//
341// TODO(b/179354495): Fix the structure in this test once the main Android build has been fixed.
342func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
343 result := android.GroupFixturePreparers(
344 prepareForTestWithPlatformBootclasspath,
345 prepareForTestWithMyapex,
346 // Configure two libraries, the first is a java_sdk_library whose prebuilt will be used because
347 // of AlwaysUsePrebuiltsSdk() but does not have an appropriate apex variant and does not provide
348 // a boot dex jar. The second is a normal library that is unaffected. The order matters because
349 // if the dependency on myapex:foo is filtered out because of either of those conditions then
350 // the dependencies resolved by the platform_bootclasspath will not match the configured list
351 // and so will fail the test.
satayevd604b212021-07-21 14:23:52 +0100352 java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
Paul Duffin7487a7a2021-05-19 09:36:09 +0100353 java.PrepareForTestWithJavaSdkLibraryFiles,
354 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
355 variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
356 }),
357 java.FixtureWithPrebuiltApis(map[string][]string{
358 "current": {},
359 "30": {"foo"},
360 }),
361 ).RunTestWithBp(t, `
362 apex {
363 name: "myapex",
364 key: "myapex.key",
365 bootclasspath_fragments: [
366 "mybootclasspath-fragment",
367 ],
368 updatable: false,
369 }
370
371 apex_key {
372 name: "myapex.key",
373 public_key: "testkey.avbpubkey",
374 private_key: "testkey.pem",
375 }
376
377 java_library {
378 name: "bar",
379 srcs: ["b.java"],
380 installable: true,
381 apex_available: ["myapex"],
382 permitted_packages: ["bar"],
383 }
384
385 java_sdk_library {
386 name: "foo",
387 srcs: ["b.java"],
388 shared_library: false,
389 public: {
390 enabled: true,
391 },
392 apex_available: ["myapex"],
393 permitted_packages: ["foo"],
394 }
395
396 // A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
397 // because AlwaysUsePrebuiltSdks() is true.
398 java_sdk_library_import {
399 name: "foo",
400 prefer: false,
401 shared_library: false,
Paul Duffin630b11e2021-07-15 13:35:26 +0100402 permitted_packages: ["foo"],
Paul Duffin7487a7a2021-05-19 09:36:09 +0100403 public: {
404 jars: ["sdk_library/public/foo-stubs.jar"],
405 stub_srcs: ["sdk_library/public/foo_stub_sources"],
406 current_api: "sdk_library/public/foo.txt",
407 removed_api: "sdk_library/public/foo-removed.txt",
408 sdk_version: "current",
409 },
410 apex_available: ["myapex"],
411 }
412
413 // This always depends on the source foo module, its dependencies are not affected by the
414 // AlwaysUsePrebuiltSdks().
415 bootclasspath_fragment {
416 name: "mybootclasspath-fragment",
417 apex_available: [
418 "myapex",
419 ],
420 contents: [
421 "foo", "bar",
422 ],
423 }
424
425 platform_bootclasspath {
426 name: "myplatform-bootclasspath",
Paul Duffin89f570a2021-06-16 01:42:33 +0100427 fragments: [
428 {
429 apex: "myapex",
430 module:"mybootclasspath-fragment",
431 },
432 ],
Paul Duffin7487a7a2021-05-19 09:36:09 +0100433 }
434`,
435 )
436
437 java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
438 // The configured contents of BootJars.
439 "platform:prebuilt_foo", // Note: This is the platform not myapex variant.
440 "myapex:bar",
441 })
442
443 // Make sure that the myplatform-bootclasspath has the correct dependencies.
444 CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
445 // The following are stubs.
446 "platform:prebuilt_sdk_public_current_android",
447 "platform:prebuilt_sdk_system_current_android",
448 "platform:prebuilt_sdk_test_current_android",
449
450 // Not a prebuilt as no prebuilt existed when it was added.
451 "platform:legacy.core.platform.api.stubs",
452
453 // Needed for generating the boot image.
Paul Duffin89f570a2021-06-16 01:42:33 +0100454 "platform:dex2oatd",
Paul Duffin7487a7a2021-05-19 09:36:09 +0100455
456 // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
457 // modules when available as it does not know which one will be preferred.
458 //
459 // The source module has an APEX variant but the prebuilt does not.
460 "myapex:foo",
461 "platform:prebuilt_foo",
462
463 // Only a source module exists.
464 "myapex:bar",
Paul Duffin89f570a2021-06-16 01:42:33 +0100465
466 // The fragments.
467 "myapex:mybootclasspath-fragment",
Paul Duffin7487a7a2021-05-19 09:36:09 +0100468 })
469}
470
Paul Duffinb432df92021-03-22 22:09:42 +0000471// CheckModuleDependencies checks the dependencies of the selected module against the expected list.
472//
473// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
474// name of the apex, or platform is it is not part of an apex and <module> is the module name.
475func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
476 t.Helper()
477 module := ctx.ModuleForTests(name, variant).Module()
478 modules := []android.Module{}
479 ctx.VisitDirectDeps(module, func(m blueprint.Module) {
480 modules = append(modules, m.(android.Module))
481 })
482
483 pairs := java.ApexNamePairsFromModules(ctx, modules)
484 android.AssertDeepEquals(t, "module dependencies", expected, pairs)
485}
satayevb3090502021-06-15 17:49:10 +0100486
487// TestPlatformBootclasspath_IncludesRemainingApexJars verifies that any apex boot jar is present in
488// platform_bootclasspath's classpaths.proto config, if the apex does not generate its own config
489// by setting generate_classpaths_proto property to false.
490func TestPlatformBootclasspath_IncludesRemainingApexJars(t *testing.T) {
491 result := android.GroupFixturePreparers(
492 prepareForTestWithPlatformBootclasspath,
493 prepareForTestWithMyapex,
satayevd604b212021-07-21 14:23:52 +0100494 java.FixtureConfigureApexBootJars("myapex:foo"),
satayevb3090502021-06-15 17:49:10 +0100495 android.FixtureWithRootAndroidBp(`
496 platform_bootclasspath {
497 name: "platform-bootclasspath",
498 fragments: [
499 {
500 apex: "myapex",
501 module:"foo-fragment",
502 },
503 ],
504 }
505
506 apex {
507 name: "myapex",
508 key: "myapex.key",
509 bootclasspath_fragments: ["foo-fragment"],
510 updatable: false,
511 }
512
513 apex_key {
514 name: "myapex.key",
515 public_key: "testkey.avbpubkey",
516 private_key: "testkey.pem",
517 }
518
519 bootclasspath_fragment {
520 name: "foo-fragment",
521 generate_classpaths_proto: false,
522 contents: ["foo"],
523 apex_available: ["myapex"],
524 }
525
526 java_library {
527 name: "foo",
528 srcs: ["a.java"],
529 system_modules: "none",
530 sdk_version: "none",
531 compile_dex: true,
532 apex_available: ["myapex"],
533 permitted_packages: ["foo"],
534 }
535 `),
536 ).RunTest(t)
537
538 java.CheckClasspathFragmentProtoContentInfoProvider(t, result,
539 true, // proto should be generated
540 "myapex:foo", // apex doesn't generate its own config, so must be in platform_bootclasspath
541 "bootclasspath.pb",
542 "out/soong/target/product/test_device/system/etc/classpaths",
543 )
544}