blob: f6476dc68d62b34fdc5f8648da49c48c28a46004 [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
109var testEnforceRROTests = []struct {
110 name string
111 enforceRROTargets []string
112 enforceRROExcludedOverlays []string
113 fooOverlayFiles []string
114 fooRRODirs []string
115 barOverlayFiles []string
116 barRRODirs []string
117}{
118 {
119 name: "no RRO",
120 enforceRROTargets: nil,
121 enforceRROExcludedOverlays: nil,
122 fooOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800123 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800124 "device/vendor/blah/overlay/foo/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800125 },
126 fooRRODirs: nil,
127 barOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800128 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800129 "device/vendor/blah/overlay/bar/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800130 },
131 barRRODirs: nil,
132 },
133 {
134 name: "enforce RRO on foo",
135 enforceRROTargets: []string{"foo"},
136 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
137 fooOverlayFiles: []string{
138 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
139 },
140 fooRRODirs: []string{
141 "device/vendor/blah/overlay/foo/res",
142 },
143 barOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800144 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800145 "device/vendor/blah/overlay/bar/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800146 },
147 barRRODirs: nil,
148 },
149 {
150 name: "enforce RRO on all",
151 enforceRROTargets: []string{"*"},
152 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
153 fooOverlayFiles: []string{
154 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
155 },
156 fooRRODirs: []string{
157 "device/vendor/blah/overlay/foo/res",
158 },
159 barOverlayFiles: []string{
160 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
161 },
162 barRRODirs: []string{
163 "device/vendor/blah/overlay/bar/res",
164 },
165 },
166}
167
168func TestEnforceRRO(t *testing.T) {
169 resourceOverlays := []string{
170 "device/vendor/blah/overlay",
171 "device/vendor/blah/overlay2",
172 "device/vendor/blah/static_overlay",
173 }
174
175 fs := map[string][]byte{
176 "foo/res/res/values/strings.xml": nil,
177 "bar/res/res/values/strings.xml": nil,
178 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
179 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
180 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
181 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
182 "device/vendor/blah/overlay2/res/values/strings.xml": nil,
183 }
184
185 bp := `
186 android_app {
187 name: "foo",
188 resource_dirs: ["foo/res"],
189 }
190
191 android_app {
192 name: "bar",
193 resource_dirs: ["bar/res"],
194 }
195 `
196
197 for _, testCase := range testEnforceRROTests {
198 t.Run(testCase.name, func(t *testing.T) {
199 config := testConfig(nil)
Dan Willemsen674dc7f2018-03-12 18:06:05 -0700200 config.TestProductVariables.ResourceOverlays = &resourceOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800201 if testCase.enforceRROTargets != nil {
Dan Willemsen674dc7f2018-03-12 18:06:05 -0700202 config.TestProductVariables.EnforceRROTargets = &testCase.enforceRROTargets
Colin Cross890ff552017-11-30 20:13:19 -0800203 }
204 if testCase.enforceRROExcludedOverlays != nil {
Dan Willemsen674dc7f2018-03-12 18:06:05 -0700205 config.TestProductVariables.EnforceRROExcludedOverlays = &testCase.enforceRROExcludedOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800206 }
207
208 ctx := testAppContext(config, bp, fs)
209 run(t, ctx, config)
210
211 getOverlays := func(moduleName string) ([]string, []string) {
212 module := ctx.ModuleForTests(moduleName, "android_common")
213 overlayCompiledPaths := module.Output("aapt2/overlay.list").Inputs.Strings()
214
215 var overlayFiles []string
216 for _, o := range overlayCompiledPaths {
217 overlayFiles = append(overlayFiles, module.Output(o).Inputs.Strings()...)
218 }
219
220 rroDirs := module.Module().(*AndroidApp).rroDirs.Strings()
221
222 return overlayFiles, rroDirs
223 }
224
225 fooOverlayFiles, fooRRODirs := getOverlays("foo")
226 barOverlayFiles, barRRODirs := getOverlays("bar")
227
228 if !reflect.DeepEqual(fooOverlayFiles, testCase.fooOverlayFiles) {
229 t.Errorf("expected foo overlay files:\n %#v\n got:\n %#v",
230 testCase.fooOverlayFiles, fooOverlayFiles)
231 }
232 if !reflect.DeepEqual(fooRRODirs, testCase.fooRRODirs) {
233 t.Errorf("expected foo rroDirs: %#v\n got:\n %#v",
234 testCase.fooRRODirs, fooRRODirs)
235 }
236
237 if !reflect.DeepEqual(barOverlayFiles, testCase.barOverlayFiles) {
238 t.Errorf("expected bar overlay files:\n %#v\n got:\n %#v",
239 testCase.barOverlayFiles, barOverlayFiles)
240 }
241 if !reflect.DeepEqual(barRRODirs, testCase.barRRODirs) {
242 t.Errorf("expected bar rroDirs: %#v\n got:\n %#v",
243 testCase.barRRODirs, barRRODirs)
244 }
245
246 })
247 }
248}
Colin Crossd09b0b62018-04-18 11:06:47 -0700249
250func TestAppSdkVersion(t *testing.T) {
251 testCases := []struct {
252 name string
253 sdkVersion string
254 platformSdkInt int
255 platformSdkCodename string
256 platformSdkFinal bool
257 expectedMinSdkVersion string
258 }{
259 {
260 name: "current final SDK",
261 sdkVersion: "current",
262 platformSdkInt: 27,
263 platformSdkCodename: "REL",
264 platformSdkFinal: true,
265 expectedMinSdkVersion: "27",
266 },
267 {
268 name: "current non-final SDK",
269 sdkVersion: "current",
270 platformSdkInt: 27,
271 platformSdkCodename: "OMR1",
272 platformSdkFinal: false,
273 expectedMinSdkVersion: "OMR1",
274 },
275 {
276 name: "default final SDK",
277 sdkVersion: "",
278 platformSdkInt: 27,
279 platformSdkCodename: "REL",
280 platformSdkFinal: true,
281 expectedMinSdkVersion: "27",
282 },
283 {
284 name: "default non-final SDK",
285 sdkVersion: "",
286 platformSdkInt: 27,
287 platformSdkCodename: "OMR1",
288 platformSdkFinal: false,
289 expectedMinSdkVersion: "OMR1",
290 },
291 {
292 name: "14",
293 sdkVersion: "14",
294 expectedMinSdkVersion: "14",
295 },
296 }
297
298 for _, moduleType := range []string{"android_app", "android_library"} {
299 for _, test := range testCases {
300 t.Run(moduleType+" "+test.name, func(t *testing.T) {
301 bp := fmt.Sprintf(`%s {
302 name: "foo",
303 srcs: ["a.java"],
304 sdk_version: "%s",
305 }`, moduleType, test.sdkVersion)
306
307 config := testConfig(nil)
308 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
309 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
310 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
311
312 ctx := testAppContext(config, bp, nil)
313
314 run(t, ctx, config)
315
316 foo := ctx.ModuleForTests("foo", "android_common")
317 link := foo.Output("package-res.apk")
318 linkFlags := strings.Split(link.Args["flags"], " ")
319 min := android.IndexList("--min-sdk-version", linkFlags)
320 target := android.IndexList("--target-sdk-version", linkFlags)
321
322 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
323 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
324 }
325
326 gotMinSdkVersion := linkFlags[min+1]
327 gotTargetSdkVersion := linkFlags[target+1]
328
329 if gotMinSdkVersion != test.expectedMinSdkVersion {
330 t.Errorf("incorrect --min-sdk-version, expected %q got %q",
331 test.expectedMinSdkVersion, gotMinSdkVersion)
332 }
333
334 if gotTargetSdkVersion != test.expectedMinSdkVersion {
335 t.Errorf("incorrect --target-sdk-version, expected %q got %q",
336 test.expectedMinSdkVersion, gotTargetSdkVersion)
337 }
338 })
339 }
340 }
341}
Colin Crossa4f08812018-10-02 22:03:40 -0700342
343func TestJNI(t *testing.T) {
344 ctx := testJava(t, `
345 toolchain_library {
346 name: "libcompiler_rt-extras",
347 src: "",
348 }
349
350 toolchain_library {
351 name: "libatomic",
352 src: "",
353 }
354
355 toolchain_library {
356 name: "libgcc",
357 src: "",
358 }
359
360 toolchain_library {
361 name: "libclang_rt.builtins-aarch64-android",
362 src: "",
363 }
364
365 toolchain_library {
366 name: "libclang_rt.builtins-arm-android",
367 src: "",
368 }
369
370 cc_object {
371 name: "crtbegin_so",
372 stl: "none",
373 }
374
375 cc_object {
376 name: "crtend_so",
377 stl: "none",
378 }
379
380 cc_library {
381 name: "libjni",
382 system_shared_libs: [],
383 stl: "none",
384 }
385
386 android_test {
387 name: "test",
388 no_framework_libs: true,
389 jni_libs: ["libjni"],
390 }
391
392 android_test {
393 name: "test_first",
394 no_framework_libs: true,
395 compile_multilib: "first",
396 jni_libs: ["libjni"],
397 }
398
399 android_test {
400 name: "test_both",
401 no_framework_libs: true,
402 compile_multilib: "both",
403 jni_libs: ["libjni"],
404 }
405
406 android_test {
407 name: "test_32",
408 no_framework_libs: true,
409 compile_multilib: "32",
410 jni_libs: ["libjni"],
411 }
412
413 android_test {
414 name: "test_64",
415 no_framework_libs: true,
416 compile_multilib: "64",
417 jni_libs: ["libjni"],
418 }
419 `)
420
421 // check the existence of the internal modules
422 ctx.ModuleForTests("test", "android_common")
423 ctx.ModuleForTests("test_first", "android_common")
424 ctx.ModuleForTests("test_both", "android_common")
425 ctx.ModuleForTests("test_32", "android_common")
426 ctx.ModuleForTests("test_64", "android_common")
427
428 testCases := []struct {
429 name string
430 abis []string
431 }{
432 {"test", []string{"arm64-v8a"}},
433 {"test_first", []string{"arm64-v8a"}},
434 {"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
435 {"test_32", []string{"armeabi-v7a"}},
436 {"test_64", []string{"arm64-v8a"}},
437 }
438
439 for _, test := range testCases {
440 t.Run(test.name, func(t *testing.T) {
441 app := ctx.ModuleForTests(test.name, "android_common")
442 jniLibZip := app.Output("jnilibs.zip")
443 var abis []string
444 args := strings.Fields(jniLibZip.Args["jarArgs"])
445 for i := 0; i < len(args); i++ {
446 if args[i] == "-P" {
447 abis = append(abis, filepath.Base(args[i+1]))
448 i++
449 }
450 }
451 if !reflect.DeepEqual(abis, test.abis) {
452 t.Errorf("want abis %v, got %v", test.abis, abis)
453 }
454 })
455 }
456}