blob: 2e531303dc4b96387f55d0193de0c091f3e6c08e [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 Crosse20c1b12018-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 Crosse20c1b12018-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) {
64 ctx := testApp(t, `
65 android_app {
66 name: "foo",
67 srcs: ["a.java"],
68 }
69 `)
70
71 foo := ctx.ModuleForTests("foo", "android_common")
72
73 expectedLinkImplicits := []string{"AndroidManifest.xml"}
74
75 frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
76 expectedLinkImplicits = append(expectedLinkImplicits,
77 frameworkRes.Output("package-res.apk").Output.String())
78
79 // Test the mapping from input files to compiled output file names
80 compile := foo.Output(compiledResourceFiles[0])
81 if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
82 t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
83 resourceFiles, compile.Inputs.Strings())
84 }
Colin Crossb69301e2017-12-01 10:48:26 -080085
86 compiledResourceOutputs := compile.Outputs.Strings()
87 sort.Strings(compiledResourceOutputs)
88
89 expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080090
91 list := foo.Output("aapt2/res.list")
92 expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
93
94 // Check that the link rule uses
95 res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
96 if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
97 t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
98 expectedLinkImplicits, res.Implicits.Strings())
99 }
100}
Colin Cross890ff552017-11-30 20:13:19 -0800101
102var testEnforceRROTests = []struct {
103 name string
104 enforceRROTargets []string
105 enforceRROExcludedOverlays []string
106 fooOverlayFiles []string
107 fooRRODirs []string
108 barOverlayFiles []string
109 barRRODirs []string
110}{
111 {
112 name: "no RRO",
113 enforceRROTargets: nil,
114 enforceRROExcludedOverlays: nil,
115 fooOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800116 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800117 "device/vendor/blah/overlay/foo/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800118 },
119 fooRRODirs: nil,
120 barOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800121 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800122 "device/vendor/blah/overlay/bar/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800123 },
124 barRRODirs: nil,
125 },
126 {
127 name: "enforce RRO on foo",
128 enforceRROTargets: []string{"foo"},
129 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
130 fooOverlayFiles: []string{
131 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
132 },
133 fooRRODirs: []string{
134 "device/vendor/blah/overlay/foo/res",
135 },
136 barOverlayFiles: []string{
Colin Cross890ff552017-11-30 20:13:19 -0800137 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
Colin Cross68a70232018-01-04 14:50:13 -0800138 "device/vendor/blah/overlay/bar/res/values/strings.xml",
Colin Cross890ff552017-11-30 20:13:19 -0800139 },
140 barRRODirs: nil,
141 },
142 {
143 name: "enforce RRO on all",
144 enforceRROTargets: []string{"*"},
145 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
146 fooOverlayFiles: []string{
147 "device/vendor/blah/static_overlay/foo/res/values/strings.xml",
148 },
149 fooRRODirs: []string{
150 "device/vendor/blah/overlay/foo/res",
151 },
152 barOverlayFiles: []string{
153 "device/vendor/blah/static_overlay/bar/res/values/strings.xml",
154 },
155 barRRODirs: []string{
156 "device/vendor/blah/overlay/bar/res",
157 },
158 },
159}
160
161func TestEnforceRRO(t *testing.T) {
162 resourceOverlays := []string{
163 "device/vendor/blah/overlay",
164 "device/vendor/blah/overlay2",
165 "device/vendor/blah/static_overlay",
166 }
167
168 fs := map[string][]byte{
169 "foo/res/res/values/strings.xml": nil,
170 "bar/res/res/values/strings.xml": nil,
171 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil,
172 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil,
173 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
174 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
175 "device/vendor/blah/overlay2/res/values/strings.xml": nil,
176 }
177
178 bp := `
179 android_app {
180 name: "foo",
181 resource_dirs: ["foo/res"],
182 }
183
184 android_app {
185 name: "bar",
186 resource_dirs: ["bar/res"],
187 }
188 `
189
190 for _, testCase := range testEnforceRROTests {
191 t.Run(testCase.name, func(t *testing.T) {
192 config := testConfig(nil)
Dan Willemsencb3bff12018-03-12 18:06:05 -0700193 config.TestProductVariables.ResourceOverlays = &resourceOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800194 if testCase.enforceRROTargets != nil {
Dan Willemsencb3bff12018-03-12 18:06:05 -0700195 config.TestProductVariables.EnforceRROTargets = &testCase.enforceRROTargets
Colin Cross890ff552017-11-30 20:13:19 -0800196 }
197 if testCase.enforceRROExcludedOverlays != nil {
Dan Willemsencb3bff12018-03-12 18:06:05 -0700198 config.TestProductVariables.EnforceRROExcludedOverlays = &testCase.enforceRROExcludedOverlays
Colin Cross890ff552017-11-30 20:13:19 -0800199 }
200
201 ctx := testAppContext(config, bp, fs)
202 run(t, ctx, config)
203
204 getOverlays := func(moduleName string) ([]string, []string) {
205 module := ctx.ModuleForTests(moduleName, "android_common")
206 overlayCompiledPaths := module.Output("aapt2/overlay.list").Inputs.Strings()
207
208 var overlayFiles []string
209 for _, o := range overlayCompiledPaths {
210 overlayFiles = append(overlayFiles, module.Output(o).Inputs.Strings()...)
211 }
212
213 rroDirs := module.Module().(*AndroidApp).rroDirs.Strings()
214
215 return overlayFiles, rroDirs
216 }
217
218 fooOverlayFiles, fooRRODirs := getOverlays("foo")
219 barOverlayFiles, barRRODirs := getOverlays("bar")
220
221 if !reflect.DeepEqual(fooOverlayFiles, testCase.fooOverlayFiles) {
222 t.Errorf("expected foo overlay files:\n %#v\n got:\n %#v",
223 testCase.fooOverlayFiles, fooOverlayFiles)
224 }
225 if !reflect.DeepEqual(fooRRODirs, testCase.fooRRODirs) {
226 t.Errorf("expected foo rroDirs: %#v\n got:\n %#v",
227 testCase.fooRRODirs, fooRRODirs)
228 }
229
230 if !reflect.DeepEqual(barOverlayFiles, testCase.barOverlayFiles) {
231 t.Errorf("expected bar overlay files:\n %#v\n got:\n %#v",
232 testCase.barOverlayFiles, barOverlayFiles)
233 }
234 if !reflect.DeepEqual(barRRODirs, testCase.barRRODirs) {
235 t.Errorf("expected bar rroDirs: %#v\n got:\n %#v",
236 testCase.barRRODirs, barRRODirs)
237 }
238
239 })
240 }
241}
Colin Crosse20c1b12018-04-18 11:06:47 -0700242
243func TestAppSdkVersion(t *testing.T) {
244 testCases := []struct {
245 name string
246 sdkVersion string
247 platformSdkInt int
248 platformSdkCodename string
249 platformSdkFinal bool
250 expectedMinSdkVersion string
251 }{
252 {
253 name: "current final SDK",
254 sdkVersion: "current",
255 platformSdkInt: 27,
256 platformSdkCodename: "REL",
257 platformSdkFinal: true,
258 expectedMinSdkVersion: "27",
259 },
260 {
261 name: "current non-final SDK",
262 sdkVersion: "current",
263 platformSdkInt: 27,
264 platformSdkCodename: "OMR1",
265 platformSdkFinal: false,
266 expectedMinSdkVersion: "OMR1",
267 },
268 {
269 name: "default final SDK",
270 sdkVersion: "",
271 platformSdkInt: 27,
272 platformSdkCodename: "REL",
273 platformSdkFinal: true,
274 expectedMinSdkVersion: "27",
275 },
276 {
277 name: "default non-final SDK",
278 sdkVersion: "",
279 platformSdkInt: 27,
280 platformSdkCodename: "OMR1",
281 platformSdkFinal: false,
282 expectedMinSdkVersion: "OMR1",
283 },
284 {
285 name: "14",
286 sdkVersion: "14",
287 expectedMinSdkVersion: "14",
288 },
289 }
290
291 for _, test := range testCases {
292 t.Run(test.name, func(t *testing.T) {
293 bp := fmt.Sprintf(`android_app {
294 name: "foo",
295 srcs: ["a.java"],
296 sdk_version: "%s",
297 }`, test.sdkVersion)
298
299 config := testConfig(nil)
300 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt
301 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename
302 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal
303
304 ctx := testAppContext(config, bp, nil)
305
306 run(t, ctx, config)
307
308 foo := ctx.ModuleForTests("foo", "android_common")
309 link := foo.Output("package-res.apk")
310 linkFlags := strings.Split(link.Args["flags"], " ")
311 min := android.IndexList("--min-sdk-version", linkFlags)
312 target := android.IndexList("--target-sdk-version", linkFlags)
313
314 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
315 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
316 }
317
318 gotMinSdkVersion := linkFlags[min+1]
319 gotTargetSdkVersion := linkFlags[target+1]
320
321 if gotMinSdkVersion != test.expectedMinSdkVersion {
322 t.Errorf("incorrect --min-sdk-version, expected %q got %q",
323 test.expectedMinSdkVersion, gotMinSdkVersion)
324 }
325
326 if gotTargetSdkVersion != test.expectedMinSdkVersion {
327 t.Errorf("incorrect --target-sdk-version, expected %q got %q",
328 test.expectedMinSdkVersion, gotTargetSdkVersion)
329 }
330 })
331 }
332}