blob: f21d450c5a76e2e21864f2d6e1937f77d9ca3301 [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
Jaewoong Jungf9a04432019-07-17 11:15:09 -070046func testAppContext(bp string, fs map[string][]byte) *android.TestContext {
Colin Cross527012a2017-11-30 22:56:16 -080047 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
Jaewoong Jungf9a04432019-07-17 11:15:09 -070056 return testContext(bp, appFS)
Colin Cross527012a2017-11-30 22:56:16 -080057}
58
59func testApp(t *testing.T, bp string) *android.TestContext {
60 config := testConfig(nil)
61
Jaewoong Jungf9a04432019-07-17 11:15:09 -070062 ctx := testAppContext(bp, nil)
Colin Cross527012a2017-11-30 22:56:16 -080063
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)
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700179 ctx := testContext(fmt.Sprintf(bp, testCase.prop), fs)
Colin Cross0ddae7f2019-02-07 15:30:01 -0800180 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
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700391 ctx := testAppContext(bp, fs)
Colin Cross890ff552017-11-30 20:13:19 -0800392 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
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700518 ctx := testAppContext(bp, nil)
Colin Crossd09b0b62018-04-18 11:06:47 -0700519
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) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700550 ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
Paul Duffin50c217c2019-06-12 13:25:22 +0100551 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) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700623 ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
Paul Duffin50c217c2019-06-12 13:25:22 +0100624 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 }
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700777 ctx := testAppContext(test.bp, nil)
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800778
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 }
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700835 ctx := testAppContext(test.bp, nil)
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800836
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"}
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700868 ctx := testAppContext(bp, nil)
Jaewoong Jung4102e5d2019-02-27 16:26:28 -0800869
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) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700882 ctx, _ := testJava(t, `
Jaewoong Jung525443a2019-02-28 15:35:54 -0800883 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) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -0700983 ctx, _ := testJava(t, `
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700984 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) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -07001024 ctx, _ := testJava(t, `
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001025 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) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -07001053 ctx, _ := testJava(t, `
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001054 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) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -07001074 ctx, _ := testJava(t, `
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001075 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
Jaewoong Jungf9a04432019-07-17 11:15:09 -07001169 ctx := testAppContext(bp, nil)
Jaewoong Junga5e5abc2019-04-26 14:31:50 -07001170
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
Jaewoong Jung8aae22e2019-07-17 10:21:49 -07001185func TestAndroidAppImport_Filename(t *testing.T) {
1186 ctx, config := testJava(t, `
1187 android_app_import {
1188 name: "foo",
1189 apk: "prebuilts/apk/app.apk",
1190 presigned: true,
1191 }
1192
1193 android_app_import {
1194 name: "bar",
1195 apk: "prebuilts/apk/app.apk",
1196 presigned: true,
1197 filename: "bar_sample.apk"
1198 }
1199 `)
1200
1201 testCases := []struct {
1202 name string
1203 expected string
1204 }{
1205 {
1206 name: "foo",
1207 expected: "foo.apk",
1208 },
1209 {
1210 name: "bar",
1211 expected: "bar_sample.apk",
1212 },
1213 }
1214
1215 for _, test := range testCases {
1216 variant := ctx.ModuleForTests(test.name, "android_common")
1217 if variant.MaybeOutput(test.expected).Rule == nil {
1218 t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs())
1219 }
1220
1221 a := variant.Module().(*AndroidAppImport)
1222 expectedValues := []string{test.expected}
1223 actualValues := android.AndroidMkEntriesForTest(
1224 t, config, "", a).EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
1225 if !reflect.DeepEqual(actualValues, expectedValues) {
1226 t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
1227 actualValues, expectedValues)
1228 }
1229 }
1230}
1231
Jaewoong Jungbc625cd2019-05-06 15:48:44 -07001232func TestStl(t *testing.T) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -07001233 ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
Jaewoong Jungbc625cd2019-05-06 15:48:44 -07001234 cc_library {
1235 name: "libjni",
1236 }
1237
1238 android_test {
1239 name: "stl",
1240 jni_libs: ["libjni"],
1241 compile_multilib: "both",
1242 sdk_version: "current",
1243 stl: "c++_shared",
1244 }
1245
1246 android_test {
1247 name: "system",
1248 jni_libs: ["libjni"],
1249 compile_multilib: "both",
1250 sdk_version: "current",
1251 }
Jaewoong Jung710756a2019-06-04 11:53:47 -07001252
1253 ndk_prebuilt_shared_stl {
1254 name: "ndk_libc++_shared",
1255 }
Jaewoong Jungbc625cd2019-05-06 15:48:44 -07001256 `)
1257
1258 testCases := []struct {
1259 name string
1260 jnis []string
1261 }{
1262 {"stl",
1263 []string{
1264 "libjni.so",
Jaewoong Jung710756a2019-06-04 11:53:47 -07001265 "libc++_shared.so",
Jaewoong Jungbc625cd2019-05-06 15:48:44 -07001266 },
1267 },
1268 {"system",
1269 []string{
1270 "libjni.so",
1271 },
1272 },
1273 }
1274
1275 for _, test := range testCases {
1276 t.Run(test.name, func(t *testing.T) {
1277 app := ctx.ModuleForTests(test.name, "android_common")
1278 jniLibZip := app.Output("jnilibs.zip")
1279 var jnis []string
1280 args := strings.Fields(jniLibZip.Args["jarArgs"])
1281 for i := 0; i < len(args); i++ {
1282 if args[i] == "-f" {
1283 jnis = append(jnis, args[i+1])
1284 i += 1
1285 }
1286 }
1287 jnisJoined := strings.Join(jnis, " ")
1288 for _, jni := range test.jnis {
1289 if !strings.Contains(jnisJoined, jni) {
1290 t.Errorf("missing jni %q in %q", jni, jnis)
1291 }
1292 }
1293 })
1294 }
1295}
Colin Cross50ddcc42019-05-16 12:28:22 -07001296
1297func TestUsesLibraries(t *testing.T) {
1298 bp := `
1299 java_sdk_library {
1300 name: "foo",
1301 srcs: ["a.java"],
1302 api_packages: ["foo"],
1303 }
1304
1305 java_sdk_library {
1306 name: "bar",
1307 srcs: ["a.java"],
1308 api_packages: ["bar"],
1309 }
1310
1311 android_app {
1312 name: "app",
1313 srcs: ["a.java"],
1314 uses_libs: ["foo"],
1315 optional_uses_libs: [
1316 "bar",
1317 "baz",
1318 ],
1319 }
1320
1321 android_app_import {
1322 name: "prebuilt",
1323 apk: "prebuilts/apk/app.apk",
1324 certificate: "platform",
1325 uses_libs: ["foo"],
1326 optional_uses_libs: [
1327 "bar",
1328 "baz",
1329 ],
1330 }
1331 `
1332
1333 config := testConfig(nil)
1334 config.TestProductVariables.MissingUsesLibraries = []string{"baz"}
1335
Jaewoong Jungf9a04432019-07-17 11:15:09 -07001336 ctx := testAppContext(bp, nil)
Colin Cross50ddcc42019-05-16 12:28:22 -07001337
1338 run(t, ctx, config)
1339
1340 app := ctx.ModuleForTests("app", "android_common")
1341 prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
1342
1343 // Test that all libraries are verified
1344 cmd := app.Rule("verify_uses_libraries").RuleParams.Command
1345 if w := "--uses-library foo"; !strings.Contains(cmd, w) {
1346 t.Errorf("wanted %q in %q", w, cmd)
1347 }
1348
1349 if w := "--optional-uses-library bar --optional-uses-library baz"; !strings.Contains(cmd, w) {
1350 t.Errorf("wanted %q in %q", w, cmd)
1351 }
1352
1353 cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
1354
1355 if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) {
1356 t.Errorf("wanted %q in %q", w, cmd)
1357 }
1358
1359 if w := `optional_uses_library_names="bar baz"`; !strings.Contains(cmd, w) {
1360 t.Errorf("wanted %q in %q", w, cmd)
1361 }
1362
1363 // Test that only present libraries are preopted
1364 cmd = app.Rule("dexpreopt").RuleParams.Command
1365
1366 if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
1367 t.Errorf("wanted %q in %q", w, cmd)
1368 }
1369
1370 cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
1371
1372 if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
1373 t.Errorf("wanted %q in %q", w, cmd)
1374 }
1375}
Jaewoong Jungc27ab662019-05-30 15:51:14 -07001376
1377func TestCodelessApp(t *testing.T) {
1378 testCases := []struct {
1379 name string
1380 bp string
1381 noCode bool
1382 }{
1383 {
1384 name: "normal",
1385 bp: `
1386 android_app {
1387 name: "foo",
1388 srcs: ["a.java"],
1389 }
1390 `,
1391 noCode: false,
1392 },
1393 {
1394 name: "app without sources",
1395 bp: `
1396 android_app {
1397 name: "foo",
1398 }
1399 `,
1400 noCode: true,
1401 },
1402 {
1403 name: "app with libraries",
1404 bp: `
1405 android_app {
1406 name: "foo",
1407 static_libs: ["lib"],
1408 }
1409
1410 java_library {
1411 name: "lib",
1412 srcs: ["a.java"],
1413 }
1414 `,
1415 noCode: false,
1416 },
1417 {
1418 name: "app with sourceless libraries",
1419 bp: `
1420 android_app {
1421 name: "foo",
1422 static_libs: ["lib"],
1423 }
1424
1425 java_library {
1426 name: "lib",
1427 }
1428 `,
1429 // TODO(jungjw): this should probably be true
1430 noCode: false,
1431 },
1432 }
1433
1434 for _, test := range testCases {
1435 t.Run(test.name, func(t *testing.T) {
1436 ctx := testApp(t, test.bp)
1437
1438 foo := ctx.ModuleForTests("foo", "android_common")
1439 manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
1440 if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode {
1441 t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs)
1442 }
1443 })
1444 }
1445}
Jaewoong Jung5b425e22019-06-17 17:40:56 -07001446
1447func TestEmbedNotice(t *testing.T) {
Jaewoong Jungf9a04432019-07-17 11:15:09 -07001448 ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
Jaewoong Jung5b425e22019-06-17 17:40:56 -07001449 android_app {
1450 name: "foo",
1451 srcs: ["a.java"],
1452 static_libs: ["javalib"],
1453 jni_libs: ["libjni"],
1454 notice: "APP_NOTICE",
1455 embed_notices: true,
1456 }
1457
1458 // No embed_notice flag
1459 android_app {
1460 name: "bar",
1461 srcs: ["a.java"],
1462 jni_libs: ["libjni"],
1463 notice: "APP_NOTICE",
1464 }
1465
1466 // No NOTICE files
1467 android_app {
1468 name: "baz",
1469 srcs: ["a.java"],
1470 embed_notices: true,
1471 }
1472
1473 cc_library {
1474 name: "libjni",
1475 system_shared_libs: [],
1476 stl: "none",
1477 notice: "LIB_NOTICE",
1478 }
1479
1480 java_library {
1481 name: "javalib",
1482 srcs: [
1483 ":gen",
1484 ],
1485 }
1486
1487 genrule {
1488 name: "gen",
1489 tools: ["gentool"],
1490 out: ["gen.java"],
1491 notice: "GENRULE_NOTICE",
1492 }
1493
1494 java_binary_host {
1495 name: "gentool",
1496 srcs: ["b.java"],
1497 notice: "TOOL_NOTICE",
1498 }
1499 `)
1500
1501 // foo has NOTICE files to process, and embed_notices is true.
1502 foo := ctx.ModuleForTests("foo", "android_common")
1503 // verify merge notices rule.
1504 mergeNotices := foo.Rule("mergeNoticesRule")
1505 noticeInputs := mergeNotices.Inputs.Strings()
1506 // TOOL_NOTICE should be excluded as it's a host module.
1507 if len(mergeNotices.Inputs) != 3 {
1508 t.Errorf("number of input notice files: expected = 3, actual = %q", noticeInputs)
1509 }
1510 if !inList("APP_NOTICE", noticeInputs) {
1511 t.Errorf("APP_NOTICE is missing from notice files, %q", noticeInputs)
1512 }
1513 if !inList("LIB_NOTICE", noticeInputs) {
1514 t.Errorf("LIB_NOTICE is missing from notice files, %q", noticeInputs)
1515 }
1516 if !inList("GENRULE_NOTICE", noticeInputs) {
1517 t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs)
1518 }
1519 // aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets.
1520 res := foo.Output("package-res.apk")
1521 aapt2Flags := res.Args["flags"]
1522 e := "-A " + buildDir + "/.intermediates/foo/android_common/NOTICE"
1523 if !strings.Contains(aapt2Flags, e) {
1524 t.Errorf("asset dir flag for NOTICE, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
1525 }
1526
1527 // bar has NOTICE files to process, but embed_notices is not set.
1528 bar := ctx.ModuleForTests("bar", "android_common")
Jaewoong Jung98772792019-07-01 17:15:13 -07001529 res = bar.Output("package-res.apk")
1530 aapt2Flags = res.Args["flags"]
1531 e = "-A " + buildDir + "/.intermediates/bar/android_common/NOTICE"
1532 if strings.Contains(aapt2Flags, e) {
1533 t.Errorf("bar shouldn't have the asset dir flag for NOTICE: %q", e)
Jaewoong Jung5b425e22019-06-17 17:40:56 -07001534 }
1535
1536 // baz's embed_notice is true, but it doesn't have any NOTICE files.
1537 baz := ctx.ModuleForTests("baz", "android_common")
Jaewoong Jung98772792019-07-01 17:15:13 -07001538 res = baz.Output("package-res.apk")
1539 aapt2Flags = res.Args["flags"]
1540 e = "-A " + buildDir + "/.intermediates/baz/android_common/NOTICE"
1541 if strings.Contains(aapt2Flags, e) {
1542 t.Errorf("baz shouldn't have the asset dir flag for NOTICE: %q", e)
Jaewoong Jung5b425e22019-06-17 17:40:56 -07001543 }
1544}
Colin Cross53a87f52019-06-25 13:35:30 -07001545
1546func TestUncompressDex(t *testing.T) {
1547 testCases := []struct {
1548 name string
1549 bp string
1550
1551 uncompressedPlatform bool
1552 uncompressedUnbundled bool
1553 }{
1554 {
1555 name: "normal",
1556 bp: `
1557 android_app {
1558 name: "foo",
1559 srcs: ["a.java"],
1560 }
1561 `,
1562 uncompressedPlatform: true,
1563 uncompressedUnbundled: false,
1564 },
1565 {
1566 name: "use_embedded_dex",
1567 bp: `
1568 android_app {
1569 name: "foo",
1570 use_embedded_dex: true,
1571 srcs: ["a.java"],
1572 }
1573 `,
1574 uncompressedPlatform: true,
1575 uncompressedUnbundled: true,
1576 },
1577 {
1578 name: "privileged",
1579 bp: `
1580 android_app {
1581 name: "foo",
1582 privileged: true,
1583 srcs: ["a.java"],
1584 }
1585 `,
1586 uncompressedPlatform: true,
1587 uncompressedUnbundled: true,
1588 },
1589 }
1590
1591 test := func(t *testing.T, bp string, want bool, unbundled bool) {
1592 t.Helper()
1593
1594 config := testConfig(nil)
1595 if unbundled {
1596 config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
1597 }
1598
Jaewoong Jungf9a04432019-07-17 11:15:09 -07001599 ctx := testAppContext(bp, nil)
Colin Cross53a87f52019-06-25 13:35:30 -07001600
1601 run(t, ctx, config)
1602
1603 foo := ctx.ModuleForTests("foo", "android_common")
1604 dex := foo.Rule("r8")
1605 uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0")
1606 aligned := foo.MaybeRule("zipalign").Rule != nil
1607
1608 if uncompressedInDexJar != want {
1609 t.Errorf("want uncompressed in dex %v, got %v", want, uncompressedInDexJar)
1610 }
1611
1612 if aligned != want {
1613 t.Errorf("want aligned %v, got %v", want, aligned)
1614 }
1615 }
1616
1617 for _, tt := range testCases {
1618 t.Run(tt.name, func(t *testing.T) {
1619 t.Run("platform", func(t *testing.T) {
1620 test(t, tt.bp, tt.uncompressedPlatform, false)
1621 })
1622 t.Run("unbundled", func(t *testing.T) {
1623 test(t, tt.bp, tt.uncompressedUnbundled, true)
1624 })
1625 })
1626 }
1627}