123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- // Copyright 2017 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package main
- import (
- "bytes"
- "fmt"
- "reflect"
- "testing"
- "android/soong/third_party/zip"
- )
- var testCases = []struct {
- name string
- inputFiles []string
- sortGlobs bool
- sortJava bool
- args []string
- excludes []string
- includes []string
- uncompresses []string
- outputFiles []string
- storedFiles []string
- err error
- }{
- { // This is modelled after the update package build rules in build/make/core/Makefile
- name: "filter globs",
- inputFiles: []string{
- "RADIO/a",
- "IMAGES/system.img",
- "IMAGES/b.txt",
- "IMAGES/recovery.img",
- "IMAGES/vendor.img",
- "OTA/android-info.txt",
- "OTA/b",
- },
- args: []string{"OTA/android-info.txt:android-info.txt", "IMAGES/*.img:."},
- outputFiles: []string{
- "android-info.txt",
- "system.img",
- "recovery.img",
- "vendor.img",
- },
- },
- {
- name: "sorted filter globs",
- inputFiles: []string{
- "RADIO/a",
- "IMAGES/system.img",
- "IMAGES/b.txt",
- "IMAGES/recovery.img",
- "IMAGES/vendor.img",
- "OTA/android-info.txt",
- "OTA/b",
- },
- sortGlobs: true,
- args: []string{"IMAGES/*.img:.", "OTA/android-info.txt:android-info.txt"},
- outputFiles: []string{
- "recovery.img",
- "system.img",
- "vendor.img",
- "android-info.txt",
- },
- },
- {
- name: "sort all",
- inputFiles: []string{
- "RADIO/",
- "RADIO/a",
- "IMAGES/",
- "IMAGES/system.img",
- "IMAGES/b.txt",
- "IMAGES/recovery.img",
- "IMAGES/vendor.img",
- "OTA/",
- "OTA/b",
- "OTA/android-info.txt",
- },
- sortGlobs: true,
- args: []string{"**/*"},
- outputFiles: []string{
- "IMAGES/b.txt",
- "IMAGES/recovery.img",
- "IMAGES/system.img",
- "IMAGES/vendor.img",
- "OTA/android-info.txt",
- "OTA/b",
- "RADIO/a",
- },
- },
- {
- name: "sort all implicit",
- inputFiles: []string{
- "RADIO/",
- "RADIO/a",
- "IMAGES/",
- "IMAGES/system.img",
- "IMAGES/b.txt",
- "IMAGES/recovery.img",
- "IMAGES/vendor.img",
- "OTA/",
- "OTA/b",
- "OTA/android-info.txt",
- },
- sortGlobs: true,
- args: nil,
- outputFiles: []string{
- "IMAGES/",
- "IMAGES/b.txt",
- "IMAGES/recovery.img",
- "IMAGES/system.img",
- "IMAGES/vendor.img",
- "OTA/",
- "OTA/android-info.txt",
- "OTA/b",
- "RADIO/",
- "RADIO/a",
- },
- },
- {
- name: "sort jar",
- inputFiles: []string{
- "MANIFEST.MF",
- "META-INF/MANIFEST.MF",
- "META-INF/aaa/",
- "META-INF/aaa/aaa",
- "META-INF/AAA",
- "META-INF.txt",
- "META-INF/",
- "AAA",
- "aaa",
- },
- sortJava: true,
- args: nil,
- outputFiles: []string{
- "META-INF/",
- "META-INF/MANIFEST.MF",
- "META-INF/AAA",
- "META-INF/aaa/",
- "META-INF/aaa/aaa",
- "AAA",
- "MANIFEST.MF",
- "META-INF.txt",
- "aaa",
- },
- },
- {
- name: "double input",
- inputFiles: []string{
- "b",
- "a",
- },
- args: []string{"a:a2", "**/*"},
- outputFiles: []string{
- "a2",
- "b",
- "a",
- },
- },
- {
- name: "multiple matches",
- inputFiles: []string{
- "a/a",
- },
- args: []string{"a/a", "a/*"},
- outputFiles: []string{
- "a/a",
- },
- },
- {
- name: "multiple conflicting matches",
- inputFiles: []string{
- "a/a",
- "a/b",
- },
- args: []string{"a/b:a/a", "a/*"},
- err: fmt.Errorf(`multiple entries for "a/a" with different contents`),
- },
- {
- name: "excludes",
- inputFiles: []string{
- "a/a",
- "a/b",
- },
- args: nil,
- excludes: []string{"a/a"},
- outputFiles: []string{
- "a/b",
- },
- },
- {
- name: "excludes with args",
- inputFiles: []string{
- "a/a",
- "a/b",
- },
- args: []string{"a/*"},
- excludes: []string{"a/a"},
- outputFiles: []string{
- "a/b",
- },
- },
- {
- name: "excludes over args",
- inputFiles: []string{
- "a/a",
- "a/b",
- },
- args: []string{"a/a"},
- excludes: []string{"a/*"},
- outputFiles: nil,
- },
- {
- name: "excludes with includes",
- inputFiles: []string{
- "a/a",
- "a/b",
- },
- args: nil,
- excludes: []string{"a/*"},
- includes: []string{"a/b"},
- outputFiles: []string{"a/b"},
- },
- {
- name: "excludes with glob",
- inputFiles: []string{
- "a/a",
- "a/b",
- },
- args: []string{"a/*"},
- excludes: []string{"a/*"},
- outputFiles: nil,
- },
- {
- name: "uncompress one",
- inputFiles: []string{
- "a/a",
- "a/b",
- },
- uncompresses: []string{"a/a"},
- outputFiles: []string{
- "a/a",
- "a/b",
- },
- storedFiles: []string{
- "a/a",
- },
- },
- {
- name: "uncompress two",
- inputFiles: []string{
- "a/a",
- "a/b",
- },
- uncompresses: []string{"a/a", "a/b"},
- outputFiles: []string{
- "a/a",
- "a/b",
- },
- storedFiles: []string{
- "a/a",
- "a/b",
- },
- },
- {
- name: "uncompress glob",
- inputFiles: []string{
- "a/a",
- "a/b",
- "a/c.so",
- "a/d.so",
- },
- uncompresses: []string{"a/*.so"},
- outputFiles: []string{
- "a/a",
- "a/b",
- "a/c.so",
- "a/d.so",
- },
- storedFiles: []string{
- "a/c.so",
- "a/d.so",
- },
- },
- {
- name: "uncompress rename",
- inputFiles: []string{
- "a/a",
- },
- args: []string{"a/a:a/b"},
- uncompresses: []string{"a/b"},
- outputFiles: []string{
- "a/b",
- },
- storedFiles: []string{
- "a/b",
- },
- },
- {
- name: "recursive glob",
- inputFiles: []string{
- "a/a/a",
- "a/a/b",
- },
- args: []string{"a/**/*:b"},
- outputFiles: []string{
- "b/a/a",
- "b/a/b",
- },
- },
- {
- name: "glob",
- inputFiles: []string{
- "a/a/a",
- "a/a/b",
- "a/b",
- "a/c",
- },
- args: []string{"a/*:b"},
- outputFiles: []string{
- "b/b",
- "b/c",
- },
- },
- {
- name: "top level glob",
- inputFiles: []string{
- "a",
- "b",
- },
- args: []string{"*:b"},
- outputFiles: []string{
- "b/a",
- "b/b",
- },
- },
- {
- name: "multilple glob",
- inputFiles: []string{
- "a/a/a",
- "a/a/b",
- },
- args: []string{"a/*/*:b"},
- outputFiles: []string{
- "b/a/a",
- "b/a/b",
- },
- },
- {
- name: "escaping",
- inputFiles: []string{"a"},
- args: []string{"\\a"},
- outputFiles: []string{"a"},
- },
- }
- func errorString(e error) string {
- if e == nil {
- return ""
- }
- return e.Error()
- }
- func TestZip2Zip(t *testing.T) {
- for _, testCase := range testCases {
- t.Run(testCase.name, func(t *testing.T) {
- inputBuf := &bytes.Buffer{}
- outputBuf := &bytes.Buffer{}
- inputWriter := zip.NewWriter(inputBuf)
- for _, file := range testCase.inputFiles {
- w, err := inputWriter.Create(file)
- if err != nil {
- t.Fatal(err)
- }
- fmt.Fprintln(w, "test")
- }
- inputWriter.Close()
- inputBytes := inputBuf.Bytes()
- inputReader, err := zip.NewReader(bytes.NewReader(inputBytes), int64(len(inputBytes)))
- if err != nil {
- t.Fatal(err)
- }
- outputWriter := zip.NewWriter(outputBuf)
- err = zip2zip(inputReader, outputWriter, testCase.sortGlobs, testCase.sortJava, false,
- testCase.args, testCase.excludes, testCase.includes, testCase.uncompresses)
- if errorString(testCase.err) != errorString(err) {
- t.Fatalf("Unexpected error:\n got: %q\nwant: %q", errorString(err), errorString(testCase.err))
- }
- outputWriter.Close()
- outputBytes := outputBuf.Bytes()
- outputReader, err := zip.NewReader(bytes.NewReader(outputBytes), int64(len(outputBytes)))
- if err != nil {
- t.Fatal(err)
- }
- var outputFiles []string
- var storedFiles []string
- if len(outputReader.File) > 0 {
- outputFiles = make([]string, len(outputReader.File))
- for i, file := range outputReader.File {
- outputFiles[i] = file.Name
- if file.Method == zip.Store {
- storedFiles = append(storedFiles, file.Name)
- }
- }
- }
- if !reflect.DeepEqual(testCase.outputFiles, outputFiles) {
- t.Fatalf("Output file list does not match:\nwant: %v\n got: %v", testCase.outputFiles, outputFiles)
- }
- if !reflect.DeepEqual(testCase.storedFiles, storedFiles) {
- t.Fatalf("Stored file list does not match:\nwant: %v\n got: %v", testCase.storedFiles, storedFiles)
- }
- })
- }
- }
- func TestConstantPartOfPattern(t *testing.T) {
- testCases := []struct{ in, out string }{
- {
- in: "",
- out: "",
- },
- {
- in: "a",
- out: "a",
- },
- {
- in: "*",
- out: "",
- },
- {
- in: "a/a",
- out: "a/a",
- },
- {
- in: "a/*",
- out: "a",
- },
- {
- in: "a/*/a",
- out: "a",
- },
- {
- in: "a/**/*",
- out: "a",
- },
- }
- for _, test := range testCases {
- t.Run(test.in, func(t *testing.T) {
- got := constantPartOfPattern(test.in)
- if got != test.out {
- t.Errorf("want %q, got %q", test.out, got)
- }
- })
- }
- }
|