diff options
author | 2018-09-27 15:06:19 -0700 | |
---|---|---|
committer | 2018-09-28 13:56:06 -0700 | |
commit | 05518bc13b3cd31e6cb7158a41aa124b224c3bc4 (patch) | |
tree | 65dbf6c09827df7f23d973ef6419fea543580d52 /zip/zip_test.go | |
parent | b051ab5cb54f8802807680a8fb24092b445a3ddb (diff) |
soong_zip: Add tests
Add test that cover basic command line usage of soong_zip. -D
is not covered yet as the implementation will be replaced with
one that is also more easily testable in the next patch.
Bug: 116751500
Test: zip_test.go
Change-Id: I5a1bcee74ebc9cb3cf332c36f89bc12c0e807ad2
Diffstat (limited to 'zip/zip_test.go')
-rw-r--r-- | zip/zip_test.go | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/zip/zip_test.go b/zip/zip_test.go index 03e7958fb..0c2105c67 100644 --- a/zip/zip_test.go +++ b/zip/zip_test.go @@ -15,10 +15,395 @@ package zip import ( + "bytes" + "hash/crc32" + "io" + "os" "reflect" + "syscall" "testing" + + "android/soong/third_party/zip" + + "github.com/google/blueprint/pathtools" +) + +var ( + fileA = []byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + fileB = []byte("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB") + fileC = []byte("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC") + fileEmpty = []byte("") + fileManifest = []byte("Manifest-Version: 1.0\nCreated-By: soong_zip\n\n") + + fileCustomManifest = []byte("Custom manifest: true\n") + customManifestAfter = []byte("Manifest-Version: 1.0\nCreated-By: soong_zip\nCustom manifest: true\n\n") ) +var mockFs = pathtools.MockFs(map[string][]byte{ + "a/a/a": fileA, + "a/a/b": fileB, + "a/a/c -> ../../c": nil, + "a/a/d -> b": nil, + "c": fileC, + "l": []byte("a/a/a\na/a/b\nc\n"), + "l2": []byte("missing\n"), + "manifest.txt": fileCustomManifest, +}) + +func fh(name string, contents []byte, method uint16) zip.FileHeader { + return zip.FileHeader{ + Name: name, + Method: method, + CRC32: crc32.ChecksumIEEE(contents), + UncompressedSize64: uint64(len(contents)), + ExternalAttrs: 0, + } +} + +func fhManifest(contents []byte) zip.FileHeader { + return zip.FileHeader{ + Name: "META-INF/MANIFEST.MF", + Method: zip.Store, + CRC32: crc32.ChecksumIEEE(contents), + UncompressedSize64: uint64(len(contents)), + ExternalAttrs: (syscall.S_IFREG | 0700) << 16, + } +} + +func fhLink(name string, to string) zip.FileHeader { + return zip.FileHeader{ + Name: name, + Method: zip.Store, + CRC32: crc32.ChecksumIEEE([]byte(to)), + UncompressedSize64: uint64(len(to)), + ExternalAttrs: (syscall.S_IFLNK | 0777) << 16, + } +} + +func fhDir(name string) zip.FileHeader { + return zip.FileHeader{ + Name: name, + Method: zip.Store, + CRC32: crc32.ChecksumIEEE(nil), + UncompressedSize64: 0, + ExternalAttrs: (syscall.S_IFDIR|0700)<<16 | 0x10, + } +} + +func fileArgsBuilder() *FileArgsBuilder { + return &FileArgsBuilder{ + fs: mockFs, + } +} + +func TestZip(t *testing.T) { + testCases := []struct { + name string + args *FileArgsBuilder + compressionLevel int + emulateJar bool + nonDeflatedFiles map[string]bool + dirEntries bool + manifest string + + files []zip.FileHeader + err error + }{ + { + name: "empty args", + args: fileArgsBuilder(), + + files: []zip.FileHeader{}, + }, + { + name: "files", + args: fileArgsBuilder(). + File("a/a/a"). + File("a/a/b"). + File("c"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("a/a/a", fileA, zip.Deflate), + fh("a/a/b", fileB, zip.Deflate), + fh("c", fileC, zip.Deflate), + }, + }, + { + name: "stored files", + args: fileArgsBuilder(). + File("a/a/a"). + File("a/a/b"). + File("c"), + compressionLevel: 0, + + files: []zip.FileHeader{ + fh("a/a/a", fileA, zip.Store), + fh("a/a/b", fileB, zip.Store), + fh("c", fileC, zip.Store), + }, + }, + { + name: "symlinks in zip", + args: fileArgsBuilder(). + File("a/a/a"). + File("a/a/b"). + File("a/a/c"). + File("a/a/d"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("a/a/a", fileA, zip.Deflate), + fh("a/a/b", fileB, zip.Deflate), + fhLink("a/a/c", "../../c"), + fhLink("a/a/d", "b"), + }, + }, + { + name: "list", + args: fileArgsBuilder(). + List("l"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("a/a/a", fileA, zip.Deflate), + fh("a/a/b", fileB, zip.Deflate), + fh("c", fileC, zip.Deflate), + }, + }, + { + name: "prefix in zip", + args: fileArgsBuilder(). + PathPrefixInZip("foo"). + File("a/a/a"). + File("a/a/b"). + File("c"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("foo/a/a/a", fileA, zip.Deflate), + fh("foo/a/a/b", fileB, zip.Deflate), + fh("foo/c", fileC, zip.Deflate), + }, + }, + { + name: "relative root", + args: fileArgsBuilder(). + SourcePrefixToStrip("a"). + File("a/a/a"). + File("a/a/b"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("a/a", fileA, zip.Deflate), + fh("a/b", fileB, zip.Deflate), + }, + }, + { + name: "multiple relative root", + args: fileArgsBuilder(). + SourcePrefixToStrip("a"). + File("a/a/a"). + SourcePrefixToStrip("a/a"). + File("a/a/b"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("a/a", fileA, zip.Deflate), + fh("b", fileB, zip.Deflate), + }, + }, + { + name: "emulate jar", + args: fileArgsBuilder(). + File("a/a/a"). + File("a/a/b"), + compressionLevel: 9, + emulateJar: true, + + files: []zip.FileHeader{ + fhDir("META-INF/"), + fhManifest(fileManifest), + fhDir("a/"), + fhDir("a/a/"), + fh("a/a/a", fileA, zip.Deflate), + fh("a/a/b", fileB, zip.Deflate), + }, + }, + { + name: "emulate jar with manifest", + args: fileArgsBuilder(). + File("a/a/a"). + File("a/a/b"), + compressionLevel: 9, + emulateJar: true, + manifest: "manifest.txt", + + files: []zip.FileHeader{ + fhDir("META-INF/"), + fhManifest(customManifestAfter), + fhDir("a/"), + fhDir("a/a/"), + fh("a/a/a", fileA, zip.Deflate), + fh("a/a/b", fileB, zip.Deflate), + }, + }, + { + name: "dir entries", + args: fileArgsBuilder(). + File("a/a/a"). + File("a/a/b"), + compressionLevel: 9, + dirEntries: true, + + files: []zip.FileHeader{ + fhDir("a/"), + fhDir("a/a/"), + fh("a/a/a", fileA, zip.Deflate), + fh("a/a/b", fileB, zip.Deflate), + }, + }, + { + name: "junk paths", + args: fileArgsBuilder(). + JunkPaths(true). + File("a/a/a"). + File("a/a/b"), + compressionLevel: 9, + + files: []zip.FileHeader{ + fh("a", fileA, zip.Deflate), + fh("b", fileB, zip.Deflate), + }, + }, + { + name: "non deflated files", + args: fileArgsBuilder(). + File("a/a/a"). + File("a/a/b"), + compressionLevel: 9, + nonDeflatedFiles: map[string]bool{"a/a/a": true}, + + files: []zip.FileHeader{ + fh("a/a/a", fileA, zip.Store), + fh("a/a/b", fileB, zip.Deflate), + }, + }, + + // errors + { + name: "error missing file", + args: fileArgsBuilder(). + File("missing"), + err: os.ErrNotExist, + }, + { + name: "error missing file in list", + args: fileArgsBuilder(). + List("l2"), + err: os.ErrNotExist, + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + if test.args.Error() != nil { + t.Fatal(test.args.Error()) + } + + args := ZipArgs{} + args.FileArgs = test.args.FileArgs() + args.CompressionLevel = test.compressionLevel + args.EmulateJar = test.emulateJar + args.AddDirectoryEntriesToZip = test.dirEntries + args.NonDeflatedFiles = test.nonDeflatedFiles + args.ManifestSourcePath = test.manifest + args.Filesystem = mockFs + + buf := &bytes.Buffer{} + err := ZipTo(args, buf) + + if (err != nil) != (test.err != nil) { + t.Fatalf("want error %v, got %v", test.err, err) + } else if test.err != nil { + if os.IsNotExist(test.err) { + if !os.IsNotExist(test.err) { + t.Fatalf("want error %v, got %v", test.err, err) + } + } else { + t.Fatalf("want error %v, got %v", test.err, err) + } + return + } + + br := bytes.NewReader(buf.Bytes()) + zr, err := zip.NewReader(br, int64(br.Len())) + if err != nil { + t.Fatal(err) + } + + var files []zip.FileHeader + for _, f := range zr.File { + r, err := f.Open() + if err != nil { + t.Fatalf("error when opening %s: %s", f.Name, err) + } + + crc := crc32.NewIEEE() + len, err := io.Copy(crc, r) + r.Close() + if err != nil { + t.Fatalf("error when reading %s: %s", f.Name, err) + } + + if uint64(len) != f.UncompressedSize64 { + t.Errorf("incorrect length for %s, want %d got %d", f.Name, f.UncompressedSize64, len) + } + + if crc.Sum32() != f.CRC32 { + t.Errorf("incorrect crc for %s, want %x got %x", f.Name, f.CRC32, crc) + } + + files = append(files, f.FileHeader) + } + + if len(files) != len(test.files) { + t.Fatalf("want %d files, got %d", len(test.files), len(files)) + } + + for i := range files { + want := test.files[i] + got := files[i] + + if want.Name != got.Name { + t.Errorf("incorrect file %d want %q got %q", i, want.Name, got.Name) + continue + } + + if want.UncompressedSize64 != got.UncompressedSize64 { + t.Errorf("incorrect file %s length want %v got %v", want.Name, + want.UncompressedSize64, got.UncompressedSize64) + } + + if want.ExternalAttrs != got.ExternalAttrs { + t.Errorf("incorrect file %s attrs want %x got %x", want.Name, + want.ExternalAttrs, got.ExternalAttrs) + } + + if want.CRC32 != got.CRC32 { + t.Errorf("incorrect file %s crc want %v got %v", want.Name, + want.CRC32, got.CRC32) + } + + if want.Method != got.Method { + t.Errorf("incorrect file %s method want %v got %v", want.Name, + want.Method, got.Method) + } + } + }) + } +} + func TestReadRespFile(t *testing.T) { testCases := []struct { name, in string |