blob: 9aedebd76ec35076caa45ff41fc6d6684e535c19 [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
Colin Cross47fa9d32019-03-26 10:51:39 -0700549func TestJNIABI(t *testing.T) {
550 ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
Colin Crossa4f08812018-10-02 22:03:40 -0700551 cc_library {
552 name: "libjni",
553 system_shared_libs: [],
554 stl: "none",
555 }
556
557 android_test {
558 name: "test",
559 no_framework_libs: true,
560 jni_libs: ["libjni"],
561 }
562
563 android_test {
564 name: "test_first",
565 no_framework_libs: true,
566 compile_multilib: "first",
567 jni_libs: ["libjni"],
568 }
569
570 android_test {
571 name: "test_both",
572 no_framework_libs: true,
573 compile_multilib: "both",
574 jni_libs: ["libjni"],
575 }
576
577 android_test {
578 name: "test_32",
579 no_framework_libs: true,
580 compile_multilib: "32",
581 jni_libs: ["libjni"],
582 }
583
584 android_test {
585 name: "test_64",
586 no_framework_libs: true,
587 compile_multilib: "64",
588 jni_libs: ["libjni"],
589 }
590 `)
591
Colin Crossa4f08812018-10-02 22:03:40 -0700592 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}
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800621
Colin Cross47fa9d32019-03-26 10:51:39 -0700622func 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 no_framework_libs: true,
650 jni_libs: ["libjni"],
651 }
652
653 android_test {
654 name: "test_noembed",
655 no_framework_libs: true,
656 jni_libs: ["libjni"],
657 use_embedded_native_libs: false,
658 }
659
660 android_test_helper_app {
661 name: "test_helper",
662 no_framework_libs: true,
663 jni_libs: ["libjni"],
664 }
665
666 android_test_helper_app {
667 name: "test_helper_noembed",
668 no_framework_libs: true,
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 }
703
704}
705
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800706func TestCertificates(t *testing.T) {
707 testCases := []struct {
708 name string
709 bp string
710 certificateOverride string
711 expected string
712 }{
713 {
714 name: "default",
715 bp: `
716 android_app {
717 name: "foo",
718 srcs: ["a.java"],
719 }
720 `,
721 certificateOverride: "",
Dan Willemsen412160e2019-04-09 21:36:26 -0700722 expected: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8",
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800723 },
724 {
725 name: "module certificate property",
726 bp: `
727 android_app {
728 name: "foo",
729 srcs: ["a.java"],
730 certificate: ":new_certificate"
731 }
732
733 android_app_certificate {
734 name: "new_certificate",
735 certificate: "cert/new_cert",
736 }
737 `,
738 certificateOverride: "",
739 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
740 },
741 {
742 name: "path certificate property",
743 bp: `
744 android_app {
745 name: "foo",
746 srcs: ["a.java"],
747 certificate: "expiredkey"
748 }
749 `,
750 certificateOverride: "",
Dan Willemsen412160e2019-04-09 21:36:26 -0700751 expected: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800752 },
753 {
754 name: "certificate overrides",
755 bp: `
756 android_app {
757 name: "foo",
758 srcs: ["a.java"],
759 certificate: "expiredkey"
760 }
761
762 android_app_certificate {
763 name: "new_certificate",
764 certificate: "cert/new_cert",
765 }
766 `,
767 certificateOverride: "foo:new_certificate",
768 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
769 },
770 }
771
772 for _, test := range testCases {
773 t.Run(test.name, func(t *testing.T) {
774 config := testConfig(nil)
775 if test.certificateOverride != "" {
776 config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride}
777 }
778 ctx := testAppContext(config, test.bp, nil)
779
780 run(t, ctx, config)
781 foo := ctx.ModuleForTests("foo", "android_common")
782
783 signapk := foo.Output("foo.apk")
784 signFlags := signapk.Args["certificates"]
785 if test.expected != signFlags {
786 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags)
787 }
788 })
789 }
790}
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800791
792func TestPackageNameOverride(t *testing.T) {
793 testCases := []struct {
794 name string
795 bp string
796 packageNameOverride string
797 expected []string
798 }{
799 {
800 name: "default",
801 bp: `
802 android_app {
803 name: "foo",
804 srcs: ["a.java"],
805 }
806 `,
807 packageNameOverride: "",
808 expected: []string{
809 buildDir + "/.intermediates/foo/android_common/foo.apk",
810 buildDir + "/target/product/test_device/system/app/foo/foo.apk",
811 },
812 },
813 {
814 name: "overridden",
815 bp: `
816 android_app {
817 name: "foo",
818 srcs: ["a.java"],
819 }
820 `,
821 packageNameOverride: "foo:bar",
822 expected: []string{
823 // The package apk should be still be the original name for test dependencies.
824 buildDir + "/.intermediates/foo/android_common/foo.apk",
825 buildDir + "/target/product/test_device/system/app/bar/bar.apk",
826 },
827 },
828 }
829
830 for _, test := range testCases {
831 t.Run(test.name, func(t *testing.T) {
832 config := testConfig(nil)
833 if test.packageNameOverride != "" {
834 config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride}
835 }
836 ctx := testAppContext(config, test.bp, nil)
837
838 run(t, ctx, config)
839 foo := ctx.ModuleForTests("foo", "android_common")
840
841 outputs := foo.AllOutputs()
842 outputMap := make(map[string]bool)
843 for _, o := range outputs {
844 outputMap[o] = true
845 }
846 for _, e := range test.expected {
847 if _, exist := outputMap[e]; !exist {
848 t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
849 }
850 }
851 })
852 }
853}
Jaewoong Jung4102e5d2019-02-27 16:26:28 -0800854
855func TestInstrumentationTargetOverridden(t *testing.T) {
856 bp := `
857 android_app {
858 name: "foo",
859 srcs: ["a.java"],
860 }
861
862 android_test {
863 name: "bar",
864 instrumentation_for: "foo",
865 }
866 `
867 config := testConfig(nil)
868 config.TestProductVariables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"}
869 ctx := testAppContext(config, bp, nil)
870
871 run(t, ctx, config)
872
873 bar := ctx.ModuleForTests("bar", "android_common")
874 res := bar.Output("package-res.apk")
875 aapt2Flags := res.Args["flags"]
876 e := "--rename-instrumentation-target-package org.dandroid.bp"
877 if !strings.Contains(aapt2Flags, e) {
878 t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
879 }
880}
Jaewoong Jung525443a2019-02-28 15:35:54 -0800881
882func TestOverrideAndroidApp(t *testing.T) {
883 ctx := testJava(t, `
884 android_app {
885 name: "foo",
886 srcs: ["a.java"],
Jaewoong Junga641ee92019-03-27 11:17:14 -0700887 certificate: "expiredkey",
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700888 overrides: ["qux"],
Jaewoong Jung525443a2019-02-28 15:35:54 -0800889 }
890
891 override_android_app {
892 name: "bar",
893 base: "foo",
894 certificate: ":new_certificate",
895 }
896
897 android_app_certificate {
898 name: "new_certificate",
899 certificate: "cert/new_cert",
900 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700901
902 override_android_app {
903 name: "baz",
904 base: "foo",
905 package_name: "org.dandroid.bp",
906 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800907 `)
908
909 expectedVariants := []struct {
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700910 moduleName string
Jaewoong Jung525443a2019-02-28 15:35:54 -0800911 variantName string
912 apkName string
913 apkPath string
914 signFlag string
915 overrides []string
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700916 aaptFlag string
Jaewoong Jung525443a2019-02-28 15:35:54 -0800917 }{
918 {
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700919 moduleName: "foo",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800920 variantName: "android_common",
921 apkPath: "/target/product/test_device/system/app/foo/foo.apk",
Dan Willemsen412160e2019-04-09 21:36:26 -0700922 signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700923 overrides: []string{"qux"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700924 aaptFlag: "",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800925 },
926 {
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700927 moduleName: "bar",
928 variantName: "android_common_bar",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800929 apkPath: "/target/product/test_device/system/app/bar/bar.apk",
930 signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700931 overrides: []string{"qux", "foo"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700932 aaptFlag: "",
933 },
934 {
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700935 moduleName: "baz",
936 variantName: "android_common_baz",
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700937 apkPath: "/target/product/test_device/system/app/baz/baz.apk",
Dan Willemsen412160e2019-04-09 21:36:26 -0700938 signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700939 overrides: []string{"qux", "foo"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700940 aaptFlag: "--rename-manifest-package org.dandroid.bp",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800941 },
942 }
943 for _, expected := range expectedVariants {
944 variant := ctx.ModuleForTests("foo", expected.variantName)
945
946 // Check the final apk name
947 outputs := variant.AllOutputs()
948 expectedApkPath := buildDir + expected.apkPath
949 found := false
950 for _, o := range outputs {
951 if o == expectedApkPath {
952 found = true
953 break
954 }
955 }
956 if !found {
957 t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs)
958 }
959
960 // Check the certificate paths
961 signapk := variant.Output("foo.apk")
962 signFlag := signapk.Args["certificates"]
963 if expected.signFlag != signFlag {
964 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag)
965 }
966
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700967 // Check if the overrides field values are correctly aggregated.
Jaewoong Jung525443a2019-02-28 15:35:54 -0800968 mod := variant.Module().(*AndroidApp)
969 if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) {
970 t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
971 expected.overrides, mod.appProperties.Overrides)
972 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700973
974 // Check the package renaming flag, if exists.
975 res := variant.Output("package-res.apk")
976 aapt2Flags := res.Args["flags"]
977 if !strings.Contains(aapt2Flags, expected.aaptFlag) {
978 t.Errorf("package renaming flag, %q is missing in aapt2 link flags, %q", expected.aaptFlag, aapt2Flags)
979 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800980 }
981}
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700982
Jaewoong Jungb639a6a2019-05-10 15:16:29 -0700983func TestOverrideAndroidAppDependency(t *testing.T) {
984 ctx := testJava(t, `
985 android_app {
986 name: "foo",
987 srcs: ["a.java"],
988 }
989
990 override_android_app {
991 name: "bar",
992 base: "foo",
993 package_name: "org.dandroid.bp",
994 }
995
996 android_test {
997 name: "baz",
998 srcs: ["b.java"],
999 instrumentation_for: "foo",
1000 }
1001
1002 android_test {
1003 name: "qux",
1004 srcs: ["b.java"],
1005 instrumentation_for: "bar",
1006 }
1007 `)
1008
1009 // Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
1010 javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
1011 fooTurbine := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
1012 if !strings.Contains(javac.Args["classpath"], fooTurbine) {
1013 t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
1014 }
1015
1016 // Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
1017 javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
1018 barTurbine := filepath.Join(buildDir, ".intermediates", "foo", "android_common_bar", "turbine-combined", "foo.jar")
1019 if !strings.Contains(javac.Args["classpath"], barTurbine) {
1020 t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
1021 }
1022}
1023
Jaewoong Jungccbb3932019-04-15 09:48:31 -07001024func TestAndroidAppImport(t *testing.T) {
1025 ctx := testJava(t, `
1026 android_app_import {
1027 name: "foo",
1028 apk: "prebuilts/apk/app.apk",
1029 certificate: "platform",
1030 dex_preopt: {
1031 enabled: true,
1032 },
1033 }
1034 `)
1035
1036 variant := ctx.ModuleForTests("foo", "android_common")
1037
1038 // Check dexpreopt outputs.
1039 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
1040 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
1041 t.Errorf("can't find dexpreopt outputs")
1042 }
1043
1044 // Check cert signing flag.
1045 signedApk := variant.Output("signed/foo.apk")
1046 signingFlag := signedApk.Args["certificates"]
1047 expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
1048 if expected != signingFlag {
1049 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
1050 }
1051}
1052
1053func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
1054 ctx := testJava(t, `
1055 android_app_import {
1056 name: "foo",
1057 apk: "prebuilts/apk/app.apk",
1058 certificate: "platform",
1059 dex_preopt: {
1060 enabled: false,
1061 },
1062 }
1063 `)
1064
1065 variant := ctx.ModuleForTests("foo", "android_common")
1066
1067 // Check dexpreopt outputs. They shouldn't exist.
1068 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
1069 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
1070 t.Errorf("dexpreopt shouldn't have run.")
1071 }
1072}
1073
1074func TestAndroidAppImport_Presigned(t *testing.T) {
1075 ctx := testJava(t, `
1076 android_app_import {
1077 name: "foo",
1078 apk: "prebuilts/apk/app.apk",
1079 presigned: true,
1080 dex_preopt: {
1081 enabled: true,
1082 },
1083 }
1084 `)
1085
1086 variant := ctx.ModuleForTests("foo", "android_common")
1087
1088 // Check dexpreopt outputs.
1089 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
1090 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
1091 t.Errorf("can't find dexpreopt outputs")
1092 }
1093 // Make sure stripping wasn't done.
1094 stripRule := variant.Output("dexpreopt/foo.apk")
1095 if !strings.HasPrefix(stripRule.RuleParams.Command, "cp -f") {
1096 t.Errorf("unexpected, non-skipping strip command: %q", stripRule.RuleParams.Command)
1097 }
1098
1099 // Make sure signing was skipped and aligning was done instead.
1100 if variant.MaybeOutput("signed/foo.apk").Rule != nil {
1101 t.Errorf("signing rule shouldn't be included.")
1102 }
1103 if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
1104 t.Errorf("can't find aligning rule")
1105 }
1106}
Jaewoong Junga5e5abc2019-04-26 14:31:50 -07001107
1108func TestAndroidAppImport_DpiVariants(t *testing.T) {
1109 bp := `
1110 android_app_import {
1111 name: "foo",
1112 apk: "prebuilts/apk/app.apk",
1113 dpi_variants: {
1114 xhdpi: {
1115 apk: "prebuilts/apk/app_xhdpi.apk",
1116 },
1117 xxhdpi: {
1118 apk: "prebuilts/apk/app_xxhdpi.apk",
1119 },
1120 },
1121 certificate: "PRESIGNED",
1122 dex_preopt: {
1123 enabled: true,
1124 },
1125 }
1126 `
1127 testCases := []struct {
1128 name string
1129 aaptPreferredConfig *string
1130 aaptPrebuiltDPI []string
1131 expected string
1132 }{
1133 {
1134 name: "no preferred",
1135 aaptPreferredConfig: nil,
1136 aaptPrebuiltDPI: []string{},
1137 expected: "prebuilts/apk/app.apk",
1138 },
1139 {
1140 name: "AAPTPreferredConfig matches",
1141 aaptPreferredConfig: proptools.StringPtr("xhdpi"),
1142 aaptPrebuiltDPI: []string{"xxhdpi", "lhdpi"},
1143 expected: "prebuilts/apk/app_xhdpi.apk",
1144 },
1145 {
1146 name: "AAPTPrebuiltDPI matches",
1147 aaptPreferredConfig: proptools.StringPtr("mdpi"),
1148 aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
1149 expected: "prebuilts/apk/app_xxhdpi.apk",
1150 },
1151 {
1152 name: "non-first AAPTPrebuiltDPI matches",
1153 aaptPreferredConfig: proptools.StringPtr("mdpi"),
1154 aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
1155 expected: "prebuilts/apk/app_xhdpi.apk",
1156 },
1157 {
1158 name: "no matches",
1159 aaptPreferredConfig: proptools.StringPtr("mdpi"),
1160 aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
1161 expected: "prebuilts/apk/app.apk",
1162 },
1163 }
1164
1165 jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)")
1166 for _, test := range testCases {
1167 config := testConfig(nil)
1168 config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig
1169 config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
1170 ctx := testAppContext(config, bp, nil)
1171
1172 run(t, ctx, config)
1173
1174 variant := ctx.ModuleForTests("foo", "android_common")
1175 jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
1176 matches := jniRuleRe.FindStringSubmatch(jniRuleCommand)
1177 if len(matches) != 2 {
1178 t.Errorf("failed to extract the src apk path from %q", jniRuleCommand)
1179 }
1180 if test.expected != matches[1] {
1181 t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
1182 }
1183 }
1184}
Jaewoong Jungbc625cd2019-05-06 15:48:44 -07001185
1186func TestStl(t *testing.T) {
1187 ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
1188 cc_library {
1189 name: "libjni",
1190 }
1191
1192 android_test {
1193 name: "stl",
1194 jni_libs: ["libjni"],
1195 compile_multilib: "both",
1196 sdk_version: "current",
1197 stl: "c++_shared",
1198 }
1199
1200 android_test {
1201 name: "system",
1202 jni_libs: ["libjni"],
1203 compile_multilib: "both",
1204 sdk_version: "current",
1205 }
1206 `)
1207
1208 testCases := []struct {
1209 name string
1210 jnis []string
1211 }{
1212 {"stl",
1213 []string{
1214 "libjni.so",
1215 "libc++.so",
1216 },
1217 },
1218 {"system",
1219 []string{
1220 "libjni.so",
1221 },
1222 },
1223 }
1224
1225 for _, test := range testCases {
1226 t.Run(test.name, func(t *testing.T) {
1227 app := ctx.ModuleForTests(test.name, "android_common")
1228 jniLibZip := app.Output("jnilibs.zip")
1229 var jnis []string
1230 args := strings.Fields(jniLibZip.Args["jarArgs"])
1231 for i := 0; i < len(args); i++ {
1232 if args[i] == "-f" {
1233 jnis = append(jnis, args[i+1])
1234 i += 1
1235 }
1236 }
1237 jnisJoined := strings.Join(jnis, " ")
1238 for _, jni := range test.jnis {
1239 if !strings.Contains(jnisJoined, jni) {
1240 t.Errorf("missing jni %q in %q", jni, jnis)
1241 }
1242 }
1243 })
1244 }
1245}
Colin Cross50ddcc42019-05-16 12:28:22 -07001246
1247func TestUsesLibraries(t *testing.T) {
1248 bp := `
1249 java_sdk_library {
1250 name: "foo",
1251 srcs: ["a.java"],
1252 api_packages: ["foo"],
1253 }
1254
1255 java_sdk_library {
1256 name: "bar",
1257 srcs: ["a.java"],
1258 api_packages: ["bar"],
1259 }
1260
1261 android_app {
1262 name: "app",
1263 srcs: ["a.java"],
1264 uses_libs: ["foo"],
1265 optional_uses_libs: [
1266 "bar",
1267 "baz",
1268 ],
1269 }
1270
1271 android_app_import {
1272 name: "prebuilt",
1273 apk: "prebuilts/apk/app.apk",
1274 certificate: "platform",
1275 uses_libs: ["foo"],
1276 optional_uses_libs: [
1277 "bar",
1278 "baz",
1279 ],
1280 }
1281 `
1282
1283 config := testConfig(nil)
1284 config.TestProductVariables.MissingUsesLibraries = []string{"baz"}
1285
1286 ctx := testAppContext(config, bp, nil)
1287
1288 run(t, ctx, config)
1289
1290 app := ctx.ModuleForTests("app", "android_common")
1291 prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
1292
1293 // Test that all libraries are verified
1294 cmd := app.Rule("verify_uses_libraries").RuleParams.Command
1295 if w := "--uses-library foo"; !strings.Contains(cmd, w) {
1296 t.Errorf("wanted %q in %q", w, cmd)
1297 }
1298
1299 if w := "--optional-uses-library bar --optional-uses-library baz"; !strings.Contains(cmd, w) {
1300 t.Errorf("wanted %q in %q", w, cmd)
1301 }
1302
1303 cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
1304
1305 if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) {
1306 t.Errorf("wanted %q in %q", w, cmd)
1307 }
1308
1309 if w := `optional_uses_library_names="bar baz"`; !strings.Contains(cmd, w) {
1310 t.Errorf("wanted %q in %q", w, cmd)
1311 }
1312
1313 // Test that only present libraries are preopted
1314 cmd = app.Rule("dexpreopt").RuleParams.Command
1315
1316 if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
1317 t.Errorf("wanted %q in %q", w, cmd)
1318 }
1319
1320 cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
1321
1322 if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
1323 t.Errorf("wanted %q in %q", w, cmd)
1324 }
1325}