blob: 6bbaac09b79334e40e970ecfb30c52199dbe59f4 [file] [log] [blame]
Colin Cross3bc7ffa2017-11-22 16:19:37 -08001// Copyright 2017 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 "android/soong/android"
Colin Crossd09b0b62018-04-18 11:06:47 -070019 "fmt"
Colin Crossa4f08812018-10-02 22:03:40 -070020 "path/filepath"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080021 "reflect"
Colin Crossb69301e2017-12-01 10:48:26 -080022 "sort"
Colin Crossd09b0b62018-04-18 11:06:47 -070023 "strings"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080024 "testing"
25)
26
27var (
28 resourceFiles = []string{
29 "res/layout/layout.xml",
30 "res/values/strings.xml",
31 "res/values-en-rUS/strings.xml",
32 }
33
34 compiledResourceFiles = []string{
35 "aapt2/res/layout_layout.xml.flat",
36 "aapt2/res/values_strings.arsc.flat",
37 "aapt2/res/values-en-rUS_strings.arsc.flat",
38 }
39)
40
Colin Cross527012a2017-11-30 22:56:16 -080041func testAppContext(config android.Config, bp string, fs map[string][]byte) *android.TestContext {
42 appFS := map[string][]byte{}
43 for k, v := range fs {
44 appFS[k] = v
Colin Cross3bc7ffa2017-11-22 16:19:37 -080045 }
46
Colin Cross527012a2017-11-30 22:56:16 -080047 for _, file := range resourceFiles {
48 appFS[file] = nil
49 }
50
51 return testContext(config, bp, appFS)
52}
53
54func testApp(t *testing.T, bp string) *android.TestContext {
55 config := testConfig(nil)
56
57 ctx := testAppContext(config, bp, nil)
58
59 run(t, ctx, config)
60
61 return ctx
Colin Cross3bc7ffa2017-11-22 16:19:37 -080062}
63
64func TestApp(t *testing.T) {
Colin Crossa97c5d32018-03-28 14:58:31 -070065 for _, moduleType := range []string{"android_app", "android_library"} {
66 t.Run(moduleType, func(t *testing.T) {
67 ctx := testApp(t, moduleType+` {
68 name: "foo",
69 srcs: ["a.java"],
70 }
71 `)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080072
Colin Crossa97c5d32018-03-28 14:58:31 -070073 foo := ctx.ModuleForTests("foo", "android_common")
Colin Cross3bc7ffa2017-11-22 16:19:37 -080074
Colin Cross31656952018-05-24 16:11:20 -070075 var expectedLinkImplicits []string
76
77 manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
78 expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080079
Colin Crossa97c5d32018-03-28 14:58:31 -070080 frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
81 expectedLinkImplicits = append(expectedLinkImplicits,
82 frameworkRes.Output("package-res.apk").Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080083
Colin Crossa97c5d32018-03-28 14:58:31 -070084 // Test the mapping from input files to compiled output file names
85 compile := foo.Output(compiledResourceFiles[0])
86 if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
87 t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
88 resourceFiles, compile.Inputs.Strings())
89 }
Colin Crossb69301e2017-12-01 10:48:26 -080090
Colin Crossa97c5d32018-03-28 14:58:31 -070091 compiledResourceOutputs := compile.Outputs.Strings()
92 sort.Strings(compiledResourceOutputs)
Colin Crossb69301e2017-12-01 10:48:26 -080093
Colin Crossa97c5d32018-03-28 14:58:31 -070094 expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080095
Colin Crossa97c5d32018-03-28 14:58:31 -070096 list := foo.Output("aapt2/res.list")
97 expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080098
Colin Crossa97c5d32018-03-28 14:58:31 -070099 // Check that the link rule uses
100 res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
101 if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
102 t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
103 expectedLinkImplicits, res.Implicits.Strings())
104 }
105 })
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800106 }
107}
Colin Cross890ff552017-11-30 20:13:19 -0800108
Colin Cross890ff552017-11-30 20:13:19 -0800109func TestEnforceRRO(t *testing.T) {
Colin Cross5c4791c2019-02-01 11:44:44 -0800110 testCases := []struct {
111 name string
112 enforceRROTargets []string
113 enforceRROExcludedOverlays []string
114 overlayFiles map[string][]string
115 rroDirs map[string][]string
116 }{
117 {
118 name: "no RRO",
119 enforceRROTargets: nil,
120 enforceRROExcludedOverlays: nil,
121 overlayFiles: map[string][]string{
122 "foo": []string{
Colin Cross6ed7dea2019-01-31 14:44:30 -0800123 buildDir + "/.intermediates/lib/android_common/package-res.apk",
124 "foo/res/res/values/strings.xml",
Colin Cross5c4791c2019-02-01 11:44:44 -0800125 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
126 "device/vendor/blah/overlay/foo/res/values/strings.xml",
127 },
128 "bar": []string{
129 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
130 "device/vendor/blah/overlay/bar/res/values/strings.xml",
131 },
132 },
133 rroDirs: map[string][]string{
134 "foo": nil,
135 "bar": nil,
136 },
137 },
138 {
139 name: "enforce RRO on foo",
140 enforceRROTargets: []string{"foo"},
141 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
142 overlayFiles: map[string][]string{
Colin Cross6ed7dea2019-01-31 14:44:30 -0800143 "foo": []string{
144 buildDir + "/.intermediates/lib/android_common/package-res.apk",
145 "foo/res/res/values/strings.xml",
146 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
147 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800148 "bar": []string{
149 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
150 "device/vendor/blah/overlay/bar/res/values/strings.xml",
151 },
152 },
153 rroDirs: map[string][]string{
154 "foo": []string{"device/vendor/blah/overlay/foo/res"},
155 "bar": nil,
156 },
157 },
158 {
159 name: "enforce RRO on all",
160 enforceRROTargets: []string{"*"},
161 enforceRROExcludedOverlays: []string{
162 // Excluding specific apps/res directories also allowed.
163 "device/vendor/blah/static_overlay/foo",
164 "device/vendor/blah/static_overlay/bar/res",
165 },
166 overlayFiles: map[string][]string{
Colin Cross6ed7dea2019-01-31 14:44:30 -0800167 "foo": []string{
168 buildDir + "/.intermediates/lib/android_common/package-res.apk",
169 "foo/res/res/values/strings.xml",
170 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
171 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800172 "bar": []string{"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
173 },
174 rroDirs: map[string][]string{
175 "foo": []string{"device/vendor/blah/overlay/foo/res"},
176 "bar": []string{"device/vendor/blah/overlay/bar/res"},
177 },
178 },
179 }
180
Colin Cross890ff552017-11-30 20:13:19 -0800181 resourceOverlays := []string{
182 "device/vendor/blah/overlay",
183 "device/vendor/blah/overlay2",
184 "device/vendor/blah/static_overlay",
185 }
186
187 fs := map[string][]byte{
188 "foo/res/res/values/strings.xml": nil,
189 "bar/res/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800190 "lib/res/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800191 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
192 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800193 "device/vendor/blah/overlay/lib/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800194 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
195 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
196 "device/vendor/blah/overlay2/res/values/strings.xml": nil,
197 }
198
199 bp := `
200 android_app {
201 name: "foo",
202 resource_dirs: ["foo/res"],
Colin Cross6ed7dea2019-01-31 14:44:30 -0800203 static_libs: ["lib"],
Colin Cross890ff552017-11-30 20:13:19 -0800204 }
205
206 android_app {
207 name: "bar",
208 resource_dirs: ["bar/res"],
209 }
Colin Cross6ed7dea2019-01-31 14:44:30 -0800210
211 android_library {
212 name: "lib",
213 resource_dirs: ["lib/res"],
214 }
Colin Cross890ff552017-11-30 20:13:19 -0800215 `
216
Colin Cross5c4791c2019-02-01 11:44:44 -0800217 for _, testCase := range testCases {
Colin Cross890ff552017-11-30 20:13:19 -0800218 t.Run(testCase.name, func(t *testing.T) {
219 config := testConfig(nil)
Colin Crossa74ca042019-01-31 14:31:51 -0800220 config.TestProductVariables.ResourceOverlays = resourceOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800221 if testCase.enforceRROTargets != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800222 config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
Colin Cross890ff552017-11-30 20:13:19 -0800223 }
224 if testCase.enforceRROExcludedOverlays != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800225 config.TestProductVariables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800226 }
227
228 ctx := testAppContext(config, bp, fs)
229 run(t, ctx, config)
230
231 getOverlays := func(moduleName string) ([]string, []string) {
232 module := ctx.ModuleForTests(moduleName, "android_common")
Anton Hansson94c93f32019-01-30 16:03:37 +0000233 overlayFile := module.MaybeOutput("aapt2/overlay.list")
Colin Cross890ff552017-11-30 20:13:19 -0800234 var overlayFiles []string
Anton Hansson94c93f32019-01-30 16:03:37 +0000235 if overlayFile.Rule != nil {
236 for _, o := range overlayFile.Inputs.Strings() {
Colin Cross6ed7dea2019-01-31 14:44:30 -0800237 overlayOutput := module.MaybeOutput(o)
238 if overlayOutput.Rule != nil {
239 // If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
240 // verify the inputs to the .arsc.flat rule.
241 overlayFiles = append(overlayFiles, overlayOutput.Inputs.Strings()...)
242 } else {
243 // Otherwise, verify the full path to the output of the other module
244 overlayFiles = append(overlayFiles, o)
245 }
Anton Hansson94c93f32019-01-30 16:03:37 +0000246 }
Colin Cross890ff552017-11-30 20:13:19 -0800247 }
248
249 rroDirs := module.Module().(*AndroidApp).rroDirs.Strings()
250
251 return overlayFiles, rroDirs
252 }
253
Anton Hansson0375a4f2019-01-24 14:39:19 +0000254 apps := []string{"foo", "bar"}
255 for _, app := range apps {
256 overlayFiles, rroDirs := getOverlays(app)
Colin Cross890ff552017-11-30 20:13:19 -0800257
Anton Hansson0375a4f2019-01-24 14:39:19 +0000258 if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[app]) {
259 t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v",
260 app, testCase.overlayFiles[app], overlayFiles)
261 }
262 if !reflect.DeepEqual(rroDirs, testCase.rroDirs[app]) {
263 t.Errorf("expected %s rroDirs: %#v\n got:\n %#v",
264 app, testCase.rroDirs[app], rroDirs)
265 }
Colin Cross890ff552017-11-30 20:13:19 -0800266 }
Colin Cross890ff552017-11-30 20:13:19 -0800267 })
268 }
269}
Colin Crossd09b0b62018-04-18 11:06:47 -0700270
271func TestAppSdkVersion(t *testing.T) {
272 testCases := []struct {
273 name string
274 sdkVersion string
275 platformSdkInt int
276 platformSdkCodename string
277 platformSdkFinal bool
278 expectedMinSdkVersion string
279 }{
280 {
281 name: "current final SDK",
282 sdkVersion: "current",
283 platformSdkInt: 27,
284 platformSdkCodename: "REL",
285 platformSdkFinal: true,
286 expectedMinSdkVersion: "27",
287 },
288 {
289 name: "current non-final SDK",
290 sdkVersion: "current",
291 platformSdkInt: 27,
292 platformSdkCodename: "OMR1",
293 platformSdkFinal: false,
294 expectedMinSdkVersion: "OMR1",
295 },
296 {
297 name: "default final SDK",
298 sdkVersion: "",
299 platformSdkInt: 27,
300 platformSdkCodename: "REL",
301 platformSdkFinal: true,
302 expectedMinSdkVersion: "27",
303 },
304 {
305 name: "default non-final SDK",
306 sdkVersion: "",
307 platformSdkInt: 27,
308 platformSdkCodename: "OMR1",
309 platformSdkFinal: false,
310 expectedMinSdkVersion: "OMR1",
311 },
312 {
313 name: "14",
314 sdkVersion: "14",
315 expectedMinSdkVersion: "14",
316 },
317 }
318
319 for _, moduleType := range []string{"android_app", "android_library"} {
320 for _, test := range testCases {
321 t.Run(moduleType+" "+test.name, func(t *testing.T) {
322 bp := fmt.Sprintf(`%s {
323 name: "foo",
324 srcs: ["a.java"],
325 sdk_version: "%s",
326 }`, moduleType, test.sdkVersion)
327
328 config := testConfig(nil)
329 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
330 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
331 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
332
333 ctx := testAppContext(config, bp, nil)
334
335 run(t, ctx, config)
336
337 foo := ctx.ModuleForTests("foo", "android_common")
338 link := foo.Output("package-res.apk")
339 linkFlags := strings.Split(link.Args["flags"], " ")
340 min := android.IndexList("--min-sdk-version", linkFlags)
341 target := android.IndexList("--target-sdk-version", linkFlags)
342
343 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
344 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
345 }
346
347 gotMinSdkVersion := linkFlags[min+1]
348 gotTargetSdkVersion := linkFlags[target+1]
349
350 if gotMinSdkVersion != test.expectedMinSdkVersion {
351 t.Errorf("incorrect --min-sdk-version, expected %q got %q",
352 test.expectedMinSdkVersion, gotMinSdkVersion)
353 }
354
355 if gotTargetSdkVersion != test.expectedMinSdkVersion {
356 t.Errorf("incorrect --target-sdk-version, expected %q got %q",
357 test.expectedMinSdkVersion, gotTargetSdkVersion)
358 }
359 })
360 }
361 }
362}
Colin Crossa4f08812018-10-02 22:03:40 -0700363
364func TestJNI(t *testing.T) {
365 ctx := testJava(t, `
366 toolchain_library {
367 name: "libcompiler_rt-extras",
368 src: "",
369 }
370
371 toolchain_library {
372 name: "libatomic",
373 src: "",
374 }
375
376 toolchain_library {
377 name: "libgcc",
378 src: "",
379 }
380
381 toolchain_library {
382 name: "libclang_rt.builtins-aarch64-android",
383 src: "",
384 }
385
386 toolchain_library {
387 name: "libclang_rt.builtins-arm-android",
388 src: "",
389 }
390
391 cc_object {
392 name: "crtbegin_so",
393 stl: "none",
394 }
395
396 cc_object {
397 name: "crtend_so",
398 stl: "none",
399 }
400
401 cc_library {
402 name: "libjni",
403 system_shared_libs: [],
404 stl: "none",
405 }
406
407 android_test {
408 name: "test",
409 no_framework_libs: true,
410 jni_libs: ["libjni"],
411 }
412
413 android_test {
414 name: "test_first",
415 no_framework_libs: true,
416 compile_multilib: "first",
417 jni_libs: ["libjni"],
418 }
419
420 android_test {
421 name: "test_both",
422 no_framework_libs: true,
423 compile_multilib: "both",
424 jni_libs: ["libjni"],
425 }
426
427 android_test {
428 name: "test_32",
429 no_framework_libs: true,
430 compile_multilib: "32",
431 jni_libs: ["libjni"],
432 }
433
434 android_test {
435 name: "test_64",
436 no_framework_libs: true,
437 compile_multilib: "64",
438 jni_libs: ["libjni"],
439 }
440 `)
441
442 // check the existence of the internal modules
443 ctx.ModuleForTests("test", "android_common")
444 ctx.ModuleForTests("test_first", "android_common")
445 ctx.ModuleForTests("test_both", "android_common")
446 ctx.ModuleForTests("test_32", "android_common")
447 ctx.ModuleForTests("test_64", "android_common")
448
449 testCases := []struct {
450 name string
451 abis []string
452 }{
453 {"test", []string{"arm64-v8a"}},
454 {"test_first", []string{"arm64-v8a"}},
455 {"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
456 {"test_32", []string{"armeabi-v7a"}},
457 {"test_64", []string{"arm64-v8a"}},
458 }
459
460 for _, test := range testCases {
461 t.Run(test.name, func(t *testing.T) {
462 app := ctx.ModuleForTests(test.name, "android_common")
463 jniLibZip := app.Output("jnilibs.zip")
464 var abis []string
465 args := strings.Fields(jniLibZip.Args["jarArgs"])
466 for i := 0; i < len(args); i++ {
467 if args[i] == "-P" {
468 abis = append(abis, filepath.Base(args[i+1]))
469 i++
470 }
471 }
472 if !reflect.DeepEqual(abis, test.abis) {
473 t.Errorf("want abis %v, got %v", test.abis, abis)
474 }
475 })
476 }
477}
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800478
479func TestCertificates(t *testing.T) {
480 testCases := []struct {
481 name string
482 bp string
483 certificateOverride string
484 expected string
485 }{
486 {
487 name: "default",
488 bp: `
489 android_app {
490 name: "foo",
491 srcs: ["a.java"],
492 }
493 `,
494 certificateOverride: "",
495 expected: "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
496 },
497 {
498 name: "module certificate property",
499 bp: `
500 android_app {
501 name: "foo",
502 srcs: ["a.java"],
503 certificate: ":new_certificate"
504 }
505
506 android_app_certificate {
507 name: "new_certificate",
508 certificate: "cert/new_cert",
509 }
510 `,
511 certificateOverride: "",
512 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
513 },
514 {
515 name: "path certificate property",
516 bp: `
517 android_app {
518 name: "foo",
519 srcs: ["a.java"],
520 certificate: "expiredkey"
521 }
522 `,
523 certificateOverride: "",
524 expected: "build/target/product/security/expiredkey.x509.pem build/target/product/security/expiredkey.pk8",
525 },
526 {
527 name: "certificate overrides",
528 bp: `
529 android_app {
530 name: "foo",
531 srcs: ["a.java"],
532 certificate: "expiredkey"
533 }
534
535 android_app_certificate {
536 name: "new_certificate",
537 certificate: "cert/new_cert",
538 }
539 `,
540 certificateOverride: "foo:new_certificate",
541 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
542 },
543 }
544
545 for _, test := range testCases {
546 t.Run(test.name, func(t *testing.T) {
547 config := testConfig(nil)
548 if test.certificateOverride != "" {
549 config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride}
550 }
551 ctx := testAppContext(config, test.bp, nil)
552
553 run(t, ctx, config)
554 foo := ctx.ModuleForTests("foo", "android_common")
555
556 signapk := foo.Output("foo.apk")
557 signFlags := signapk.Args["certificates"]
558 if test.expected != signFlags {
559 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags)
560 }
561 })
562 }
563}
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800564
565func TestPackageNameOverride(t *testing.T) {
566 testCases := []struct {
567 name string
568 bp string
569 packageNameOverride string
570 expected []string
571 }{
572 {
573 name: "default",
574 bp: `
575 android_app {
576 name: "foo",
577 srcs: ["a.java"],
578 }
579 `,
580 packageNameOverride: "",
581 expected: []string{
582 buildDir + "/.intermediates/foo/android_common/foo.apk",
583 buildDir + "/target/product/test_device/system/app/foo/foo.apk",
584 },
585 },
586 {
587 name: "overridden",
588 bp: `
589 android_app {
590 name: "foo",
591 srcs: ["a.java"],
592 }
593 `,
594 packageNameOverride: "foo:bar",
595 expected: []string{
596 // The package apk should be still be the original name for test dependencies.
597 buildDir + "/.intermediates/foo/android_common/foo.apk",
598 buildDir + "/target/product/test_device/system/app/bar/bar.apk",
599 },
600 },
601 }
602
603 for _, test := range testCases {
604 t.Run(test.name, func(t *testing.T) {
605 config := testConfig(nil)
606 if test.packageNameOverride != "" {
607 config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride}
608 }
609 ctx := testAppContext(config, test.bp, nil)
610
611 run(t, ctx, config)
612 foo := ctx.ModuleForTests("foo", "android_common")
613
614 outputs := foo.AllOutputs()
615 outputMap := make(map[string]bool)
616 for _, o := range outputs {
617 outputMap[o] = true
618 }
619 for _, e := range test.expected {
620 if _, exist := outputMap[e]; !exist {
621 t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
622 }
623 }
624 })
625 }
626}