mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	to cover a couple of use-cases: * 1mb file, using no compression * 1mb file, using compression * 1024 1k files, using no compression * 1024 1k files, using compression Docker-DCO-1.1-Signed-off-by: Vincent Batts <vbatts@redhat.com> (github: vbatts)
		
			
				
	
	
		
			224 lines
		
	
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
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)
 | 
						|
	}
 | 
						|
}
 |