123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- package utils
- import (
- "bytes"
- "crypto/rand"
- "fmt"
- "github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
- "io"
- "io/ioutil"
- "os"
- "testing"
- )
- type testLayer struct {
- filename string
- options *sizedOptions
- jsonfile string
- gzip bool
- tarsum string
- }
- var testLayers = []testLayer{
- {
- filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
- jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
- tarsum: "tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b"},
- {
- filename: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar",
- jsonfile: "testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/json",
- gzip: true,
- tarsum: "tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b"},
- {
- filename: "testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar",
- jsonfile: "testdata/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json",
- tarsum: "tarsum+sha256:ac672ee85da9ab7f9667ae3c32841d3e42f33cc52c273c23341dabba1c8b0c8b"},
- {
- options: &sizedOptions{1, 1024 * 1024, false, false}, // a 1mb file (in memory)
- tarsum: "tarsum+sha256:8bf12d7e67c51ee2e8306cba569398b1b9f419969521a12ffb9d8875e8836738"},
- }
- type sizedOptions struct {
- num int64
- size int64
- isRand bool
- realFile bool
- }
- // make a tar:
- // * num is the number of files the tar should have
- // * size is the bytes per file
- // * isRand is whether the contents of the files should be a random chunk (otherwise it's all zeros)
- // * realFile will write to a TempFile, instead of an in memory buffer
- func sizedTar(opts sizedOptions) io.Reader {
- var (
- fh io.ReadWriter
- err error
- )
- if opts.realFile {
- fh, err = ioutil.TempFile("", "tarsum")
- if err != nil {
- return nil
- }
- } else {
- fh = bytes.NewBuffer([]byte{})
- }
- tarW := tar.NewWriter(fh)
- for i := int64(0); i < opts.num; i++ {
- err := tarW.WriteHeader(&tar.Header{
- Name: fmt.Sprintf("/testdata%d", i),
- Mode: 0755,
- Uid: 0,
- Gid: 0,
- Size: opts.size,
- })
- if err != nil {
- return nil
- }
- var rBuf []byte
- if opts.isRand {
- rBuf = make([]byte, 8)
- _, err = rand.Read(rBuf)
- if err != nil {
- return nil
- }
- } else {
- rBuf = []byte{0, 0, 0, 0, 0, 0, 0, 0}
- }
- for i := int64(0); i < opts.size/int64(8); i++ {
- tarW.Write(rBuf)
- }
- }
- return fh
- }
- func TestTarSums(t *testing.T) {
- for _, layer := range testLayers {
- var (
- fh io.Reader
- err error
- )
- if len(layer.filename) > 0 {
- fh, err = os.Open(layer.filename)
- if err != nil {
- t.Errorf("failed to open %s: %s", layer.filename, err)
- continue
- }
- } else if layer.options != nil {
- fh = sizedTar(*layer.options)
- } else {
- // What else is there to test?
- t.Errorf("what to do with %#V", layer)
- continue
- }
- if file, ok := fh.(*os.File); ok {
- defer file.Close()
- }
- // double negatives!
- ts := &TarSum{Reader: fh, DisableCompression: !layer.gzip}
- _, err = io.Copy(ioutil.Discard, ts)
- if err != nil {
- t.Errorf("failed to copy from %s: %s", layer.filename, err)
- continue
- }
- var gotSum string
- if len(layer.jsonfile) > 0 {
- jfh, err := os.Open(layer.jsonfile)
- if err != nil {
- t.Errorf("failed to open %s: %s", layer.jsonfile, err)
- continue
- }
- buf, err := ioutil.ReadAll(jfh)
- if err != nil {
- t.Errorf("failed to readAll %s: %s", layer.jsonfile, err)
- continue
- }
- gotSum = ts.Sum(buf)
- } else {
- gotSum = ts.Sum(nil)
- }
- if layer.tarsum != gotSum {
- t.Errorf("expecting [%s], but got [%s]", layer.tarsum, gotSum)
- }
- }
- }
- func Benchmark9kTar(b *testing.B) {
- buf := bytes.NewBuffer([]byte{})
- fh, err := os.Open("testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar")
- if err != nil {
- b.Error(err)
- return
- }
- n, err := io.Copy(buf, fh)
- fh.Close()
- b.SetBytes(n)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- ts := &TarSum{Reader: buf, DisableCompression: true}
- io.Copy(ioutil.Discard, ts)
- ts.Sum(nil)
- }
- }
- func Benchmark9kTarGzip(b *testing.B) {
- buf := bytes.NewBuffer([]byte{})
- fh, err := os.Open("testdata/46af0962ab5afeb5ce6740d4d91652e69206fc991fd5328c1a94d364ad00e457/layer.tar")
- if err != nil {
- b.Error(err)
- return
- }
- n, err := io.Copy(buf, fh)
- fh.Close()
- b.SetBytes(n)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- ts := &TarSum{Reader: buf, DisableCompression: false}
- io.Copy(ioutil.Discard, ts)
- ts.Sum(nil)
- }
- }
- // this is a single big file in the tar archive
- func Benchmark1mbSingleFileTar(b *testing.B) {
- benchmarkTar(b, sizedOptions{1, 1024 * 1024, true, true}, false)
- }
- // this is a single big file in the tar archive
- func Benchmark1mbSingleFileTarGzip(b *testing.B) {
- benchmarkTar(b, sizedOptions{1, 1024 * 1024, true, true}, true)
- }
- // this is 1024 1k files in the tar archive
- func Benchmark1kFilesTar(b *testing.B) {
- benchmarkTar(b, sizedOptions{1024, 1024, true, true}, false)
- }
- // this is 1024 1k files in the tar archive
- func Benchmark1kFilesTarGzip(b *testing.B) {
- benchmarkTar(b, sizedOptions{1024, 1024, true, true}, true)
- }
- func benchmarkTar(b *testing.B, opts sizedOptions, isGzip bool) {
- var fh *os.File
- tarReader := sizedTar(opts)
- if br, ok := tarReader.(*os.File); ok {
- fh = br
- }
- defer os.Remove(fh.Name())
- defer fh.Close()
- b.SetBytes(opts.size * opts.num)
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- ts := &TarSum{Reader: fh, DisableCompression: !isGzip}
- io.Copy(ioutil.Discard, ts)
- ts.Sum(nil)
- fh.Seek(0, 0)
- }
- }
|