blob: 781fdfffb10249200fc615c36bc1551be9fe527f [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: "",
715 expected: "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
716 },
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: "",
744 expected: "build/target/product/security/expiredkey.x509.pem build/target/product/security/expiredkey.pk8",
745 },
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"],
880 overrides: ["baz"],
881 }
882
883 override_android_app {
884 name: "bar",
885 base: "foo",
886 certificate: ":new_certificate",
887 }
888
889 android_app_certificate {
890 name: "new_certificate",
891 certificate: "cert/new_cert",
892 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700893
894 override_android_app {
895 name: "baz",
896 base: "foo",
897 package_name: "org.dandroid.bp",
898 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800899 `)
900
901 expectedVariants := []struct {
902 variantName string
903 apkName string
904 apkPath string
905 signFlag string
906 overrides []string
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700907 aaptFlag string
Jaewoong Jung525443a2019-02-28 15:35:54 -0800908 }{
909 {
910 variantName: "android_common",
911 apkPath: "/target/product/test_device/system/app/foo/foo.apk",
912 signFlag: "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
913 overrides: []string{"baz"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700914 aaptFlag: "",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800915 },
916 {
917 variantName: "bar_android_common",
918 apkPath: "/target/product/test_device/system/app/bar/bar.apk",
919 signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
920 overrides: []string{"baz", "foo"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700921 aaptFlag: "",
922 },
923 {
924 variantName: "baz_android_common",
925 apkPath: "/target/product/test_device/system/app/baz/baz.apk",
926 signFlag: "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
927 overrides: []string{"baz", "foo"},
928 aaptFlag: "--rename-manifest-package org.dandroid.bp",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800929 },
930 }
931 for _, expected := range expectedVariants {
932 variant := ctx.ModuleForTests("foo", expected.variantName)
933
934 // Check the final apk name
935 outputs := variant.AllOutputs()
936 expectedApkPath := buildDir + expected.apkPath
937 found := false
938 for _, o := range outputs {
939 if o == expectedApkPath {
940 found = true
941 break
942 }
943 }
944 if !found {
945 t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs)
946 }
947
948 // Check the certificate paths
949 signapk := variant.Output("foo.apk")
950 signFlag := signapk.Args["certificates"]
951 if expected.signFlag != signFlag {
952 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag)
953 }
954
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700955 // Check if the overrides field values are correctly aggregated.
Jaewoong Jung525443a2019-02-28 15:35:54 -0800956 mod := variant.Module().(*AndroidApp)
957 if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) {
958 t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
959 expected.overrides, mod.appProperties.Overrides)
960 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700961
962 // Check the package renaming flag, if exists.
963 res := variant.Output("package-res.apk")
964 aapt2Flags := res.Args["flags"]
965 if !strings.Contains(aapt2Flags, expected.aaptFlag) {
966 t.Errorf("package renaming flag, %q is missing in aapt2 link flags, %q", expected.aaptFlag, aapt2Flags)
967 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800968 }
969}