@@ -3,25 +3,24 @@ package archive
3
3
import (
4
4
"archive/tar"
5
5
"bytes"
6
- "compress/gzip"
7
6
"errors"
8
7
"fmt"
9
8
"io"
10
9
"io/fs"
11
10
"os"
12
11
"os/exec"
13
12
"path/filepath"
14
- "reflect"
15
13
"runtime"
16
14
"strings"
17
15
"testing"
18
- "time"
19
16
20
17
"github.com/moby/sys/user"
21
18
"github.com/moby/sys/userns"
22
19
"gotest.tools/v3/assert"
23
20
is "gotest.tools/v3/assert/cmp"
24
21
"gotest.tools/v3/skip"
22
+
23
+ "github.com/moby/go-archive/compression"
25
24
)
26
25
27
26
var defaultArchiver = NewDefaultArchiver ()
@@ -104,205 +103,6 @@ func TestIsArchivePathTar(t *testing.T) {
104
103
}
105
104
}
106
105
107
- func testDecompressStream (t * testing.T , ext , compressCommand string ) io.Reader {
108
- tmp := t .TempDir ()
109
- archivePath := toUnixPath (filepath .Join (tmp , "archive" ))
110
- cmd := exec .Command ("sh" , "-c" , fmt .Sprintf ("touch %[1]s && %[2]s %[1]s" , archivePath , compressCommand ))
111
- output , err := cmd .CombinedOutput ()
112
- if err != nil {
113
- t .Fatalf ("Failed to create archive file (%v):\n command: %s\n output: %s" , err , cmd .String (), output )
114
- }
115
- filename := "archive." + ext
116
- archive , err := os .Open (filepath .Join (tmp , filename ))
117
- if err != nil {
118
- t .Fatalf ("Failed to open file %s: %v" , filename , err )
119
- }
120
- defer archive .Close ()
121
-
122
- r , err := DecompressStream (archive )
123
- if err != nil {
124
- t .Fatalf ("Failed to decompress %s: %v" , filename , err )
125
- }
126
- if _ , err = io .ReadAll (r ); err != nil {
127
- t .Fatalf ("Failed to read the decompressed stream: %v " , err )
128
- }
129
- if err = r .Close (); err != nil {
130
- t .Fatalf ("Failed to close the decompressed stream: %v " , err )
131
- }
132
-
133
- return r
134
- }
135
-
136
- func TestDecompressStreamGzip (t * testing.T ) {
137
- testDecompressStream (t , "gz" , "gzip -f" )
138
- }
139
-
140
- func TestDecompressStreamBzip2 (t * testing.T ) {
141
- // TODO Windows: Failing with "bzip2.exe: Can't open input file (...)/archive: No such file or directory."
142
- if runtime .GOOS == "windows" {
143
- t .Skip ("Failing on Windows CI machines" )
144
- }
145
- testDecompressStream (t , "bz2" , "bzip2 -f" )
146
- }
147
-
148
- func TestDecompressStreamXz (t * testing.T ) {
149
- if runtime .GOOS == "windows" {
150
- t .Skip ("Xz not present in msys2" )
151
- }
152
- testDecompressStream (t , "xz" , "xz -f" )
153
- }
154
-
155
- func TestDecompressStreamZstd (t * testing.T ) {
156
- // TODO Windows: Failing with "zstd: can't stat (...)/archive : No such file or directory -- ignored"
157
- if runtime .GOOS == "windows" {
158
- t .Skip ("Failing on Windows CI machines" )
159
- }
160
- if _ , err := exec .LookPath ("zstd" ); err != nil {
161
- t .Skip ("zstd not installed" )
162
- }
163
- testDecompressStream (t , "zst" , "zstd -f" )
164
- }
165
-
166
- func TestCompressStreamXzUnsupported (t * testing.T ) {
167
- dest , err := os .Create (filepath .Join (t .TempDir (), "dest" ))
168
- if err != nil {
169
- t .Fatalf ("Fail to create the destination file" )
170
- }
171
- defer dest .Close ()
172
-
173
- _ , err = CompressStream (dest , Xz )
174
- if err == nil {
175
- t .Fatalf ("Should fail as xz is unsupported for compression format." )
176
- }
177
- }
178
-
179
- func TestCompressStreamBzip2Unsupported (t * testing.T ) {
180
- dest , err := os .Create (filepath .Join (t .TempDir (), "dest" ))
181
- if err != nil {
182
- t .Fatalf ("Fail to create the destination file" )
183
- }
184
- defer dest .Close ()
185
-
186
- _ , err = CompressStream (dest , Bzip2 )
187
- if err == nil {
188
- t .Fatalf ("Should fail as bzip2 is unsupported for compression format." )
189
- }
190
- }
191
-
192
- func TestCompressStreamInvalid (t * testing.T ) {
193
- dest , err := os .Create (filepath .Join (t .TempDir (), "dest" ))
194
- if err != nil {
195
- t .Fatalf ("Fail to create the destination file" )
196
- }
197
- defer dest .Close ()
198
-
199
- _ , err = CompressStream (dest , - 1 )
200
- if err == nil {
201
- t .Fatalf ("Should fail as xz is unsupported for compression format." )
202
- }
203
- }
204
-
205
- func TestExtensionInvalid (t * testing.T ) {
206
- compression := Compression (- 1 )
207
- output := compression .Extension ()
208
- if output != "" {
209
- t .Fatalf ("The extension of an invalid compression should be an empty string." )
210
- }
211
- }
212
-
213
- func TestExtensionUncompressed (t * testing.T ) {
214
- compression := Uncompressed
215
- output := compression .Extension ()
216
- if output != "tar" {
217
- t .Fatalf ("The extension of an uncompressed archive should be 'tar'." )
218
- }
219
- }
220
-
221
- func TestExtensionBzip2 (t * testing.T ) {
222
- compression := Bzip2
223
- output := compression .Extension ()
224
- if output != "tar.bz2" {
225
- t .Fatalf ("The extension of a bzip2 archive should be 'tar.bz2'" )
226
- }
227
- }
228
-
229
- func TestExtensionGzip (t * testing.T ) {
230
- compression := Gzip
231
- output := compression .Extension ()
232
- if output != "tar.gz" {
233
- t .Fatalf ("The extension of a gzip archive should be 'tar.gz'" )
234
- }
235
- }
236
-
237
- func TestExtensionXz (t * testing.T ) {
238
- compression := Xz
239
- output := compression .Extension ()
240
- if output != "tar.xz" {
241
- t .Fatalf ("The extension of a xz archive should be 'tar.xz'" )
242
- }
243
- }
244
-
245
- func TestExtensionZstd (t * testing.T ) {
246
- compression := Zstd
247
- output := compression .Extension ()
248
- if output != "tar.zst" {
249
- t .Fatalf ("The extension of a zstd archive should be 'tar.zst'" )
250
- }
251
- }
252
-
253
- func TestCmdStreamLargeStderr (t * testing.T ) {
254
- cmd := exec .Command ("sh" , "-c" , "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello" )
255
- out , err := cmdStream (cmd , nil )
256
- if err != nil {
257
- t .Fatalf ("Failed to start command: %s, output: %s" , err , out )
258
- }
259
- errCh := make (chan error , 1 )
260
- go func () {
261
- _ , err := io .Copy (io .Discard , out )
262
- errCh <- err
263
- }()
264
- select {
265
- case err := <- errCh :
266
- if err != nil {
267
- t .Fatalf ("Command should not have failed (err=%.100s...)" , err )
268
- }
269
- case <- time .After (5 * time .Second ):
270
- t .Fatalf ("Command did not complete in 5 seconds; probable deadlock" )
271
- }
272
- }
273
-
274
- func TestCmdStreamBad (t * testing.T ) {
275
- // TODO Windows: Figure out why this is failing in CI but not locally
276
- if runtime .GOOS == "windows" {
277
- t .Skip ("Failing on Windows CI machines" )
278
- }
279
- badCmd := exec .Command ("sh" , "-c" , "echo hello; echo >&2 error couldn\\ 't reverse the phase pulser; exit 1" )
280
- out , err := cmdStream (badCmd , nil )
281
- if err != nil {
282
- t .Fatalf ("Failed to start command: %s" , err )
283
- }
284
- if output , err := io .ReadAll (out ); err == nil {
285
- t .Fatalf ("Command should have failed" )
286
- } else if err .Error () != "exit status 1: error couldn't reverse the phase pulser\n " {
287
- t .Fatalf ("Wrong error value (%s)" , err )
288
- } else if s := string (output ); s != "hello\n " {
289
- t .Fatalf ("Command output should be '%s', not '%s'" , "hello\\ n" , output )
290
- }
291
- }
292
-
293
- func TestCmdStreamGood (t * testing.T ) {
294
- cmd := exec .Command ("sh" , "-c" , "echo hello; exit 0" )
295
- out , err := cmdStream (cmd , nil )
296
- if err != nil {
297
- t .Fatal (err )
298
- }
299
- if output , err := io .ReadAll (out ); err != nil {
300
- t .Fatalf ("Command should not have failed (err=%s)" , err )
301
- } else if s := string (output ); s != "hello\n " {
302
- t .Fatalf ("Command output should be '%s', not '%s'" , "hello\\ n" , output )
303
- }
304
- }
305
-
306
106
func TestUntarPathWithInvalidDest (t * testing.T ) {
307
107
tempFolder := t .TempDir ()
308
108
invalidDestFolder := filepath .Join (tempFolder , "invalidDest" )
@@ -649,7 +449,7 @@ func tarUntar(t *testing.T, origin string, options *TarOptions) ([]Change, error
649
449
}
650
450
wrap := io .MultiReader (bytes .NewReader (buf ), archive )
651
451
652
- detectedCompression := DetectCompression (buf )
452
+ detectedCompression := compression . Detect (buf )
653
453
expected := options .Compression
654
454
if detectedCompression .Extension () != expected .Extension () {
655
455
return nil , fmt .Errorf ("wrong compression detected; expected: %s, got: %s" , expected .Extension (), detectedCompression .Extension ())
@@ -666,34 +466,6 @@ func tarUntar(t *testing.T, origin string, options *TarOptions) ([]Change, error
666
466
return ChangesDirs (origin , tmp )
667
467
}
668
468
669
- func TestDetectCompressionZstd (t * testing.T ) {
670
- // test zstd compression without skippable frames.
671
- compressedData := []byte {
672
- 0x28 , 0xb5 , 0x2f , 0xfd , // magic number of Zstandard frame: 0xFD2FB528
673
- 0x04 , 0x00 , 0x31 , 0x00 , 0x00 , // frame header
674
- 0x64 , 0x6f , 0x63 , 0x6b , 0x65 , 0x72 , // data block "docker"
675
- 0x16 , 0x0e , 0x21 , 0xc3 , // content checksum
676
- }
677
- compression := DetectCompression (compressedData )
678
- if compression != Zstd {
679
- t .Fatal ("Unexpected compression" )
680
- }
681
- // test zstd compression with skippable frames.
682
- hex := []byte {
683
- 0x50 , 0x2a , 0x4d , 0x18 , // magic number of skippable frame: 0x184D2A50 to 0x184D2A5F
684
- 0x04 , 0x00 , 0x00 , 0x00 , // frame size
685
- 0x5d , 0x00 , 0x00 , 0x00 , // user data
686
- 0x28 , 0xb5 , 0x2f , 0xfd , // magic number of Zstandard frame: 0xFD2FB528
687
- 0x04 , 0x00 , 0x31 , 0x00 , 0x00 , // frame header
688
- 0x64 , 0x6f , 0x63 , 0x6b , 0x65 , 0x72 , // data block "docker"
689
- 0x16 , 0x0e , 0x21 , 0xc3 , // content checksum
690
- }
691
- compression = DetectCompression (hex )
692
- if compression != Zstd {
693
- t .Fatal ("Unexpected compression" )
694
- }
695
- }
696
-
697
469
func TestTarUntar (t * testing.T ) {
698
470
origin := t .TempDir ()
699
471
if err := os .WriteFile (filepath .Join (origin , "1" ), []byte ("hello world" ), 0o700 ); err != nil {
@@ -706,9 +478,9 @@ func TestTarUntar(t *testing.T) {
706
478
t .Fatal (err )
707
479
}
708
480
709
- for _ , c := range []Compression {
710
- Uncompressed ,
711
- Gzip ,
481
+ for _ , c := range []compression. Compression {
482
+ compression . None ,
483
+ compression . Gzip ,
712
484
} {
713
485
changes , err := tarUntar (t , origin , & TarOptions {
714
486
Compression : c ,
@@ -1352,39 +1124,6 @@ func readFileFromArchive(t *testing.T, archive io.ReadCloser, name string, expec
1352
1124
return string (content )
1353
1125
}
1354
1126
1355
- func TestDisablePigz (t * testing.T ) {
1356
- _ , err := exec .LookPath ("unpigz" )
1357
- if err != nil {
1358
- t .Log ("Test will not check full path when Pigz not installed" )
1359
- }
1360
-
1361
- t .Setenv ("MOBY_DISABLE_PIGZ" , "true" )
1362
-
1363
- r := testDecompressStream (t , "gz" , "gzip -f" )
1364
-
1365
- // wrapped in closer to cancel contex and release buffer to pool
1366
- wrapper := r .(* readCloserWrapper )
1367
-
1368
- assert .Equal (t , reflect .TypeOf (wrapper .Reader ), reflect .TypeOf (& gzip.Reader {}))
1369
- }
1370
-
1371
- func TestPigz (t * testing.T ) {
1372
- r := testDecompressStream (t , "gz" , "gzip -f" )
1373
- // wrapper for buffered reader and context cancel
1374
- wrapper := r .(* readCloserWrapper )
1375
-
1376
- _ , err := exec .LookPath ("unpigz" )
1377
- if err == nil {
1378
- t .Log ("Tested whether Pigz is used, as it installed" )
1379
- // For the command wait wrapper
1380
- cmdWaitCloserWrapper := wrapper .Reader .(* readCloserWrapper )
1381
- assert .Equal (t , reflect .TypeOf (cmdWaitCloserWrapper .Reader ), reflect .TypeOf (& io.PipeReader {}))
1382
- } else {
1383
- t .Log ("Tested whether Pigz is not used, as it not installed" )
1384
- assert .Equal (t , reflect .TypeOf (wrapper .Reader ), reflect .TypeOf (& gzip.Reader {}))
1385
- }
1386
- }
1387
-
1388
1127
func TestNosysFileInfo (t * testing.T ) {
1389
1128
st , err := os .Stat ("archive_test.go" )
1390
1129
assert .NilError (t , err )
0 commit comments