@@ -3,25 +3,24 @@ package archive
33import (
44 "archive/tar"
55 "bytes"
6- "compress/gzip"
76 "errors"
87 "fmt"
98 "io"
109 "io/fs"
1110 "os"
1211 "os/exec"
1312 "path/filepath"
14- "reflect"
1513 "runtime"
1614 "strings"
1715 "testing"
18- "time"
1916
2017 "github.com/moby/sys/user"
2118 "github.com/moby/sys/userns"
2219 "gotest.tools/v3/assert"
2320 is "gotest.tools/v3/assert/cmp"
2421 "gotest.tools/v3/skip"
22+
23+ "github.com/moby/go-archive/compression"
2524)
2625
2726var defaultArchiver = NewDefaultArchiver ()
@@ -104,205 +103,6 @@ func TestIsArchivePathTar(t *testing.T) {
104103 }
105104}
106105
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-
306106func TestUntarPathWithInvalidDest (t * testing.T ) {
307107 tempFolder := t .TempDir ()
308108 invalidDestFolder := filepath .Join (tempFolder , "invalidDest" )
@@ -649,7 +449,7 @@ func tarUntar(t *testing.T, origin string, options *TarOptions) ([]Change, error
649449 }
650450 wrap := io .MultiReader (bytes .NewReader (buf ), archive )
651451
652- detectedCompression := DetectCompression (buf )
452+ detectedCompression := compression . Detect (buf )
653453 expected := options .Compression
654454 if detectedCompression .Extension () != expected .Extension () {
655455 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
666466 return ChangesDirs (origin , tmp )
667467}
668468
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-
697469func TestTarUntar (t * testing.T ) {
698470 origin := t .TempDir ()
699471 if err := os .WriteFile (filepath .Join (origin , "1" ), []byte ("hello world" ), 0o700 ); err != nil {
@@ -706,9 +478,9 @@ func TestTarUntar(t *testing.T) {
706478 t .Fatal (err )
707479 }
708480
709- for _ , c := range []Compression {
710- Uncompressed ,
711- Gzip ,
481+ for _ , c := range []compression. Compression {
482+ compression . None ,
483+ compression . Gzip ,
712484 } {
713485 changes , err := tarUntar (t , origin , & TarOptions {
714486 Compression : c ,
@@ -1352,39 +1124,6 @@ func readFileFromArchive(t *testing.T, archive io.ReadCloser, name string, expec
13521124 return string (content )
13531125}
13541126
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-
13881127func TestNosysFileInfo (t * testing.T ) {
13891128 st , err := os .Stat ("archive_test.go" )
13901129 assert .NilError (t , err )
0 commit comments