blob: e6ac0bf5ce39f3fe56074f6dd2849bb686da0e1e [file] [log] [blame]
Dan Willemsen82218f22017-06-19 16:35:00 -07001// 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 main
16
17import (
18 "bytes"
19 "fmt"
20 "reflect"
21 "testing"
22
23 "android/soong/third_party/zip"
24)
25
26var testCases = []struct {
27 name string
28
Colin Crossb1a5e9c2018-10-07 21:30:12 -070029 inputFiles []string
30 sortGlobs bool
31 sortJava bool
32 args []string
33 excludes []string
Colin Cross38247712018-10-09 10:19:54 -070034 includes []string
Colin Crossb1a5e9c2018-10-07 21:30:12 -070035 uncompresses []string
Dan Willemsen82218f22017-06-19 16:35:00 -070036
37 outputFiles []string
Colin Crossb1a5e9c2018-10-07 21:30:12 -070038 storedFiles []string
Dan Willemsen82218f22017-06-19 16:35:00 -070039 err error
40}{
41 {
42 name: "unsupported \\",
43
44 args: []string{"a\\b:b"},
45
46 err: fmt.Errorf("\\ characters are not currently supported"),
47 },
Dan Willemsen82218f22017-06-19 16:35:00 -070048 { // This is modelled after the update package build rules in build/make/core/Makefile
49 name: "filter globs",
50
51 inputFiles: []string{
52 "RADIO/a",
53 "IMAGES/system.img",
54 "IMAGES/b.txt",
55 "IMAGES/recovery.img",
56 "IMAGES/vendor.img",
57 "OTA/android-info.txt",
58 "OTA/b",
59 },
60 args: []string{"OTA/android-info.txt:android-info.txt", "IMAGES/*.img:."},
61
62 outputFiles: []string{
63 "android-info.txt",
64 "system.img",
65 "recovery.img",
66 "vendor.img",
67 },
68 },
69 {
70 name: "sorted filter globs",
71
72 inputFiles: []string{
73 "RADIO/a",
74 "IMAGES/system.img",
75 "IMAGES/b.txt",
76 "IMAGES/recovery.img",
77 "IMAGES/vendor.img",
78 "OTA/android-info.txt",
79 "OTA/b",
80 },
81 sortGlobs: true,
82 args: []string{"IMAGES/*.img:.", "OTA/android-info.txt:android-info.txt"},
83
84 outputFiles: []string{
85 "recovery.img",
86 "system.img",
87 "vendor.img",
88 "android-info.txt",
89 },
90 },
91 {
92 name: "sort all",
93
94 inputFiles: []string{
Colin Crossf3831d02017-11-22 12:53:08 -080095 "RADIO/",
Dan Willemsen82218f22017-06-19 16:35:00 -070096 "RADIO/a",
Colin Crossf3831d02017-11-22 12:53:08 -080097 "IMAGES/",
Dan Willemsen82218f22017-06-19 16:35:00 -070098 "IMAGES/system.img",
99 "IMAGES/b.txt",
100 "IMAGES/recovery.img",
101 "IMAGES/vendor.img",
Colin Crossf3831d02017-11-22 12:53:08 -0800102 "OTA/",
Dan Willemsen82218f22017-06-19 16:35:00 -0700103 "OTA/b",
104 "OTA/android-info.txt",
105 },
106 sortGlobs: true,
Colin Crossf3831d02017-11-22 12:53:08 -0800107 args: []string{"**/*"},
Dan Willemsen82218f22017-06-19 16:35:00 -0700108
109 outputFiles: []string{
110 "IMAGES/b.txt",
111 "IMAGES/recovery.img",
112 "IMAGES/system.img",
113 "IMAGES/vendor.img",
114 "OTA/android-info.txt",
115 "OTA/b",
116 "RADIO/a",
117 },
118 },
119 {
Colin Cross06382992017-06-23 14:08:42 -0700120 name: "sort all implicit",
121
122 inputFiles: []string{
Colin Crossf3831d02017-11-22 12:53:08 -0800123 "RADIO/",
Colin Cross06382992017-06-23 14:08:42 -0700124 "RADIO/a",
Colin Crossf3831d02017-11-22 12:53:08 -0800125 "IMAGES/",
Colin Cross06382992017-06-23 14:08:42 -0700126 "IMAGES/system.img",
127 "IMAGES/b.txt",
128 "IMAGES/recovery.img",
129 "IMAGES/vendor.img",
Colin Crossf3831d02017-11-22 12:53:08 -0800130 "OTA/",
Colin Cross06382992017-06-23 14:08:42 -0700131 "OTA/b",
132 "OTA/android-info.txt",
133 },
134 sortGlobs: true,
135 args: nil,
136
137 outputFiles: []string{
Colin Crossf3831d02017-11-22 12:53:08 -0800138 "IMAGES/",
Colin Cross06382992017-06-23 14:08:42 -0700139 "IMAGES/b.txt",
140 "IMAGES/recovery.img",
141 "IMAGES/system.img",
142 "IMAGES/vendor.img",
Colin Crossf3831d02017-11-22 12:53:08 -0800143 "OTA/",
Colin Cross06382992017-06-23 14:08:42 -0700144 "OTA/android-info.txt",
145 "OTA/b",
Colin Crossf3831d02017-11-22 12:53:08 -0800146 "RADIO/",
Colin Cross06382992017-06-23 14:08:42 -0700147 "RADIO/a",
148 },
149 },
150 {
Colin Cross8936b022017-06-23 13:00:17 -0700151 name: "sort jar",
152
153 inputFiles: []string{
154 "MANIFEST.MF",
155 "META-INF/MANIFEST.MF",
156 "META-INF/aaa/",
157 "META-INF/aaa/aaa",
158 "META-INF/AAA",
159 "META-INF.txt",
160 "META-INF/",
161 "AAA",
162 "aaa",
163 },
164 sortJava: true,
165 args: nil,
166
167 outputFiles: []string{
168 "META-INF/",
169 "META-INF/MANIFEST.MF",
170 "META-INF/AAA",
171 "META-INF/aaa/",
172 "META-INF/aaa/aaa",
173 "AAA",
174 "MANIFEST.MF",
175 "META-INF.txt",
176 "aaa",
177 },
178 },
179 {
Dan Willemsen82218f22017-06-19 16:35:00 -0700180 name: "double input",
181
182 inputFiles: []string{
183 "b",
184 "a",
185 },
Colin Crossf3831d02017-11-22 12:53:08 -0800186 args: []string{"a:a2", "**/*"},
Dan Willemsen82218f22017-06-19 16:35:00 -0700187
188 outputFiles: []string{
189 "a2",
190 "b",
191 "a",
192 },
193 },
Colin Crossf3831d02017-11-22 12:53:08 -0800194 {
195 name: "multiple matches",
196
197 inputFiles: []string{
198 "a/a",
199 },
200 args: []string{"a/a", "a/*"},
201
202 outputFiles: []string{
203 "a/a",
204 },
205 },
206 {
207 name: "multiple conflicting matches",
208
209 inputFiles: []string{
210 "a/a",
211 "a/b",
212 },
213 args: []string{"a/b:a/a", "a/*"},
214
215 err: fmt.Errorf(`multiple entries for "a/a" with different contents`),
216 },
217 {
218 name: "excludes",
219
220 inputFiles: []string{
221 "a/a",
222 "a/b",
223 },
224 args: nil,
225 excludes: []string{"a/a"},
226
227 outputFiles: []string{
228 "a/b",
229 },
230 },
231 {
Colin Cross38247712018-10-09 10:19:54 -0700232 name: "excludes with args",
Colin Crossf3831d02017-11-22 12:53:08 -0800233
234 inputFiles: []string{
235 "a/a",
236 "a/b",
237 },
238 args: []string{"a/*"},
239 excludes: []string{"a/a"},
240
241 outputFiles: []string{
242 "a/b",
243 },
244 },
245 {
Colin Cross38247712018-10-09 10:19:54 -0700246 name: "excludes over args",
247
248 inputFiles: []string{
249 "a/a",
250 "a/b",
251 },
252 args: []string{"a/a"},
253 excludes: []string{"a/*"},
254
255 outputFiles: nil,
256 },
257 {
258 name: "excludes with includes",
259
260 inputFiles: []string{
261 "a/a",
262 "a/b",
263 },
264 args: nil,
265 excludes: []string{"a/*"},
266 includes: []string{"a/b"},
267
268 outputFiles: []string{"a/b"},
269 },
270 {
Colin Crossf3831d02017-11-22 12:53:08 -0800271 name: "excludes with glob",
272
273 inputFiles: []string{
274 "a/a",
275 "a/b",
276 },
277 args: []string{"a/*"},
278 excludes: []string{"a/*"},
279
280 outputFiles: nil,
281 },
Colin Crossb1a5e9c2018-10-07 21:30:12 -0700282 {
283 name: "uncompress one",
284
285 inputFiles: []string{
286 "a/a",
287 "a/b",
288 },
289 uncompresses: []string{"a/a"},
290
291 outputFiles: []string{
292 "a/a",
293 "a/b",
294 },
295 storedFiles: []string{
296 "a/a",
297 },
298 },
299 {
300 name: "uncompress two",
301
302 inputFiles: []string{
303 "a/a",
304 "a/b",
305 },
306 uncompresses: []string{"a/a", "a/b"},
307
308 outputFiles: []string{
309 "a/a",
310 "a/b",
311 },
312 storedFiles: []string{
313 "a/a",
314 "a/b",
315 },
316 },
317 {
318 name: "uncompress glob",
319
320 inputFiles: []string{
321 "a/a",
322 "a/b",
323 "a/c.so",
324 "a/d.so",
325 },
326 uncompresses: []string{"a/*.so"},
327
328 outputFiles: []string{
329 "a/a",
330 "a/b",
331 "a/c.so",
332 "a/d.so",
333 },
334 storedFiles: []string{
335 "a/c.so",
336 "a/d.so",
337 },
338 },
339 {
340 name: "uncompress rename",
341
342 inputFiles: []string{
343 "a/a",
344 },
345 args: []string{"a/a:a/b"},
346 uncompresses: []string{"a/b"},
347
348 outputFiles: []string{
349 "a/b",
350 },
351 storedFiles: []string{
352 "a/b",
353 },
354 },
Colin Cross714614c2018-11-01 13:27:58 -0700355 {
356 name: "recursive glob",
357
358 inputFiles: []string{
359 "a/a/a",
360 "a/a/b",
361 },
362 args: []string{"a/**/*:b"},
363 outputFiles: []string{
364 "b/a/a",
365 "b/a/b",
366 },
367 },
368 {
369 name: "glob",
370
371 inputFiles: []string{
372 "a/a/a",
373 "a/a/b",
374 "a/b",
375 "a/c",
376 },
377 args: []string{"a/*:b"},
378 outputFiles: []string{
379 "b/b",
380 "b/c",
381 },
382 },
383 {
384 name: "top level glob",
385
386 inputFiles: []string{
387 "a",
388 "b",
389 },
390 args: []string{"*:b"},
391 outputFiles: []string{
392 "b/a",
393 "b/b",
394 },
395 },
396 {
397 name: "multilple glob",
398
399 inputFiles: []string{
400 "a/a/a",
401 "a/a/b",
402 },
403 args: []string{"a/*/*:b"},
404 outputFiles: []string{
405 "b/a/a",
406 "b/a/b",
407 },
408 },
Dan Willemsen82218f22017-06-19 16:35:00 -0700409}
410
411func errorString(e error) string {
412 if e == nil {
413 return ""
414 }
415 return e.Error()
416}
417
418func TestZip2Zip(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700419 t.Parallel()
Dan Willemsen82218f22017-06-19 16:35:00 -0700420 for _, testCase := range testCases {
421 t.Run(testCase.name, func(t *testing.T) {
422 inputBuf := &bytes.Buffer{}
423 outputBuf := &bytes.Buffer{}
424
425 inputWriter := zip.NewWriter(inputBuf)
426 for _, file := range testCase.inputFiles {
427 w, err := inputWriter.Create(file)
428 if err != nil {
429 t.Fatal(err)
430 }
431 fmt.Fprintln(w, "test")
432 }
433 inputWriter.Close()
434 inputBytes := inputBuf.Bytes()
435 inputReader, err := zip.NewReader(bytes.NewReader(inputBytes), int64(len(inputBytes)))
436 if err != nil {
437 t.Fatal(err)
438 }
439
440 outputWriter := zip.NewWriter(outputBuf)
Colin Crossb1a5e9c2018-10-07 21:30:12 -0700441 err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false,
Colin Cross38247712018-10-09 10:19:54 -0700442 testCase.args, testCase.excludes, testCase.includes, testCase.uncompresses)
Dan Willemsen82218f22017-06-19 16:35:00 -0700443 if errorString(testCase.err) != errorString(err) {
444 t.Fatalf("Unexpected error:\n got: %q\nwant: %q", errorString(err), errorString(testCase.err))
445 }
446
447 outputWriter.Close()
448 outputBytes := outputBuf.Bytes()
449 outputReader, err := zip.NewReader(bytes.NewReader(outputBytes), int64(len(outputBytes)))
450 if err != nil {
451 t.Fatal(err)
452 }
453 var outputFiles []string
Colin Crossb1a5e9c2018-10-07 21:30:12 -0700454 var storedFiles []string
Dan Willemsen82218f22017-06-19 16:35:00 -0700455 if len(outputReader.File) > 0 {
456 outputFiles = make([]string, len(outputReader.File))
457 for i, file := range outputReader.File {
458 outputFiles[i] = file.Name
Colin Crossb1a5e9c2018-10-07 21:30:12 -0700459 if file.Method == zip.Store {
460 storedFiles = append(storedFiles, file.Name)
461 }
Dan Willemsen82218f22017-06-19 16:35:00 -0700462 }
463 }
464
465 if !reflect.DeepEqual(testCase.outputFiles, outputFiles) {
Colin Crossb1a5e9c2018-10-07 21:30:12 -0700466 t.Fatalf("Output file list does not match:\nwant: %v\n got: %v", testCase.outputFiles, outputFiles)
467 }
468 if !reflect.DeepEqual(testCase.storedFiles, storedFiles) {
469 t.Fatalf("Stored file list does not match:\nwant: %v\n got: %v", testCase.storedFiles, storedFiles)
Dan Willemsen82218f22017-06-19 16:35:00 -0700470 }
471 })
472 }
473}
Colin Cross714614c2018-11-01 13:27:58 -0700474
475func TestConstantPartOfPattern(t *testing.T) {
Colin Cross323dc602020-09-18 14:25:31 -0700476 t.Parallel()
Colin Cross714614c2018-11-01 13:27:58 -0700477 testCases := []struct{ in, out string }{
478 {
479 in: "",
480 out: "",
481 },
482 {
483 in: "a",
484 out: "a",
485 },
486 {
487 in: "*",
488 out: "",
489 },
490 {
491 in: "a/a",
492 out: "a/a",
493 },
494 {
495 in: "a/*",
496 out: "a",
497 },
498 {
499 in: "a/*/a",
500 out: "a",
501 },
502 {
503 in: "a/**/*",
504 out: "a",
505 },
506 }
507
508 for _, test := range testCases {
509 t.Run(test.in, func(t *testing.T) {
510 got := constantPartOfPattern(test.in)
511 if got != test.out {
512 t.Errorf("want %q, got %q", test.out, got)
513 }
514 })
515 }
516}