blob: c3e6a2def423eb6a3f34eebdd717cee2679bb823 [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"
Sasha Smundak7a894a62020-05-06 21:23:08 -070019 "reflect"
20 "testing"
21
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -070022 "github.com/golang/protobuf/proto"
23
Sasha Smundak7a894a62020-05-06 21:23:08 -070024 bp "android/soong/cmd/extract_apks/bundle_proto"
25 "android/soong/third_party/zip"
26)
27
Sasha Smundak827c55f2020-05-20 13:10:59 -070028type testConfigDesc struct {
Sasha Smundak7a894a62020-05-06 21:23:08 -070029 name string
30 targetConfig TargetConfig
31 expected SelectionResult
32}
33
Sasha Smundak827c55f2020-05-20 13:10:59 -070034type testDesc struct {
Sasha Smundak7a894a62020-05-06 21:23:08 -070035 protoText string
Sasha Smundak827c55f2020-05-20 13:10:59 -070036 configs []testConfigDesc
Sasha Smundak7a894a62020-05-06 21:23:08 -070037}
38
Jaewoong Jungfa00c062020-05-14 14:15:24 -070039func TestSelectApks_ApkSet(t *testing.T) {
Sasha Smundak827c55f2020-05-20 13:10:59 -070040 testCases := []testDesc{
Sasha Smundak7a894a62020-05-06 21:23:08 -070041 {
42 protoText: `
43variant {
44 targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070045 sdk_version_targeting {
Sasha Smundak7a894a62020-05-06 21:23:08 -070046 value { min { value: 29 } } } }
47 apk_set {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070048 module_metadata {
Sasha Smundak7a894a62020-05-06 21:23:08 -070049 name: "base" targeting {} delivery_type: INSTALL_TIME }
50 apk_description {
51 targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070052 screen_density_targeting {
Sasha Smundak7a894a62020-05-06 21:23:08 -070053 value { density_alias: LDPI } }
54 sdk_version_targeting {
55 value { min { value: 21 } } } }
56 path: "splits/base-ldpi.apk"
57 split_apk_metadata { split_id: "config.ldpi" } }
58 apk_description {
59 targeting {
60 screen_density_targeting {
61 value { density_alias: MDPI } }
62 sdk_version_targeting {
63 value { min { value: 21 } } } }
64 path: "splits/base-mdpi.apk"
65 split_apk_metadata { split_id: "config.mdpi" } }
66 apk_description {
67 targeting {
68 sdk_version_targeting {
69 value { min { value: 21 } } } }
70 path: "splits/base-master.apk"
71 split_apk_metadata { is_master_split: true } }
72 apk_description {
73 targeting {
74 abi_targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070075 value { alias: ARMEABI_V7A }
76 alternatives { alias: ARM64_V8A }
77 alternatives { alias: X86 }
78 alternatives { alias: X86_64 } }
Sasha Smundak7a894a62020-05-06 21:23:08 -070079 sdk_version_targeting {
80 value { min { value: 21 } } } }
81 path: "splits/base-armeabi_v7a.apk"
82 split_apk_metadata { split_id: "config.armeabi_v7a" } }
83 apk_description {
84 targeting {
85 abi_targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070086 value { alias: ARM64_V8A }
87 alternatives { alias: ARMEABI_V7A }
88 alternatives { alias: X86 }
89 alternatives { alias: X86_64 } }
Sasha Smundak7a894a62020-05-06 21:23:08 -070090 sdk_version_targeting {
91 value { min { value: 21 } } } }
92 path: "splits/base-arm64_v8a.apk"
93 split_apk_metadata { split_id: "config.arm64_v8a" } }
94 apk_description {
95 targeting {
96 abi_targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -070097 value { alias: X86 }
98 alternatives { alias: ARMEABI_V7A }
99 alternatives { alias: ARM64_V8A }
100 alternatives { alias: X86_64 } }
Sasha Smundak7a894a62020-05-06 21:23:08 -0700101 sdk_version_targeting {
102 value { min { value: 21 } } } }
103 path: "splits/base-x86.apk"
104 split_apk_metadata { split_id: "config.x86" } }
105 apk_description {
106 targeting {
107 abi_targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700108 value { alias: X86_64 }
109 alternatives { alias: ARMEABI_V7A }
110 alternatives { alias: ARM64_V8A }
111 alternatives { alias: X86 } }
Sasha Smundak7a894a62020-05-06 21:23:08 -0700112 sdk_version_targeting {
113 value { min { value: 21 } } } }
114 path: "splits/base-x86_64.apk"
115 split_apk_metadata { split_id: "config.x86_64" } } }
116}
117bundletool {
118 version: "0.10.3" }
119
120`,
Sasha Smundak827c55f2020-05-20 13:10:59 -0700121 configs: []testConfigDesc{
Sasha Smundak7a894a62020-05-06 21:23:08 -0700122 {
123 name: "one",
124 targetConfig: TargetConfig{
125 sdkVersion: 29,
126 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
127 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
128 },
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700129 abis: map[bp.Abi_AbiAlias]int{
130 bp.Abi_ARMEABI_V7A: 0,
131 bp.Abi_ARM64_V8A: 1,
Sasha Smundak7a894a62020-05-06 21:23:08 -0700132 },
133 },
134 expected: SelectionResult{
135 "base",
136 []string{
137 "splits/base-ldpi.apk",
138 "splits/base-mdpi.apk",
139 "splits/base-master.apk",
140 "splits/base-armeabi_v7a.apk",
Sasha Smundak7a894a62020-05-06 21:23:08 -0700141 },
142 },
143 },
144 {
145 name: "two",
146 targetConfig: TargetConfig{
147 sdkVersion: 29,
148 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
149 bp.ScreenDensity_LDPI: true,
150 },
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700151 abis: map[bp.Abi_AbiAlias]int{},
Sasha Smundak7a894a62020-05-06 21:23:08 -0700152 },
153 expected: SelectionResult{
154 "base",
155 []string{
156 "splits/base-ldpi.apk",
157 "splits/base-master.apk",
158 },
159 },
160 },
161 {
162 name: "three",
163 targetConfig: TargetConfig{
164 sdkVersion: 20,
165 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
166 bp.ScreenDensity_LDPI: true,
167 },
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700168 abis: map[bp.Abi_AbiAlias]int{},
Sasha Smundak7a894a62020-05-06 21:23:08 -0700169 },
170 expected: SelectionResult{
171 "",
172 nil,
173 },
174 },
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700175 {
176 name: "four",
177 targetConfig: TargetConfig{
178 sdkVersion: 29,
179 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
180 bp.ScreenDensity_MDPI: true,
181 },
182 abis: map[bp.Abi_AbiAlias]int{
183 bp.Abi_ARM64_V8A: 0,
184 bp.Abi_ARMEABI_V7A: 1,
185 },
186 },
187 expected: SelectionResult{
188 "base",
189 []string{
190 "splits/base-mdpi.apk",
191 "splits/base-master.apk",
192 "splits/base-arm64_v8a.apk",
193 },
194 },
195 },
Sasha Smundak7a894a62020-05-06 21:23:08 -0700196 },
197 },
198 {
199 protoText: `
200variant {
201 targeting {
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700202 sdk_version_targeting {
Sasha Smundak7a894a62020-05-06 21:23:08 -0700203 value { min { value: 10000 } } } }
204 apk_set {
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700205 module_metadata {
Sasha Smundak7a894a62020-05-06 21:23:08 -0700206 name: "base" targeting {} delivery_type: INSTALL_TIME }
207 apk_description {
208 targeting {
209 sdk_version_targeting {
210 value { min { value: 21 } } } }
211 path: "splits/base-master.apk"
212 split_apk_metadata { is_master_split: true } } } }`,
Sasha Smundak827c55f2020-05-20 13:10:59 -0700213 configs: []testConfigDesc{
Sasha Smundak7a894a62020-05-06 21:23:08 -0700214 {
215 name: "Prerelease",
216 targetConfig: TargetConfig{
217 sdkVersion: 30,
218 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{},
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700219 abis: map[bp.Abi_AbiAlias]int{},
Sasha Smundak7a894a62020-05-06 21:23:08 -0700220 allowPrereleased: true,
221 },
222 expected: SelectionResult{
223 "base",
224 []string{"splits/base-master.apk"},
225 },
226 },
227 },
228 },
Sasha Smundak827c55f2020-05-20 13:10:59 -0700229 {
230 protoText: `
231variant {
232 targeting {
233 sdk_version_targeting {
234 value { min { value: 29 } } } }
235 apk_set {
236 module_metadata {
237 name: "base" targeting {} delivery_type: INSTALL_TIME }
238 apk_description {
239 targeting {}
240 path: "universal.apk"
241 standalone_apk_metadata { fused_module_name: "base" } } } }`,
242 configs: []testConfigDesc{
243 {
244 name: "Universal",
245 targetConfig: TargetConfig{sdkVersion: 30},
246 expected: SelectionResult{
247 "base",
248 []string{"universal.apk"},
249 },
250 },
251 },
252 },
Sasha Smundak7a894a62020-05-06 21:23:08 -0700253 }
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700254 for _, testCase := range testCases {
255 var toc bp.BuildApksResult
256 if err := proto.UnmarshalText(testCase.protoText, &toc); err != nil {
257 t.Fatal(err)
258 }
259 for _, config := range testCase.configs {
260 actual := selectApks(&toc, config.targetConfig)
261 if !reflect.DeepEqual(config.expected, actual) {
262 t.Errorf("%s: expected %v, got %v", config.name, config.expected, actual)
263 }
264 }
265 }
266}
Sasha Smundak7a894a62020-05-06 21:23:08 -0700267
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700268func TestSelectApks_ApexSet(t *testing.T) {
Sasha Smundak827c55f2020-05-20 13:10:59 -0700269 testCases := []testDesc{
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700270 {
271 protoText: `
272variant {
273 targeting {
274 sdk_version_targeting {
275 value { min { value: 29 } } } }
276 apk_set {
277 module_metadata {
278 name: "base" targeting {} delivery_type: INSTALL_TIME }
279 apk_description {
280 targeting {
281 multi_abi_targeting {
282 value { abi { alias: ARMEABI_V7A } }
283 alternatives { abi { alias: ARM64_V8A } }
284 alternatives { abi { alias: X86 } }
285 alternatives { abi { alias: X86_64 } } }
286 sdk_version_targeting {
287 value { min { value: 21 } } } }
288 path: "standalones/standalone-armeabi_v7a.apex"
289 apex_apk_metadata { } }
290 apk_description {
291 targeting {
292 multi_abi_targeting {
293 value { abi { alias: ARM64_V8A } }
294 alternatives { abi { alias: ARMEABI_V7A } }
295 alternatives { abi { alias: X86 } }
296 alternatives { abi { alias: X86_64 } } }
297 sdk_version_targeting {
298 value { min { value: 21 } } } }
299 path: "standalones/standalone-arm64_v8a.apex"
300 apex_apk_metadata { } }
301 apk_description {
302 targeting {
303 multi_abi_targeting {
304 value { abi { alias: X86 } }
305 alternatives { abi { alias: ARMEABI_V7A } }
306 alternatives { abi { alias: ARM64_V8A } }
307 alternatives { abi { alias: X86_64 } } }
308 sdk_version_targeting {
309 value { min { value: 21 } } } }
310 path: "standalones/standalone-x86.apex"
311 apex_apk_metadata { } }
312 apk_description {
313 targeting {
314 multi_abi_targeting {
315 value { abi { alias: X86_64 } }
316 alternatives { abi { alias: ARMEABI_V7A } }
317 alternatives { abi { alias: ARM64_V8A } }
318 alternatives { abi { alias: X86 } } }
319 sdk_version_targeting {
320 value { min { value: 21 } } } }
321 path: "standalones/standalone-x86_64.apex"
322 apex_apk_metadata { } } }
323}
324bundletool {
325 version: "0.10.3" }
326
327`,
Sasha Smundak827c55f2020-05-20 13:10:59 -0700328 configs: []testConfigDesc{
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700329 {
330 name: "order matches priorities",
331 targetConfig: TargetConfig{
332 sdkVersion: 29,
333 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
334 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
335 },
336 abis: map[bp.Abi_AbiAlias]int{
337 bp.Abi_ARM64_V8A: 0,
338 bp.Abi_ARMEABI_V7A: 1,
339 },
340 },
341 expected: SelectionResult{
342 "base",
343 []string{
344 "standalones/standalone-arm64_v8a.apex",
345 },
346 },
347 },
348 {
349 name: "order doesn't match priorities",
350 targetConfig: TargetConfig{
351 sdkVersion: 29,
352 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
353 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
354 },
355 abis: map[bp.Abi_AbiAlias]int{
356 bp.Abi_ARMEABI_V7A: 0,
357 bp.Abi_ARM64_V8A: 1,
358 },
359 },
360 expected: SelectionResult{
361 "base",
362 []string{
363 "standalones/standalone-arm64_v8a.apex",
364 },
365 },
366 },
367 {
368 name: "single choice",
369 targetConfig: TargetConfig{
370 sdkVersion: 29,
371 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
372 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
373 },
374 abis: map[bp.Abi_AbiAlias]int{
375 bp.Abi_ARMEABI_V7A: 0,
376 },
377 },
378 expected: SelectionResult{
379 "base",
380 []string{
381 "standalones/standalone-armeabi_v7a.apex",
382 },
383 },
384 },
385 {
386 name: "cross platform",
387 targetConfig: TargetConfig{
388 sdkVersion: 29,
389 screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
390 bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
391 },
392 abis: map[bp.Abi_AbiAlias]int{
393 bp.Abi_ARM64_V8A: 0,
394 bp.Abi_MIPS64: 1,
395 bp.Abi_X86: 2,
396 },
397 },
398 expected: SelectionResult{
399 "base",
400 []string{
401 "standalones/standalone-x86.apex",
402 },
403 },
404 },
405 },
406 },
407 }
Sasha Smundak7a894a62020-05-06 21:23:08 -0700408 for _, testCase := range testCases {
409 var toc bp.BuildApksResult
410 if err := proto.UnmarshalText(testCase.protoText, &toc); err != nil {
411 t.Fatal(err)
412 }
413 for _, config := range testCase.configs {
414 actual := selectApks(&toc, config.targetConfig)
415 if !reflect.DeepEqual(config.expected, actual) {
416 t.Errorf("%s: expected %v, got %v", config.name, config.expected, actual)
417 }
418 }
419 }
420}
421
422type testZip2ZipWriter struct {
423 entries map[string]string
424}
425
426func (w testZip2ZipWriter) CopyFrom(file *zip.File, out string) error {
427 if x, ok := w.entries[out]; ok {
428 return fmt.Errorf("%s and %s both write to %s", x, file.Name, out)
429 }
430 w.entries[out] = file.Name
431 return nil
432}
433
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700434type testCaseWriteApks struct {
Sasha Smundak827c55f2020-05-20 13:10:59 -0700435 name string
436 moduleName string
437 stem string
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700438 partition string
Sasha Smundak7a894a62020-05-06 21:23:08 -0700439 // what we write from what
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700440 expectedZipEntries map[string]string
441 expectedApkcerts []string
Sasha Smundak827c55f2020-05-20 13:10:59 -0700442}
443
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700444func TestWriteApks(t *testing.T) {
445 testCases := []testCaseWriteApks{
Sasha Smundak827c55f2020-05-20 13:10:59 -0700446 {
447 name: "splits",
448 moduleName: "mybase",
449 stem: "Foo",
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700450 partition: "system",
451 expectedZipEntries: map[string]string{
Sasha Smundak827c55f2020-05-20 13:10:59 -0700452 "Foo.apk": "splits/mybase-master.apk",
453 "Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
454 },
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700455 expectedApkcerts: []string{
456 `name="Foo-xhdpi.apk" certificate="PRESIGNED" private_key="" partition="system"`,
457 `name="Foo.apk" certificate="PRESIGNED" private_key="" partition="system"`,
458 },
Sasha Smundak827c55f2020-05-20 13:10:59 -0700459 },
460 {
461 name: "universal",
462 moduleName: "base",
463 stem: "Bar",
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700464 partition: "product",
465 expectedZipEntries: map[string]string{
Sasha Smundak827c55f2020-05-20 13:10:59 -0700466 "Bar.apk": "universal.apk",
467 },
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700468 expectedApkcerts: []string{
469 `name="Bar.apk" certificate="PRESIGNED" private_key="" partition="product"`,
470 },
Sasha Smundak827c55f2020-05-20 13:10:59 -0700471 },
Sasha Smundak7a894a62020-05-06 21:23:08 -0700472 }
Sasha Smundak827c55f2020-05-20 13:10:59 -0700473 for _, testCase := range testCases {
474 apkSet := ApkSet{entries: make(map[string]*zip.File)}
475 sel := SelectionResult{moduleName: testCase.moduleName}
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700476 for _, in := range testCase.expectedZipEntries {
Sasha Smundak827c55f2020-05-20 13:10:59 -0700477 apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
478 sel.entries = append(sel.entries, in)
479 }
480 writer := testZip2ZipWriter{make(map[string]string)}
481 config := TargetConfig{stem: testCase.stem}
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700482 apkcerts, err := apkSet.writeApks(sel, config, writer, testCase.partition)
483 if err != nil {
Sasha Smundak827c55f2020-05-20 13:10:59 -0700484 t.Error(err)
485 }
Jaewoong Jung11c1e0f2020-06-29 19:18:44 -0700486 if !reflect.DeepEqual(testCase.expectedZipEntries, writer.entries) {
487 t.Errorf("expected zip entries %v, got %v", testCase.expectedZipEntries, writer.entries)
488 }
489 if !reflect.DeepEqual(testCase.expectedApkcerts, apkcerts) {
490 t.Errorf("expected apkcerts %v, got %v", testCase.expectedApkcerts, apkcerts)
Sasha Smundak827c55f2020-05-20 13:10:59 -0700491 }
Sasha Smundak7a894a62020-05-06 21:23:08 -0700492 }
493}