blob: d266242611b1060f34c482013ca1f60fde536f98 [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 Crossd09b0b62018-04-18 11:06:47 -070019 "fmt"
Colin Crossa4f08812018-10-02 22:03:40 -070020 "path/filepath"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080021 "reflect"
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"
25)
26
27var (
28 resourceFiles = []string{
29 "res/layout/layout.xml",
30 "res/values/strings.xml",
31 "res/values-en-rUS/strings.xml",
32 }
33
34 compiledResourceFiles = []string{
35 "aapt2/res/layout_layout.xml.flat",
36 "aapt2/res/values_strings.arsc.flat",
37 "aapt2/res/values-en-rUS_strings.arsc.flat",
38 }
39)
40
Colin Cross527012a2017-11-30 22:56:16 -080041func testAppContext(config android.Config, bp string, fs map[string][]byte) *android.TestContext {
42 appFS := map[string][]byte{}
43 for k, v := range fs {
44 appFS[k] = v
Colin Cross3bc7ffa2017-11-22 16:19:37 -080045 }
46
Colin Cross527012a2017-11-30 22:56:16 -080047 for _, file := range resourceFiles {
48 appFS[file] = nil
49 }
50
51 return testContext(config, bp, appFS)
52}
53
54func testApp(t *testing.T, bp string) *android.TestContext {
55 config := testConfig(nil)
56
57 ctx := testAppContext(config, bp, nil)
58
59 run(t, ctx, config)
60
61 return ctx
Colin Cross3bc7ffa2017-11-22 16:19:37 -080062}
63
64func TestApp(t *testing.T) {
Colin Crossa97c5d32018-03-28 14:58:31 -070065 for _, moduleType := range []string{"android_app", "android_library"} {
66 t.Run(moduleType, func(t *testing.T) {
67 ctx := testApp(t, moduleType+` {
68 name: "foo",
69 srcs: ["a.java"],
70 }
71 `)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080072
Colin Crossa97c5d32018-03-28 14:58:31 -070073 foo := ctx.ModuleForTests("foo", "android_common")
Colin Cross3bc7ffa2017-11-22 16:19:37 -080074
Colin Cross31656952018-05-24 16:11:20 -070075 var expectedLinkImplicits []string
76
77 manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
78 expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080079
Colin Crossa97c5d32018-03-28 14:58:31 -070080 frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
81 expectedLinkImplicits = append(expectedLinkImplicits,
82 frameworkRes.Output("package-res.apk").Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080083
Colin Crossa97c5d32018-03-28 14:58:31 -070084 // Test the mapping from input files to compiled output file names
85 compile := foo.Output(compiledResourceFiles[0])
86 if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
87 t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
88 resourceFiles, compile.Inputs.Strings())
89 }
Colin Crossb69301e2017-12-01 10:48:26 -080090
Colin Crossa97c5d32018-03-28 14:58:31 -070091 compiledResourceOutputs := compile.Outputs.Strings()
92 sort.Strings(compiledResourceOutputs)
Colin Crossb69301e2017-12-01 10:48:26 -080093
Colin Crossa97c5d32018-03-28 14:58:31 -070094 expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080095
Colin Crossa97c5d32018-03-28 14:58:31 -070096 list := foo.Output("aapt2/res.list")
97 expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080098
Colin Crossa97c5d32018-03-28 14:58:31 -070099 // Check that the link rule uses
100 res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
101 if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
102 t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
103 expectedLinkImplicits, res.Implicits.Strings())
104 }
105 })
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800106 }
107}
Colin Cross890ff552017-11-30 20:13:19 -0800108
Colin Crosse560c4a2019-03-19 16:03:11 -0700109func TestAppSplits(t *testing.T) {
110 ctx := testApp(t, `
111 android_app {
112 name: "foo",
113 srcs: ["a.java"],
114 package_splits: ["v4", "v7,hdpi"],
115 }`)
116
117 foo := ctx.ModuleForTests("foo", "android_common")
118
119 expectedOutputs := []string{
120 filepath.Join(buildDir, ".intermediates/foo/android_common/foo.apk"),
121 filepath.Join(buildDir, ".intermediates/foo/android_common/foo_v4.apk"),
122 filepath.Join(buildDir, ".intermediates/foo/android_common/foo_v7_hdpi.apk"),
123 }
124 for _, expectedOutput := range expectedOutputs {
125 foo.Output(expectedOutput)
126 }
127
128 if g, w := foo.Module().(*AndroidApp).Srcs().Strings(), expectedOutputs; !reflect.DeepEqual(g, w) {
129 t.Errorf("want Srcs() = %q, got %q", w, g)
130 }
131}
132
Colin Cross0ddae7f2019-02-07 15:30:01 -0800133func TestResourceDirs(t *testing.T) {
134 testCases := []struct {
135 name string
136 prop string
137 resources []string
138 }{
139 {
140 name: "no resource_dirs",
141 prop: "",
142 resources: []string{"res/res/values/strings.xml"},
143 },
144 {
145 name: "resource_dirs",
146 prop: `resource_dirs: ["res"]`,
147 resources: []string{"res/res/values/strings.xml"},
148 },
149 {
150 name: "empty resource_dirs",
151 prop: `resource_dirs: []`,
152 resources: nil,
153 },
154 }
155
156 fs := map[string][]byte{
157 "res/res/values/strings.xml": nil,
158 }
159
160 bp := `
161 android_app {
162 name: "foo",
163 %s
164 }
165 `
166
167 for _, testCase := range testCases {
168 t.Run(testCase.name, func(t *testing.T) {
169 config := testConfig(nil)
170 ctx := testContext(config, fmt.Sprintf(bp, testCase.prop), fs)
171 run(t, ctx, config)
172
173 module := ctx.ModuleForTests("foo", "android_common")
174 resourceList := module.MaybeOutput("aapt2/res.list")
175
176 var resources []string
177 if resourceList.Rule != nil {
178 for _, compiledResource := range resourceList.Inputs.Strings() {
179 resources = append(resources, module.Output(compiledResource).Inputs.Strings()...)
180 }
181 }
182
183 if !reflect.DeepEqual(resources, testCase.resources) {
184 t.Errorf("expected resource files %q, got %q",
185 testCase.resources, resources)
186 }
187 })
188 }
189}
190
Colin Crossbec85302019-02-13 13:15:46 -0800191func TestAndroidResources(t *testing.T) {
Colin Cross5c4791c2019-02-01 11:44:44 -0800192 testCases := []struct {
193 name string
194 enforceRROTargets []string
195 enforceRROExcludedOverlays []string
Colin Crossbec85302019-02-13 13:15:46 -0800196 resourceFiles map[string][]string
Colin Cross5c4791c2019-02-01 11:44:44 -0800197 overlayFiles map[string][]string
198 rroDirs map[string][]string
199 }{
200 {
201 name: "no RRO",
202 enforceRROTargets: nil,
203 enforceRROExcludedOverlays: nil,
Colin Crossbec85302019-02-13 13:15:46 -0800204 resourceFiles: map[string][]string{
205 "foo": nil,
206 "bar": {"bar/res/res/values/strings.xml"},
207 "lib": nil,
208 "lib2": {"lib2/res/res/values/strings.xml"},
209 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800210 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800211 "foo": {
212 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800213 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000214 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800215 "foo/res/res/values/strings.xml",
Colin Cross5c4791c2019-02-01 11:44:44 -0800216 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
217 "device/vendor/blah/overlay/foo/res/values/strings.xml",
Anton Hansson53c88442019-03-18 15:53:16 +0000218 "product/vendor/blah/overlay/foo/res/values/strings.xml",
Colin Cross5c4791c2019-02-01 11:44:44 -0800219 },
Colin Crossbec85302019-02-13 13:15:46 -0800220 "bar": {
Colin Cross5c4791c2019-02-01 11:44:44 -0800221 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
222 "device/vendor/blah/overlay/bar/res/values/strings.xml",
223 },
Colin Crossbec85302019-02-13 13:15:46 -0800224 "lib": {
225 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
226 "lib/res/res/values/strings.xml",
227 "device/vendor/blah/overlay/lib/res/values/strings.xml",
228 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800229 },
230 rroDirs: map[string][]string{
231 "foo": nil,
232 "bar": nil,
233 },
234 },
235 {
236 name: "enforce RRO on foo",
237 enforceRROTargets: []string{"foo"},
238 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
Colin Crossbec85302019-02-13 13:15:46 -0800239 resourceFiles: map[string][]string{
240 "foo": nil,
241 "bar": {"bar/res/res/values/strings.xml"},
242 "lib": nil,
243 "lib2": {"lib2/res/res/values/strings.xml"},
244 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800245 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800246 "foo": {
247 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800248 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000249 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800250 "foo/res/res/values/strings.xml",
251 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
252 },
Colin Crossbec85302019-02-13 13:15:46 -0800253 "bar": {
Colin Cross5c4791c2019-02-01 11:44:44 -0800254 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
255 "device/vendor/blah/overlay/bar/res/values/strings.xml",
256 },
Colin Crossbec85302019-02-13 13:15:46 -0800257 "lib": {
258 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
259 "lib/res/res/values/strings.xml",
260 "device/vendor/blah/overlay/lib/res/values/strings.xml",
261 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800262 },
Colin Crossc1c37552019-01-31 11:42:41 -0800263
Colin Cross5c4791c2019-02-01 11:44:44 -0800264 rroDirs: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800265 "foo": {
Anton Hansson53c88442019-03-18 15:53:16 +0000266 "device:device/vendor/blah/overlay/foo/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800267 // Enforce RRO on "foo" could imply RRO on static dependencies, but for now it doesn't.
268 // "device/vendor/blah/overlay/lib/res",
Anton Hansson53c88442019-03-18 15:53:16 +0000269 "product:product/vendor/blah/overlay/foo/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800270 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800271 "bar": nil,
Colin Crossbec85302019-02-13 13:15:46 -0800272 "lib": nil,
Colin Cross5c4791c2019-02-01 11:44:44 -0800273 },
274 },
275 {
276 name: "enforce RRO on all",
277 enforceRROTargets: []string{"*"},
278 enforceRROExcludedOverlays: []string{
279 // Excluding specific apps/res directories also allowed.
280 "device/vendor/blah/static_overlay/foo",
281 "device/vendor/blah/static_overlay/bar/res",
282 },
Colin Crossbec85302019-02-13 13:15:46 -0800283 resourceFiles: map[string][]string{
284 "foo": nil,
285 "bar": {"bar/res/res/values/strings.xml"},
286 "lib": nil,
287 "lib2": {"lib2/res/res/values/strings.xml"},
288 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800289 overlayFiles: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800290 "foo": {
291 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800292 buildDir + "/.intermediates/lib/android_common/package-res.apk",
Anton Hansson53c88442019-03-18 15:53:16 +0000293 buildDir + "/.intermediates/lib3/android_common/package-res.apk",
Colin Cross6ed7dea2019-01-31 14:44:30 -0800294 "foo/res/res/values/strings.xml",
295 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
296 },
Colin Crossbec85302019-02-13 13:15:46 -0800297 "bar": {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
298 "lib": {
299 buildDir + "/.intermediates/lib2/android_common/package-res.apk",
300 "lib/res/res/values/strings.xml",
301 },
Colin Cross5c4791c2019-02-01 11:44:44 -0800302 },
303 rroDirs: map[string][]string{
Colin Crossbec85302019-02-13 13:15:46 -0800304 "foo": {
Anton Hansson53c88442019-03-18 15:53:16 +0000305 "device:device/vendor/blah/overlay/foo/res",
306 "product:product/vendor/blah/overlay/foo/res",
307 // Lib dep comes after the direct deps
308 "device:device/vendor/blah/overlay/lib/res",
Colin Crossc1c37552019-01-31 11:42:41 -0800309 },
Anton Hansson53c88442019-03-18 15:53:16 +0000310 "bar": {"device:device/vendor/blah/overlay/bar/res"},
311 "lib": {"device:device/vendor/blah/overlay/lib/res"},
Colin Cross5c4791c2019-02-01 11:44:44 -0800312 },
313 },
314 }
315
Anton Hansson53c88442019-03-18 15:53:16 +0000316 deviceResourceOverlays := []string{
Colin Cross890ff552017-11-30 20:13:19 -0800317 "device/vendor/blah/overlay",
318 "device/vendor/blah/overlay2",
319 "device/vendor/blah/static_overlay",
320 }
321
Anton Hansson53c88442019-03-18 15:53:16 +0000322 productResourceOverlays := []string{
323 "product/vendor/blah/overlay",
324 }
325
Colin Cross890ff552017-11-30 20:13:19 -0800326 fs := map[string][]byte{
327 "foo/res/res/values/strings.xml": nil,
328 "bar/res/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800329 "lib/res/res/values/strings.xml": nil,
Colin Crossbec85302019-02-13 13:15:46 -0800330 "lib2/res/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800331 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
332 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
Colin Cross6ed7dea2019-01-31 14:44:30 -0800333 "device/vendor/blah/overlay/lib/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800334 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
335 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
336 "device/vendor/blah/overlay2/res/values/strings.xml": nil,
Anton Hansson53c88442019-03-18 15:53:16 +0000337 "product/vendor/blah/overlay/foo/res/values/strings.xml": nil,
Colin Cross890ff552017-11-30 20:13:19 -0800338 }
339
340 bp := `
341 android_app {
342 name: "foo",
343 resource_dirs: ["foo/res"],
Anton Hansson53c88442019-03-18 15:53:16 +0000344 static_libs: ["lib", "lib3"],
Colin Cross890ff552017-11-30 20:13:19 -0800345 }
346
347 android_app {
348 name: "bar",
349 resource_dirs: ["bar/res"],
350 }
Colin Cross6ed7dea2019-01-31 14:44:30 -0800351
352 android_library {
353 name: "lib",
354 resource_dirs: ["lib/res"],
Colin Crossbec85302019-02-13 13:15:46 -0800355 static_libs: ["lib2"],
356 }
357
358 android_library {
359 name: "lib2",
360 resource_dirs: ["lib2/res"],
Colin Cross6ed7dea2019-01-31 14:44:30 -0800361 }
Anton Hansson53c88442019-03-18 15:53:16 +0000362
363 // This library has the same resources as lib (should not lead to dupe RROs)
364 android_library {
365 name: "lib3",
366 resource_dirs: ["lib/res"]
367 }
Colin Cross890ff552017-11-30 20:13:19 -0800368 `
369
Colin Cross5c4791c2019-02-01 11:44:44 -0800370 for _, testCase := range testCases {
Colin Cross890ff552017-11-30 20:13:19 -0800371 t.Run(testCase.name, func(t *testing.T) {
372 config := testConfig(nil)
Anton Hansson53c88442019-03-18 15:53:16 +0000373 config.TestProductVariables.DeviceResourceOverlays = deviceResourceOverlays
374 config.TestProductVariables.ProductResourceOverlays = productResourceOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800375 if testCase.enforceRROTargets != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800376 config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets
Colin Cross890ff552017-11-30 20:13:19 -0800377 }
378 if testCase.enforceRROExcludedOverlays != nil {
Colin Crossa74ca042019-01-31 14:31:51 -0800379 config.TestProductVariables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800380 }
381
382 ctx := testAppContext(config, bp, fs)
383 run(t, ctx, config)
384
Colin Crossbec85302019-02-13 13:15:46 -0800385 resourceListToFiles := func(module android.TestingModule, list []string) (files []string) {
386 for _, o := range list {
387 res := module.MaybeOutput(o)
388 if res.Rule != nil {
389 // If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
390 // verify the inputs to the .arsc.flat rule.
391 files = append(files, res.Inputs.Strings()...)
392 } else {
393 // Otherwise, verify the full path to the output of the other module
394 files = append(files, o)
Anton Hansson94c93f32019-01-30 16:03:37 +0000395 }
Colin Cross890ff552017-11-30 20:13:19 -0800396 }
Colin Crossbec85302019-02-13 13:15:46 -0800397 return files
Colin Cross890ff552017-11-30 20:13:19 -0800398 }
399
Colin Crossbec85302019-02-13 13:15:46 -0800400 getResources := func(moduleName string) (resourceFiles, overlayFiles, rroDirs []string) {
401 module := ctx.ModuleForTests(moduleName, "android_common")
402 resourceList := module.MaybeOutput("aapt2/res.list")
403 if resourceList.Rule != nil {
404 resourceFiles = resourceListToFiles(module, resourceList.Inputs.Strings())
Anton Hansson0375a4f2019-01-24 14:39:19 +0000405 }
Colin Crossbec85302019-02-13 13:15:46 -0800406 overlayList := module.MaybeOutput("aapt2/overlay.list")
407 if overlayList.Rule != nil {
408 overlayFiles = resourceListToFiles(module, overlayList.Inputs.Strings())
409 }
410
Anton Hansson53c88442019-03-18 15:53:16 +0000411 for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() {
412 var prefix string
413 if d.overlayType == device {
414 prefix = "device:"
415 } else if d.overlayType == product {
416 prefix = "product:"
417 } else {
418 t.Fatalf("Unexpected overlayType %d", d.overlayType)
419 }
420 rroDirs = append(rroDirs, prefix+d.path.String())
421 }
Colin Crossbec85302019-02-13 13:15:46 -0800422
423 return resourceFiles, overlayFiles, rroDirs
424 }
425
426 modules := []string{"foo", "bar", "lib", "lib2"}
427 for _, module := range modules {
428 resourceFiles, overlayFiles, rroDirs := getResources(module)
429
430 if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[module]) {
431 t.Errorf("expected %s resource files:\n %#v\n got:\n %#v",
432 module, testCase.resourceFiles[module], resourceFiles)
433 }
434 if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[module]) {
435 t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v",
436 module, testCase.overlayFiles[module], overlayFiles)
437 }
438 if !reflect.DeepEqual(rroDirs, testCase.rroDirs[module]) {
Anton Hansson0375a4f2019-01-24 14:39:19 +0000439 t.Errorf("expected %s rroDirs: %#v\n got:\n %#v",
Colin Crossbec85302019-02-13 13:15:46 -0800440 module, testCase.rroDirs[module], rroDirs)
Anton Hansson0375a4f2019-01-24 14:39:19 +0000441 }
Colin Cross890ff552017-11-30 20:13:19 -0800442 }
Colin Cross890ff552017-11-30 20:13:19 -0800443 })
444 }
445}
Colin Crossd09b0b62018-04-18 11:06:47 -0700446
447func TestAppSdkVersion(t *testing.T) {
448 testCases := []struct {
449 name string
450 sdkVersion string
451 platformSdkInt int
452 platformSdkCodename string
453 platformSdkFinal bool
454 expectedMinSdkVersion string
455 }{
456 {
457 name: "current final SDK",
458 sdkVersion: "current",
459 platformSdkInt: 27,
460 platformSdkCodename: "REL",
461 platformSdkFinal: true,
462 expectedMinSdkVersion: "27",
463 },
464 {
465 name: "current non-final SDK",
466 sdkVersion: "current",
467 platformSdkInt: 27,
468 platformSdkCodename: "OMR1",
469 platformSdkFinal: false,
470 expectedMinSdkVersion: "OMR1",
471 },
472 {
473 name: "default final SDK",
474 sdkVersion: "",
475 platformSdkInt: 27,
476 platformSdkCodename: "REL",
477 platformSdkFinal: true,
478 expectedMinSdkVersion: "27",
479 },
480 {
481 name: "default non-final SDK",
482 sdkVersion: "",
483 platformSdkInt: 27,
484 platformSdkCodename: "OMR1",
485 platformSdkFinal: false,
486 expectedMinSdkVersion: "OMR1",
487 },
488 {
489 name: "14",
490 sdkVersion: "14",
491 expectedMinSdkVersion: "14",
492 },
493 }
494
495 for _, moduleType := range []string{"android_app", "android_library"} {
496 for _, test := range testCases {
497 t.Run(moduleType+" "+test.name, func(t *testing.T) {
498 bp := fmt.Sprintf(`%s {
499 name: "foo",
500 srcs: ["a.java"],
501 sdk_version: "%s",
502 }`, moduleType, test.sdkVersion)
503
504 config := testConfig(nil)
505 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
506 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
507 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
508
509 ctx := testAppContext(config, bp, nil)
510
511 run(t, ctx, config)
512
513 foo := ctx.ModuleForTests("foo", "android_common")
514 link := foo.Output("package-res.apk")
515 linkFlags := strings.Split(link.Args["flags"], " ")
516 min := android.IndexList("--min-sdk-version", linkFlags)
517 target := android.IndexList("--target-sdk-version", linkFlags)
518
519 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
520 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
521 }
522
523 gotMinSdkVersion := linkFlags[min+1]
524 gotTargetSdkVersion := linkFlags[target+1]
525
526 if gotMinSdkVersion != test.expectedMinSdkVersion {
527 t.Errorf("incorrect --min-sdk-version, expected %q got %q",
528 test.expectedMinSdkVersion, gotMinSdkVersion)
529 }
530
531 if gotTargetSdkVersion != test.expectedMinSdkVersion {
532 t.Errorf("incorrect --target-sdk-version, expected %q got %q",
533 test.expectedMinSdkVersion, gotTargetSdkVersion)
534 }
535 })
536 }
537 }
538}
Colin Crossa4f08812018-10-02 22:03:40 -0700539
540func TestJNI(t *testing.T) {
541 ctx := testJava(t, `
542 toolchain_library {
543 name: "libcompiler_rt-extras",
544 src: "",
545 }
546
547 toolchain_library {
548 name: "libatomic",
549 src: "",
550 }
551
552 toolchain_library {
553 name: "libgcc",
554 src: "",
555 }
556
557 toolchain_library {
558 name: "libclang_rt.builtins-aarch64-android",
559 src: "",
560 }
561
562 toolchain_library {
563 name: "libclang_rt.builtins-arm-android",
564 src: "",
565 }
566
567 cc_object {
568 name: "crtbegin_so",
569 stl: "none",
570 }
571
572 cc_object {
573 name: "crtend_so",
574 stl: "none",
575 }
576
577 cc_library {
578 name: "libjni",
579 system_shared_libs: [],
580 stl: "none",
581 }
582
583 android_test {
584 name: "test",
585 no_framework_libs: true,
586 jni_libs: ["libjni"],
587 }
588
589 android_test {
590 name: "test_first",
591 no_framework_libs: true,
592 compile_multilib: "first",
593 jni_libs: ["libjni"],
594 }
595
596 android_test {
597 name: "test_both",
598 no_framework_libs: true,
599 compile_multilib: "both",
600 jni_libs: ["libjni"],
601 }
602
603 android_test {
604 name: "test_32",
605 no_framework_libs: true,
606 compile_multilib: "32",
607 jni_libs: ["libjni"],
608 }
609
610 android_test {
611 name: "test_64",
612 no_framework_libs: true,
613 compile_multilib: "64",
614 jni_libs: ["libjni"],
615 }
616 `)
617
618 // check the existence of the internal modules
619 ctx.ModuleForTests("test", "android_common")
620 ctx.ModuleForTests("test_first", "android_common")
621 ctx.ModuleForTests("test_both", "android_common")
622 ctx.ModuleForTests("test_32", "android_common")
623 ctx.ModuleForTests("test_64", "android_common")
624
625 testCases := []struct {
626 name string
627 abis []string
628 }{
629 {"test", []string{"arm64-v8a"}},
630 {"test_first", []string{"arm64-v8a"}},
631 {"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
632 {"test_32", []string{"armeabi-v7a"}},
633 {"test_64", []string{"arm64-v8a"}},
634 }
635
636 for _, test := range testCases {
637 t.Run(test.name, func(t *testing.T) {
638 app := ctx.ModuleForTests(test.name, "android_common")
639 jniLibZip := app.Output("jnilibs.zip")
640 var abis []string
641 args := strings.Fields(jniLibZip.Args["jarArgs"])
642 for i := 0; i < len(args); i++ {
643 if args[i] == "-P" {
644 abis = append(abis, filepath.Base(args[i+1]))
645 i++
646 }
647 }
648 if !reflect.DeepEqual(abis, test.abis) {
649 t.Errorf("want abis %v, got %v", test.abis, abis)
650 }
651 })
652 }
653}
Jaewoong Jung2ad817c2019-01-18 14:27:16 -0800654
655func TestCertificates(t *testing.T) {
656 testCases := []struct {
657 name string
658 bp string
659 certificateOverride string
660 expected string
661 }{
662 {
663 name: "default",
664 bp: `
665 android_app {
666 name: "foo",
667 srcs: ["a.java"],
668 }
669 `,
670 certificateOverride: "",
671 expected: "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
672 },
673 {
674 name: "module certificate property",
675 bp: `
676 android_app {
677 name: "foo",
678 srcs: ["a.java"],
679 certificate: ":new_certificate"
680 }
681
682 android_app_certificate {
683 name: "new_certificate",
684 certificate: "cert/new_cert",
685 }
686 `,
687 certificateOverride: "",
688 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
689 },
690 {
691 name: "path certificate property",
692 bp: `
693 android_app {
694 name: "foo",
695 srcs: ["a.java"],
696 certificate: "expiredkey"
697 }
698 `,
699 certificateOverride: "",
700 expected: "build/target/product/security/expiredkey.x509.pem build/target/product/security/expiredkey.pk8",
701 },
702 {
703 name: "certificate overrides",
704 bp: `
705 android_app {
706 name: "foo",
707 srcs: ["a.java"],
708 certificate: "expiredkey"
709 }
710
711 android_app_certificate {
712 name: "new_certificate",
713 certificate: "cert/new_cert",
714 }
715 `,
716 certificateOverride: "foo:new_certificate",
717 expected: "cert/new_cert.x509.pem cert/new_cert.pk8",
718 },
719 }
720
721 for _, test := range testCases {
722 t.Run(test.name, func(t *testing.T) {
723 config := testConfig(nil)
724 if test.certificateOverride != "" {
725 config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride}
726 }
727 ctx := testAppContext(config, test.bp, nil)
728
729 run(t, ctx, config)
730 foo := ctx.ModuleForTests("foo", "android_common")
731
732 signapk := foo.Output("foo.apk")
733 signFlags := signapk.Args["certificates"]
734 if test.expected != signFlags {
735 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags)
736 }
737 })
738 }
739}
Jaewoong Jung9d22a912019-01-23 16:27:47 -0800740
741func TestPackageNameOverride(t *testing.T) {
742 testCases := []struct {
743 name string
744 bp string
745 packageNameOverride string
746 expected []string
747 }{
748 {
749 name: "default",
750 bp: `
751 android_app {
752 name: "foo",
753 srcs: ["a.java"],
754 }
755 `,
756 packageNameOverride: "",
757 expected: []string{
758 buildDir + "/.intermediates/foo/android_common/foo.apk",
759 buildDir + "/target/product/test_device/system/app/foo/foo.apk",
760 },
761 },
762 {
763 name: "overridden",
764 bp: `
765 android_app {
766 name: "foo",
767 srcs: ["a.java"],
768 }
769 `,
770 packageNameOverride: "foo:bar",
771 expected: []string{
772 // The package apk should be still be the original name for test dependencies.
773 buildDir + "/.intermediates/foo/android_common/foo.apk",
774 buildDir + "/target/product/test_device/system/app/bar/bar.apk",
775 },
776 },
777 }
778
779 for _, test := range testCases {
780 t.Run(test.name, func(t *testing.T) {
781 config := testConfig(nil)
782 if test.packageNameOverride != "" {
783 config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride}
784 }
785 ctx := testAppContext(config, test.bp, nil)
786
787 run(t, ctx, config)
788 foo := ctx.ModuleForTests("foo", "android_common")
789
790 outputs := foo.AllOutputs()
791 outputMap := make(map[string]bool)
792 for _, o := range outputs {
793 outputMap[o] = true
794 }
795 for _, e := range test.expected {
796 if _, exist := outputMap[e]; !exist {
797 t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
798 }
799 }
800 })
801 }
802}
Jaewoong Jung4102e5d2019-02-27 16:26:28 -0800803
804func TestInstrumentationTargetOverridden(t *testing.T) {
805 bp := `
806 android_app {
807 name: "foo",
808 srcs: ["a.java"],
809 }
810
811 android_test {
812 name: "bar",
813 instrumentation_for: "foo",
814 }
815 `
816 config := testConfig(nil)
817 config.TestProductVariables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"}
818 ctx := testAppContext(config, bp, nil)
819
820 run(t, ctx, config)
821
822 bar := ctx.ModuleForTests("bar", "android_common")
823 res := bar.Output("package-res.apk")
824 aapt2Flags := res.Args["flags"]
825 e := "--rename-instrumentation-target-package org.dandroid.bp"
826 if !strings.Contains(aapt2Flags, e) {
827 t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
828 }
829}
Jaewoong Jung525443a2019-02-28 15:35:54 -0800830
831func TestOverrideAndroidApp(t *testing.T) {
832 ctx := testJava(t, `
833 android_app {
834 name: "foo",
835 srcs: ["a.java"],
836 overrides: ["baz"],
837 }
838
839 override_android_app {
840 name: "bar",
841 base: "foo",
842 certificate: ":new_certificate",
843 }
844
845 android_app_certificate {
846 name: "new_certificate",
847 certificate: "cert/new_cert",
848 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700849
850 override_android_app {
851 name: "baz",
852 base: "foo",
853 package_name: "org.dandroid.bp",
854 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800855 `)
856
857 expectedVariants := []struct {
858 variantName string
859 apkName string
860 apkPath string
861 signFlag string
862 overrides []string
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700863 aaptFlag string
Jaewoong Jung525443a2019-02-28 15:35:54 -0800864 }{
865 {
866 variantName: "android_common",
867 apkPath: "/target/product/test_device/system/app/foo/foo.apk",
868 signFlag: "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
869 overrides: []string{"baz"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700870 aaptFlag: "",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800871 },
872 {
873 variantName: "bar_android_common",
874 apkPath: "/target/product/test_device/system/app/bar/bar.apk",
875 signFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
876 overrides: []string{"baz", "foo"},
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700877 aaptFlag: "",
878 },
879 {
880 variantName: "baz_android_common",
881 apkPath: "/target/product/test_device/system/app/baz/baz.apk",
882 signFlag: "build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8",
883 overrides: []string{"baz", "foo"},
884 aaptFlag: "--rename-manifest-package org.dandroid.bp",
Jaewoong Jung525443a2019-02-28 15:35:54 -0800885 },
886 }
887 for _, expected := range expectedVariants {
888 variant := ctx.ModuleForTests("foo", expected.variantName)
889
890 // Check the final apk name
891 outputs := variant.AllOutputs()
892 expectedApkPath := buildDir + expected.apkPath
893 found := false
894 for _, o := range outputs {
895 if o == expectedApkPath {
896 found = true
897 break
898 }
899 }
900 if !found {
901 t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs)
902 }
903
904 // Check the certificate paths
905 signapk := variant.Output("foo.apk")
906 signFlag := signapk.Args["certificates"]
907 if expected.signFlag != signFlag {
908 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.signFlag, signFlag)
909 }
910
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700911 // Check if the overrides field values are correctly aggregated.
Jaewoong Jung525443a2019-02-28 15:35:54 -0800912 mod := variant.Module().(*AndroidApp)
913 if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) {
914 t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
915 expected.overrides, mod.appProperties.Overrides)
916 }
Jaewoong Jung6f373f62019-03-13 10:13:24 -0700917
918 // Check the package renaming flag, if exists.
919 res := variant.Output("package-res.apk")
920 aapt2Flags := res.Args["flags"]
921 if !strings.Contains(aapt2Flags, expected.aaptFlag) {
922 t.Errorf("package renaming flag, %q is missing in aapt2 link flags, %q", expected.aaptFlag, aapt2Flags)
923 }
Jaewoong Jung525443a2019-02-28 15:35:54 -0800924 }
925}