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