blob: d7f69eb367e820f0a23154f748513df76ab0fadb [file] [log] [blame]
Jaewoong Jungf9b44652020-12-21 12:29:12 -08001// 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 "reflect"
19 "regexp"
20 "strings"
21 "testing"
22
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26)
27
28func TestAndroidAppImport(t *testing.T) {
29 ctx, _ := testJava(t, `
30 android_app_import {
31 name: "foo",
32 apk: "prebuilts/apk/app.apk",
33 certificate: "platform",
34 dex_preopt: {
35 enabled: true,
36 },
37 }
38 `)
39
40 variant := ctx.ModuleForTests("foo", "android_common")
41
42 // Check dexpreopt outputs.
43 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
44 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
45 t.Errorf("can't find dexpreopt outputs")
46 }
47
48 // Check cert signing flag.
49 signedApk := variant.Output("signed/foo.apk")
50 signingFlag := signedApk.Args["certificates"]
51 expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
52 if expected != signingFlag {
53 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
54 }
55}
56
57func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
58 ctx, _ := testJava(t, `
59 android_app_import {
60 name: "foo",
61 apk: "prebuilts/apk/app.apk",
62 certificate: "platform",
63 dex_preopt: {
64 enabled: false,
65 },
66 }
67 `)
68
69 variant := ctx.ModuleForTests("foo", "android_common")
70
71 // Check dexpreopt outputs. They shouldn't exist.
72 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
73 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
74 t.Errorf("dexpreopt shouldn't have run.")
75 }
76}
77
78func TestAndroidAppImport_Presigned(t *testing.T) {
79 ctx, _ := testJava(t, `
80 android_app_import {
81 name: "foo",
82 apk: "prebuilts/apk/app.apk",
83 presigned: true,
84 dex_preopt: {
85 enabled: true,
86 },
87 }
88 `)
89
90 variant := ctx.ModuleForTests("foo", "android_common")
91
92 // Check dexpreopt outputs.
93 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
94 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
95 t.Errorf("can't find dexpreopt outputs")
96 }
97 // Make sure signing was skipped and aligning was done.
98 if variant.MaybeOutput("signed/foo.apk").Rule != nil {
99 t.Errorf("signing rule shouldn't be included.")
100 }
101 if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
102 t.Errorf("can't find aligning rule")
103 }
104}
105
106func TestAndroidAppImport_SigningLineage(t *testing.T) {
107 ctx, _ := testJava(t, `
108 android_app_import {
109 name: "foo",
110 apk: "prebuilts/apk/app.apk",
111 certificate: "platform",
112 lineage: "lineage.bin",
113 }
114 `)
115
116 variant := ctx.ModuleForTests("foo", "android_common")
117
118 // Check cert signing lineage flag.
119 signedApk := variant.Output("signed/foo.apk")
120 signingFlag := signedApk.Args["flags"]
121 expected := "--lineage lineage.bin"
122 if expected != signingFlag {
123 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
124 }
125}
126
127func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
128 ctx, _ := testJava(t, `
129 android_app_import {
130 name: "foo",
131 apk: "prebuilts/apk/app.apk",
132 default_dev_cert: true,
133 dex_preopt: {
134 enabled: true,
135 },
136 }
137 `)
138
139 variant := ctx.ModuleForTests("foo", "android_common")
140
141 // Check dexpreopt outputs.
142 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
143 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
144 t.Errorf("can't find dexpreopt outputs")
145 }
146
147 // Check cert signing flag.
148 signedApk := variant.Output("signed/foo.apk")
149 signingFlag := signedApk.Args["certificates"]
150 expected := "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8"
151 if expected != signingFlag {
152 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
153 }
154}
155
156func TestAndroidAppImport_DpiVariants(t *testing.T) {
157 bp := `
158 android_app_import {
159 name: "foo",
160 apk: "prebuilts/apk/app.apk",
161 dpi_variants: {
162 xhdpi: {
163 apk: "prebuilts/apk/app_xhdpi.apk",
164 },
165 xxhdpi: {
166 apk: "prebuilts/apk/app_xxhdpi.apk",
167 },
168 },
169 presigned: true,
170 dex_preopt: {
171 enabled: true,
172 },
173 }
174 `
175 testCases := []struct {
176 name string
177 aaptPreferredConfig *string
178 aaptPrebuiltDPI []string
179 expected string
180 }{
181 {
182 name: "no preferred",
183 aaptPreferredConfig: nil,
184 aaptPrebuiltDPI: []string{},
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000185 expected: "verify_uses_libraries/apk/app.apk",
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800186 },
187 {
188 name: "AAPTPreferredConfig matches",
189 aaptPreferredConfig: proptools.StringPtr("xhdpi"),
190 aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000191 expected: "verify_uses_libraries/apk/app_xhdpi.apk",
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800192 },
193 {
194 name: "AAPTPrebuiltDPI matches",
195 aaptPreferredConfig: proptools.StringPtr("mdpi"),
196 aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000197 expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800198 },
199 {
200 name: "non-first AAPTPrebuiltDPI matches",
201 aaptPreferredConfig: proptools.StringPtr("mdpi"),
202 aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000203 expected: "verify_uses_libraries/apk/app_xhdpi.apk",
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800204 },
205 {
206 name: "no matches",
207 aaptPreferredConfig: proptools.StringPtr("mdpi"),
208 aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000209 expected: "verify_uses_libraries/apk/app.apk",
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800210 },
211 }
212
213 jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
214 for _, test := range testCases {
215 config := testAppConfig(nil, bp, nil)
216 config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig
217 config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
218 ctx := testContext(config)
219
220 run(t, ctx, config)
221
222 variant := ctx.ModuleForTests("foo", "android_common")
223 jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
224 matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
225 if len(matches) != 2 {
226 t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
227 }
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000228 if strings.HasSuffix(matches[1], test.expected) {
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800229 t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
230 }
231 }
232}
233
234func TestAndroidAppImport_Filename(t *testing.T) {
235 ctx, config := testJava(t, `
236 android_app_import {
237 name: "foo",
238 apk: "prebuilts/apk/app.apk",
239 presigned: true,
240 }
241
242 android_app_import {
243 name: "bar",
244 apk: "prebuilts/apk/app.apk",
245 presigned: true,
246 filename: "bar_sample.apk"
247 }
248 `)
249
250 testCases := []struct {
251 name string
252 expected string
253 }{
254 {
255 name: "foo",
256 expected: "foo.apk",
257 },
258 {
259 name: "bar",
260 expected: "bar_sample.apk",
261 },
262 }
263
264 for _, test := range testCases {
265 variant := ctx.ModuleForTests(test.name, "android_common")
266 if variant.MaybeOutput(test.expected).Rule == nil {
267 t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs())
268 }
269
270 a := variant.Module().(*AndroidAppImport)
271 expectedValues := []string{test.expected}
272 actualValues := android.AndroidMkEntriesForTest(
273 t, config, "", a)[0].EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
274 if !reflect.DeepEqual(actualValues, expectedValues) {
275 t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
276 actualValues, expectedValues)
277 }
278 }
279}
280
281func TestAndroidAppImport_ArchVariants(t *testing.T) {
282 // The test config's target arch is ARM64.
283 testCases := []struct {
284 name string
285 bp string
286 expected string
287 }{
288 {
289 name: "matching arch",
290 bp: `
291 android_app_import {
292 name: "foo",
293 apk: "prebuilts/apk/app.apk",
294 arch: {
295 arm64: {
296 apk: "prebuilts/apk/app_arm64.apk",
297 },
298 },
299 presigned: true,
300 dex_preopt: {
301 enabled: true,
302 },
303 }
304 `,
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000305 expected: "verify_uses_libraries/apk/app_arm64.apk",
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800306 },
307 {
308 name: "no matching arch",
309 bp: `
310 android_app_import {
311 name: "foo",
312 apk: "prebuilts/apk/app.apk",
313 arch: {
314 arm: {
315 apk: "prebuilts/apk/app_arm.apk",
316 },
317 },
318 presigned: true,
319 dex_preopt: {
320 enabled: true,
321 },
322 }
323 `,
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000324 expected: "verify_uses_libraries/apk/app.apk",
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800325 },
326 {
327 name: "no matching arch without default",
328 bp: `
329 android_app_import {
330 name: "foo",
331 arch: {
332 arm: {
333 apk: "prebuilts/apk/app_arm.apk",
334 },
335 },
336 presigned: true,
337 dex_preopt: {
338 enabled: true,
339 },
340 }
341 `,
342 expected: "",
343 },
344 }
345
346 jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
347 for _, test := range testCases {
348 ctx, _ := testJava(t, test.bp)
349
350 variant := ctx.ModuleForTests("foo", "android_common")
351 if test.expected == "" {
352 if variant.Module().Enabled() {
353 t.Error("module should have been disabled, but wasn't")
354 }
355 continue
356 }
357 jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
358 matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
359 if len(matches) != 2 {
360 t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
361 }
Ulya Trafimovich22890c42021-01-05 12:04:17 +0000362 if strings.HasSuffix(matches[1], test.expected) {
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800363 t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
364 }
365 }
366}
367
368func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) {
369 ctx, _ := testJava(t, `
370 android_app {
371 name: "foo",
372 srcs: ["a.java"],
373 enabled: false,
374 }
375
376 android_app_import {
377 name: "foo",
378 apk: "prebuilts/apk/app.apk",
379 certificate: "platform",
380 prefer: true,
381 }
382 `)
383
384 variant := ctx.ModuleForTests("prebuilt_foo", "android_common")
385 a := variant.Module().(*AndroidAppImport)
386 // The prebuilt module should still be enabled and active even if the source-based counterpart
387 // is disabled.
388 if !a.prebuilt.UsePrebuilt() {
389 t.Errorf("prebuilt foo module is not active")
390 }
391 if !a.Enabled() {
392 t.Errorf("prebuilt foo module is disabled")
393 }
394}
395
Bill Peckhama036da92021-01-08 16:09:09 -0800396func TestAndroidAppImport_frameworkRes(t *testing.T) {
397 ctx, config := testJava(t, `
398 android_app_import {
399 name: "framework-res",
400 certificate: "platform",
401 apk: "package-res.apk",
402 prefer: true,
403 export_package_resources: true,
404 // Disable dexpreopt and verify_uses_libraries check as the app
405 // contains no Java code to be dexpreopted.
406 enforce_uses_libs: false,
407 dex_preopt: {
408 enabled: false,
409 },
410 }
411 `)
412
413 mod := ctx.ModuleForTests("prebuilt_framework-res", "android_common").Module()
414 a := mod.(*AndroidAppImport)
415
416 if !a.preprocessed {
417 t.Errorf("prebuilt framework-res is not preprocessed")
418 }
419
420 expectedInstallPath := buildDir + "/target/product/test_device/system/framework/framework-res.apk"
421
422 if a.dexpreopter.installPath.String() != expectedInstallPath {
423 t.Errorf("prebuilt framework-res installed to incorrect location, actual: %s, expected: %s", a.dexpreopter.installPath, expectedInstallPath)
424
425 }
426
427 entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
428
429 expectedPath := "."
430 // From apk property above, in the root of the source tree.
431 expectedPrebuiltModuleFile := "package-res.apk"
432 // Verify that the apk is preprocessed: The export package is the same
433 // as the prebuilt.
434 expectedSoongResourceExportPackage := expectedPrebuiltModuleFile
435
436 actualPath := entries.EntryMap["LOCAL_PATH"]
437 actualPrebuiltModuleFile := entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"]
438 actualSoongResourceExportPackage := entries.EntryMap["LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE"]
439
440 if len(actualPath) != 1 {
441 t.Errorf("LOCAL_PATH incorrect len %d", len(actualPath))
442 } else if actualPath[0] != expectedPath {
443 t.Errorf("LOCAL_PATH mismatch, actual: %s, expected: %s", actualPath[0], expectedPath)
444 }
445
446 if len(actualPrebuiltModuleFile) != 1 {
447 t.Errorf("LOCAL_PREBUILT_MODULE_FILE incorrect len %d", len(actualPrebuiltModuleFile))
448 } else if actualPrebuiltModuleFile[0] != expectedPrebuiltModuleFile {
449 t.Errorf("LOCAL_PREBUILT_MODULE_FILE mismatch, actual: %s, expected: %s", actualPrebuiltModuleFile[0], expectedPrebuiltModuleFile)
450 }
451
452 if len(actualSoongResourceExportPackage) != 1 {
453 t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE incorrect len %d", len(actualSoongResourceExportPackage))
454 } else if actualSoongResourceExportPackage[0] != expectedSoongResourceExportPackage {
455 t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE mismatch, actual: %s, expected: %s", actualSoongResourceExportPackage[0], expectedSoongResourceExportPackage)
456 }
457}
458
Jaewoong Jungf9b44652020-12-21 12:29:12 -0800459func TestAndroidTestImport(t *testing.T) {
460 ctx, config := testJava(t, `
461 android_test_import {
462 name: "foo",
463 apk: "prebuilts/apk/app.apk",
464 presigned: true,
465 data: [
466 "testdata/data",
467 ],
468 }
469 `)
470
471 test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport)
472
473 // Check android mks.
474 entries := android.AndroidMkEntriesForTest(t, config, "", test)[0]
475 expected := []string{"tests"}
476 actual := entries.EntryMap["LOCAL_MODULE_TAGS"]
477 if !reflect.DeepEqual(expected, actual) {
478 t.Errorf("Unexpected module tags - expected: %q, actual: %q", expected, actual)
479 }
480 expected = []string{"testdata/data:testdata/data"}
481 actual = entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
482 if !reflect.DeepEqual(expected, actual) {
483 t.Errorf("Unexpected test data - expected: %q, actual: %q", expected, actual)
484 }
485}
486
487func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) {
488 ctx, _ := testJava(t, `
489 android_test_import {
490 name: "foo",
491 apk: "prebuilts/apk/app.apk",
492 certificate: "cert/new_cert",
493 data: [
494 "testdata/data",
495 ],
496 }
497
498 android_test_import {
499 name: "foo_presigned",
500 apk: "prebuilts/apk/app.apk",
501 presigned: true,
502 data: [
503 "testdata/data",
504 ],
505 }
506 `)
507
508 variant := ctx.ModuleForTests("foo", "android_common")
509 jniRule := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
510 if !strings.HasPrefix(jniRule, "if (zipinfo") {
511 t.Errorf("Unexpected JNI uncompress rule command: " + jniRule)
512 }
513
514 variant = ctx.ModuleForTests("foo_presigned", "android_common")
515 jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String()
516 if jniRule != android.Cp.String() {
517 t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
518 }
519 if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil {
520 t.Errorf("Presigned test apk should be aligned")
521 }
522}
523
524func TestAndroidTestImport_Preprocessed(t *testing.T) {
525 ctx, _ := testJava(t, `
526 android_test_import {
527 name: "foo",
528 apk: "prebuilts/apk/app.apk",
529 presigned: true,
530 preprocessed: true,
531 }
532
533 android_test_import {
534 name: "foo_cert",
535 apk: "prebuilts/apk/app.apk",
536 certificate: "cert/new_cert",
537 preprocessed: true,
538 }
539 `)
540
541 testModules := []string{"foo", "foo_cert"}
542 for _, m := range testModules {
543 apkName := m + ".apk"
544 variant := ctx.ModuleForTests(m, "android_common")
545 jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
546 if jniRule != android.Cp.String() {
547 t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
548 }
549
550 // Make sure signing and aligning were skipped.
551 if variant.MaybeOutput("signed/"+apkName).Rule != nil {
552 t.Errorf("signing rule shouldn't be included for preprocessed.")
553 }
554 if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
555 t.Errorf("aligning rule shouldn't be for preprocessed")
556 }
557 }
558}