blob: 9acbd02cc595463acd16780cf7a2e1a40d7d59bb [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 (
Colin Crossd09b0b62018-04-18 11:06:47 -070018 "fmt"
Colin Crossa4f08812018-10-02 22:03:40 -070019 "path/filepath"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080020 "reflect"
Jaewoong Junga5e5abc2019-04-26 14:31:50 -070021 "regexp"
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"
Jaewoong Junga5e5abc2019-04-26 14:31:50 -070025
26 "github.com/google/blueprint/proptools"
27
28 "android/soong/android"
29 "android/soong/cc"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080030)
31
32var (
33 resourceFiles = []string{
34 "res/layout/layout.xml",
35 "res/values/strings.xml",
36 "res/values-en-rUS/strings.xml",
37 }
38
39 compiledResourceFiles = []string{
40 "aapt2/res/layout_layout.xml.flat",
41 "aapt2/res/values_strings.arsc.flat",
42 "aapt2/res/values-en-rUS_strings.arsc.flat",
43 }
44)
45
Colin Cross527012a2017-11-30 22:56:16 -080046func testAppContext(config android.Config, bp string, fs map[string][]byte) *android.TestContext {
47 appFS := map[string][]byte{}
48 for k, v := range fs {
49 appFS[k] = v
Colin Cross3bc7ffa2017-11-22 16:19:37 -080050 }
51
Colin Cross527012a2017-11-30 22:56:16 -080052 for _, file := range resourceFiles {
53 appFS[file] = nil
54 }
55
56 return testContext(config, bp, appFS)
57}
58
59func testApp(t *testing.T, bp string) *android.TestContext {
60 config := testConfig(nil)
61
62 ctx := testAppContext(config, bp, nil)
63
64 run(t, ctx, config)
65
66 return ctx
Colin Cross3bc7ffa2017-11-22 16:19:37 -080067}
68
69func TestApp(t *testing.T) {
Colin Crossa97c5d32018-03-28 14:58:31 -070070 for _, moduleType := range []string{"android_app", "android_library"} {
71 t.Run(moduleType, func(t *testing.T) {
72 ctx := testApp(t, moduleType+` {
73 name: "foo",
74 srcs: ["a.java"],
75 }
76 `)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080077
Colin Crossa97c5d32018-03-28 14:58:31 -070078 foo := ctx.ModuleForTests("foo", "android_common")
Colin Cross3bc7ffa2017-11-22 16:19:37 -080079
Colin Cross31656952018-05-24 16:11:20 -070080 var expectedLinkImplicits []string
81
82 manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
83 expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080084
Colin Crossa97c5d32018-03-28 14:58:31 -070085 frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
86 expectedLinkImplicits = append(expectedLinkImplicits,
87 frameworkRes.Output("package-res.apk").Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080088
Colin Crossa97c5d32018-03-28 14:58:31 -070089 // Test the mapping from input files to compiled output file names
90 compile := foo.Output(compiledResourceFiles[0])
91 if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
92 t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
93 resourceFiles, compile.Inputs.Strings())
94 }
Colin Crossb69301e2017-12-01 10:48:26 -080095
Colin Crossa97c5d32018-03-28 14:58:31 -070096 compiledResourceOutputs := compile.Outputs.Strings()
97 sort.Strings(compiledResourceOutputs)
Colin Crossb69301e2017-12-01 10:48:26 -080098
Colin Crossa97c5d32018-03-28 14:58:31 -070099 expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800100
Colin Crossa97c5d32018-03-28 14:58:31 -0700101 list := foo.Output("aapt2/res.list")
102 expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800103
Colin Crossa97c5d32018-03-28 14:58:31 -0700104 // Check that the link rule uses
105 res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
106 if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
107 t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
108 expectedLinkImplicits, res.Implicits.Strings())
109 }
110 })
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800111 }
112}
Colin Cross890ff552017-11-30 20:13:19 -0800113
Colin Crosse560c4a2019-03-19 16:03:11 -0700114func TestAppSplits(t *testing.T) {
115 ctx := testApp(t, `
116 android_app {
117 name: "foo",
118 srcs: ["a.java"],
119 package_splits: ["v4", "v7,hdpi"],
120 }`)
121
122 foo := ctx.ModuleForTests("foo", "android_common")
123
124 expectedOutputs := []string{
125 filepath.Join(buildDir, ".intermediates/foo/android_common/foo.apk"),
126 filepath.Join(buildDir, ".intermediates/foo/android_common/foo_v4.apk"),
127 filepath.Join(buildDir, ".intermediates/foo/android_common/foo_v7_hdpi.apk"),
128 }
129 for _, expectedOutput := range expectedOutputs {
130 foo.Output(expectedOutput)
131 }
132
Colin Cross41955e82019-05-29 14:40:35 -0700133 outputFiles, err := foo.Module().(*AndroidApp).OutputFiles("")
134 if err != nil {
135 t.Fatal(err)
136 }
137 if g, w := outputFiles.Strings(), expectedOutputs; !reflect.DeepEqual(g, w) {
138 t.Errorf(`want OutputFiles("") = %q, got %q`, w, g)
Colin Crosse560c4a2019-03-19 16:03:11 -0700139 }
140}
141
Colin Cross0ddae7f2019-02-07 15:30:01 -0800142func TestResourceDirs(t *testing.T) {
143 testCases := []struct {
144 name string
145 prop string
146 resources []string
147 }{
148 {
149 name: "no resource_dirs",
150 prop: "",
151 resources: []string{"res/res/values/strings.xml"},
152 },
153 {
154 name: "resource_dirs",
155 prop: `resource_dirs: ["res"]`,
156 resources: []string{"res/res/values/strings.xml"},
157 },
158 {
159 name: "empty resource_dirs",
160 prop: `resource_dirs: []`,
161 resources: nil,
162 },
163 }
164
165 fs := map[string][]byte{
166 "res/res/values/strings.xml": nil,
167 }
168
169 bp := `
170 android_app {
171 name: "foo",
172 %s
173 }
174 `
175
176 for _, testCase := range testCases {
177 t.Run(testCase.name, func(t *testing.T) {
178 config := testConfig(nil)
179 ctx := testContext(config, fmt.Sprintf(bp, testCase.prop), fs)
180 run(t, ctx, config)
181
182 module := ctx.ModuleForTests("foo", "android_common")
183 resourceList := module.MaybeOutput("aapt2/res.list")
184
185 var resources []string
186 if resourceList.Rule != nil {
187 for _, compiledResource := range resourceList.Inputs.Strings() {
188 resources = append(resources, module.Output(compiledResource).Inputs.Strings()...)
189 }
190 }
191
192 if !reflect.DeepEqual(resources, testCase.resources) {
193 t.Errorf("expected resource files %q, got %q",
194 testCase.resources, resources)
195 }
196 })
197 }
198}
199
Colin Crossbec85302019-02-13 13:15:46 -0800200func TestAndroidResources(t *testing.T) {
Colin Cross5c4791c2019-02-01 11:44:44 -0800201 testCases := []struct {
202 name string
203 enforceRROTargets []string
204 enforceRROExcludedOverlays []string
Colin Crossbec85302019-02-13 13:15:46 -0800205 resourceFiles map[string][]string
Colin Cross5c4791c2019-02-01 11:44:44 -0800206 overlayFiles map[string][]string
207 rroDirs map[string][]string
208 }{
209 {
210 name: "no RRO",
211 enforceRROTargets: nil,
212 enforceRROExcludedOverlays: nil,
Colin Crossbec85302019-02-13 13:15:46 -0800213 resourceFiles: map[string][]string{
214 "foo": nil,
215 "bar": {"bar/res/res/values/strings.xml"},
216 "lib": nil,
217 "lib2": {"lib2/res/res/values/strings.xml"},
218 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800219 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800220 "foo": {
221 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800222 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000223 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800224 "foo/res/res/values/strings.xml",
Colin Cross5c4791c2019-02-01 11:44:44 -0800225 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
226 "device/vendor/blah/overlay/foo/res/values/strings.xml",
Anton Hansson53c88442019-03-18 15:53:16 +0000227 "product/vendor/blah/overlay/foo/res/values/strings.xml",
Colin Cross5c4791c2019-02-01 11:44:44 -0800228 },
Colin Crossbec85302019-02-13 13:15:46 -0800229 "bar": {
Colin Cross5c4791c2019-02-01 11:44:44 -0800230 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
231 "device/vendor/blah/overlay/bar/res/values/strings.xml",
232 },
Colin Crossbec85302019-02-13 13:15:46 -0800233 "lib": {
234 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
235 "lib/res/res/values/strings.xml",
236 "device/vendor/blah/overlay/lib/res/values/strings.xml",
237 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800238 },
239 rroDirs: map[string][]string{
240 "foo": nil,
241 "bar": nil,
242 },
243 },
244 {
245 name: "enforce RRO on foo",
246 enforceRROTargets: []string{"foo"},
247 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
Colin Crossbec85302019-02-13 13:15:46 -0800248 resourceFiles: map[string][]string{
249 "foo": nil,
250 "bar": {"bar/res/res/values/strings.xml"},
251 "lib": nil,
252 "lib2": {"lib2/res/res/values/strings.xml"},
253 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800254 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800255 "foo": {
256 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800257 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000258 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800259 "foo/res/res/values/strings.xml",
260 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
261 },
Colin Crossbec85302019-02-13 13:15:46 -0800262 "bar": {
Colin Cross5c4791c2019-02-01 11:44:44 -0800263 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
264 "device/vendor/blah/overlay/bar/res/values/strings.xml",
265 },
Colin Crossbec85302019-02-13 13:15:46 -0800266 "lib": {
267 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
268 "lib/res/res/values/strings.xml",
269 "device/vendor/blah/overlay/lib/res/values/strings.xml",
270 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800271 },
Colin Crossc1c37552019-01-31 11:42:41 -0800272
Colin Cross5c4791c2019-02-01 11:44:44 -0800273 rroDirs: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800274 "foo": {
Anton Hansson53c88442019-03-18 15:53:16 +0000275 "device:device/vendor/blah/overlay/foo/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800276 // Enforce RRO on "foo" could imply RRO on static dependencies, but for now it doesn't.
277 // "device/vendor/blah/overlay/lib/res",
Anton Hansson53c88442019-03-18 15:53:16 +0000278 "product:product/vendor/blah/overlay/foo/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800279 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800280 "bar": nil,
Colin Crossbec85302019-02-13 13:15:46 -0800281 "lib": nil,
Colin Cross5c4791c2019-02-01 11:44:44 -0800282 },
283 },
284 {
285 name: "enforce RRO on all",
286 enforceRROTargets: []string{"*"},
287 enforceRROExcludedOverlays: []string{
288 // Excluding specific apps/res directories also allowed.
289 "device/vendor/blah/static_overlay/foo",
290 "device/vendor/blah/static_overlay/bar/res",
291 },
Colin Crossbec85302019-02-13 13:15:46 -0800292 resourceFiles: map[string][]string{
293 "foo": nil,
294 "bar": {"bar/res/res/values/strings.xml"},
295 "lib": nil,
296 "lib2": {"lib2/res/res/values/strings.xml"},
297 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800298 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800299 "foo": {
300 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800301 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000302 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800303 "foo/res/res/values/strings.xml",
304 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
305 },
Colin Crossbec85302019-02-13 13:15:46 -0800306 "bar": {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
307 "lib": {
308 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
309 "lib/res/res/values/strings.xml",
310 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800311 },
312 rroDirs: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800313 "foo": {
Anton Hansson53c88442019-03-18 15:53:16 +0000314 "device:device/vendor/blah/overlay/foo/res",
315 "product:product/vendor/blah/overlay/foo/res",
316 // Lib dep comes after the direct deps
317 "device:device/vendor/blah/overlay/lib/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800318 },
Anton Hansson53c88442019-03-18 15:53:16 +0000319 "bar": {"device:device/vendor/blah/overlay/bar/res"},
320 "lib": {"device:device/vendor/blah/overlay/lib/res"},
Colin Cross5c4791c2019-02-01 11:44:44 -0800321 },
322 },
323 }
324
Anton Hansson53c88442019-03-18 15:53:16 +0000325 deviceResourceOverlays := []string{
Colin Cross890ff552017-11-30 20:13:19 -0800326 "device/vendor/blah/overlay",
327 "device/vendor/blah/overlay2",
328 "device/vendor/blah/static_overlay",
329 }
330
Anton Hansson53c88442019-03-18 15:53:16 +0000331 productResourceOverlays := []string{
332 "product/vendor/blah/overlay",
333 }
334
Colin Cross890ff552017-11-30 20:13:19 -0800335 fs := map[string][]byte{
336 "foo/res/res/values/strings.xml": nil,
337 "bar/res/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800338 "lib/res/res/values/strings.xml": nil,
Colin Crossbec85302019-02-13 13:15:46 -0800339 "lib2/res/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800340 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
341 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800342 "device/vendor/blah/overlay/lib/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800343 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
344 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
345 "device/vendor/blah/overlay2/res/values/strings.xml": nil,
Anton Hansson53c88442019-03-18 15:53:16 +0000346 "product/vendor/blah/overlay/foo/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800347 }
348
349 bp := `
350 android_app {
351 name: "foo",
352 resource_dirs: ["foo/res"],
Anton Hansson53c88442019-03-18 15:53:16 +0000353 static_libs: ["lib", "lib3"],
Colin Cross890ff552017-11-30 20:13:19 -0800354 }
355
356 android_app {
357 name: "bar",
358 resource_dirs: ["bar/res"],
359 }
Colin Cross6ed7dea2019-01-31 14:44:30 -0800360
361 android_library {
362 name: "lib",
363 resource_dirs: ["lib/res"],
Colin Crossbec85302019-02-13 13:15:46 -0800364 static_libs: ["lib2"],
365 }
366
367 android_library {
368 name: "lib2",
369 resource_dirs: ["lib2/res"],
Colin Cross6ed7dea2019-01-31 14:44:30 -0800370 }
Anton Hansson53c88442019-03-18 15:53:16 +0000371
372 // This library has the same resources as lib (should not lead to dupe RROs)
373 android_library {
374 name: "lib3",
375 resource_dirs: ["lib/res"]
376 }
Colin Cross890ff552017-11-30 20:13:19 -0800377 `
378
Colin Cross5c4791c2019-02-01 11:44:44 -0800379 for _, testCase := range testCases {
Colin Cross890ff552017-11-30 20:13:19 -0800380 t.Run(testCase.name, func(t *testing.T) {
381 config := testConfig(nil)
Anton Hansson53c88442019-03-18 15:53:16 +0000382 config.TestProductVariables.DeviceResourceOverlays = deviceResourceOverlays
383 config.TestProductVariables.ProductResourceOverlays = productResourceOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800384 if testCase.enforceRROTargets != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800385 config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
Colin Cross890ff552017-11-30 20:13:19 -0800386 }
387 if testCase.enforceRROExcludedOverlays != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800388 config.TestProductVariables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800389 }
390
391 ctx := testAppContext(config, bp, fs)
392 run(t, ctx, config)
393
Colin Crossbec85302019-02-13 13:15:46 -0800394 resourceListToFiles := func(module android.TestingModule, list []string) (files []string) {
395 for _, o := range list {
396 res := module.MaybeOutput(o)
397 if res.Rule != nil {
398 // If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
399 // verify the inputs to the .arsc.flat rule.
400 files = append(files, res.Inputs.Strings()...)
401 } else {
402 // Otherwise, verify the full path to the output of the other module
403 files = append(files, o)
Anton Hansson94c93f32019-01-30 16:03:37 +0000404 }
Colin Cross890ff552017-11-30 20:13:19 -0800405 }
Colin Crossbec85302019-02-13 13:15:46 -0800406 return files
Colin Cross890ff552017-11-30 20:13:19 -0800407 }
408
Colin Crossbec85302019-02-13 13:15:46 -0800409 getResources := func(moduleName string) (resourceFiles, overlayFiles, rroDirs []string) {
410 module := ctx.ModuleForTests(moduleName, "android_common")
411 resourceList := module.MaybeOutput("aapt2/res.list")
412 if resourceList.Rule != nil {
413 resourceFiles = resourceListToFiles(module, resourceList.Inputs.Strings())
Anton Hansson0375a4f2019-01-24 14:39:19 +0000414 }
Colin Crossbec85302019-02-13 13:15:46 -0800415 overlayList := module.MaybeOutput("aapt2/overlay.list")
416 if overlayList.Rule != nil {
417 overlayFiles = resourceListToFiles(module, overlayList.Inputs.Strings())
418 }
419
Anton Hansson53c88442019-03-18 15:53:16 +0000420 for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() {
421 var prefix string
422 if d.overlayType == device {
423 prefix = "device:"
424 } else if d.overlayType == product {
425 prefix = "product:"
426 } else {
427 t.Fatalf("Unexpected overlayType %d", d.overlayType)
428 }
429 rroDirs = append(rroDirs, prefix+d.path.String())
430 }
Colin Crossbec85302019-02-13 13:15:46 -0800431
432 return resourceFiles, overlayFiles, rroDirs
433 }
434
435 modules := []string{"foo", "bar", "lib", "lib2"}
436 for _, module := range modules {
437 resourceFiles, overlayFiles, rroDirs := getResources(module)
438
439 if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[module]) {
440 t.Errorf("expected %s resource files:\n %#v\n got:\n %#v",
441 module, testCase.resourceFiles[module], resourceFiles)
442 }
443 if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[module]) {
444 t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v",
445 module, testCase.overlayFiles[module], overlayFiles)
446 }
447 if !reflect.DeepEqual(rroDirs, testCase.rroDirs[module]) {
Anton Hansson0375a4f2019-01-24 14:39:19 +0000448 t.Errorf("expected %s rroDirs: %#v\n got:\n %#v",
Colin Crossbec85302019-02-13 13:15:46 -0800449 module, testCase.rroDirs[module], rroDirs)
Anton Hansson0375a4f2019-01-24 14:39:19 +0000450 }
Colin Cross890ff552017-11-30 20:13:19 -0800451 }
Colin Cross890ff552017-11-30 20:13:19 -0800452 })
453 }
454}
Colin Crossd09b0b62018-04-18 11:06:47 -0700455
456func TestAppSdkVersion(t *testing.T) {
457 testCases := []struct {
458 name string
459 sdkVersion string
460 platformSdkInt int
461 platformSdkCodename string
462 platformSdkFinal bool
463 expectedMinSdkVersion string
464 }{
465 {
466 name: "current final SDK",
467 sdkVersion: "current",
468 platformSdkInt: 27,
469 platformSdkCodename: "REL",
470 platformSdkFinal: true,
471 expectedMinSdkVersion: "27",
472 },
473 {
474 name: "current non-final SDK",
475 sdkVersion: "current",
476 platformSdkInt: 27,
477 platformSdkCodename: "OMR1",
478 platformSdkFinal: false,
479 expectedMinSdkVersion: "OMR1",
480 },
481 {
482 name: "default final SDK",
483 sdkVersion: "",
484 platformSdkInt: 27,
485 platformSdkCodename: "REL",
486 platformSdkFinal: true,
487 expectedMinSdkVersion: "27",
488 },
489 {
490 name: "default non-final SDK",
491 sdkVersion: "",
492 platformSdkInt: 27,
493 platformSdkCodename: "OMR1",
494 platformSdkFinal: false,
495 expectedMinSdkVersion: "OMR1",
496 },
497 {
498 name: "14",
499 sdkVersion: "14",
500 expectedMinSdkVersion: "14",
501 },
502 }
503
504 for _, moduleType := range []string{"android_app", "android_library"} {
505 for _, test := range testCases {
506 t.Run(moduleType+" "+test.name, func(t *testing.T) {
507 bp := fmt.Sprintf(`%s {
508 name: "foo",
509 srcs: ["a.java"],
510 sdk_version: "%s",
511 }`, moduleType, test.sdkVersion)
512
513 config := testConfig(nil)
514 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
515 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
516 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
517
518 ctx := testAppContext(config, bp, nil)
519
520 run(t, ctx, config)
521
522 foo := ctx.ModuleForTests("foo", "android_common")
523 link := foo.Output("package-res.apk")
524 linkFlags := strings.Split(link.Args["flags"], " ")
525 min := android.IndexList("--min-sdk-version", linkFlags)
526 target := android.IndexList("--target-sdk-version", linkFlags)
527
528 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
529 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
530 }
531
532 gotMinSdkVersion := linkFlags[min+1]
533 gotTargetSdkVersion := linkFlags[target+1]
534
535 if gotMinSdkVersion != test.expectedMinSdkVersion {
536 t.Errorf("incorrect --min-sdk-version, expected %q got %q",
537 test.expectedMinSdkVersion, gotMinSdkVersion)
538 }
539
540 if gotTargetSdkVersion != test.expectedMinSdkVersion {
541 t.Errorf("incorrect --target-sdk-version, expected %q got %q",
542 test.expectedMinSdkVersion, gotTargetSdkVersion)
543 }
544 })
545 }
546 }
547}
Colin Crossa4f08812018-10-02 22:03:40 -0700548
Paul Duffin50c217c2019-06-12 13:25:22 +0100549func TestJNIABI(t *testing.T) {
550 ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
551 cc_library {
552 name: "libjni",
553 system_shared_libs: [],
554 stl: "none",
555 }
556
557 android_test {
558 name: "test",
559 sdk_version: "core_platform",
560 jni_libs: ["libjni"],
561 }
562
563 android_test {
564 name: "test_first",
565 sdk_version: "core_platform",
566 compile_multilib: "first",
567 jni_libs: ["libjni"],
568 }
569
570 android_test {
571 name: "test_both",
572 sdk_version: "core_platform",
573 compile_multilib: "both",
574 jni_libs: ["libjni"],
575 }
576
577 android_test {
578 name: "test_32",
579 sdk_version: "core_platform",
580 compile_multilib: "32",
581 jni_libs: ["libjni"],
582 }
583
584 android_test {
585 name: "test_64",
586 sdk_version: "core_platform",
587 compile_multilib: "64",
588 jni_libs: ["libjni"],
589 }
590 `)
591
592 testCases := []struct {
593 name string
594 abis []string
595 }{
596 {"test", []string{"arm64-v8a"}},
597 {"test_first", []string{"arm64-v8a"}},
598 {"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
599 {"test_32", []string{"armeabi-v7a"}},
600 {"test_64", []string{"arm64-v8a"}},
601 }
602
603 for _, test := range testCases {
604 t.Run(test.name, func(t *testing.T) {
605 app := ctx.ModuleForTests(test.name, "android_common")
606 jniLibZip := app.Output("jnilibs.zip")
607 var abis []string
608 args := strings.Fields(jniLibZip.Args["jarArgs"])
609 for i := 0; i < len(args); i++ {
610 if args[i] == "-P" {
611 abis = append(abis, filepath.Base(args[i+1]))
612 i++
613 }
614 }
615 if !reflect.DeepEqual(abis, test.abis) {
616 t.Errorf("want abis %v, got %v", test.abis, abis)
617 }
618 })
619 }
620}
621
Paul Duffin50c217c2019-06-12 13:25:22 +0100622func TestJNIPackaging(t *testing.T) {
623 ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
624 cc_library {
625 name: "libjni",
626 system_shared_libs: [],
627 stl: "none",
628 }
629
630 android_app {
631 name: "app",
632 jni_libs: ["libjni"],
633 }
634
635 android_app {
636 name: "app_noembed",
637 jni_libs: ["libjni"],
638 use_embedded_native_libs: false,
639 }
640
641 android_app {
642 name: "app_embed",
643 jni_libs: ["libjni"],
644 use_embedded_native_libs: true,
645 }
646
647 android_test {
648 name: "test",
649 sdk_version: "core_platform",
650 jni_libs: ["libjni"],
651 }
652
653 android_test {
654 name: "test_noembed",
655 sdk_version: "core_platform",
656 jni_libs: ["libjni"],
657 use_embedded_native_libs: false,
658 }
659
660 android_test_helper_app {
661 name: "test_helper",
662 sdk_version: "core_platform",
663 jni_libs: ["libjni"],
664 }
665
666 android_test_helper_app {
667 name: "test_helper_noembed",
668 sdk_version: "core_platform",
669 jni_libs: ["libjni"],
670 use_embedded_native_libs: false,
671 }
672 `)
673
674 testCases := []struct {
675 name string
676 packaged bool
677 compressed bool
678 }{
679 {"app", false, false},
680 {"app_noembed", false, false},
681 {"app_embed", true, false},
682 {"test", true, false},
683 {"test_noembed", true, true},
684 {"test_helper", true, false},
685 {"test_helper_noembed", true, true},
686 }
687
688 for _, test := range testCases {
689 t.Run(test.name, func(t *testing.T) {
690 app := ctx.ModuleForTests(test.name, "android_common")
691 jniLibZip := app.MaybeOutput("jnilibs.zip")
692 if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
693 t.Errorf("expected jni packaged %v, got %v", w, g)
694 }
695
696 if jniLibZip.Rule != nil {
697 if g, w := !strings.Contains(jniLibZip.Args["jarArgs"], "-L 0"), test.compressed; g != w {
698 t.Errorf("expected jni compressed %v, got %v", w, g)
699 }
700 }
701 })
702 }
Colin Cross47fa9d32019-03-26 10:51:39 -0700703}
704
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800705func TestCertificates(t *testing.T) {
706 testCases := []struct {
707 name string
708 bp string
709 certificateOverride string
710 expected string
711 }{
712 {
713 name: "default",
714 bp: `
715 android_app {
716 name: "foo",
717 srcs: ["a.java"],
718 }
719 `,
720 certificateOverride: "",
Dan Willemsen412160e2019-04-09 21:36:26 -0700721 expected: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8",
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800722 },
723 {
724 name: "module certificate property",
725 bp: `
726 android_app {
727 name: "foo",
728 srcs: ["a.java"],
729 certificate: ":new_certificate"
730 }
731
732 android_app_certificate {
733 name: "new_certificate",
734 certificate: "cert/new_cert",
735 }
736 `,
737 certificateOverride: "",
738 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
739 },
740 {
741 name: "path certificate property",
742 bp: `
743 android_app {
744 name: "foo",
745 srcs: ["a.java"],
746 certificate: "expiredkey"
747 }
748 `,
749 certificateOverride: "",
Dan Willemsen412160e2019-04-09 21:36:26 -0700750 expected: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800751 },
752 {
753 name: "certificate overrides",
754 bp: `
755 android_app {
756 name: "foo",
757 srcs: ["a.java"],
758 certificate: "expiredkey"
759 }
760
761 android_app_certificate {
762 name: "new_certificate",
763 certificate: "cert/new_cert",
764 }
765 `,
766 certificateOverride: "foo:new_certificate",
767 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
768 },
769 }
770
771 for _, test := range testCases {
772 t.Run(test.name, func(t *testing.T) {
773 config := testConfig(nil)
774 if test.certificateOverride != "" {
775 config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride}
776 }
777 ctx := testAppContext(config, test.bp, nil)
778
779 run(t, ctx, config)
780 foo := ctx.ModuleForTests("foo", "android_common")
781
782 signapk := foo.Output("foo.apk")
783 signFlags := signapk.Args["certificates"]
784 if test.expected != signFlags {
785 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags)
786 }
787 })
788 }
789}
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800790
791func TestPackageNameOverride(t *testing.T) {
792 testCases := []struct {
793 name string
794 bp string
795 packageNameOverride string
796 expected []string
797 }{
798 {
799 name: "default",
800 bp: `
801 android_app {
802 name: "foo",
803 srcs: ["a.java"],
804 }
805 `,
806 packageNameOverride: "",
807 expected: []string{
808 buildDir + "/.intermediates/foo/android_common/foo.apk",
809 buildDir + "/target/product/test_device/system/app/foo/foo.apk",
810 },
811 },
812 {
813 name: "overridden",
814 bp: `
815 android_app {
816 name: "foo",
817 srcs: ["a.java"],
818 }
819 `,
820 packageNameOverride: "foo:bar",
821 expected: []string{
822 // The package apk should be still be the original name for test dependencies.
823 buildDir + "/.intermediates/foo/android_common/foo.apk",
824 buildDir + "/target/product/test_device/system/app/bar/bar.apk",
825 },
826 },
827 }
828
829 for _, test := range testCases {
830 t.Run(test.name, func(t *testing.T) {
831 config := testConfig(nil)
832 if test.packageNameOverride != "" {
833 config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride}
834 }
835 ctx := testAppContext(config, test.bp, nil)
836
837 run(t, ctx, config)
838 foo := ctx.ModuleForTests("foo", "android_common")
839
840 outputs := foo.AllOutputs()
841 outputMap := make(map[string]bool)
842 for _, o := range outputs {
843 outputMap[o] = true
844 }
845 for _, e := range test.expected {
846 if _, exist := outputMap[e]; !exist {
847 t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
848 }
849 }
850 })
851 }
852}
Jaewoong Jung4102e5d2019-02-27 16:26:28 -0800853
854func TestInstrumentationTargetOverridden(t *testing.T) {
855 bp := `
856 android_app {
857 name: "foo",
858 srcs: ["a.java"],
859 }
860
861 android_test {
862 name: "bar",
863 instrumentation_for: "foo",
864 }
865 `
866 config := testConfig(nil)
867 config.TestProductVariables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"}
868 ctx := testAppContext(config, bp, nil)
869
870 run(t, ctx, config)
871
872 bar := ctx.ModuleForTests("bar", "android_common")
873 res := bar.Output("package-res.apk")
874 aapt2Flags := res.Args["flags"]
875 e := "--rename-instrumentation-target-package org.dandroid.bp"
876 if !strings.Contains(aapt2Flags, e) {
877 t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
878 }
879}
Jaewoong Jung525443a2019-02-28 15:35:54 -0800880
881func TestOverrideAndroidApp(t *testing.T) {
882 ctx := testJava(t, `
883 android_app {
884 name: "foo",
885 srcs: ["a.java"],
Jaewoong Junga641ee92019-03-27 11:17:14 -0700886 certificate: "expiredkey",
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700887 overrides: ["qux"],
Jaewoong Jung525443a2019-02-28 15:35:54 -0800888 }
889
890 override_android_app {
891 name: "bar",
892 base: "foo",
893 certificate: ":new_certificate",
894 }
895
896 android_app_certificate {
897 name: "new_certificate",
898 certificate: "cert/new_cert",
899 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700900
901 override_android_app {
902 name: "baz",
903 base: "foo",
904 package_name: "org.dandroid.bp",
905 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800906 `)
907
908 expectedVariants := []struct {
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700909 moduleName string
Jaewoong Jung525443a2019-02-28 15:35:54 -0800910 variantName string
911 apkName string
912 apkPath string
913 signFlag string
914 overrides []string
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700915 aaptFlag string
Jaewoong Jung525443a2019-02-28 15:35:54 -0800916 }{
917 {
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700918 moduleName: "foo",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800919 variantName: "android_common",
920 apkPath: "/target/product/test_device/system/app/foo/foo.apk",
Dan Willemsen412160e2019-04-09 21:36:26 -0700921 signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700922 overrides: []string{"qux"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700923 aaptFlag: "",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800924 },
925 {
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700926 moduleName: "bar",
927 variantName: "android_common_bar",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800928 apkPath: "/target/product/test_device/system/app/bar/bar.apk",
929 signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700930 overrides: []string{"qux", "foo"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700931 aaptFlag: "",
932 },
933 {
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700934 moduleName: "baz",
935 variantName: "android_common_baz",
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700936 apkPath: "/target/product/test_device/system/app/baz/baz.apk",
Dan Willemsen412160e2019-04-09 21:36:26 -0700937 signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700938 overrides: []string{"qux", "foo"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700939 aaptFlag: "--rename-manifest-package org.dandroid.bp",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800940 },
941 }
942 for _, expected := range expectedVariants {
943 variant := ctx.ModuleForTests("foo", expected.variantName)
944
945 // Check the final apk name
946 outputs := variant.AllOutputs()
947 expectedApkPath := buildDir + expected.apkPath
948 found := false
949 for _, o := range outputs {
950 if o == expectedApkPath {
951 found = true
952 break
953 }
954 }
955 if !found {
956 t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs)
957 }
958
959 // Check the certificate paths
960 signapk := variant.Output("foo.apk")
961 signFlag := signapk.Args["certificates"]
962 if expected.signFlag != signFlag {
963 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag)
964 }
965
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700966 // Check if the overrides field values are correctly aggregated.
Jaewoong Jung525443a2019-02-28 15:35:54 -0800967 mod := variant.Module().(*AndroidApp)
968 if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) {
969 t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
970 expected.overrides, mod.appProperties.Overrides)
971 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700972
973 // Check the package renaming flag, if exists.
974 res := variant.Output("package-res.apk")
975 aapt2Flags := res.Args["flags"]
976 if !strings.Contains(aapt2Flags, expected.aaptFlag) {
977 t.Errorf("package renaming flag, %q is missing in aapt2 link flags, %q", expected.aaptFlag, aapt2Flags)
978 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800979 }
980}
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700981
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700982func TestOverrideAndroidAppDependency(t *testing.T) {
983 ctx := testJava(t, `
984 android_app {
985 name: "foo",
986 srcs: ["a.java"],
987 }
988
989 override_android_app {
990 name: "bar",
991 base: "foo",
992 package_name: "org.dandroid.bp",
993 }
994
995 android_test {
996 name: "baz",
997 srcs: ["b.java"],
998 instrumentation_for: "foo",
999 }
1000
1001 android_test {
1002 name: "qux",
1003 srcs: ["b.java"],
1004 instrumentation_for: "bar",
1005 }
1006 `)
1007
1008 // Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
1009 javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
1010 fooTurbine := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
1011 if !strings.Contains(javac.Args["classpath"], fooTurbine) {
1012 t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
1013 }
1014
1015 // Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
1016 javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
1017 barTurbine := filepath.Join(buildDir, ".intermediates", "foo", "android_common_bar", "turbine-combined", "foo.jar")
1018 if !strings.Contains(javac.Args["classpath"], barTurbine) {
1019 t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
1020 }
1021}
1022
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001023func TestAndroidAppImport(t *testing.T) {
1024 ctx := testJava(t, `
1025 android_app_import {
1026 name: "foo",
1027 apk: "prebuilts/apk/app.apk",
1028 certificate: "platform",
1029 dex_preopt: {
1030 enabled: true,
1031 },
1032 }
1033 `)
1034
1035 variant := ctx.ModuleForTests("foo", "android_common")
1036
1037 // Check dexpreopt outputs.
1038 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
1039 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
1040 t.Errorf("can't find dexpreopt outputs")
1041 }
1042
1043 // Check cert signing flag.
1044 signedApk := variant.Output("signed/foo.apk")
1045 signingFlag := signedApk.Args["certificates"]
1046 expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
1047 if expected != signingFlag {
1048 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
1049 }
1050}
1051
1052func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
1053 ctx := testJava(t, `
1054 android_app_import {
1055 name: "foo",
1056 apk: "prebuilts/apk/app.apk",
1057 certificate: "platform",
1058 dex_preopt: {
1059 enabled: false,
1060 },
1061 }
1062 `)
1063
1064 variant := ctx.ModuleForTests("foo", "android_common")
1065
1066 // Check dexpreopt outputs. They shouldn't exist.
1067 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
1068 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
1069 t.Errorf("dexpreopt shouldn't have run.")
1070 }
1071}
1072
1073func TestAndroidAppImport_Presigned(t *testing.T) {
1074 ctx := testJava(t, `
1075 android_app_import {
1076 name: "foo",
1077 apk: "prebuilts/apk/app.apk",
1078 presigned: true,
1079 dex_preopt: {
1080 enabled: true,
1081 },
1082 }
1083 `)
1084
1085 variant := ctx.ModuleForTests("foo", "android_common")
1086
1087 // Check dexpreopt outputs.
1088 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
1089 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
1090 t.Errorf("can't find dexpreopt outputs")
1091 }
1092 // Make sure stripping wasn't done.
1093 stripRule := variant.Output("dexpreopt/foo.apk")
1094 if !strings.HasPrefix(stripRule.RuleParams.Command, "cp -f") {
1095 t.Errorf("unexpected, non-skipping strip command: %q", stripRule.RuleParams.Command)
1096 }
1097
1098 // Make sure signing was skipped and aligning was done instead.
1099 if variant.MaybeOutput("signed/foo.apk").Rule != nil {
1100 t.Errorf("signing rule shouldn't be included.")
1101 }
1102 if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
1103 t.Errorf("can't find aligning rule")
1104 }
1105}
Jaewoong Junga5e5abc2019-04-26 14:31:50 -07001106
1107func TestAndroidAppImport_DpiVariants(t *testing.T) {
1108 bp := `
1109 android_app_import {
1110 name: "foo",
1111 apk: "prebuilts/apk/app.apk",
1112 dpi_variants: {
1113 xhdpi: {
1114 apk: "prebuilts/apk/app_xhdpi.apk",
1115 },
1116 xxhdpi: {
1117 apk: "prebuilts/apk/app_xxhdpi.apk",
1118 },
1119 },
1120 certificate: "PRESIGNED",
1121 dex_preopt: {
1122 enabled: true,
1123 },
1124 }
1125 `
1126 testCases := []struct {
1127 name string
1128 aaptPreferredConfig *string
1129 aaptPrebuiltDPI []string
1130 expected string
1131 }{
1132 {
1133 name: "no preferred",
1134 aaptPreferredConfig: nil,
1135 aaptPrebuiltDPI: []string{},
1136 expected: "prebuilts/apk/app.apk",
1137 },
1138 {
1139 name: "AAPTPreferredConfig matches",
1140 aaptPreferredConfig: proptools.StringPtr("xhdpi"),
Jaewoong Jung3e18b192019-06-11 12:25:34 -07001141 aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
Jaewoong Junga5e5abc2019-04-26 14:31:50 -07001142 expected: "prebuilts/apk/app_xhdpi.apk",
1143 },
1144 {
1145 name: "AAPTPrebuiltDPI matches",
1146 aaptPreferredConfig: proptools.StringPtr("mdpi"),
1147 aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
1148 expected: "prebuilts/apk/app_xxhdpi.apk",
1149 },
1150 {
1151 name: "non-first AAPTPrebuiltDPI matches",
1152 aaptPreferredConfig: proptools.StringPtr("mdpi"),
1153 aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
1154 expected: "prebuilts/apk/app_xhdpi.apk",
1155 },
1156 {
1157 name: "no matches",
1158 aaptPreferredConfig: proptools.StringPtr("mdpi"),
1159 aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
1160 expected: "prebuilts/apk/app.apk",
1161 },
1162 }
1163
1164 jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
1165 for _, test := range testCases {
1166 config := testConfig(nil)
1167 config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig
1168 config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
1169 ctx := testAppContext(config, bp, nil)
1170
1171 run(t, ctx, config)
1172
1173 variant := ctx.ModuleForTests("foo", "android_common")
1174 jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
1175 matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
1176 if len(matches) != 2 {
1177 t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
1178 }
1179 if test.expected != matches[1] {
1180 t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
1181 }
1182 }
1183}
Jaewoong Jungbc625cd2019-05-06 15:48:44 -07001184
1185func TestStl(t *testing.T) {
1186 ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
1187 cc_library {
1188 name: "libjni",
1189 }
1190
1191 android_test {
1192 name: "stl",
1193 jni_libs: ["libjni"],
1194 compile_multilib: "both",
1195 sdk_version: "current",
1196 stl: "c++_shared",
1197 }
1198
1199 android_test {
1200 name: "system",
1201 jni_libs: ["libjni"],
1202 compile_multilib: "both",
1203 sdk_version: "current",
1204 }
Jaewoong Jung710756a2019-06-04 11:53:47 -07001205
1206 ndk_prebuilt_shared_stl {
1207 name: "ndk_libc++_shared",
1208 }
Jaewoong Jungbc625cd2019-05-06 15:48:44 -07001209 `)
1210
1211 testCases := []struct {
1212 name string
1213 jnis []string
1214 }{
1215 {"stl",
1216 []string{
1217 "libjni.so",
Jaewoong Jung710756a2019-06-04 11:53:47 -07001218 "libc++_shared.so",
Jaewoong Jungbc625cd2019-05-06 15:48:44 -07001219 },
1220 },
1221 {"system",
1222 []string{
1223 "libjni.so",
1224 },
1225 },
1226 }
1227
1228 for _, test := range testCases {
1229 t.Run(test.name, func(t *testing.T) {
1230 app := ctx.ModuleForTests(test.name, "android_common")
1231 jniLibZip := app.Output("jnilibs.zip")
1232 var jnis []string
1233 args := strings.Fields(jniLibZip.Args["jarArgs"])
1234 for i := 0; i < len(args); i++ {
1235 if args[i] == "-f" {
1236 jnis = append(jnis, args[i+1])
1237 i += 1
1238 }
1239 }
1240 jnisJoined := strings.Join(jnis, " ")
1241 for _, jni := range test.jnis {
1242 if !strings.Contains(jnisJoined, jni) {
1243 t.Errorf("missing jni %q in %q", jni, jnis)
1244 }
1245 }
1246 })
1247 }
1248}
Colin Cross50ddcc42019-05-16 12:28:22 -07001249
1250func TestUsesLibraries(t *testing.T) {
1251 bp := `
1252 java_sdk_library {
1253 name: "foo",
1254 srcs: ["a.java"],
1255 api_packages: ["foo"],
1256 }
1257
1258 java_sdk_library {
1259 name: "bar",
1260 srcs: ["a.java"],
1261 api_packages: ["bar"],
1262 }
1263
1264 android_app {
1265 name: "app",
1266 srcs: ["a.java"],
1267 uses_libs: ["foo"],
1268 optional_uses_libs: [
1269 "bar",
1270 "baz",
1271 ],
1272 }
1273
1274 android_app_import {
1275 name: "prebuilt",
1276 apk: "prebuilts/apk/app.apk",
1277 certificate: "platform",
1278 uses_libs: ["foo"],
1279 optional_uses_libs: [
1280 "bar",
1281 "baz",
1282 ],
1283 }
1284 `
1285
1286 config := testConfig(nil)
1287 config.TestProductVariables.MissingUsesLibraries = []string{"baz"}
1288
1289 ctx := testAppContext(config, bp, nil)
1290
1291 run(t, ctx, config)
1292
1293 app := ctx.ModuleForTests("app", "android_common")
1294 prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
1295
1296 // Test that all libraries are verified
1297 cmd := app.Rule("verify_uses_libraries").RuleParams.Command
1298 if w := "--uses-library foo"; !strings.Contains(cmd, w) {
1299 t.Errorf("wanted %q in %q", w, cmd)
1300 }
1301
1302 if w := "--optional-uses-library bar --optional-uses-library baz"; !strings.Contains(cmd, w) {
1303 t.Errorf("wanted %q in %q", w, cmd)
1304 }
1305
1306 cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
1307
1308 if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) {
1309 t.Errorf("wanted %q in %q", w, cmd)
1310 }
1311
1312 if w := `optional_uses_library_names="bar baz"`; !strings.Contains(cmd, w) {
1313 t.Errorf("wanted %q in %q", w, cmd)
1314 }
1315
1316 // Test that only present libraries are preopted
1317 cmd = app.Rule("dexpreopt").RuleParams.Command
1318
1319 if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
1320 t.Errorf("wanted %q in %q", w, cmd)
1321 }
1322
1323 cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
1324
1325 if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
1326 t.Errorf("wanted %q in %q", w, cmd)
1327 }
1328}
Jaewoong Jungc27ab662019-05-30 15:51:14 -07001329
1330func TestCodelessApp(t *testing.T) {
1331 testCases := []struct {
1332 name string
1333 bp string
1334 noCode bool
1335 }{
1336 {
1337 name: "normal",
1338 bp: `
1339 android_app {
1340 name: "foo",
1341 srcs: ["a.java"],
1342 }
1343 `,
1344 noCode: false,
1345 },
1346 {
1347 name: "app without sources",
1348 bp: `
1349 android_app {
1350 name: "foo",
1351 }
1352 `,
1353 noCode: true,
1354 },
1355 {
1356 name: "app with libraries",
1357 bp: `
1358 android_app {
1359 name: "foo",
1360 static_libs: ["lib"],
1361 }
1362
1363 java_library {
1364 name: "lib",
1365 srcs: ["a.java"],
1366 }
1367 `,
1368 noCode: false,
1369 },
1370 {
1371 name: "app with sourceless libraries",
1372 bp: `
1373 android_app {
1374 name: "foo",
1375 static_libs: ["lib"],
1376 }
1377
1378 java_library {
1379 name: "lib",
1380 }
1381 `,
1382 // TODO(jungjw): this should probably be true
1383 noCode: false,
1384 },
1385 }
1386
1387 for _, test := range testCases {
1388 t.Run(test.name, func(t *testing.T) {
1389 ctx := testApp(t, test.bp)
1390
1391 foo := ctx.ModuleForTests("foo", "android_common")
1392 manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
1393 if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode {
1394 t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs)
1395 }
1396 })
1397 }
1398}
Jaewoong Jung5b425e22019-06-17 17:40:56 -07001399
1400func TestEmbedNotice(t *testing.T) {
1401 ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
1402 android_app {
1403 name: "foo",
1404 srcs: ["a.java"],
1405 static_libs: ["javalib"],
1406 jni_libs: ["libjni"],
1407 notice: "APP_NOTICE",
1408 embed_notices: true,
1409 }
1410
1411 // No embed_notice flag
1412 android_app {
1413 name: "bar",
1414 srcs: ["a.java"],
1415 jni_libs: ["libjni"],
1416 notice: "APP_NOTICE",
1417 }
1418
1419 // No NOTICE files
1420 android_app {
1421 name: "baz",
1422 srcs: ["a.java"],
1423 embed_notices: true,
1424 }
1425
1426 cc_library {
1427 name: "libjni",
1428 system_shared_libs: [],
1429 stl: "none",
1430 notice: "LIB_NOTICE",
1431 }
1432
1433 java_library {
1434 name: "javalib",
1435 srcs: [
1436 ":gen",
1437 ],
1438 }
1439
1440 genrule {
1441 name: "gen",
1442 tools: ["gentool"],
1443 out: ["gen.java"],
1444 notice: "GENRULE_NOTICE",
1445 }
1446
1447 java_binary_host {
1448 name: "gentool",
1449 srcs: ["b.java"],
1450 notice: "TOOL_NOTICE",
1451 }
1452 `)
1453
1454 // foo has NOTICE files to process, and embed_notices is true.
1455 foo := ctx.ModuleForTests("foo", "android_common")
1456 // verify merge notices rule.
1457 mergeNotices := foo.Rule("mergeNoticesRule")
1458 noticeInputs := mergeNotices.Inputs.Strings()
1459 // TOOL_NOTICE should be excluded as it's a host module.
1460 if len(mergeNotices.Inputs) != 3 {
1461 t.Errorf("number of input notice files: expected = 3, actual = %q", noticeInputs)
1462 }
1463 if !inList("APP_NOTICE", noticeInputs) {
1464 t.Errorf("APP_NOTICE is missing from notice files, %q", noticeInputs)
1465 }
1466 if !inList("LIB_NOTICE", noticeInputs) {
1467 t.Errorf("LIB_NOTICE is missing from notice files, %q", noticeInputs)
1468 }
1469 if !inList("GENRULE_NOTICE", noticeInputs) {
1470 t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs)
1471 }
1472 // aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets.
1473 res := foo.Output("package-res.apk")
1474 aapt2Flags := res.Args["flags"]
1475 e := "-A " + buildDir + "/.intermediates/foo/android_common/NOTICE"
1476 if !strings.Contains(aapt2Flags, e) {
1477 t.Errorf("asset dir flag for NOTICE, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
1478 }
1479
1480 // bar has NOTICE files to process, but embed_notices is not set.
1481 bar := ctx.ModuleForTests("bar", "android_common")
1482 mergeNotices = bar.MaybeRule("mergeNoticesRule")
1483 if mergeNotices.Rule != nil {
1484 t.Errorf("mergeNotices shouldn't have run for bar")
1485 }
1486
1487 // baz's embed_notice is true, but it doesn't have any NOTICE files.
1488 baz := ctx.ModuleForTests("baz", "android_common")
1489 mergeNotices = baz.MaybeRule("mergeNoticesRule")
1490 if mergeNotices.Rule != nil {
1491 t.Errorf("mergeNotices shouldn't have run for baz")
1492 }
1493}
Colin Cross53a87f52019-06-25 13:35:30 -07001494
1495func TestUncompressDex(t *testing.T) {
1496 testCases := []struct {
1497 name string
1498 bp string
1499
1500 uncompressedPlatform bool
1501 uncompressedUnbundled bool
1502 }{
1503 {
1504 name: "normal",
1505 bp: `
1506 android_app {
1507 name: "foo",
1508 srcs: ["a.java"],
1509 }
1510 `,
1511 uncompressedPlatform: true,
1512 uncompressedUnbundled: false,
1513 },
1514 {
1515 name: "use_embedded_dex",
1516 bp: `
1517 android_app {
1518 name: "foo",
1519 use_embedded_dex: true,
1520 srcs: ["a.java"],
1521 }
1522 `,
1523 uncompressedPlatform: true,
1524 uncompressedUnbundled: true,
1525 },
1526 {
1527 name: "privileged",
1528 bp: `
1529 android_app {
1530 name: "foo",
1531 privileged: true,
1532 srcs: ["a.java"],
1533 }
1534 `,
1535 uncompressedPlatform: true,
1536 uncompressedUnbundled: true,
1537 },
1538 }
1539
1540 test := func(t *testing.T, bp string, want bool, unbundled bool) {
1541 t.Helper()
1542
1543 config := testConfig(nil)
1544 if unbundled {
1545 config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
1546 }
1547
1548 ctx := testAppContext(config, bp, nil)
1549
1550 run(t, ctx, config)
1551
1552 foo := ctx.ModuleForTests("foo", "android_common")
1553 dex := foo.Rule("r8")
1554 uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0")
1555 aligned := foo.MaybeRule("zipalign").Rule != nil
1556
1557 if uncompressedInDexJar != want {
1558 t.Errorf("want uncompressed in dex %v, got %v", want, uncompressedInDexJar)
1559 }
1560
1561 if aligned != want {
1562 t.Errorf("want aligned %v, got %v", want, aligned)
1563 }
1564 }
1565
1566 for _, tt := range testCases {
1567 t.Run(tt.name, func(t *testing.T) {
1568 t.Run("platform", func(t *testing.T) {
1569 test(t, tt.bp, tt.uncompressedPlatform, false)
1570 })
1571 t.Run("unbundled", func(t *testing.T) {
1572 test(t, tt.bp, tt.uncompressedUnbundled, true)
1573 })
1574 })
1575 }
1576}