blob: e4c6afe29ef5a67aeae2bce76d19d729336a130e [file] [log] [blame]
Colin Cross3bc7ffa2017-11-22 16:19:37 -08001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18 "android/soong/android"
Colin Cross47fa9d32019-03-26 10:51:39 -070019 "android/soong/cc"
20
Colin Crossd09b0b62018-04-18 11:06:47 -070021 "fmt"
Colin Crossa4f08812018-10-02 22:03:40 -070022 "path/filepath"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080023 "reflect"
Colin Crossb69301e2017-12-01 10:48:26 -080024 "sort"
Colin Crossd09b0b62018-04-18 11:06:47 -070025 "strings"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080026 "testing"
27)
28
29var (
30 resourceFiles = []string{
31 "res/layout/layout.xml",
32 "res/values/strings.xml",
33 "res/values-en-rUS/strings.xml",
34 }
35
36 compiledResourceFiles = []string{
37 "aapt2/res/layout_layout.xml.flat",
38 "aapt2/res/values_strings.arsc.flat",
39 "aapt2/res/values-en-rUS_strings.arsc.flat",
40 }
41)
42
Colin Cross527012a2017-11-30 22:56:16 -080043func testAppContext(config android.Config, bp string, fs map[string][]byte) *android.TestContext {
44 appFS := map[string][]byte{}
45 for k, v := range fs {
46 appFS[k] = v
Colin Cross3bc7ffa2017-11-22 16:19:37 -080047 }
48
Colin Cross527012a2017-11-30 22:56:16 -080049 for _, file := range resourceFiles {
50 appFS[file] = nil
51 }
52
53 return testContext(config, bp, appFS)
54}
55
56func testApp(t *testing.T, bp string) *android.TestContext {
57 config := testConfig(nil)
58
59 ctx := testAppContext(config, bp, nil)
60
61 run(t, ctx, config)
62
63 return ctx
Colin Cross3bc7ffa2017-11-22 16:19:37 -080064}
65
66func TestApp(t *testing.T) {
Colin Crossa97c5d32018-03-28 14:58:31 -070067 for _, moduleType := range []string{"android_app", "android_library"} {
68 t.Run(moduleType, func(t *testing.T) {
69 ctx := testApp(t, moduleType+` {
70 name: "foo",
71 srcs: ["a.java"],
72 }
73 `)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080074
Colin Crossa97c5d32018-03-28 14:58:31 -070075 foo := ctx.ModuleForTests("foo", "android_common")
Colin Cross3bc7ffa2017-11-22 16:19:37 -080076
Colin Cross31656952018-05-24 16:11:20 -070077 var expectedLinkImplicits []string
78
79 manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
80 expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080081
Colin Crossa97c5d32018-03-28 14:58:31 -070082 frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
83 expectedLinkImplicits = append(expectedLinkImplicits,
84 frameworkRes.Output("package-res.apk").Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080085
Colin Crossa97c5d32018-03-28 14:58:31 -070086 // Test the mapping from input files to compiled output file names
87 compile := foo.Output(compiledResourceFiles[0])
88 if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
89 t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
90 resourceFiles, compile.Inputs.Strings())
91 }
Colin Crossb69301e2017-12-01 10:48:26 -080092
Colin Crossa97c5d32018-03-28 14:58:31 -070093 compiledResourceOutputs := compile.Outputs.Strings()
94 sort.Strings(compiledResourceOutputs)
Colin Crossb69301e2017-12-01 10:48:26 -080095
Colin Crossa97c5d32018-03-28 14:58:31 -070096 expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080097
Colin Crossa97c5d32018-03-28 14:58:31 -070098 list := foo.Output("aapt2/res.list")
99 expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800100
Colin Crossa97c5d32018-03-28 14:58:31 -0700101 // Check that the link rule uses
102 res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
103 if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
104 t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
105 expectedLinkImplicits, res.Implicits.Strings())
106 }
107 })
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800108 }
109}
Colin Cross890ff552017-11-30 20:13:19 -0800110
Colin Crosse560c4a2019-03-19 16:03:11 -0700111func TestAppSplits(t *testing.T) {
112 ctx := testApp(t, `
113 android_app {
114 name: "foo",
115 srcs: ["a.java"],
116 package_splits: ["v4", "v7,hdpi"],
117 }`)
118
119 foo := ctx.ModuleForTests("foo", "android_common")
120
121 expectedOutputs := []string{
122 filepath.Join(buildDir, ".intermediates/foo/android_common/foo.apk"),
123 filepath.Join(buildDir, ".intermediates/foo/android_common/foo_v4.apk"),
124 filepath.Join(buildDir, ".intermediates/foo/android_common/foo_v7_hdpi.apk"),
125 }
126 for _, expectedOutput := range expectedOutputs {
127 foo.Output(expectedOutput)
128 }
129
130 if g, w := foo.Module().(*AndroidApp).Srcs().Strings(), expectedOutputs; !reflect.DeepEqual(g, w) {
131 t.Errorf("want Srcs() = %q, got %q", w, g)
132 }
133}
134
Colin Cross0ddae7f2019-02-07 15:30:01 -0800135func TestResourceDirs(t *testing.T) {
136 testCases := []struct {
137 name string
138 prop string
139 resources []string
140 }{
141 {
142 name: "no resource_dirs",
143 prop: "",
144 resources: []string{"res/res/values/strings.xml"},
145 },
146 {
147 name: "resource_dirs",
148 prop: `resource_dirs: ["res"]`,
149 resources: []string{"res/res/values/strings.xml"},
150 },
151 {
152 name: "empty resource_dirs",
153 prop: `resource_dirs: []`,
154 resources: nil,
155 },
156 }
157
158 fs := map[string][]byte{
159 "res/res/values/strings.xml": nil,
160 }
161
162 bp := `
163 android_app {
164 name: "foo",
165 %s
166 }
167 `
168
169 for _, testCase := range testCases {
170 t.Run(testCase.name, func(t *testing.T) {
171 config := testConfig(nil)
172 ctx := testContext(config, fmt.Sprintf(bp, testCase.prop), fs)
173 run(t, ctx, config)
174
175 module := ctx.ModuleForTests("foo", "android_common")
176 resourceList := module.MaybeOutput("aapt2/res.list")
177
178 var resources []string
179 if resourceList.Rule != nil {
180 for _, compiledResource := range resourceList.Inputs.Strings() {
181 resources = append(resources, module.Output(compiledResource).Inputs.Strings()...)
182 }
183 }
184
185 if !reflect.DeepEqual(resources, testCase.resources) {
186 t.Errorf("expected resource files %q, got %q",
187 testCase.resources, resources)
188 }
189 })
190 }
191}
192
Colin Crossbec85302019-02-13 13:15:46 -0800193func TestAndroidResources(t *testing.T) {
Colin Cross5c4791c2019-02-01 11:44:44 -0800194 testCases := []struct {
195 name string
196 enforceRROTargets []string
197 enforceRROExcludedOverlays []string
Colin Crossbec85302019-02-13 13:15:46 -0800198 resourceFiles map[string][]string
Colin Cross5c4791c2019-02-01 11:44:44 -0800199 overlayFiles map[string][]string
200 rroDirs map[string][]string
201 }{
202 {
203 name: "no RRO",
204 enforceRROTargets: nil,
205 enforceRROExcludedOverlays: nil,
Colin Crossbec85302019-02-13 13:15:46 -0800206 resourceFiles: map[string][]string{
207 "foo": nil,
208 "bar": {"bar/res/res/values/strings.xml"},
209 "lib": nil,
210 "lib2": {"lib2/res/res/values/strings.xml"},
211 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800212 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800213 "foo": {
214 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800215 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000216 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800217 "foo/res/res/values/strings.xml",
Colin Cross5c4791c2019-02-01 11:44:44 -0800218 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
219 "device/vendor/blah/overlay/foo/res/values/strings.xml",
Anton Hansson53c88442019-03-18 15:53:16 +0000220 "product/vendor/blah/overlay/foo/res/values/strings.xml",
Colin Cross5c4791c2019-02-01 11:44:44 -0800221 },
Colin Crossbec85302019-02-13 13:15:46 -0800222 "bar": {
Colin Cross5c4791c2019-02-01 11:44:44 -0800223 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
224 "device/vendor/blah/overlay/bar/res/values/strings.xml",
225 },
Colin Crossbec85302019-02-13 13:15:46 -0800226 "lib": {
227 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
228 "lib/res/res/values/strings.xml",
229 "device/vendor/blah/overlay/lib/res/values/strings.xml",
230 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800231 },
232 rroDirs: map[string][]string{
233 "foo": nil,
234 "bar": nil,
235 },
236 },
237 {
238 name: "enforce RRO on foo",
239 enforceRROTargets: []string{"foo"},
240 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
Colin Crossbec85302019-02-13 13:15:46 -0800241 resourceFiles: map[string][]string{
242 "foo": nil,
243 "bar": {"bar/res/res/values/strings.xml"},
244 "lib": nil,
245 "lib2": {"lib2/res/res/values/strings.xml"},
246 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800247 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800248 "foo": {
249 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800250 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000251 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800252 "foo/res/res/values/strings.xml",
253 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
254 },
Colin Crossbec85302019-02-13 13:15:46 -0800255 "bar": {
Colin Cross5c4791c2019-02-01 11:44:44 -0800256 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
257 "device/vendor/blah/overlay/bar/res/values/strings.xml",
258 },
Colin Crossbec85302019-02-13 13:15:46 -0800259 "lib": {
260 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
261 "lib/res/res/values/strings.xml",
262 "device/vendor/blah/overlay/lib/res/values/strings.xml",
263 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800264 },
Colin Crossc1c37552019-01-31 11:42:41 -0800265
Colin Cross5c4791c2019-02-01 11:44:44 -0800266 rroDirs: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800267 "foo": {
Anton Hansson53c88442019-03-18 15:53:16 +0000268 "device:device/vendor/blah/overlay/foo/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800269 // Enforce RRO on "foo" could imply RRO on static dependencies, but for now it doesn't.
270 // "device/vendor/blah/overlay/lib/res",
Anton Hansson53c88442019-03-18 15:53:16 +0000271 "product:product/vendor/blah/overlay/foo/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800272 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800273 "bar": nil,
Colin Crossbec85302019-02-13 13:15:46 -0800274 "lib": nil,
Colin Cross5c4791c2019-02-01 11:44:44 -0800275 },
276 },
277 {
278 name: "enforce RRO on all",
279 enforceRROTargets: []string{"*"},
280 enforceRROExcludedOverlays: []string{
281 // Excluding specific apps/res directories also allowed.
282 "device/vendor/blah/static_overlay/foo",
283 "device/vendor/blah/static_overlay/bar/res",
284 },
Colin Crossbec85302019-02-13 13:15:46 -0800285 resourceFiles: map[string][]string{
286 "foo": nil,
287 "bar": {"bar/res/res/values/strings.xml"},
288 "lib": nil,
289 "lib2": {"lib2/res/res/values/strings.xml"},
290 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800291 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800292 "foo": {
293 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800294 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000295 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800296 "foo/res/res/values/strings.xml",
297 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
298 },
Colin Crossbec85302019-02-13 13:15:46 -0800299 "bar": {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
300 "lib": {
301 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
302 "lib/res/res/values/strings.xml",
303 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800304 },
305 rroDirs: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800306 "foo": {
Anton Hansson53c88442019-03-18 15:53:16 +0000307 "device:device/vendor/blah/overlay/foo/res",
308 "product:product/vendor/blah/overlay/foo/res",
309 // Lib dep comes after the direct deps
310 "device:device/vendor/blah/overlay/lib/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800311 },
Anton Hansson53c88442019-03-18 15:53:16 +0000312 "bar": {"device:device/vendor/blah/overlay/bar/res"},
313 "lib": {"device:device/vendor/blah/overlay/lib/res"},
Colin Cross5c4791c2019-02-01 11:44:44 -0800314 },
315 },
316 }
317
Anton Hansson53c88442019-03-18 15:53:16 +0000318 deviceResourceOverlays := []string{
Colin Cross890ff552017-11-30 20:13:19 -0800319 "device/vendor/blah/overlay",
320 "device/vendor/blah/overlay2",
321 "device/vendor/blah/static_overlay",
322 }
323
Anton Hansson53c88442019-03-18 15:53:16 +0000324 productResourceOverlays := []string{
325 "product/vendor/blah/overlay",
326 }
327
Colin Cross890ff552017-11-30 20:13:19 -0800328 fs := map[string][]byte{
329 "foo/res/res/values/strings.xml": nil,
330 "bar/res/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800331 "lib/res/res/values/strings.xml": nil,
Colin Crossbec85302019-02-13 13:15:46 -0800332 "lib2/res/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800333 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
334 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800335 "device/vendor/blah/overlay/lib/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800336 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
337 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
338 "device/vendor/blah/overlay2/res/values/strings.xml": nil,
Anton Hansson53c88442019-03-18 15:53:16 +0000339 "product/vendor/blah/overlay/foo/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800340 }
341
342 bp := `
343 android_app {
344 name: "foo",
345 resource_dirs: ["foo/res"],
Anton Hansson53c88442019-03-18 15:53:16 +0000346 static_libs: ["lib", "lib3"],
Colin Cross890ff552017-11-30 20:13:19 -0800347 }
348
349 android_app {
350 name: "bar",
351 resource_dirs: ["bar/res"],
352 }
Colin Cross6ed7dea2019-01-31 14:44:30 -0800353
354 android_library {
355 name: "lib",
356 resource_dirs: ["lib/res"],
Colin Crossbec85302019-02-13 13:15:46 -0800357 static_libs: ["lib2"],
358 }
359
360 android_library {
361 name: "lib2",
362 resource_dirs: ["lib2/res"],
Colin Cross6ed7dea2019-01-31 14:44:30 -0800363 }
Anton Hansson53c88442019-03-18 15:53:16 +0000364
365 // This library has the same resources as lib (should not lead to dupe RROs)
366 android_library {
367 name: "lib3",
368 resource_dirs: ["lib/res"]
369 }
Colin Cross890ff552017-11-30 20:13:19 -0800370 `
371
Colin Cross5c4791c2019-02-01 11:44:44 -0800372 for _, testCase := range testCases {
Colin Cross890ff552017-11-30 20:13:19 -0800373 t.Run(testCase.name, func(t *testing.T) {
374 config := testConfig(nil)
Anton Hansson53c88442019-03-18 15:53:16 +0000375 config.TestProductVariables.DeviceResourceOverlays = deviceResourceOverlays
376 config.TestProductVariables.ProductResourceOverlays = productResourceOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800377 if testCase.enforceRROTargets != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800378 config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
Colin Cross890ff552017-11-30 20:13:19 -0800379 }
380 if testCase.enforceRROExcludedOverlays != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800381 config.TestProductVariables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800382 }
383
384 ctx := testAppContext(config, bp, fs)
385 run(t, ctx, config)
386
Colin Crossbec85302019-02-13 13:15:46 -0800387 resourceListToFiles := func(module android.TestingModule, list []string) (files []string) {
388 for _, o := range list {
389 res := module.MaybeOutput(o)
390 if res.Rule != nil {
391 // If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
392 // verify the inputs to the .arsc.flat rule.
393 files = append(files, res.Inputs.Strings()...)
394 } else {
395 // Otherwise, verify the full path to the output of the other module
396 files = append(files, o)
Anton Hansson94c93f32019-01-30 16:03:37 +0000397 }
Colin Cross890ff552017-11-30 20:13:19 -0800398 }
Colin Crossbec85302019-02-13 13:15:46 -0800399 return files
Colin Cross890ff552017-11-30 20:13:19 -0800400 }
401
Colin Crossbec85302019-02-13 13:15:46 -0800402 getResources := func(moduleName string) (resourceFiles, overlayFiles, rroDirs []string) {
403 module := ctx.ModuleForTests(moduleName, "android_common")
404 resourceList := module.MaybeOutput("aapt2/res.list")
405 if resourceList.Rule != nil {
406 resourceFiles = resourceListToFiles(module, resourceList.Inputs.Strings())
Anton Hansson0375a4f2019-01-24 14:39:19 +0000407 }
Colin Crossbec85302019-02-13 13:15:46 -0800408 overlayList := module.MaybeOutput("aapt2/overlay.list")
409 if overlayList.Rule != nil {
410 overlayFiles = resourceListToFiles(module, overlayList.Inputs.Strings())
411 }
412
Anton Hansson53c88442019-03-18 15:53:16 +0000413 for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() {
414 var prefix string
415 if d.overlayType == device {
416 prefix = "device:"
417 } else if d.overlayType == product {
418 prefix = "product:"
419 } else {
420 t.Fatalf("Unexpected overlayType %d", d.overlayType)
421 }
422 rroDirs = append(rroDirs, prefix+d.path.String())
423 }
Colin Crossbec85302019-02-13 13:15:46 -0800424
425 return resourceFiles, overlayFiles, rroDirs
426 }
427
428 modules := []string{"foo", "bar", "lib", "lib2"}
429 for _, module := range modules {
430 resourceFiles, overlayFiles, rroDirs := getResources(module)
431
432 if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[module]) {
433 t.Errorf("expected %s resource files:\n %#v\n got:\n %#v",
434 module, testCase.resourceFiles[module], resourceFiles)
435 }
436 if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[module]) {
437 t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v",
438 module, testCase.overlayFiles[module], overlayFiles)
439 }
440 if !reflect.DeepEqual(rroDirs, testCase.rroDirs[module]) {
Anton Hansson0375a4f2019-01-24 14:39:19 +0000441 t.Errorf("expected %s rroDirs: %#v\n got:\n %#v",
Colin Crossbec85302019-02-13 13:15:46 -0800442 module, testCase.rroDirs[module], rroDirs)
Anton Hansson0375a4f2019-01-24 14:39:19 +0000443 }
Colin Cross890ff552017-11-30 20:13:19 -0800444 }
Colin Cross890ff552017-11-30 20:13:19 -0800445 })
446 }
447}
Colin Crossd09b0b62018-04-18 11:06:47 -0700448
449func TestAppSdkVersion(t *testing.T) {
450 testCases := []struct {
451 name string
452 sdkVersion string
453 platformSdkInt int
454 platformSdkCodename string
455 platformSdkFinal bool
456 expectedMinSdkVersion string
457 }{
458 {
459 name: "current final SDK",
460 sdkVersion: "current",
461 platformSdkInt: 27,
462 platformSdkCodename: "REL",
463 platformSdkFinal: true,
464 expectedMinSdkVersion: "27",
465 },
466 {
467 name: "current non-final SDK",
468 sdkVersion: "current",
469 platformSdkInt: 27,
470 platformSdkCodename: "OMR1",
471 platformSdkFinal: false,
472 expectedMinSdkVersion: "OMR1",
473 },
474 {
475 name: "default final SDK",
476 sdkVersion: "",
477 platformSdkInt: 27,
478 platformSdkCodename: "REL",
479 platformSdkFinal: true,
480 expectedMinSdkVersion: "27",
481 },
482 {
483 name: "default non-final SDK",
484 sdkVersion: "",
485 platformSdkInt: 27,
486 platformSdkCodename: "OMR1",
487 platformSdkFinal: false,
488 expectedMinSdkVersion: "OMR1",
489 },
490 {
491 name: "14",
492 sdkVersion: "14",
493 expectedMinSdkVersion: "14",
494 },
495 }
496
497 for _, moduleType := range []string{"android_app", "android_library"} {
498 for _, test := range testCases {
499 t.Run(moduleType+" "+test.name, func(t *testing.T) {
500 bp := fmt.Sprintf(`%s {
501 name: "foo",
502 srcs: ["a.java"],
503 sdk_version: "%s",
504 }`, moduleType, test.sdkVersion)
505
506 config := testConfig(nil)
507 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
508 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
509 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
510
511 ctx := testAppContext(config, bp, nil)
512
513 run(t, ctx, config)
514
515 foo := ctx.ModuleForTests("foo", "android_common")
516 link := foo.Output("package-res.apk")
517 linkFlags := strings.Split(link.Args["flags"], " ")
518 min := android.IndexList("--min-sdk-version", linkFlags)
519 target := android.IndexList("--target-sdk-version", linkFlags)
520
521 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
522 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
523 }
524
525 gotMinSdkVersion := linkFlags[min+1]
526 gotTargetSdkVersion := linkFlags[target+1]
527
528 if gotMinSdkVersion != test.expectedMinSdkVersion {
529 t.Errorf("incorrect --min-sdk-version, expected %q got %q",
530 test.expectedMinSdkVersion, gotMinSdkVersion)
531 }
532
533 if gotTargetSdkVersion != test.expectedMinSdkVersion {
534 t.Errorf("incorrect --target-sdk-version, expected %q got %q",
535 test.expectedMinSdkVersion, gotTargetSdkVersion)
536 }
537 })
538 }
539 }
540}
Colin Crossa4f08812018-10-02 22:03:40 -0700541
Colin Cross47fa9d32019-03-26 10:51:39 -0700542func TestJNIABI(t *testing.T) {
543 ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
Colin Crossa4f08812018-10-02 22:03:40 -0700544 cc_library {
545 name: "libjni",
546 system_shared_libs: [],
547 stl: "none",
548 }
549
550 android_test {
551 name: "test",
552 no_framework_libs: true,
553 jni_libs: ["libjni"],
554 }
555
556 android_test {
557 name: "test_first",
558 no_framework_libs: true,
559 compile_multilib: "first",
560 jni_libs: ["libjni"],
561 }
562
563 android_test {
564 name: "test_both",
565 no_framework_libs: true,
566 compile_multilib: "both",
567 jni_libs: ["libjni"],
568 }
569
570 android_test {
571 name: "test_32",
572 no_framework_libs: true,
573 compile_multilib: "32",
574 jni_libs: ["libjni"],
575 }
576
577 android_test {
578 name: "test_64",
579 no_framework_libs: true,
580 compile_multilib: "64",
581 jni_libs: ["libjni"],
582 }
583 `)
584
Colin Crossa4f08812018-10-02 22:03:40 -0700585 testCases := []struct {
586 name string
587 abis []string
588 }{
589 {"test", []string{"arm64-v8a"}},
590 {"test_first", []string{"arm64-v8a"}},
591 {"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
592 {"test_32", []string{"armeabi-v7a"}},
593 {"test_64", []string{"arm64-v8a"}},
594 }
595
596 for _, test := range testCases {
597 t.Run(test.name, func(t *testing.T) {
598 app := ctx.ModuleForTests(test.name, "android_common")
599 jniLibZip := app.Output("jnilibs.zip")
600 var abis []string
601 args := strings.Fields(jniLibZip.Args["jarArgs"])
602 for i := 0; i < len(args); i++ {
603 if args[i] == "-P" {
604 abis = append(abis, filepath.Base(args[i+1]))
605 i++
606 }
607 }
608 if !reflect.DeepEqual(abis, test.abis) {
609 t.Errorf("want abis %v, got %v", test.abis, abis)
610 }
611 })
612 }
613}
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800614
Colin Cross47fa9d32019-03-26 10:51:39 -0700615func TestJNIPackaging(t *testing.T) {
616 ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
617 cc_library {
618 name: "libjni",
619 system_shared_libs: [],
620 stl: "none",
621 }
622
623 android_app {
624 name: "app",
625 jni_libs: ["libjni"],
626 }
627
628 android_app {
629 name: "app_noembed",
630 jni_libs: ["libjni"],
631 use_embedded_native_libs: false,
632 }
633
634 android_app {
635 name: "app_embed",
636 jni_libs: ["libjni"],
637 use_embedded_native_libs: true,
638 }
639
640 android_test {
641 name: "test",
642 no_framework_libs: true,
643 jni_libs: ["libjni"],
644 }
645
646 android_test {
647 name: "test_noembed",
648 no_framework_libs: true,
649 jni_libs: ["libjni"],
650 use_embedded_native_libs: false,
651 }
652
653 android_test_helper_app {
654 name: "test_helper",
655 no_framework_libs: true,
656 jni_libs: ["libjni"],
657 }
658
659 android_test_helper_app {
660 name: "test_helper_noembed",
661 no_framework_libs: true,
662 jni_libs: ["libjni"],
663 use_embedded_native_libs: false,
664 }
665 `)
666
667 testCases := []struct {
668 name string
669 packaged bool
670 compressed bool
671 }{
672 {"app", false, false},
673 {"app_noembed", false, false},
674 {"app_embed", true, false},
675 {"test", true, false},
676 {"test_noembed", true, true},
677 {"test_helper", true, false},
678 {"test_helper_noembed", true, true},
679 }
680
681 for _, test := range testCases {
682 t.Run(test.name, func(t *testing.T) {
683 app := ctx.ModuleForTests(test.name, "android_common")
684 jniLibZip := app.MaybeOutput("jnilibs.zip")
685 if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
686 t.Errorf("expected jni packaged %v, got %v", w, g)
687 }
688
689 if jniLibZip.Rule != nil {
690 if g, w := !strings.Contains(jniLibZip.Args["jarArgs"], "-L 0"), test.compressed; g != w {
691 t.Errorf("expected jni compressed %v, got %v", w, g)
692 }
693 }
694 })
695 }
696
697}
698
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800699func TestCertificates(t *testing.T) {
700 testCases := []struct {
701 name string
702 bp string
703 certificateOverride string
704 expected string
705 }{
706 {
707 name: "default",
708 bp: `
709 android_app {
710 name: "foo",
711 srcs: ["a.java"],
712 }
713 `,
714 certificateOverride: "",
Dan Willemsen412160e2019-04-09 21:36:26 -0700715 expected: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8",
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800716 },
717 {
718 name: "module certificate property",
719 bp: `
720 android_app {
721 name: "foo",
722 srcs: ["a.java"],
723 certificate: ":new_certificate"
724 }
725
726 android_app_certificate {
727 name: "new_certificate",
728 certificate: "cert/new_cert",
729 }
730 `,
731 certificateOverride: "",
732 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
733 },
734 {
735 name: "path certificate property",
736 bp: `
737 android_app {
738 name: "foo",
739 srcs: ["a.java"],
740 certificate: "expiredkey"
741 }
742 `,
743 certificateOverride: "",
Dan Willemsen412160e2019-04-09 21:36:26 -0700744 expected: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800745 },
746 {
747 name: "certificate overrides",
748 bp: `
749 android_app {
750 name: "foo",
751 srcs: ["a.java"],
752 certificate: "expiredkey"
753 }
754
755 android_app_certificate {
756 name: "new_certificate",
757 certificate: "cert/new_cert",
758 }
759 `,
760 certificateOverride: "foo:new_certificate",
761 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
762 },
763 }
764
765 for _, test := range testCases {
766 t.Run(test.name, func(t *testing.T) {
767 config := testConfig(nil)
768 if test.certificateOverride != "" {
769 config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride}
770 }
771 ctx := testAppContext(config, test.bp, nil)
772
773 run(t, ctx, config)
774 foo := ctx.ModuleForTests("foo", "android_common")
775
776 signapk := foo.Output("foo.apk")
777 signFlags := signapk.Args["certificates"]
778 if test.expected != signFlags {
779 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags)
780 }
781 })
782 }
783}
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800784
785func TestPackageNameOverride(t *testing.T) {
786 testCases := []struct {
787 name string
788 bp string
789 packageNameOverride string
790 expected []string
791 }{
792 {
793 name: "default",
794 bp: `
795 android_app {
796 name: "foo",
797 srcs: ["a.java"],
798 }
799 `,
800 packageNameOverride: "",
801 expected: []string{
802 buildDir + "/.intermediates/foo/android_common/foo.apk",
803 buildDir + "/target/product/test_device/system/app/foo/foo.apk",
804 },
805 },
806 {
807 name: "overridden",
808 bp: `
809 android_app {
810 name: "foo",
811 srcs: ["a.java"],
812 }
813 `,
814 packageNameOverride: "foo:bar",
815 expected: []string{
816 // The package apk should be still be the original name for test dependencies.
817 buildDir + "/.intermediates/foo/android_common/foo.apk",
818 buildDir + "/target/product/test_device/system/app/bar/bar.apk",
819 },
820 },
821 }
822
823 for _, test := range testCases {
824 t.Run(test.name, func(t *testing.T) {
825 config := testConfig(nil)
826 if test.packageNameOverride != "" {
827 config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride}
828 }
829 ctx := testAppContext(config, test.bp, nil)
830
831 run(t, ctx, config)
832 foo := ctx.ModuleForTests("foo", "android_common")
833
834 outputs := foo.AllOutputs()
835 outputMap := make(map[string]bool)
836 for _, o := range outputs {
837 outputMap[o] = true
838 }
839 for _, e := range test.expected {
840 if _, exist := outputMap[e]; !exist {
841 t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
842 }
843 }
844 })
845 }
846}
Jaewoong Jung4102e5d2019-02-27 16:26:28 -0800847
848func TestInstrumentationTargetOverridden(t *testing.T) {
849 bp := `
850 android_app {
851 name: "foo",
852 srcs: ["a.java"],
853 }
854
855 android_test {
856 name: "bar",
857 instrumentation_for: "foo",
858 }
859 `
860 config := testConfig(nil)
861 config.TestProductVariables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"}
862 ctx := testAppContext(config, bp, nil)
863
864 run(t, ctx, config)
865
866 bar := ctx.ModuleForTests("bar", "android_common")
867 res := bar.Output("package-res.apk")
868 aapt2Flags := res.Args["flags"]
869 e := "--rename-instrumentation-target-package org.dandroid.bp"
870 if !strings.Contains(aapt2Flags, e) {
871 t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
872 }
873}
Jaewoong Jung525443a2019-02-28 15:35:54 -0800874
875func TestOverrideAndroidApp(t *testing.T) {
876 ctx := testJava(t, `
877 android_app {
878 name: "foo",
879 srcs: ["a.java"],
Jaewoong Junga641ee92019-03-27 11:17:14 -0700880 certificate: "expiredkey",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800881 overrides: ["baz"],
882 }
883
884 override_android_app {
885 name: "bar",
886 base: "foo",
887 certificate: ":new_certificate",
888 }
889
890 android_app_certificate {
891 name: "new_certificate",
892 certificate: "cert/new_cert",
893 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700894
895 override_android_app {
896 name: "baz",
897 base: "foo",
898 package_name: "org.dandroid.bp",
899 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800900 `)
901
902 expectedVariants := []struct {
903 variantName string
904 apkName string
905 apkPath string
906 signFlag string
907 overrides []string
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700908 aaptFlag string
Jaewoong Jung525443a2019-02-28 15:35:54 -0800909 }{
910 {
911 variantName: "android_common",
912 apkPath: "/target/product/test_device/system/app/foo/foo.apk",
Dan Willemsen412160e2019-04-09 21:36:26 -0700913 signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800914 overrides: []string{"baz"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700915 aaptFlag: "",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800916 },
917 {
918 variantName: "bar_android_common",
919 apkPath: "/target/product/test_device/system/app/bar/bar.apk",
920 signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
921 overrides: []string{"baz", "foo"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700922 aaptFlag: "",
923 },
924 {
925 variantName: "baz_android_common",
926 apkPath: "/target/product/test_device/system/app/baz/baz.apk",
Dan Willemsen412160e2019-04-09 21:36:26 -0700927 signFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700928 overrides: []string{"baz", "foo"},
929 aaptFlag: "--rename-manifest-package org.dandroid.bp",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800930 },
931 }
932 for _, expected := range expectedVariants {
933 variant := ctx.ModuleForTests("foo", expected.variantName)
934
935 // Check the final apk name
936 outputs := variant.AllOutputs()
937 expectedApkPath := buildDir + expected.apkPath
938 found := false
939 for _, o := range outputs {
940 if o == expectedApkPath {
941 found = true
942 break
943 }
944 }
945 if !found {
946 t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs)
947 }
948
949 // Check the certificate paths
950 signapk := variant.Output("foo.apk")
951 signFlag := signapk.Args["certificates"]
952 if expected.signFlag != signFlag {
953 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag)
954 }
955
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700956 // Check if the overrides field values are correctly aggregated.
Jaewoong Jung525443a2019-02-28 15:35:54 -0800957 mod := variant.Module().(*AndroidApp)
958 if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) {
959 t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
960 expected.overrides, mod.appProperties.Overrides)
961 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700962
963 // Check the package renaming flag, if exists.
964 res := variant.Output("package-res.apk")
965 aapt2Flags := res.Args["flags"]
966 if !strings.Contains(aapt2Flags, expected.aaptFlag) {
967 t.Errorf("package renaming flag, %q is missing in aapt2 link flags, %q", expected.aaptFlag, aapt2Flags)
968 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800969 }
970}
Jaewoong Jungccbb3932019-04-15 09:48:31 -0700971
972func TestAndroidAppImport(t *testing.T) {
973 ctx := testJava(t, `
974 android_app_import {
975 name: "foo",
976 apk: "prebuilts/apk/app.apk",
977 certificate: "platform",
978 dex_preopt: {
979 enabled: true,
980 },
981 }
982 `)
983
984 variant := ctx.ModuleForTests("foo", "android_common")
985
986 // Check dexpreopt outputs.
987 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
988 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
989 t.Errorf("can't find dexpreopt outputs")
990 }
991
992 // Check cert signing flag.
993 signedApk := variant.Output("signed/foo.apk")
994 signingFlag := signedApk.Args["certificates"]
995 expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
996 if expected != signingFlag {
997 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
998 }
999}
1000
1001func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
1002 ctx := testJava(t, `
1003 android_app_import {
1004 name: "foo",
1005 apk: "prebuilts/apk/app.apk",
1006 certificate: "platform",
1007 dex_preopt: {
1008 enabled: false,
1009 },
1010 }
1011 `)
1012
1013 variant := ctx.ModuleForTests("foo", "android_common")
1014
1015 // Check dexpreopt outputs. They shouldn't exist.
1016 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
1017 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
1018 t.Errorf("dexpreopt shouldn't have run.")
1019 }
1020}
1021
1022func TestAndroidAppImport_Presigned(t *testing.T) {
1023 ctx := testJava(t, `
1024 android_app_import {
1025 name: "foo",
1026 apk: "prebuilts/apk/app.apk",
1027 presigned: true,
1028 dex_preopt: {
1029 enabled: true,
1030 },
1031 }
1032 `)
1033
1034 variant := ctx.ModuleForTests("foo", "android_common")
1035
1036 // Check dexpreopt outputs.
1037 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
1038 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
1039 t.Errorf("can't find dexpreopt outputs")
1040 }
1041 // Make sure stripping wasn't done.
1042 stripRule := variant.Output("dexpreopt/foo.apk")
1043 if !strings.HasPrefix(stripRule.RuleParams.Command, "cp -f") {
1044 t.Errorf("unexpected, non-skipping strip command: %q", stripRule.RuleParams.Command)
1045 }
1046
1047 // Make sure signing was skipped and aligning was done instead.
1048 if variant.MaybeOutput("signed/foo.apk").Rule != nil {
1049 t.Errorf("signing rule shouldn't be included.")
1050 }
1051 if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
1052 t.Errorf("can't find aligning rule")
1053 }
1054}