blob: 279cf54defc5b9a3206e27a69765df2c80795e5f [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, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/stub-flags.csv"}, info.StubFlagsPaths)
163 android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
164 android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
165 android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/index.csv"}, info.IndexPaths)
166 android.AssertPathsRelativeToTopEquals(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex10000/modular-hiddenapi/all-flags.csv"}, info.AllFlagsPaths)
Paul Duffinffa83752021-06-09 14:32:53 +0100167}
168
Paul Duffinb432df92021-03-22 22:09:42 +0000169func TestPlatformBootclasspathDependencies(t *testing.T) {
170 result := android.GroupFixturePreparers(
171 prepareForTestWithPlatformBootclasspath,
172 prepareForTestWithArtApex,
173 prepareForTestWithMyapex,
174 // Configure some libraries in the art and framework boot images.
Paul Duffin60264a02021-04-12 20:02:36 +0100175 java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo"),
176 java.FixtureConfigureUpdatableBootJars("myapex:bar"),
Paul Duffinb432df92021-03-22 22:09:42 +0000177 java.PrepareForTestWithJavaSdkLibraryFiles,
178 java.FixtureWithLastReleaseApis("foo"),
179 ).RunTestWithBp(t, `
180 apex {
181 name: "com.android.art",
182 key: "com.android.art.key",
183 bootclasspath_fragments: [
184 "art-bootclasspath-fragment",
185 ],
186 updatable: false,
187 }
188
189 apex_key {
190 name: "com.android.art.key",
191 public_key: "com.android.art.avbpubkey",
192 private_key: "com.android.art.pem",
193 }
194
195 bootclasspath_fragment {
196 name: "art-bootclasspath-fragment",
197 apex_available: [
198 "com.android.art",
199 ],
200 contents: [
201 "baz",
202 "quuz",
203 ],
204 }
205
206 java_library {
207 name: "baz",
208 apex_available: [
209 "com.android.art",
210 ],
211 srcs: ["b.java"],
212 installable: true,
213 }
214
215 // Add a java_import that is not preferred and so won't have an appropriate apex variant created
216 // for it to make sure that the platform_bootclasspath doesn't try and add a dependency onto it.
217 java_import {
218 name: "baz",
219 apex_available: [
220 "com.android.art",
221 ],
222 jars: ["b.jar"],
223 }
224
225 java_library {
226 name: "quuz",
227 apex_available: [
228 "com.android.art",
229 ],
230 srcs: ["b.java"],
231 installable: true,
232 }
233
234 apex {
235 name: "myapex",
236 key: "myapex.key",
Paul Duffin89f570a2021-06-16 01:42:33 +0100237 bootclasspath_fragments: [
238 "my-bootclasspath-fragment",
Paul Duffinb432df92021-03-22 22:09:42 +0000239 ],
240 updatable: false,
241 }
242
Paul Duffin89f570a2021-06-16 01:42:33 +0100243 bootclasspath_fragment {
244 name: "my-bootclasspath-fragment",
245 contents: ["bar"],
246 apex_available: ["myapex"],
247 }
248
Paul Duffinb432df92021-03-22 22:09:42 +0000249 apex_key {
250 name: "myapex.key",
251 public_key: "testkey.avbpubkey",
252 private_key: "testkey.pem",
253 }
254
255 java_sdk_library {
256 name: "foo",
257 srcs: ["b.java"],
258 }
259
260 java_library {
261 name: "bar",
262 srcs: ["b.java"],
263 installable: true,
264 apex_available: ["myapex"],
265 permitted_packages: ["bar"],
266 }
267
268 platform_bootclasspath {
269 name: "myplatform-bootclasspath",
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100270
271 fragments: [
272 {
273 apex: "com.android.art",
274 module: "art-bootclasspath-fragment",
275 },
Paul Duffin89f570a2021-06-16 01:42:33 +0100276 {
277 apex: "myapex",
278 module: "my-bootclasspath-fragment",
279 },
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100280 ],
Paul Duffinb432df92021-03-22 22:09:42 +0000281 }
282`,
283 )
284
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100285 java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
Paul Duffin74431d52021-04-21 14:10:42 +0100286 // The configured contents of BootJars.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100287 "com.android.art:baz",
288 "com.android.art:quuz",
289 "platform:foo",
Paul Duffin74431d52021-04-21 14:10:42 +0100290
291 // The configured contents of UpdatableBootJars.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100292 "myapex:bar",
293 })
294
295 java.CheckPlatformBootclasspathFragments(t, result, "myplatform-bootclasspath", []string{
Paul Duffin89f570a2021-06-16 01:42:33 +0100296 "com.android.art:art-bootclasspath-fragment",
297 "myapex:my-bootclasspath-fragment",
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100298 })
299
Paul Duffinb432df92021-03-22 22:09:42 +0000300 // Make sure that the myplatform-bootclasspath has the correct dependencies.
301 CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
Paul Duffin74431d52021-04-21 14:10:42 +0100302 // The following are stubs.
303 `platform:android_stubs_current`,
304 `platform:android_system_stubs_current`,
305 `platform:android_test_stubs_current`,
306 `platform:legacy.core.platform.api.stubs`,
307
308 // Needed for generating the boot image.
Paul Duffinb432df92021-03-22 22:09:42 +0000309 `platform:dex2oatd`,
Paul Duffin74431d52021-04-21 14:10:42 +0100310
311 // The configured contents of BootJars.
Paul Duffinb432df92021-03-22 22:09:42 +0000312 `com.android.art:baz`,
313 `com.android.art:quuz`,
314 `platform:foo`,
Paul Duffin74431d52021-04-21 14:10:42 +0100315
316 // The configured contents of UpdatableBootJars.
Paul Duffinb432df92021-03-22 22:09:42 +0000317 `myapex:bar`,
Paul Duffin74431d52021-04-21 14:10:42 +0100318
319 // The fragments.
Paul Duffin62d8c3b2021-04-07 20:35:11 +0100320 `com.android.art:art-bootclasspath-fragment`,
Paul Duffin89f570a2021-06-16 01:42:33 +0100321 `myapex:my-bootclasspath-fragment`,
Paul Duffinb432df92021-03-22 22:09:42 +0000322 })
323}
324
Paul Duffin7487a7a2021-05-19 09:36:09 +0100325// TestPlatformBootclasspath_AlwaysUsePrebuiltSdks verifies that the build does not fail when
326// AlwaysUsePrebuiltSdk() returns true. The structure of the modules in this test matches what
327// currently exists in some places in the Android build but it is not the intended structure. It is
328// in fact an invalid structure that should cause build failures. However, fixing that structure
329// will take too long so in the meantime this tests the workarounds to avoid build breakages.
330//
331// The main issues with this structure are:
332// 1. There is no prebuilt_bootclasspath_fragment referencing the "foo" java_sdk_library_import.
333// 2. There is no prebuilt_apex/apex_set which makes the dex implementation jar available to the
334// prebuilt_bootclasspath_fragment and the "foo" java_sdk_library_import.
335//
336// Together these cause the following symptoms:
337// 1. The "foo" java_sdk_library_import does not have a dex implementation jar.
338// 2. The "foo" java_sdk_library_import does not have a myapex variant.
339//
340// TODO(b/179354495): Fix the structure in this test once the main Android build has been fixed.
341func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
342 result := android.GroupFixturePreparers(
343 prepareForTestWithPlatformBootclasspath,
344 prepareForTestWithMyapex,
345 // Configure two libraries, the first is a java_sdk_library whose prebuilt will be used because
346 // of AlwaysUsePrebuiltsSdk() but does not have an appropriate apex variant and does not provide
347 // a boot dex jar. The second is a normal library that is unaffected. The order matters because
348 // if the dependency on myapex:foo is filtered out because of either of those conditions then
349 // the dependencies resolved by the platform_bootclasspath will not match the configured list
350 // and so will fail the test.
351 java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"),
352 java.PrepareForTestWithJavaSdkLibraryFiles,
353 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
354 variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
355 }),
356 java.FixtureWithPrebuiltApis(map[string][]string{
357 "current": {},
358 "30": {"foo"},
359 }),
360 ).RunTestWithBp(t, `
361 apex {
362 name: "myapex",
363 key: "myapex.key",
364 bootclasspath_fragments: [
365 "mybootclasspath-fragment",
366 ],
367 updatable: false,
368 }
369
370 apex_key {
371 name: "myapex.key",
372 public_key: "testkey.avbpubkey",
373 private_key: "testkey.pem",
374 }
375
376 java_library {
377 name: "bar",
378 srcs: ["b.java"],
379 installable: true,
380 apex_available: ["myapex"],
381 permitted_packages: ["bar"],
382 }
383
384 java_sdk_library {
385 name: "foo",
386 srcs: ["b.java"],
387 shared_library: false,
388 public: {
389 enabled: true,
390 },
391 apex_available: ["myapex"],
392 permitted_packages: ["foo"],
393 }
394
395 // A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
396 // because AlwaysUsePrebuiltSdks() is true.
397 java_sdk_library_import {
398 name: "foo",
399 prefer: false,
400 shared_library: false,
401 public: {
402 jars: ["sdk_library/public/foo-stubs.jar"],
403 stub_srcs: ["sdk_library/public/foo_stub_sources"],
404 current_api: "sdk_library/public/foo.txt",
405 removed_api: "sdk_library/public/foo-removed.txt",
406 sdk_version: "current",
407 },
408 apex_available: ["myapex"],
409 }
410
411 // This always depends on the source foo module, its dependencies are not affected by the
412 // AlwaysUsePrebuiltSdks().
413 bootclasspath_fragment {
414 name: "mybootclasspath-fragment",
415 apex_available: [
416 "myapex",
417 ],
418 contents: [
419 "foo", "bar",
420 ],
421 }
422
423 platform_bootclasspath {
424 name: "myplatform-bootclasspath",
Paul Duffin89f570a2021-06-16 01:42:33 +0100425 fragments: [
426 {
427 apex: "myapex",
428 module:"mybootclasspath-fragment",
429 },
430 ],
Paul Duffin7487a7a2021-05-19 09:36:09 +0100431 }
432`,
433 )
434
435 java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
436 // The configured contents of BootJars.
437 "platform:prebuilt_foo", // Note: This is the platform not myapex variant.
438 "myapex:bar",
439 })
440
441 // Make sure that the myplatform-bootclasspath has the correct dependencies.
442 CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
443 // The following are stubs.
444 "platform:prebuilt_sdk_public_current_android",
445 "platform:prebuilt_sdk_system_current_android",
446 "platform:prebuilt_sdk_test_current_android",
447
448 // Not a prebuilt as no prebuilt existed when it was added.
449 "platform:legacy.core.platform.api.stubs",
450
451 // Needed for generating the boot image.
Paul Duffin89f570a2021-06-16 01:42:33 +0100452 "platform:dex2oatd",
Paul Duffin7487a7a2021-05-19 09:36:09 +0100453
454 // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
455 // modules when available as it does not know which one will be preferred.
456 //
457 // The source module has an APEX variant but the prebuilt does not.
458 "myapex:foo",
459 "platform:prebuilt_foo",
460
461 // Only a source module exists.
462 "myapex:bar",
Paul Duffin89f570a2021-06-16 01:42:33 +0100463
464 // The fragments.
465 "myapex:mybootclasspath-fragment",
Paul Duffin7487a7a2021-05-19 09:36:09 +0100466 })
467}
468
Paul Duffinb432df92021-03-22 22:09:42 +0000469// CheckModuleDependencies checks the dependencies of the selected module against the expected list.
470//
471// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
472// name of the apex, or platform is it is not part of an apex and <module> is the module name.
473func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
474 t.Helper()
475 module := ctx.ModuleForTests(name, variant).Module()
476 modules := []android.Module{}
477 ctx.VisitDirectDeps(module, func(m blueprint.Module) {
478 modules = append(modules, m.(android.Module))
479 })
480
481 pairs := java.ApexNamePairsFromModules(ctx, modules)
482 android.AssertDeepEquals(t, "module dependencies", expected, pairs)
483}
satayevb3090502021-06-15 17:49:10 +0100484
485// TestPlatformBootclasspath_IncludesRemainingApexJars verifies that any apex boot jar is present in
486// platform_bootclasspath's classpaths.proto config, if the apex does not generate its own config
487// by setting generate_classpaths_proto property to false.
488func TestPlatformBootclasspath_IncludesRemainingApexJars(t *testing.T) {
489 result := android.GroupFixturePreparers(
490 prepareForTestWithPlatformBootclasspath,
491 prepareForTestWithMyapex,
492 java.FixtureConfigureUpdatableBootJars("myapex:foo"),
493 android.FixtureWithRootAndroidBp(`
494 platform_bootclasspath {
495 name: "platform-bootclasspath",
496 fragments: [
497 {
498 apex: "myapex",
499 module:"foo-fragment",
500 },
501 ],
502 }
503
504 apex {
505 name: "myapex",
506 key: "myapex.key",
507 bootclasspath_fragments: ["foo-fragment"],
508 updatable: false,
509 }
510
511 apex_key {
512 name: "myapex.key",
513 public_key: "testkey.avbpubkey",
514 private_key: "testkey.pem",
515 }
516
517 bootclasspath_fragment {
518 name: "foo-fragment",
519 generate_classpaths_proto: false,
520 contents: ["foo"],
521 apex_available: ["myapex"],
522 }
523
524 java_library {
525 name: "foo",
526 srcs: ["a.java"],
527 system_modules: "none",
528 sdk_version: "none",
529 compile_dex: true,
530 apex_available: ["myapex"],
531 permitted_packages: ["foo"],
532 }
533 `),
534 ).RunTest(t)
535
536 java.CheckClasspathFragmentProtoContentInfoProvider(t, result,
537 true, // proto should be generated
538 "myapex:foo", // apex doesn't generate its own config, so must be in platform_bootclasspath
539 "bootclasspath.pb",
540 "out/soong/target/product/test_device/system/etc/classpaths",
541 )
542}