Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/zip/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 18 kB image not shown  

Quelle  zip_test.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2018 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 zip

import (
 "bytes"
 "encoding/hex"
 "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")

 sha256FileA = "d53eda7a637c99cc7fb566d96e9fa109bf15c478410a3f5eb4d4c4e26cd081f6"
 sha256FileB = "430c56c5818e62bcb6d478901ef86284e97714c138f3c86aa14fd6a84b7ce5d3"
 sha256FileC = "31c5ab6111f1d6aa13c2c4e92bb3c0f7c76b61b42d141af1e846eb7f6586a51c"

 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,
 "dangling -> missing": nil,
 "a/a/d -> b":          nil,
 "c":                   fileC,
 "d/a/a":               nil,
 "l_nl":                []byte("a/a/a\na/a/b\nc\n\\[\n"),
 "l_sp":                []byte("a/a/a a/a/b c \\["),
 "l2":                  []byte("missing\n"),
 "rsp":                 []byte("'a/a/a'\na/a/b\n'@'\n'foo'\\''bar'\n'['"),
 "@ -> c":              nil,
 "foo'bar -> c":        nil,
 "manifest.txt":        fileCustomManifest,
 "[":                   fileEmpty,
})

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:      (syscall.S_IFREG | 0644) << 16,
 }
}

func fhWithSHA256(name string, contents []byte, method uint16, sha256 string) zip.FileHeader {
 h := fh(name, contents, method)
 // The extra field contains 38 bytes, including 2 bytes of header ID, 2 bytes
 // of size, 2 bytes of signature, and 32 bytes of checksum data block.
 var extra [38]byte
 // The first 6 bytes contains Sha256HeaderID (0x4967), size (unit(34)) and
 // Sha256HeaderSignature (0x9514)
 copy(extra[0:], []byte{1037334020149})
 sha256Bytes, _ := hex.DecodeString(sha256)
 copy(extra[6:], sha256Bytes)
 h.Extra = append(h.Extra, extra[:]...)
 return h
}

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 | 0644) << 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,
 }
}

type fhDirOptions struct {
 extra []byte
}

func fhDir(name string, opts fhDirOptions) zip.FileHeader {
 return zip.FileHeader{
  Name:               name,
  Method:             zip.Store,
  CRC32:              crc32.ChecksumIEEE(nil),
  UncompressedSize64: 0,
  ExternalAttrs:      (syscall.S_IFDIR|0755)<<16 | 0x10,
  Extra:              opts.extra,
 }
}

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
  storeSymlinks      bool
  ignoreMissingFiles bool
  sha256Checksum     bool

  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").
    File(`\[`),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("[", fileEmpty, zip.Store),
    fh("a/a/a", fileA, zip.Deflate),
    fh("a/a/b", fileB, zip.Deflate),
    fh("c", fileC, zip.Deflate),
   },
  },
  {
   name: "files glob",
   args: fileArgsBuilder().
    SourcePrefixToStrip("a").
    File("a/**/*"),
   compressionLevel: 9,
   storeSymlinks:    true,

   files: []zip.FileHeader{
    fh("a/a", fileA, zip.Deflate),
    fh("a/b", fileB, zip.Deflate),
    fhLink("a/c", "../../c"),
    fhLink("a/d", "b"),
   },
  },
  {
   name: "dir",
   args: fileArgsBuilder().
    SourcePrefixToStrip("a").
    Dir("a"),
   compressionLevel: 9,
   storeSymlinks:    true,

   files: []zip.FileHeader{
    fh("a/a", fileA, zip.Deflate),
    fh("a/b", fileB, zip.Deflate),
    fhLink("a/c", "../../c"),
    fhLink("a/d", "b"),
   },
  },
  {
   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,
   storeSymlinks:    true,

   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: "follow symlinks",
   args: fileArgsBuilder().
    File("a/a/a").
    File("a/a/b").
    File("a/a/c").
    File("a/a/d"),
   compressionLevel: 9,
   storeSymlinks:    false,

   files: []zip.FileHeader{
    fh("a/a/a", fileA, zip.Deflate),
    fh("a/a/b", fileB, zip.Deflate),
    fh("a/a/c", fileC, zip.Deflate),
    fh("a/a/d", fileB, zip.Deflate),
   },
  },
  {
   name: "dangling symlinks",
   args: fileArgsBuilder().
    File("dangling"),
   compressionLevel: 9,
   storeSymlinks:    true,

   files: []zip.FileHeader{
    fhLink("dangling", "missing"),
   },
  },
  {
   name: "list",
   args: fileArgsBuilder().
    List("l_nl"),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("[", fileEmpty, zip.Store),
    fh("a/a/a", fileA, zip.Deflate),
    fh("a/a/b", fileB, zip.Deflate),
    fh("c", fileC, zip.Deflate),
   },
  },
  {
   name: "list",
   args: fileArgsBuilder().
    List("l_sp"),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("[", fileEmpty, zip.Store),
    fh("a/a/a", fileA, zip.Deflate),
    fh("a/a/b", fileB, zip.Deflate),
    fh("c", fileC, zip.Deflate),
   },
  },
  {
   name: "rsp",
   args: fileArgsBuilder().
    RspFile("rsp"),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("@", fileC, zip.Deflate),
    fh("[", fileEmpty, zip.Store),
    fh("a/a/a", fileA, zip.Deflate),
    fh("a/a/b", fileB, zip.Deflate),
    fh("foo'bar", 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/", fhDirOptions{extra: []byte{25420200}}),
    fhManifest(fileManifest),
    fhDir("a/", fhDirOptions{}),
    fhDir("a/a/", fhDirOptions{}),
    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/", fhDirOptions{extra: []byte{25420200}}),
    fhManifest(customManifestAfter),
    fhDir("a/", fhDirOptions{}),
    fhDir("a/a/", fhDirOptions{}),
    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/", fhDirOptions{}),
    fhDir("a/a/", fhDirOptions{}),
    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),
   },
  },
  {
   name: "ignore missing files",
   args: fileArgsBuilder().
    File("a/a/a").
    File("a/a/b").
    File("missing"),
   compressionLevel:   9,
   ignoreMissingFiles: true,

   files: []zip.FileHeader{
    fh("a/a/a", fileA, zip.Deflate),
    fh("a/a/b", fileB, zip.Deflate),
   },
  },
  {
   name: "duplicate sources",
   args: fileArgsBuilder().
    File("a/a/a").
    File("a/a/a"),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("a/a/a", fileA, zip.Deflate),
   },
  },
  {
   name: "generate SHA256 checksum",
   args: fileArgsBuilder().
    File("a/a/a").
    File("a/a/b").
    File("a/a/c").
    File("c"),
   compressionLevel: 9,
   sha256Checksum:   true,

   files: []zip.FileHeader{
    fhWithSHA256("a/a/a", fileA, zip.Deflate, sha256FileA),
    fhWithSHA256("a/a/b", fileB, zip.Deflate, sha256FileB),
    fhWithSHA256("a/a/c", fileC, zip.Deflate, sha256FileC),
    fhWithSHA256("c", fileC, zip.Deflate, sha256FileC),
   },
  },
  {
   name: "explicit path",
   args: fileArgsBuilder().
    ExplicitPathInZip("foo").
    File("a/a/a").
    File("a/a/b"),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("a/a/b", fileB, zip.Deflate),
    fh("foo", fileA, zip.Deflate),
   },
  },
  {
   name: "explicit path with prefix",
   args: fileArgsBuilder().
    PathPrefixInZip("prefix").
    ExplicitPathInZip("foo").
    File("a/a/a").
    File("a/a/b"),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("prefix/a/a/b", fileB, zip.Deflate),
    fh("prefix/foo", fileA, zip.Deflate),
   },
  },
  {
   name: "explicit path with glob",
   args: fileArgsBuilder().
    ExplicitPathInZip("foo").
    File("a/a/a*").
    File("a/a/b"),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("a/a/b", fileB, zip.Deflate),
    fh("foo", fileA, zip.Deflate),
   },
  },
  {
   name: "explicit path with junk paths",
   args: fileArgsBuilder().
    JunkPaths(true).
    ExplicitPathInZip("foo/bar").
    File("a/a/a*").
    File("a/a/b"),
   compressionLevel: 9,

   files: []zip.FileHeader{
    fh("b", fileB, zip.Deflate),
    fh("foo/bar", fileA, zip.Deflate),
   },
  },

  // errors
  {
   name: "error missing file",
   args: fileArgsBuilder().
    File("missing"),
   err: os.ErrNotExist,
  },
  {
   name: "error missing dir",
   args: fileArgsBuilder().
    Dir("missing"),
   err: os.ErrNotExist,
  },
  {
   name: "error missing file in list",
   args: fileArgsBuilder().
    List("l2"),
   err: os.ErrNotExist,
  },
  {
   name: "error incorrect relative root",
   args: fileArgsBuilder().
    SourcePrefixToStrip("b").
    File("a/a/a"),
   err: IncorrectRelativeRootError{},
  },
  {
   name: "error conflicting file",
   args: fileArgsBuilder().
    SourcePrefixToStrip("a").
    File("a/a/a").
    SourcePrefixToStrip("d").
    File("d/a/a"),
   err: ConflictingFileError{},
  },
  {
   name: "error explicit path conflicting",
   args: fileArgsBuilder().
    ExplicitPathInZip("foo").
    File("a/a/a").
    ExplicitPathInZip("foo").
    File("a/a/b"),
   err: ConflictingFileError{},
  },
  {
   name: "error explicit path conflicting glob",
   args: fileArgsBuilder().
    ExplicitPathInZip("foo").
    File("a/a/*"),
   err: ConflictingFileError{},
  },
 }

 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.StoreSymlinks = test.storeSymlinks
   args.IgnoreMissingFiles = test.ignoreMissingFiles
   args.Sha256Checksum = test.sha256Checksum
   args.Filesystem = mockFs
   args.Stderr = &bytes.Buffer{}

   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(err) {
      t.Fatalf("want error %v, got %v", test.err, err)
     }
    } else if _, wantRelativeRootErr := test.err.(IncorrectRelativeRootError); wantRelativeRootErr {
     if _, gotRelativeRootErr := err.(IncorrectRelativeRootError); !gotRelativeRootErr {
      t.Fatalf("want error %v, got %v", test.err, err)
     }
    } else if _, wantConflictingFileError := test.err.(ConflictingFileError); wantConflictingFileError {
     if _, gotConflictingFileError := err.(ConflictingFileError); !gotConflictingFileError {
      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)
    }

    if !bytes.Equal(want.Extra, got.Extra) {
     t.Errorf("incorrect file %s extra want %v got %v", want.Name,
      want.Extra, got.Extra)
    }
   }
  })
 }
}

func TestSrcJar(t *testing.T) {
 mockFs := pathtools.MockFs(map[string][]byte{
  "wrong_package.java":       []byte("package foo;"),
  "foo/correct_package.java": []byte("package foo;"),
  "src/no_package.java":      nil,
  "src2/parse_error.java":    []byte("error"),
 })

 want := []string{
  "foo/",
  "foo/correct_package.java",
  "foo/wrong_package.java",
  "no_package.java",
  "src2/",
  "src2/parse_error.java",
 }

 args := ZipArgs{}
 args.FileArgs = NewFileArgsBuilder().File("**/*.java").FileArgs()

 args.SrcJar = true
 args.AddDirectoryEntriesToZip = true
 args.Filesystem = mockFs
 args.Stderr = &bytes.Buffer{}

 buf := &bytes.Buffer{}
 err := zipTo(args, buf)
 if err != nil {
  t.Fatalf("got error %v", err)
 }

 br := bytes.NewReader(buf.Bytes())
 zr, err := zip.NewReader(br, int64(br.Len()))
 if err != nil {
  t.Fatal(err)
 }

 var got []string
 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)
  }

  got = append(got, f.Name)
 }

 if !reflect.DeepEqual(want, got) {
  t.Errorf("want files %q, got %q", want, got)
 }
}

[Dauer der Verarbeitung: 0.24 Sekunden, vorverarbeitet 2026-06-28]