blob: bdd4becceea8190d986664f5ba8b8bc4551a569c [file] [log] [blame]
Sasha Smundak7a894a62020-05-06 21:23:08 -07001// Copyright 2020 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 main
16
17import (
18 "fmt"
19 "github.com/golang/protobuf/proto"
20 "reflect"
21 "testing"
22
23 bp "android/soong/cmd/extract_apks/bundle_proto"
24 "android/soong/third_party/zip"
25)
26
Sasha Smundak827c55f2020-05-20 13:10:59 -070027type testConfigDesc struct {
Sasha Smundak7a894a62020-05-06 21:23:08 -070028 name string
29 targetConfig TargetConfig
30 expected SelectionResult
31}
32
Sasha Smundak827c55f2020-05-20 13:10:59 -070033type testDesc struct {
Sasha Smundak7a894a62020-05-06 21:23:08 -070034 protoText string
Sasha Smundak827c55f2020-05-20 13:10:59 -070035 configs []testConfigDesc
Sasha Smundak7a894a62020-05-06 21:23:08 -070036}
37
Jaewoong Jungfa00c062020-05-14 14:15:24 -070038func TestSelectApks_ApkSet(t *testing.T) {
Sasha Smundak827c55f2020-05-20 13:10:59 -070039 testCases := []testDesc{
Sasha Smundak7a894a62020-05-06 21:23:08 -070040 {
41 protoText: `
42variant {
43 targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070044 sdk_version_targeting {
Sasha Smundak7a894a62020-05-06 21:23:08 -070045 value { min { value: 29 } } } }
46 apk_set {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070047 module_metadata {
Sasha Smundak7a894a62020-05-06 21:23:08 -070048 name: "base" targeting {} delivery_type: INSTALL_TIME }
49 apk_description {
50 targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070051 screen_density_targeting {
Sasha Smundak7a894a62020-05-06 21:23:08 -070052 value { density_alias: LDPI } }
53 sdk_version_targeting {
54 value { min { value: 21 } } } }
55 path: "splits/base-ldpi.apk"
56 split_apk_metadata { split_id: "config.ldpi" } }
57 apk_description {
58 targeting {
59 screen_density_targeting {
60 value { density_alias: MDPI } }
61 sdk_version_targeting {
62 value { min { value: 21 } } } }
63 path: "splits/base-mdpi.apk"
64 split_apk_metadata { split_id: "config.mdpi" } }
65 apk_description {
66 targeting {
67 sdk_version_targeting {
68 value { min { value: 21 } } } }
69 path: "splits/base-master.apk"
70 split_apk_metadata { is_master_split: true } }
71 apk_description {
72 targeting {
73 abi_targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070074 value { alias: ARMEABI_V7A }
75 alternatives { alias: ARM64_V8A }
76 alternatives { alias: X86 }
77 alternatives { alias: X86_64 } }
Sasha Smundak7a894a62020-05-06 21:23:08 -070078 sdk_version_targeting {
79 value { min { value: 21 } } } }
80 path: "splits/base-armeabi_v7a.apk"
81 split_apk_metadata { split_id: "config.armeabi_v7a" } }
82 apk_description {
83 targeting {
84 abi_targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070085 value { alias: ARM64_V8A }
86 alternatives { alias: ARMEABI_V7A }
87 alternatives { alias: X86 }
88 alternatives { alias: X86_64 } }
Sasha Smundak7a894a62020-05-06 21:23:08 -070089 sdk_version_targeting {
90 value { min { value: 21 } } } }
91 path: "splits/base-arm64_v8a.apk"
92 split_apk_metadata { split_id: "config.arm64_v8a" } }
93 apk_description {
94 targeting {
95 abi_targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070096 value { alias: X86 }
97 alternatives { alias: ARMEABI_V7A }
98 alternatives { alias: ARM64_V8A }
99 alternatives { alias: X86_64 } }
Sasha Smundak7a894a62020-05-06 21:23:08 -0700100 sdk_version_targeting {
101 value { min { value: 21 } } } }
102 path: "splits/base-x86.apk"
103 split_apk_metadata { split_id: "config.x86" } }
104 apk_description {
105 targeting {
106 abi_targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700107 value { alias: X86_64 }
108 alternatives { alias: ARMEABI_V7A }
109 alternatives { alias: ARM64_V8A }
110 alternatives { alias: X86 } }
Sasha Smundak7a894a62020-05-06 21:23:08 -0700111 sdk_version_targeting {
112 value { min { value: 21 } } } }
113 path: "splits/base-x86_64.apk"
114 split_apk_metadata { split_id: "config.x86_64" } } }
115}
116bundletool {
117 version: "0.10.3" }
118
119`,
Sasha Smundak827c55f2020-05-20 13:10:59 -0700120 configs: []testConfigDesc{
Sasha Smundak7a894a62020-05-06 21:23:08 -0700121 {
122 name: "one",
123 targetConfig: TargetConfig{
124 sdkVersion: 29,
125 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
126 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
127 },
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700128 abis: map[bp.Abi_AbiAlias]int{
129 bp.Abi_ARMEABI_V7A: 0,
130 bp.Abi_ARM64_V8A: 1,
Sasha Smundak7a894a62020-05-06 21:23:08 -0700131 },
132 },
133 expected: SelectionResult{
134 "base",
135 []string{
136 "splits/base-ldpi.apk",
137 "splits/base-mdpi.apk",
138 "splits/base-master.apk",
139 "splits/base-armeabi_v7a.apk",
Sasha Smundak7a894a62020-05-06 21:23:08 -0700140 },
141 },
142 },
143 {
144 name: "two",
145 targetConfig: TargetConfig{
146 sdkVersion: 29,
147 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
148 bp.ScreenDensity_LDPI: true,
149 },
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700150 abis: map[bp.Abi_AbiAlias]int{},
Sasha Smundak7a894a62020-05-06 21:23:08 -0700151 },
152 expected: SelectionResult{
153 "base",
154 []string{
155 "splits/base-ldpi.apk",
156 "splits/base-master.apk",
157 },
158 },
159 },
160 {
161 name: "three",
162 targetConfig: TargetConfig{
163 sdkVersion: 20,
164 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
165 bp.ScreenDensity_LDPI: true,
166 },
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700167 abis: map[bp.Abi_AbiAlias]int{},
Sasha Smundak7a894a62020-05-06 21:23:08 -0700168 },
169 expected: SelectionResult{
170 "",
171 nil,
172 },
173 },
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700174 {
175 name: "four",
176 targetConfig: TargetConfig{
177 sdkVersion: 29,
178 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
179 bp.ScreenDensity_MDPI: true,
180 },
181 abis: map[bp.Abi_AbiAlias]int{
182 bp.Abi_ARM64_V8A: 0,
183 bp.Abi_ARMEABI_V7A: 1,
184 },
185 },
186 expected: SelectionResult{
187 "base",
188 []string{
189 "splits/base-mdpi.apk",
190 "splits/base-master.apk",
191 "splits/base-arm64_v8a.apk",
192 },
193 },
194 },
Sasha Smundak7a894a62020-05-06 21:23:08 -0700195 },
196 },
197 {
198 protoText: `
199variant {
200 targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700201 sdk_version_targeting {
Sasha Smundak7a894a62020-05-06 21:23:08 -0700202 value { min { value: 10000 } } } }
203 apk_set {
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700204 module_metadata {
Sasha Smundak7a894a62020-05-06 21:23:08 -0700205 name: "base" targeting {} delivery_type: INSTALL_TIME }
206 apk_description {
207 targeting {
208 sdk_version_targeting {
209 value { min { value: 21 } } } }
210 path: "splits/base-master.apk"
211 split_apk_metadata { is_master_split: true } } } }`,
Sasha Smundak827c55f2020-05-20 13:10:59 -0700212 configs: []testConfigDesc{
Sasha Smundak7a894a62020-05-06 21:23:08 -0700213 {
214 name: "Prerelease",
215 targetConfig: TargetConfig{
216 sdkVersion: 30,
217 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{},
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700218 abis: map[bp.Abi_AbiAlias]int{},
Sasha Smundak7a894a62020-05-06 21:23:08 -0700219 allowPrereleased: true,
220 },
221 expected: SelectionResult{
222 "base",
223 []string{"splits/base-master.apk"},
224 },
225 },
226 },
227 },
Sasha Smundak827c55f2020-05-20 13:10:59 -0700228 {
229 protoText: `
230variant {
231 targeting {
232 sdk_version_targeting {
233 value { min { value: 29 } } } }
234 apk_set {
235 module_metadata {
236 name: "base" targeting {} delivery_type: INSTALL_TIME }
237 apk_description {
238 targeting {}
239 path: "universal.apk"
240 standalone_apk_metadata { fused_module_name: "base" } } } }`,
241 configs: []testConfigDesc{
242 {
243 name: "Universal",
244 targetConfig: TargetConfig{sdkVersion: 30},
245 expected: SelectionResult{
246 "base",
247 []string{"universal.apk"},
248 },
249 },
250 },
251 },
Sasha Smundak7a894a62020-05-06 21:23:08 -0700252 }
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700253 for _, testCase := range testCases {
254 var toc bp.BuildApksResult
255 if err := proto.UnmarshalText(testCase.protoText, &toc); err != nil {
256 t.Fatal(err)
257 }
258 for _, config := range testCase.configs {
259 actual := selectApks(&toc, config.targetConfig)
260 if !reflect.DeepEqual(config.expected, actual) {
261 t.Errorf("%s: expected %v, got %v", config.name, config.expected, actual)
262 }
263 }
264 }
265}
Sasha Smundak7a894a62020-05-06 21:23:08 -0700266
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700267func TestSelectApks_ApexSet(t *testing.T) {
Sasha Smundak827c55f2020-05-20 13:10:59 -0700268 testCases := []testDesc{
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700269 {
270 protoText: `
271variant {
272 targeting {
273 sdk_version_targeting {
274 value { min { value: 29 } } } }
275 apk_set {
276 module_metadata {
277 name: "base" targeting {} delivery_type: INSTALL_TIME }
278 apk_description {
279 targeting {
280 multi_abi_targeting {
281 value { abi { alias: ARMEABI_V7A } }
282 alternatives { abi { alias: ARM64_V8A } }
283 alternatives { abi { alias: X86 } }
284 alternatives { abi { alias: X86_64 } } }
285 sdk_version_targeting {
286 value { min { value: 21 } } } }
287 path: "standalones/standalone-armeabi_v7a.apex"
288 apex_apk_metadata { } }
289 apk_description {
290 targeting {
291 multi_abi_targeting {
292 value { abi { alias: ARM64_V8A } }
293 alternatives { abi { alias: ARMEABI_V7A } }
294 alternatives { abi { alias: X86 } }
295 alternatives { abi { alias: X86_64 } } }
296 sdk_version_targeting {
297 value { min { value: 21 } } } }
298 path: "standalones/standalone-arm64_v8a.apex"
299 apex_apk_metadata { } }
300 apk_description {
301 targeting {
302 multi_abi_targeting {
303 value { abi { alias: X86 } }
304 alternatives { abi { alias: ARMEABI_V7A } }
305 alternatives { abi { alias: ARM64_V8A } }
306 alternatives { abi { alias: X86_64 } } }
307 sdk_version_targeting {
308 value { min { value: 21 } } } }
309 path: "standalones/standalone-x86.apex"
310 apex_apk_metadata { } }
311 apk_description {
312 targeting {
313 multi_abi_targeting {
314 value { abi { alias: X86_64 } }
315 alternatives { abi { alias: ARMEABI_V7A } }
316 alternatives { abi { alias: ARM64_V8A } }
317 alternatives { abi { alias: X86 } } }
318 sdk_version_targeting {
319 value { min { value: 21 } } } }
320 path: "standalones/standalone-x86_64.apex"
321 apex_apk_metadata { } } }
322}
323bundletool {
324 version: "0.10.3" }
325
326`,
Sasha Smundak827c55f2020-05-20 13:10:59 -0700327 configs: []testConfigDesc{
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700328 {
329 name: "order matches priorities",
330 targetConfig: TargetConfig{
331 sdkVersion: 29,
332 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
333 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
334 },
335 abis: map[bp.Abi_AbiAlias]int{
336 bp.Abi_ARM64_V8A: 0,
337 bp.Abi_ARMEABI_V7A: 1,
338 },
339 },
340 expected: SelectionResult{
341 "base",
342 []string{
343 "standalones/standalone-arm64_v8a.apex",
344 },
345 },
346 },
347 {
348 name: "order doesn't match priorities",
349 targetConfig: TargetConfig{
350 sdkVersion: 29,
351 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
352 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
353 },
354 abis: map[bp.Abi_AbiAlias]int{
355 bp.Abi_ARMEABI_V7A: 0,
356 bp.Abi_ARM64_V8A: 1,
357 },
358 },
359 expected: SelectionResult{
360 "base",
361 []string{
362 "standalones/standalone-arm64_v8a.apex",
363 },
364 },
365 },
366 {
367 name: "single choice",
368 targetConfig: TargetConfig{
369 sdkVersion: 29,
370 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
371 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
372 },
373 abis: map[bp.Abi_AbiAlias]int{
374 bp.Abi_ARMEABI_V7A: 0,
375 },
376 },
377 expected: SelectionResult{
378 "base",
379 []string{
380 "standalones/standalone-armeabi_v7a.apex",
381 },
382 },
383 },
384 {
385 name: "cross platform",
386 targetConfig: TargetConfig{
387 sdkVersion: 29,
388 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
389 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
390 },
391 abis: map[bp.Abi_AbiAlias]int{
392 bp.Abi_ARM64_V8A: 0,
393 bp.Abi_MIPS64: 1,
394 bp.Abi_X86: 2,
395 },
396 },
397 expected: SelectionResult{
398 "base",
399 []string{
400 "standalones/standalone-x86.apex",
401 },
402 },
403 },
404 },
405 },
406 }
Sasha Smundak7a894a62020-05-06 21:23:08 -0700407 for _, testCase := range testCases {
408 var toc bp.BuildApksResult
409 if err := proto.UnmarshalText(testCase.protoText, &toc); err != nil {
410 t.Fatal(err)
411 }
412 for _, config := range testCase.configs {
413 actual := selectApks(&toc, config.targetConfig)
414 if !reflect.DeepEqual(config.expected, actual) {
415 t.Errorf("%s: expected %v, got %v", config.name, config.expected, actual)
416 }
417 }
418 }
419}
420
421type testZip2ZipWriter struct {
422 entries map[string]string
423}
424
425func (w testZip2ZipWriter) CopyFrom(file *zip.File, out string) error {
426 if x, ok := w.entries[out]; ok {
427 return fmt.Errorf("%s and %s both write to %s", x, file.Name, out)
428 }
429 w.entries[out] = file.Name
430 return nil
431}
432
Sasha Smundak827c55f2020-05-20 13:10:59 -0700433type testCaseWriteZip struct {
434 name string
435 moduleName string
436 stem string
Sasha Smundak7a894a62020-05-06 21:23:08 -0700437 // what we write from what
Sasha Smundak827c55f2020-05-20 13:10:59 -0700438 expected map[string]string
439}
440
441func TestWriteZip(t *testing.T) {
442 testCases := []testCaseWriteZip{
443 {
444 name: "splits",
445 moduleName: "mybase",
446 stem: "Foo",
447 expected: map[string]string{
448 "Foo.apk": "splits/mybase-master.apk",
449 "Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
450 },
451 },
452 {
453 name: "universal",
454 moduleName: "base",
455 stem: "Bar",
456 expected: map[string]string{
457 "Bar.apk": "universal.apk",
458 },
459 },
Sasha Smundak7a894a62020-05-06 21:23:08 -0700460 }
Sasha Smundak827c55f2020-05-20 13:10:59 -0700461 for _, testCase := range testCases {
462 apkSet := ApkSet{entries: make(map[string]*zip.File)}
463 sel := SelectionResult{moduleName: testCase.moduleName}
464 for _, in := range testCase.expected {
465 apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
466 sel.entries = append(sel.entries, in)
467 }
468 writer := testZip2ZipWriter{make(map[string]string)}
469 config := TargetConfig{stem: testCase.stem}
470 if err := apkSet.writeApks(sel, config, writer); err != nil {
471 t.Error(err)
472 }
473 if !reflect.DeepEqual(testCase.expected, writer.entries) {
474 t.Errorf("expected %v, got %v", testCase.expected, writer.entries)
475 }
Sasha Smundak7a894a62020-05-06 21:23:08 -0700476 }
477}