Browse code

Merge pull request #8063 from jlhawn/tarsum_empty_tar_archive

tarsum: correct close and finish reads

Vincent Batts authored on 2014/09/17 04:41:28
Showing 2 changed files
... ...
@@ -162,6 +162,12 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
162 162
 			currentHeader, err := ts.tarR.Next()
163 163
 			if err != nil {
164 164
 				if err == io.EOF {
165
+					if err := ts.tarW.Close(); err != nil {
166
+						return 0, err
167
+					}
168
+					if _, err := io.Copy(ts.gz, ts.bufTar); err != nil {
169
+						return 0, err
170
+					}
165 171
 					if err := ts.gz.Close(); err != nil {
166 172
 						return 0, err
167 173
 					}
... ...
@@ -2,7 +2,10 @@ package tarsum
2 2
 
3 3
 import (
4 4
 	"bytes"
5
+	"compress/gzip"
5 6
 	"crypto/rand"
7
+	"crypto/sha256"
8
+	"encoding/hex"
6 9
 	"fmt"
7 10
 	"io"
8 11
 	"io/ioutil"
... ...
@@ -113,6 +116,77 @@ func sizedTar(opts sizedOptions) io.Reader {
113 113
 	return fh
114 114
 }
115 115
 
116
+func emptyTarSum(gzip bool) (TarSum, error) {
117
+	reader, writer := io.Pipe()
118
+	tarWriter := tar.NewWriter(writer)
119
+
120
+	// Immediately close tarWriter and write-end of the
121
+	// Pipe in a separate goroutine so we don't block.
122
+	go func() {
123
+		tarWriter.Close()
124
+		writer.Close()
125
+	}()
126
+
127
+	return NewTarSum(reader, !gzip, Version0)
128
+}
129
+
130
+// TestEmptyTar tests that tarsum does not fail to read an empty tar
131
+// and correctly returns the hex digest of an empty hash.
132
+func TestEmptyTar(t *testing.T) {
133
+	// Test without gzip.
134
+	ts, err := emptyTarSum(false)
135
+	if err != nil {
136
+		t.Fatal(err)
137
+	}
138
+
139
+	zeroBlock := make([]byte, 1024)
140
+	buf := new(bytes.Buffer)
141
+
142
+	n, err := io.Copy(buf, ts)
143
+	if err != nil {
144
+		t.Fatal(err)
145
+	}
146
+
147
+	if n != int64(len(zeroBlock)) || !bytes.Equal(buf.Bytes(), zeroBlock) {
148
+		t.Fatalf("tarSum did not write the correct number of zeroed bytes: %d", n)
149
+	}
150
+
151
+	expectedSum := ts.Version().String() + "+sha256:" + hex.EncodeToString(sha256.New().Sum(nil))
152
+	resultSum := ts.Sum(nil)
153
+
154
+	if resultSum != expectedSum {
155
+		t.Fatalf("expected [%s] but got [%s]", expectedSum, resultSum)
156
+	}
157
+
158
+	// Test with gzip.
159
+	ts, err = emptyTarSum(true)
160
+	if err != nil {
161
+		t.Fatal(err)
162
+	}
163
+	buf.Reset()
164
+
165
+	n, err = io.Copy(buf, ts)
166
+	if err != nil {
167
+		t.Fatal(err)
168
+	}
169
+
170
+	bufgz := new(bytes.Buffer)
171
+	gz := gzip.NewWriter(bufgz)
172
+	n, err = io.Copy(gz, bytes.NewBuffer(zeroBlock))
173
+	gz.Close()
174
+	gzBytes := bufgz.Bytes()
175
+
176
+	if n != int64(len(zeroBlock)) || !bytes.Equal(buf.Bytes(), gzBytes) {
177
+		t.Fatalf("tarSum did not write the correct number of gzipped-zeroed bytes: %d", n)
178
+	}
179
+
180
+	resultSum = ts.Sum(nil)
181
+
182
+	if resultSum != expectedSum {
183
+		t.Fatalf("expected [%s] but got [%s]", expectedSum, resultSum)
184
+	}
185
+}
186
+
116 187
 func TestTarSums(t *testing.T) {
117 188
 	for _, layer := range testLayers {
118 189
 		var (