blob: 6770119ef6a3f7429b1b42a915d78e48ad93e465 [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 Cross3bc7ffa2017-11-22 16:19:37 -080020 "reflect"
Colin Crossb69301e2017-12-01 10:48:26 -080021 "sort"
Colin Crossd09b0b62018-04-18 11:06:47 -070022 "strings"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080023 "testing"
24)
25
26var (
27 resourceFiles = []string{
28 "res/layout/layout.xml",
29 "res/values/strings.xml",
30 "res/values-en-rUS/strings.xml",
31 }
32
33 compiledResourceFiles = []string{
34 "aapt2/res/layout_layout.xml.flat",
35 "aapt2/res/values_strings.arsc.flat",
36 "aapt2/res/values-en-rUS_strings.arsc.flat",
37 }
38)
39
Colin Cross527012a2017-11-30 22:56:16 -080040func testAppContext(config android.Config, bp string, fs map[string][]byte) *android.TestContext {
41 appFS := map[string][]byte{}
42 for k, v := range fs {
43 appFS[k] = v
Colin Cross3bc7ffa2017-11-22 16:19:37 -080044 }
45
Colin Cross527012a2017-11-30 22:56:16 -080046 for _, file := range resourceFiles {
47 appFS[file] = nil
48 }
49
50 return testContext(config, bp, appFS)
51}
52
53func testApp(t *testing.T, bp string) *android.TestContext {
54 config := testConfig(nil)
55
56 ctx := testAppContext(config, bp, nil)
57
58 run(t, ctx, config)
59
60 return ctx
Colin Cross3bc7ffa2017-11-22 16:19:37 -080061}
62
63func TestApp(t *testing.T) {
Colin Crossa97c5d32018-03-28 14:58:31 -070064 for _, moduleType := range []string{"android_app", "android_library"} {
65 t.Run(moduleType, func(t *testing.T) {
66 ctx := testApp(t, moduleType+` {
67 name: "foo",
68 srcs: ["a.java"],
69 }
70 `)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080071
Colin Crossa97c5d32018-03-28 14:58:31 -070072 foo := ctx.ModuleForTests("foo", "android_common")
Colin Cross3bc7ffa2017-11-22 16:19:37 -080073
Colin Crossa97c5d32018-03-28 14:58:31 -070074 expectedLinkImplicits := []string{"AndroidManifest.xml"}
Colin Cross3bc7ffa2017-11-22 16:19:37 -080075
Colin Crossa97c5d32018-03-28 14:58:31 -070076 frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
77 expectedLinkImplicits = append(expectedLinkImplicits,
78 frameworkRes.Output("package-res.apk").Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080079
Colin Crossa97c5d32018-03-28 14:58:31 -070080 // Test the mapping from input files to compiled output file names
81 compile := foo.Output(compiledResourceFiles[0])
82 if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
83 t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
84 resourceFiles, compile.Inputs.Strings())
85 }
Colin Crossb69301e2017-12-01 10:48:26 -080086
Colin Crossa97c5d32018-03-28 14:58:31 -070087 compiledResourceOutputs := compile.Outputs.Strings()
88 sort.Strings(compiledResourceOutputs)
Colin Crossb69301e2017-12-01 10:48:26 -080089
Colin Crossa97c5d32018-03-28 14:58:31 -070090 expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080091
Colin Crossa97c5d32018-03-28 14:58:31 -070092 list := foo.Output("aapt2/res.list")
93 expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
Colin Cross3bc7ffa2017-11-22 16:19:37 -080094
Colin Crossa97c5d32018-03-28 14:58:31 -070095 // Check that the link rule uses
96 res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
97 if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
98 t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
99 expectedLinkImplicits, res.Implicits.Strings())
100 }
101 })
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800102 }
103}
Colin Cross890ff552017-11-30 20:13:19 -0800104
105var testEnforceRROTests = []struct {
106 name string
107 enforceRROTargets []string
108 enforceRROExcludedOverlays []string
109 fooOverlayFiles []string
110 fooRRODirs []string
111 barOverlayFiles []string
112 barRRODirs []string
113}{
114 {
115 name: "no RRO",
116 enforceRROTargets: nil,
117 enforceRROExcludedOverlays: nil,
118 fooOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800119 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800120 "device/vendor/blah/overlay/foo/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800121 },
122 fooRRODirs: nil,
123 barOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800124 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800125 "device/vendor/blah/overlay/bar/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800126 },
127 barRRODirs: nil,
128 },
129 {
130 name: "enforce RRO on foo",
131 enforceRROTargets: []string{"foo"},
132 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
133 fooOverlayFiles: []string{
134 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
135 },
136 fooRRODirs: []string{
137 "device/vendor/blah/overlay/foo/res",
138 },
139 barOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800140 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800141 "device/vendor/blah/overlay/bar/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800142 },
143 barRRODirs: nil,
144 },
145 {
146 name: "enforce RRO on all",
147 enforceRROTargets: []string{"*"},
148 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
149 fooOverlayFiles: []string{
150 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
151 },
152 fooRRODirs: []string{
153 "device/vendor/blah/overlay/foo/res",
154 },
155 barOverlayFiles: []string{
156 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
157 },
158 barRRODirs: []string{
159 "device/vendor/blah/overlay/bar/res",
160 },
161 },
162}
163
164func TestEnforceRRO(t *testing.T) {
165 resourceOverlays := []string{
166 "device/vendor/blah/overlay",
167 "device/vendor/blah/overlay2",
168 "device/vendor/blah/static_overlay",
169 }
170
171 fs := map[string][]byte{
172 "foo/res/res/values/strings.xml": nil,
173 "bar/res/res/values/strings.xml": nil,
174 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
175 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
176 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
177 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
178 "device/vendor/blah/overlay2/res/values/strings.xml": nil,
179 }
180
181 bp := `
182 android_app {
183 name: "foo",
184 resource_dirs: ["foo/res"],
185 }
186
187 android_app {
188 name: "bar",
189 resource_dirs: ["bar/res"],
190 }
191 `
192
193 for _, testCase := range testEnforceRROTests {
194 t.Run(testCase.name, func(t *testing.T) {
195 config := testConfig(nil)
Dan Willemsen674dc7f2018-03-12 18:06:05 -0700196 config.TestProductVariables.ResourceOverlays = &resourceOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800197 if testCase.enforceRROTargets != nil {
Dan Willemsen674dc7f2018-03-12 18:06:05 -0700198 config.TestProductVariables.EnforceRROTargets = &testCase.enforceRROTargets
Colin Cross890ff552017-11-30 20:13:19 -0800199 }
200 if testCase.enforceRROExcludedOverlays != nil {
Dan Willemsen674dc7f2018-03-12 18:06:05 -0700201 config.TestProductVariables.EnforceRROExcludedOverlays = &testCase.enforceRROExcludedOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800202 }
203
204 ctx := testAppContext(config, bp, fs)
205 run(t, ctx, config)
206
207 getOverlays := func(moduleName string) ([]string, []string) {
208 module := ctx.ModuleForTests(moduleName, "android_common")
209 overlayCompiledPaths := module.Output("aapt2/overlay.list").Inputs.Strings()
210
211 var overlayFiles []string
212 for _, o := range overlayCompiledPaths {
213 overlayFiles = append(overlayFiles, module.Output(o).Inputs.Strings()...)
214 }
215
216 rroDirs := module.Module().(*AndroidApp).rroDirs.Strings()
217
218 return overlayFiles, rroDirs
219 }
220
221 fooOverlayFiles, fooRRODirs := getOverlays("foo")
222 barOverlayFiles, barRRODirs := getOverlays("bar")
223
224 if !reflect.DeepEqual(fooOverlayFiles, testCase.fooOverlayFiles) {
225 t.Errorf("expected foo overlay files:\n %#v\n got:\n %#v",
226 testCase.fooOverlayFiles, fooOverlayFiles)
227 }
228 if !reflect.DeepEqual(fooRRODirs, testCase.fooRRODirs) {
229 t.Errorf("expected foo rroDirs: %#v\n got:\n %#v",
230 testCase.fooRRODirs, fooRRODirs)
231 }
232
233 if !reflect.DeepEqual(barOverlayFiles, testCase.barOverlayFiles) {
234 t.Errorf("expected bar overlay files:\n %#v\n got:\n %#v",
235 testCase.barOverlayFiles, barOverlayFiles)
236 }
237 if !reflect.DeepEqual(barRRODirs, testCase.barRRODirs) {
238 t.Errorf("expected bar rroDirs: %#v\n got:\n %#v",
239 testCase.barRRODirs, barRRODirs)
240 }
241
242 })
243 }
244}
Colin Crossd09b0b62018-04-18 11:06:47 -0700245
246func TestAppSdkVersion(t *testing.T) {
247 testCases := []struct {
248 name string
249 sdkVersion string
250 platformSdkInt int
251 platformSdkCodename string
252 platformSdkFinal bool
253 expectedMinSdkVersion string
254 }{
255 {
256 name: "current final SDK",
257 sdkVersion: "current",
258 platformSdkInt: 27,
259 platformSdkCodename: "REL",
260 platformSdkFinal: true,
261 expectedMinSdkVersion: "27",
262 },
263 {
264 name: "current non-final SDK",
265 sdkVersion: "current",
266 platformSdkInt: 27,
267 platformSdkCodename: "OMR1",
268 platformSdkFinal: false,
269 expectedMinSdkVersion: "OMR1",
270 },
271 {
272 name: "default final SDK",
273 sdkVersion: "",
274 platformSdkInt: 27,
275 platformSdkCodename: "REL",
276 platformSdkFinal: true,
277 expectedMinSdkVersion: "27",
278 },
279 {
280 name: "default non-final SDK",
281 sdkVersion: "",
282 platformSdkInt: 27,
283 platformSdkCodename: "OMR1",
284 platformSdkFinal: false,
285 expectedMinSdkVersion: "OMR1",
286 },
287 {
288 name: "14",
289 sdkVersion: "14",
290 expectedMinSdkVersion: "14",
291 },
292 }
293
294 for _, moduleType := range []string{"android_app", "android_library"} {
295 for _, test := range testCases {
296 t.Run(moduleType+" "+test.name, func(t *testing.T) {
297 bp := fmt.Sprintf(`%s {
298 name: "foo",
299 srcs: ["a.java"],
300 sdk_version: "%s",
301 }`, moduleType, test.sdkVersion)
302
303 config := testConfig(nil)
304 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
305 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
306 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
307
308 ctx := testAppContext(config, bp, nil)
309
310 run(t, ctx, config)
311
312 foo := ctx.ModuleForTests("foo", "android_common")
313 link := foo.Output("package-res.apk")
314 linkFlags := strings.Split(link.Args["flags"], " ")
315 min := android.IndexList("--min-sdk-version", linkFlags)
316 target := android.IndexList("--target-sdk-version", linkFlags)
317
318 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
319 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
320 }
321
322 gotMinSdkVersion := linkFlags[min+1]
323 gotTargetSdkVersion := linkFlags[target+1]
324
325 if gotMinSdkVersion != test.expectedMinSdkVersion {
326 t.Errorf("incorrect --min-sdk-version, expected %q got %q",
327 test.expectedMinSdkVersion, gotMinSdkVersion)
328 }
329
330 if gotTargetSdkVersion != test.expectedMinSdkVersion {
331 t.Errorf("incorrect --target-sdk-version, expected %q got %q",
332 test.expectedMinSdkVersion, gotTargetSdkVersion)
333 }
334 })
335 }
336 }
337}