From 96721b293c0923adbada3585083d1fae9eb602cc Mon Sep 17 00:00:00 2001 From: Josh Hawn Date: Mon, 15 Sep 2014 23:52:06 -0700 Subject: [PATCH] Correct tarsum finish logic Tarsum now correctly closes the internal TarWriter which appends a block of 1024 zeros to the end of the returned archive. Signed-off-by: Josh Hawn --- tarsum/tarsum.go | 6 ++++ tarsum/tarsum_test.go | 74 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/tarsum/tarsum.go b/tarsum/tarsum.go index 1399dd5..14f32b0 100644 --- a/tarsum/tarsum.go +++ b/tarsum/tarsum.go @@ -148,6 +148,12 @@ func (ts *tarSum) Read(buf []byte) (int, error) { currentHeader, err := ts.tarR.Next() if err != nil { if err == io.EOF { + if err := ts.tarW.Close(); err != nil { + return 0, err + } + if _, err := io.Copy(ts.gz, ts.bufTar); err != nil { + return 0, err + } if err := ts.gz.Close(); err != nil { return 0, err } diff --git a/tarsum/tarsum_test.go b/tarsum/tarsum_test.go index b921ad2..60d3aca 100644 --- a/tarsum/tarsum_test.go +++ b/tarsum/tarsum_test.go @@ -2,7 +2,10 @@ package tarsum import ( "bytes" + "compress/gzip" "crypto/rand" + "crypto/sha256" + "encoding/hex" "fmt" "io" "io/ioutil" @@ -101,6 +104,77 @@ func sizedTar(opts sizedOptions) io.Reader { return fh } +func emptyTarSum(gzip bool) (TarSum, error) { + reader, writer := io.Pipe() + tarWriter := tar.NewWriter(writer) + + // Immediately close tarWriter and write-end of the + // Pipe in a separate goroutine so we don't block. + go func() { + tarWriter.Close() + writer.Close() + }() + + return NewTarSum(reader, !gzip, Version0) +} + +// TestEmptyTar tests that tarsum does not fail to read an empty tar +// and correctly returns the hex digest of an empty hash. +func TestEmptyTar(t *testing.T) { + // Test without gzip. + ts, err := emptyTarSum(false) + if err != nil { + t.Fatal(err) + } + + zeroBlock := make([]byte, 1024) + buf := new(bytes.Buffer) + + n, err := io.Copy(buf, ts) + if err != nil { + t.Fatal(err) + } + + if n != int64(len(zeroBlock)) || !bytes.Equal(buf.Bytes(), zeroBlock) { + t.Fatalf("tarSum did not write the correct number of zeroed bytes: %d", n) + } + + expectedSum := ts.Version().String() + "+sha256:" + hex.EncodeToString(sha256.New().Sum(nil)) + resultSum := ts.Sum(nil) + + if resultSum != expectedSum { + t.Fatalf("expected [%s] but got [%s]", expectedSum, resultSum) + } + + // Test with gzip. + ts, err = emptyTarSum(true) + if err != nil { + t.Fatal(err) + } + buf.Reset() + + n, err = io.Copy(buf, ts) + if err != nil { + t.Fatal(err) + } + + bufgz := new(bytes.Buffer) + gz := gzip.NewWriter(bufgz) + n, err = io.Copy(gz, bytes.NewBuffer(zeroBlock)) + gz.Close() + gzBytes := bufgz.Bytes() + + if n != int64(len(zeroBlock)) || !bytes.Equal(buf.Bytes(), gzBytes) { + t.Fatalf("tarSum did not write the correct number of gzipped-zeroed bytes: %d", n) + } + + resultSum = ts.Sum(nil) + + if resultSum != expectedSum { + t.Fatalf("expected [%s] but got [%s]", expectedSum, resultSum) + } +} + func TestTarSums(t *testing.T) { for _, layer := range testLayers { var (