github.com/rhatdan/docker@v0.7.7-0.20180119204836-47a0dcbcd20a/pkg/archive/archive_test.go (about) 1 package archive 2 3 import ( 4 "archive/tar" 5 "bytes" 6 "compress/gzip" 7 "fmt" 8 "io" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "testing" 16 "time" 17 18 "github.com/docker/docker/pkg/idtools" 19 "github.com/docker/docker/pkg/ioutils" 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 ) 23 24 var tmp string 25 26 func init() { 27 tmp = "/tmp/" 28 if runtime.GOOS == "windows" { 29 tmp = os.Getenv("TEMP") + `\` 30 } 31 } 32 33 var defaultArchiver = NewDefaultArchiver() 34 35 func defaultTarUntar(src, dst string) error { 36 return defaultArchiver.TarUntar(src, dst) 37 } 38 39 func defaultUntarPath(src, dst string) error { 40 return defaultArchiver.UntarPath(src, dst) 41 } 42 43 func defaultCopyFileWithTar(src, dst string) (err error) { 44 return defaultArchiver.CopyFileWithTar(src, dst) 45 } 46 47 func defaultCopyWithTar(src, dst string) error { 48 return defaultArchiver.CopyWithTar(src, dst) 49 } 50 51 func TestIsArchivePathDir(t *testing.T) { 52 cmd := exec.Command("sh", "-c", "mkdir -p /tmp/archivedir") 53 output, err := cmd.CombinedOutput() 54 if err != nil { 55 t.Fatalf("Fail to create an archive file for test : %s.", output) 56 } 57 if IsArchivePath(tmp + "archivedir") { 58 t.Fatalf("Incorrectly recognised directory as an archive") 59 } 60 } 61 62 func TestIsArchivePathInvalidFile(t *testing.T) { 63 cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1024 count=1 of=/tmp/archive && gzip --stdout /tmp/archive > /tmp/archive.gz") 64 output, err := cmd.CombinedOutput() 65 if err != nil { 66 t.Fatalf("Fail to create an archive file for test : %s.", output) 67 } 68 if IsArchivePath(tmp + "archive") { 69 t.Fatalf("Incorrectly recognised invalid tar path as archive") 70 } 71 if IsArchivePath(tmp + "archive.gz") { 72 t.Fatalf("Incorrectly recognised invalid compressed tar path as archive") 73 } 74 } 75 76 func TestIsArchivePathTar(t *testing.T) { 77 whichTar := "tar" 78 cmdStr := fmt.Sprintf("touch /tmp/archivedata && %s -cf /tmp/archive /tmp/archivedata && gzip --stdout /tmp/archive > /tmp/archive.gz", whichTar) 79 cmd := exec.Command("sh", "-c", cmdStr) 80 output, err := cmd.CombinedOutput() 81 if err != nil { 82 t.Fatalf("Fail to create an archive file for test : %s.", output) 83 } 84 if !IsArchivePath(tmp + "/archive") { 85 t.Fatalf("Did not recognise valid tar path as archive") 86 } 87 if !IsArchivePath(tmp + "archive.gz") { 88 t.Fatalf("Did not recognise valid compressed tar path as archive") 89 } 90 } 91 92 func testDecompressStream(t *testing.T, ext, compressCommand string) io.Reader { 93 cmd := exec.Command("sh", "-c", 94 fmt.Sprintf("touch /tmp/archive && %s /tmp/archive", compressCommand)) 95 output, err := cmd.CombinedOutput() 96 if err != nil { 97 t.Fatalf("Failed to create an archive file for test : %s.", output) 98 } 99 filename := "archive." + ext 100 archive, err := os.Open(tmp + filename) 101 if err != nil { 102 t.Fatalf("Failed to open file %s: %v", filename, err) 103 } 104 defer archive.Close() 105 106 r, err := DecompressStream(archive) 107 if err != nil { 108 t.Fatalf("Failed to decompress %s: %v", filename, err) 109 } 110 if _, err = ioutil.ReadAll(r); err != nil { 111 t.Fatalf("Failed to read the decompressed stream: %v ", err) 112 } 113 if err = r.Close(); err != nil { 114 t.Fatalf("Failed to close the decompressed stream: %v ", err) 115 } 116 117 return r 118 } 119 120 func TestDecompressStreamGzip(t *testing.T) { 121 testDecompressStream(t, "gz", "gzip -f") 122 } 123 124 func TestDecompressStreamBzip2(t *testing.T) { 125 testDecompressStream(t, "bz2", "bzip2 -f") 126 } 127 128 func TestDecompressStreamXz(t *testing.T) { 129 if runtime.GOOS == "windows" { 130 t.Skip("Xz not present in msys2") 131 } 132 testDecompressStream(t, "xz", "xz -f") 133 } 134 135 func TestCompressStreamXzUnsupported(t *testing.T) { 136 dest, err := os.Create(tmp + "dest") 137 if err != nil { 138 t.Fatalf("Fail to create the destination file") 139 } 140 defer dest.Close() 141 142 _, err = CompressStream(dest, Xz) 143 if err == nil { 144 t.Fatalf("Should fail as xz is unsupported for compression format.") 145 } 146 } 147 148 func TestCompressStreamBzip2Unsupported(t *testing.T) { 149 dest, err := os.Create(tmp + "dest") 150 if err != nil { 151 t.Fatalf("Fail to create the destination file") 152 } 153 defer dest.Close() 154 155 _, err = CompressStream(dest, Xz) 156 if err == nil { 157 t.Fatalf("Should fail as xz is unsupported for compression format.") 158 } 159 } 160 161 func TestCompressStreamInvalid(t *testing.T) { 162 dest, err := os.Create(tmp + "dest") 163 if err != nil { 164 t.Fatalf("Fail to create the destination file") 165 } 166 defer dest.Close() 167 168 _, err = CompressStream(dest, -1) 169 if err == nil { 170 t.Fatalf("Should fail as xz is unsupported for compression format.") 171 } 172 } 173 174 func TestExtensionInvalid(t *testing.T) { 175 compression := Compression(-1) 176 output := compression.Extension() 177 if output != "" { 178 t.Fatalf("The extension of an invalid compression should be an empty string.") 179 } 180 } 181 182 func TestExtensionUncompressed(t *testing.T) { 183 compression := Uncompressed 184 output := compression.Extension() 185 if output != "tar" { 186 t.Fatalf("The extension of an uncompressed archive should be 'tar'.") 187 } 188 } 189 func TestExtensionBzip2(t *testing.T) { 190 compression := Bzip2 191 output := compression.Extension() 192 if output != "tar.bz2" { 193 t.Fatalf("The extension of a bzip2 archive should be 'tar.bz2'") 194 } 195 } 196 func TestExtensionGzip(t *testing.T) { 197 compression := Gzip 198 output := compression.Extension() 199 if output != "tar.gz" { 200 t.Fatalf("The extension of a bzip2 archive should be 'tar.gz'") 201 } 202 } 203 func TestExtensionXz(t *testing.T) { 204 compression := Xz 205 output := compression.Extension() 206 if output != "tar.xz" { 207 t.Fatalf("The extension of a bzip2 archive should be 'tar.xz'") 208 } 209 } 210 211 func TestCmdStreamLargeStderr(t *testing.T) { 212 cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello") 213 out, err := cmdStream(cmd, nil) 214 if err != nil { 215 t.Fatalf("Failed to start command: %s", err) 216 } 217 errCh := make(chan error) 218 go func() { 219 _, err := io.Copy(ioutil.Discard, out) 220 errCh <- err 221 }() 222 select { 223 case err := <-errCh: 224 if err != nil { 225 t.Fatalf("Command should not have failed (err=%.100s...)", err) 226 } 227 case <-time.After(5 * time.Second): 228 t.Fatalf("Command did not complete in 5 seconds; probable deadlock") 229 } 230 } 231 232 func TestCmdStreamBad(t *testing.T) { 233 // TODO Windows: Figure out why this is failing in CI but not locally 234 if runtime.GOOS == "windows" { 235 t.Skip("Failing on Windows CI machines") 236 } 237 badCmd := exec.Command("sh", "-c", "echo hello; echo >&2 error couldn\\'t reverse the phase pulser; exit 1") 238 out, err := cmdStream(badCmd, nil) 239 if err != nil { 240 t.Fatalf("Failed to start command: %s", err) 241 } 242 if output, err := ioutil.ReadAll(out); err == nil { 243 t.Fatalf("Command should have failed") 244 } else if err.Error() != "exit status 1: error couldn't reverse the phase pulser\n" { 245 t.Fatalf("Wrong error value (%s)", err) 246 } else if s := string(output); s != "hello\n" { 247 t.Fatalf("Command output should be '%s', not '%s'", "hello\\n", output) 248 } 249 } 250 251 func TestCmdStreamGood(t *testing.T) { 252 cmd := exec.Command("sh", "-c", "echo hello; exit 0") 253 out, err := cmdStream(cmd, nil) 254 if err != nil { 255 t.Fatal(err) 256 } 257 if output, err := ioutil.ReadAll(out); err != nil { 258 t.Fatalf("Command should not have failed (err=%s)", err) 259 } else if s := string(output); s != "hello\n" { 260 t.Fatalf("Command output should be '%s', not '%s'", "hello\\n", output) 261 } 262 } 263 264 func TestUntarPathWithInvalidDest(t *testing.T) { 265 tempFolder, err := ioutil.TempDir("", "docker-archive-test") 266 require.NoError(t, err) 267 defer os.RemoveAll(tempFolder) 268 invalidDestFolder := filepath.Join(tempFolder, "invalidDest") 269 // Create a src file 270 srcFile := filepath.Join(tempFolder, "src") 271 tarFile := filepath.Join(tempFolder, "src.tar") 272 os.Create(srcFile) 273 os.Create(invalidDestFolder) // being a file (not dir) should cause an error 274 275 // Translate back to Unix semantics as next exec.Command is run under sh 276 srcFileU := srcFile 277 tarFileU := tarFile 278 if runtime.GOOS == "windows" { 279 tarFileU = "/tmp/" + filepath.Base(filepath.Dir(tarFile)) + "/src.tar" 280 srcFileU = "/tmp/" + filepath.Base(filepath.Dir(srcFile)) + "/src" 281 } 282 283 cmd := exec.Command("sh", "-c", "tar cf "+tarFileU+" "+srcFileU) 284 _, err = cmd.CombinedOutput() 285 require.NoError(t, err) 286 287 err = defaultUntarPath(tarFile, invalidDestFolder) 288 if err == nil { 289 t.Fatalf("UntarPath with invalid destination path should throw an error.") 290 } 291 } 292 293 func TestUntarPathWithInvalidSrc(t *testing.T) { 294 dest, err := ioutil.TempDir("", "docker-archive-test") 295 if err != nil { 296 t.Fatalf("Fail to create the destination file") 297 } 298 defer os.RemoveAll(dest) 299 err = defaultUntarPath("/invalid/path", dest) 300 if err == nil { 301 t.Fatalf("UntarPath with invalid src path should throw an error.") 302 } 303 } 304 305 func TestUntarPath(t *testing.T) { 306 tmpFolder, err := ioutil.TempDir("", "docker-archive-test") 307 require.NoError(t, err) 308 defer os.RemoveAll(tmpFolder) 309 srcFile := filepath.Join(tmpFolder, "src") 310 tarFile := filepath.Join(tmpFolder, "src.tar") 311 os.Create(filepath.Join(tmpFolder, "src")) 312 313 destFolder := filepath.Join(tmpFolder, "dest") 314 err = os.MkdirAll(destFolder, 0740) 315 if err != nil { 316 t.Fatalf("Fail to create the destination file") 317 } 318 319 // Translate back to Unix semantics as next exec.Command is run under sh 320 srcFileU := srcFile 321 tarFileU := tarFile 322 if runtime.GOOS == "windows" { 323 tarFileU = "/tmp/" + filepath.Base(filepath.Dir(tarFile)) + "/src.tar" 324 srcFileU = "/tmp/" + filepath.Base(filepath.Dir(srcFile)) + "/src" 325 } 326 cmd := exec.Command("sh", "-c", "tar cf "+tarFileU+" "+srcFileU) 327 _, err = cmd.CombinedOutput() 328 require.NoError(t, err) 329 330 err = defaultUntarPath(tarFile, destFolder) 331 if err != nil { 332 t.Fatalf("UntarPath shouldn't throw an error, %s.", err) 333 } 334 expectedFile := filepath.Join(destFolder, srcFileU) 335 _, err = os.Stat(expectedFile) 336 if err != nil { 337 t.Fatalf("Destination folder should contain the source file but did not.") 338 } 339 } 340 341 // Do the same test as above but with the destination as file, it should fail 342 func TestUntarPathWithDestinationFile(t *testing.T) { 343 tmpFolder, err := ioutil.TempDir("", "docker-archive-test") 344 if err != nil { 345 t.Fatal(err) 346 } 347 defer os.RemoveAll(tmpFolder) 348 srcFile := filepath.Join(tmpFolder, "src") 349 tarFile := filepath.Join(tmpFolder, "src.tar") 350 os.Create(filepath.Join(tmpFolder, "src")) 351 352 // Translate back to Unix semantics as next exec.Command is run under sh 353 srcFileU := srcFile 354 tarFileU := tarFile 355 if runtime.GOOS == "windows" { 356 tarFileU = "/tmp/" + filepath.Base(filepath.Dir(tarFile)) + "/src.tar" 357 srcFileU = "/tmp/" + filepath.Base(filepath.Dir(srcFile)) + "/src" 358 } 359 cmd := exec.Command("sh", "-c", "tar cf "+tarFileU+" "+srcFileU) 360 _, err = cmd.CombinedOutput() 361 if err != nil { 362 t.Fatal(err) 363 } 364 destFile := filepath.Join(tmpFolder, "dest") 365 _, err = os.Create(destFile) 366 if err != nil { 367 t.Fatalf("Fail to create the destination file") 368 } 369 err = defaultUntarPath(tarFile, destFile) 370 if err == nil { 371 t.Fatalf("UntarPath should throw an error if the destination if a file") 372 } 373 } 374 375 // Do the same test as above but with the destination folder already exists 376 // and the destination file is a directory 377 // It's working, see https://github.com/docker/docker/issues/10040 378 func TestUntarPathWithDestinationSrcFileAsFolder(t *testing.T) { 379 tmpFolder, err := ioutil.TempDir("", "docker-archive-test") 380 if err != nil { 381 t.Fatal(err) 382 } 383 defer os.RemoveAll(tmpFolder) 384 srcFile := filepath.Join(tmpFolder, "src") 385 tarFile := filepath.Join(tmpFolder, "src.tar") 386 os.Create(srcFile) 387 388 // Translate back to Unix semantics as next exec.Command is run under sh 389 srcFileU := srcFile 390 tarFileU := tarFile 391 if runtime.GOOS == "windows" { 392 tarFileU = "/tmp/" + filepath.Base(filepath.Dir(tarFile)) + "/src.tar" 393 srcFileU = "/tmp/" + filepath.Base(filepath.Dir(srcFile)) + "/src" 394 } 395 396 cmd := exec.Command("sh", "-c", "tar cf "+tarFileU+" "+srcFileU) 397 _, err = cmd.CombinedOutput() 398 if err != nil { 399 t.Fatal(err) 400 } 401 destFolder := filepath.Join(tmpFolder, "dest") 402 err = os.MkdirAll(destFolder, 0740) 403 if err != nil { 404 t.Fatalf("Fail to create the destination folder") 405 } 406 // Let's create a folder that will has the same path as the extracted file (from tar) 407 destSrcFileAsFolder := filepath.Join(destFolder, srcFileU) 408 err = os.MkdirAll(destSrcFileAsFolder, 0740) 409 if err != nil { 410 t.Fatal(err) 411 } 412 err = defaultUntarPath(tarFile, destFolder) 413 if err != nil { 414 t.Fatalf("UntarPath should throw not throw an error if the extracted file already exists and is a folder") 415 } 416 } 417 418 func TestCopyWithTarInvalidSrc(t *testing.T) { 419 tempFolder, err := ioutil.TempDir("", "docker-archive-test") 420 if err != nil { 421 t.Fatal(nil) 422 } 423 destFolder := filepath.Join(tempFolder, "dest") 424 invalidSrc := filepath.Join(tempFolder, "doesnotexists") 425 err = os.MkdirAll(destFolder, 0740) 426 if err != nil { 427 t.Fatal(err) 428 } 429 err = defaultCopyWithTar(invalidSrc, destFolder) 430 if err == nil { 431 t.Fatalf("archiver.CopyWithTar with invalid src path should throw an error.") 432 } 433 } 434 435 func TestCopyWithTarInexistentDestWillCreateIt(t *testing.T) { 436 tempFolder, err := ioutil.TempDir("", "docker-archive-test") 437 if err != nil { 438 t.Fatal(nil) 439 } 440 srcFolder := filepath.Join(tempFolder, "src") 441 inexistentDestFolder := filepath.Join(tempFolder, "doesnotexists") 442 err = os.MkdirAll(srcFolder, 0740) 443 if err != nil { 444 t.Fatal(err) 445 } 446 err = defaultCopyWithTar(srcFolder, inexistentDestFolder) 447 if err != nil { 448 t.Fatalf("CopyWithTar with an inexistent folder shouldn't fail.") 449 } 450 _, err = os.Stat(inexistentDestFolder) 451 if err != nil { 452 t.Fatalf("CopyWithTar with an inexistent folder should create it.") 453 } 454 } 455 456 // Test CopyWithTar with a file as src 457 func TestCopyWithTarSrcFile(t *testing.T) { 458 folder, err := ioutil.TempDir("", "docker-archive-test") 459 if err != nil { 460 t.Fatal(err) 461 } 462 defer os.RemoveAll(folder) 463 dest := filepath.Join(folder, "dest") 464 srcFolder := filepath.Join(folder, "src") 465 src := filepath.Join(folder, filepath.Join("src", "src")) 466 err = os.MkdirAll(srcFolder, 0740) 467 if err != nil { 468 t.Fatal(err) 469 } 470 err = os.MkdirAll(dest, 0740) 471 if err != nil { 472 t.Fatal(err) 473 } 474 ioutil.WriteFile(src, []byte("content"), 0777) 475 err = defaultCopyWithTar(src, dest) 476 if err != nil { 477 t.Fatalf("archiver.CopyWithTar shouldn't throw an error, %s.", err) 478 } 479 _, err = os.Stat(dest) 480 // FIXME Check the content 481 if err != nil { 482 t.Fatalf("Destination file should be the same as the source.") 483 } 484 } 485 486 // Test CopyWithTar with a folder as src 487 func TestCopyWithTarSrcFolder(t *testing.T) { 488 folder, err := ioutil.TempDir("", "docker-archive-test") 489 if err != nil { 490 t.Fatal(err) 491 } 492 defer os.RemoveAll(folder) 493 dest := filepath.Join(folder, "dest") 494 src := filepath.Join(folder, filepath.Join("src", "folder")) 495 err = os.MkdirAll(src, 0740) 496 if err != nil { 497 t.Fatal(err) 498 } 499 err = os.MkdirAll(dest, 0740) 500 if err != nil { 501 t.Fatal(err) 502 } 503 ioutil.WriteFile(filepath.Join(src, "file"), []byte("content"), 0777) 504 err = defaultCopyWithTar(src, dest) 505 if err != nil { 506 t.Fatalf("archiver.CopyWithTar shouldn't throw an error, %s.", err) 507 } 508 _, err = os.Stat(dest) 509 // FIXME Check the content (the file inside) 510 if err != nil { 511 t.Fatalf("Destination folder should contain the source file but did not.") 512 } 513 } 514 515 func TestCopyFileWithTarInvalidSrc(t *testing.T) { 516 tempFolder, err := ioutil.TempDir("", "docker-archive-test") 517 if err != nil { 518 t.Fatal(err) 519 } 520 defer os.RemoveAll(tempFolder) 521 destFolder := filepath.Join(tempFolder, "dest") 522 err = os.MkdirAll(destFolder, 0740) 523 if err != nil { 524 t.Fatal(err) 525 } 526 invalidFile := filepath.Join(tempFolder, "doesnotexists") 527 err = defaultCopyFileWithTar(invalidFile, destFolder) 528 if err == nil { 529 t.Fatalf("archiver.CopyWithTar with invalid src path should throw an error.") 530 } 531 } 532 533 func TestCopyFileWithTarInexistentDestWillCreateIt(t *testing.T) { 534 tempFolder, err := ioutil.TempDir("", "docker-archive-test") 535 if err != nil { 536 t.Fatal(nil) 537 } 538 defer os.RemoveAll(tempFolder) 539 srcFile := filepath.Join(tempFolder, "src") 540 inexistentDestFolder := filepath.Join(tempFolder, "doesnotexists") 541 _, err = os.Create(srcFile) 542 if err != nil { 543 t.Fatal(err) 544 } 545 err = defaultCopyFileWithTar(srcFile, inexistentDestFolder) 546 if err != nil { 547 t.Fatalf("CopyWithTar with an inexistent folder shouldn't fail.") 548 } 549 _, err = os.Stat(inexistentDestFolder) 550 if err != nil { 551 t.Fatalf("CopyWithTar with an inexistent folder should create it.") 552 } 553 // FIXME Test the src file and content 554 } 555 556 func TestCopyFileWithTarSrcFolder(t *testing.T) { 557 folder, err := ioutil.TempDir("", "docker-archive-copyfilewithtar-test") 558 if err != nil { 559 t.Fatal(err) 560 } 561 defer os.RemoveAll(folder) 562 dest := filepath.Join(folder, "dest") 563 src := filepath.Join(folder, "srcfolder") 564 err = os.MkdirAll(src, 0740) 565 if err != nil { 566 t.Fatal(err) 567 } 568 err = os.MkdirAll(dest, 0740) 569 if err != nil { 570 t.Fatal(err) 571 } 572 err = defaultCopyFileWithTar(src, dest) 573 if err == nil { 574 t.Fatalf("CopyFileWithTar should throw an error with a folder.") 575 } 576 } 577 578 func TestCopyFileWithTarSrcFile(t *testing.T) { 579 folder, err := ioutil.TempDir("", "docker-archive-test") 580 if err != nil { 581 t.Fatal(err) 582 } 583 defer os.RemoveAll(folder) 584 dest := filepath.Join(folder, "dest") 585 srcFolder := filepath.Join(folder, "src") 586 src := filepath.Join(folder, filepath.Join("src", "src")) 587 err = os.MkdirAll(srcFolder, 0740) 588 if err != nil { 589 t.Fatal(err) 590 } 591 err = os.MkdirAll(dest, 0740) 592 if err != nil { 593 t.Fatal(err) 594 } 595 ioutil.WriteFile(src, []byte("content"), 0777) 596 err = defaultCopyWithTar(src, dest+"/") 597 if err != nil { 598 t.Fatalf("archiver.CopyFileWithTar shouldn't throw an error, %s.", err) 599 } 600 _, err = os.Stat(dest) 601 if err != nil { 602 t.Fatalf("Destination folder should contain the source file but did not.") 603 } 604 } 605 606 func TestTarFiles(t *testing.T) { 607 // TODO Windows: Figure out how to port this test. 608 if runtime.GOOS == "windows" { 609 t.Skip("Failing on Windows") 610 } 611 // try without hardlinks 612 if err := checkNoChanges(1000, false); err != nil { 613 t.Fatal(err) 614 } 615 // try with hardlinks 616 if err := checkNoChanges(1000, true); err != nil { 617 t.Fatal(err) 618 } 619 } 620 621 func checkNoChanges(fileNum int, hardlinks bool) error { 622 srcDir, err := ioutil.TempDir("", "docker-test-srcDir") 623 if err != nil { 624 return err 625 } 626 defer os.RemoveAll(srcDir) 627 628 destDir, err := ioutil.TempDir("", "docker-test-destDir") 629 if err != nil { 630 return err 631 } 632 defer os.RemoveAll(destDir) 633 634 _, err = prepareUntarSourceDirectory(fileNum, srcDir, hardlinks) 635 if err != nil { 636 return err 637 } 638 639 err = defaultTarUntar(srcDir, destDir) 640 if err != nil { 641 return err 642 } 643 644 changes, err := ChangesDirs(destDir, srcDir) 645 if err != nil { 646 return err 647 } 648 if len(changes) > 0 { 649 return fmt.Errorf("with %d files and %v hardlinks: expected 0 changes, got %d", fileNum, hardlinks, len(changes)) 650 } 651 return nil 652 } 653 654 func tarUntar(t *testing.T, origin string, options *TarOptions) ([]Change, error) { 655 archive, err := TarWithOptions(origin, options) 656 if err != nil { 657 t.Fatal(err) 658 } 659 defer archive.Close() 660 661 buf := make([]byte, 10) 662 if _, err := archive.Read(buf); err != nil { 663 return nil, err 664 } 665 wrap := io.MultiReader(bytes.NewReader(buf), archive) 666 667 detectedCompression := DetectCompression(buf) 668 compression := options.Compression 669 if detectedCompression.Extension() != compression.Extension() { 670 return nil, fmt.Errorf("Wrong compression detected. Actual compression: %s, found %s", compression.Extension(), detectedCompression.Extension()) 671 } 672 673 tmp, err := ioutil.TempDir("", "docker-test-untar") 674 if err != nil { 675 return nil, err 676 } 677 defer os.RemoveAll(tmp) 678 if err := Untar(wrap, tmp, nil); err != nil { 679 return nil, err 680 } 681 if _, err := os.Stat(tmp); err != nil { 682 return nil, err 683 } 684 685 return ChangesDirs(origin, tmp) 686 } 687 688 func TestTarUntar(t *testing.T) { 689 // TODO Windows: Figure out how to fix this test. 690 if runtime.GOOS == "windows" { 691 t.Skip("Failing on Windows") 692 } 693 origin, err := ioutil.TempDir("", "docker-test-untar-origin") 694 if err != nil { 695 t.Fatal(err) 696 } 697 defer os.RemoveAll(origin) 698 if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil { 699 t.Fatal(err) 700 } 701 if err := ioutil.WriteFile(filepath.Join(origin, "2"), []byte("welcome!"), 0700); err != nil { 702 t.Fatal(err) 703 } 704 if err := ioutil.WriteFile(filepath.Join(origin, "3"), []byte("will be ignored"), 0700); err != nil { 705 t.Fatal(err) 706 } 707 708 for _, c := range []Compression{ 709 Uncompressed, 710 Gzip, 711 } { 712 changes, err := tarUntar(t, origin, &TarOptions{ 713 Compression: c, 714 ExcludePatterns: []string{"3"}, 715 }) 716 717 if err != nil { 718 t.Fatalf("Error tar/untar for compression %s: %s", c.Extension(), err) 719 } 720 721 if len(changes) != 1 || changes[0].Path != "/3" { 722 t.Fatalf("Unexpected differences after tarUntar: %v", changes) 723 } 724 } 725 } 726 727 func TestTarWithOptionsChownOptsAlwaysOverridesIdPair(t *testing.T) { 728 origin, err := ioutil.TempDir("", "docker-test-tar-chown-opt") 729 require.NoError(t, err) 730 731 defer os.RemoveAll(origin) 732 filePath := filepath.Join(origin, "1") 733 err = ioutil.WriteFile(filePath, []byte("hello world"), 0700) 734 require.NoError(t, err) 735 736 idMaps := []idtools.IDMap{ 737 0: { 738 ContainerID: 0, 739 HostID: 0, 740 Size: 65536, 741 }, 742 1: { 743 ContainerID: 0, 744 HostID: 100000, 745 Size: 65536, 746 }, 747 } 748 749 cases := []struct { 750 opts *TarOptions 751 expectedUID int 752 expectedGID int 753 }{ 754 {&TarOptions{ChownOpts: &idtools.IDPair{UID: 1337, GID: 42}}, 1337, 42}, 755 {&TarOptions{ChownOpts: &idtools.IDPair{UID: 100001, GID: 100001}, UIDMaps: idMaps, GIDMaps: idMaps}, 100001, 100001}, 756 {&TarOptions{ChownOpts: &idtools.IDPair{UID: 0, GID: 0}, NoLchown: false}, 0, 0}, 757 {&TarOptions{ChownOpts: &idtools.IDPair{UID: 1, GID: 1}, NoLchown: true}, 1, 1}, 758 {&TarOptions{ChownOpts: &idtools.IDPair{UID: 1000, GID: 1000}, NoLchown: true}, 1000, 1000}, 759 } 760 for _, testCase := range cases { 761 reader, err := TarWithOptions(filePath, testCase.opts) 762 require.NoError(t, err) 763 tr := tar.NewReader(reader) 764 defer reader.Close() 765 for { 766 hdr, err := tr.Next() 767 if err == io.EOF { 768 // end of tar archive 769 break 770 } 771 require.NoError(t, err) 772 assert.Equal(t, hdr.Uid, testCase.expectedUID, "Uid equals expected value") 773 assert.Equal(t, hdr.Gid, testCase.expectedGID, "Gid equals expected value") 774 } 775 } 776 } 777 778 func TestTarWithOptions(t *testing.T) { 779 // TODO Windows: Figure out how to fix this test. 780 if runtime.GOOS == "windows" { 781 t.Skip("Failing on Windows") 782 } 783 origin, err := ioutil.TempDir("", "docker-test-untar-origin") 784 if err != nil { 785 t.Fatal(err) 786 } 787 if _, err := ioutil.TempDir(origin, "folder"); err != nil { 788 t.Fatal(err) 789 } 790 defer os.RemoveAll(origin) 791 if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil { 792 t.Fatal(err) 793 } 794 if err := ioutil.WriteFile(filepath.Join(origin, "2"), []byte("welcome!"), 0700); err != nil { 795 t.Fatal(err) 796 } 797 798 cases := []struct { 799 opts *TarOptions 800 numChanges int 801 }{ 802 {&TarOptions{IncludeFiles: []string{"1"}}, 2}, 803 {&TarOptions{ExcludePatterns: []string{"2"}}, 1}, 804 {&TarOptions{ExcludePatterns: []string{"1", "folder*"}}, 2}, 805 {&TarOptions{IncludeFiles: []string{"1", "1"}}, 2}, 806 {&TarOptions{IncludeFiles: []string{"1"}, RebaseNames: map[string]string{"1": "test"}}, 4}, 807 } 808 for _, testCase := range cases { 809 changes, err := tarUntar(t, origin, testCase.opts) 810 if err != nil { 811 t.Fatalf("Error tar/untar when testing inclusion/exclusion: %s", err) 812 } 813 if len(changes) != testCase.numChanges { 814 t.Errorf("Expected %d changes, got %d for %+v:", 815 testCase.numChanges, len(changes), testCase.opts) 816 } 817 } 818 } 819 820 // Some tar archives such as http://haproxy.1wt.eu/download/1.5/src/devel/haproxy-1.5-dev21.tar.gz 821 // use PAX Global Extended Headers. 822 // Failing prevents the archives from being uncompressed during ADD 823 func TestTypeXGlobalHeaderDoesNotFail(t *testing.T) { 824 hdr := tar.Header{Typeflag: tar.TypeXGlobalHeader} 825 tmpDir, err := ioutil.TempDir("", "docker-test-archive-pax-test") 826 if err != nil { 827 t.Fatal(err) 828 } 829 defer os.RemoveAll(tmpDir) 830 err = createTarFile(filepath.Join(tmpDir, "pax_global_header"), tmpDir, &hdr, nil, true, nil, false) 831 if err != nil { 832 t.Fatal(err) 833 } 834 } 835 836 // Some tar have both GNU specific (huge uid) and Ustar specific (long name) things. 837 // Not supposed to happen (should use PAX instead of Ustar for long name) but it does and it should still work. 838 func TestUntarUstarGnuConflict(t *testing.T) { 839 f, err := os.Open("testdata/broken.tar") 840 if err != nil { 841 t.Fatal(err) 842 } 843 defer f.Close() 844 845 found := false 846 tr := tar.NewReader(f) 847 // Iterate through the files in the archive. 848 for { 849 hdr, err := tr.Next() 850 if err == io.EOF { 851 // end of tar archive 852 break 853 } 854 if err != nil { 855 t.Fatal(err) 856 } 857 if hdr.Name == "root/.cpanm/work/1395823785.24209/Plack-1.0030/blib/man3/Plack::Middleware::LighttpdScriptNameFix.3pm" { 858 found = true 859 break 860 } 861 } 862 if !found { 863 t.Fatalf("%s not found in the archive", "root/.cpanm/work/1395823785.24209/Plack-1.0030/blib/man3/Plack::Middleware::LighttpdScriptNameFix.3pm") 864 } 865 } 866 867 func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) { 868 fileData := []byte("fooo") 869 for n := 0; n < numberOfFiles; n++ { 870 fileName := fmt.Sprintf("file-%d", n) 871 if err := ioutil.WriteFile(filepath.Join(targetPath, fileName), fileData, 0700); err != nil { 872 return 0, err 873 } 874 if makeLinks { 875 if err := os.Link(filepath.Join(targetPath, fileName), filepath.Join(targetPath, fileName+"-link")); err != nil { 876 return 0, err 877 } 878 } 879 } 880 totalSize := numberOfFiles * len(fileData) 881 return totalSize, nil 882 } 883 884 func BenchmarkTarUntar(b *testing.B) { 885 origin, err := ioutil.TempDir("", "docker-test-untar-origin") 886 if err != nil { 887 b.Fatal(err) 888 } 889 tempDir, err := ioutil.TempDir("", "docker-test-untar-destination") 890 if err != nil { 891 b.Fatal(err) 892 } 893 target := filepath.Join(tempDir, "dest") 894 n, err := prepareUntarSourceDirectory(100, origin, false) 895 if err != nil { 896 b.Fatal(err) 897 } 898 defer os.RemoveAll(origin) 899 defer os.RemoveAll(tempDir) 900 901 b.ResetTimer() 902 b.SetBytes(int64(n)) 903 for n := 0; n < b.N; n++ { 904 err := defaultTarUntar(origin, target) 905 if err != nil { 906 b.Fatal(err) 907 } 908 os.RemoveAll(target) 909 } 910 } 911 912 func BenchmarkTarUntarWithLinks(b *testing.B) { 913 origin, err := ioutil.TempDir("", "docker-test-untar-origin") 914 if err != nil { 915 b.Fatal(err) 916 } 917 tempDir, err := ioutil.TempDir("", "docker-test-untar-destination") 918 if err != nil { 919 b.Fatal(err) 920 } 921 target := filepath.Join(tempDir, "dest") 922 n, err := prepareUntarSourceDirectory(100, origin, true) 923 if err != nil { 924 b.Fatal(err) 925 } 926 defer os.RemoveAll(origin) 927 defer os.RemoveAll(tempDir) 928 929 b.ResetTimer() 930 b.SetBytes(int64(n)) 931 for n := 0; n < b.N; n++ { 932 err := defaultTarUntar(origin, target) 933 if err != nil { 934 b.Fatal(err) 935 } 936 os.RemoveAll(target) 937 } 938 } 939 940 func TestUntarInvalidFilenames(t *testing.T) { 941 // TODO Windows: Figure out how to fix this test. 942 if runtime.GOOS == "windows" { 943 t.Skip("Passes but hits breakoutError: platform and architecture is not supported") 944 } 945 for i, headers := range [][]*tar.Header{ 946 { 947 { 948 Name: "../victim/dotdot", 949 Typeflag: tar.TypeReg, 950 Mode: 0644, 951 }, 952 }, 953 { 954 { 955 // Note the leading slash 956 Name: "/../victim/slash-dotdot", 957 Typeflag: tar.TypeReg, 958 Mode: 0644, 959 }, 960 }, 961 } { 962 if err := testBreakout("untar", "docker-TestUntarInvalidFilenames", headers); err != nil { 963 t.Fatalf("i=%d. %v", i, err) 964 } 965 } 966 } 967 968 func TestUntarHardlinkToSymlink(t *testing.T) { 969 // TODO Windows. There may be a way of running this, but turning off for now 970 if runtime.GOOS == "windows" { 971 t.Skip("hardlinks on Windows") 972 } 973 for i, headers := range [][]*tar.Header{ 974 { 975 { 976 Name: "symlink1", 977 Typeflag: tar.TypeSymlink, 978 Linkname: "regfile", 979 Mode: 0644, 980 }, 981 { 982 Name: "symlink2", 983 Typeflag: tar.TypeLink, 984 Linkname: "symlink1", 985 Mode: 0644, 986 }, 987 { 988 Name: "regfile", 989 Typeflag: tar.TypeReg, 990 Mode: 0644, 991 }, 992 }, 993 } { 994 if err := testBreakout("untar", "docker-TestUntarHardlinkToSymlink", headers); err != nil { 995 t.Fatalf("i=%d. %v", i, err) 996 } 997 } 998 } 999 1000 func TestUntarInvalidHardlink(t *testing.T) { 1001 // TODO Windows. There may be a way of running this, but turning off for now 1002 if runtime.GOOS == "windows" { 1003 t.Skip("hardlinks on Windows") 1004 } 1005 for i, headers := range [][]*tar.Header{ 1006 { // try reading victim/hello (../) 1007 { 1008 Name: "dotdot", 1009 Typeflag: tar.TypeLink, 1010 Linkname: "../victim/hello", 1011 Mode: 0644, 1012 }, 1013 }, 1014 { // try reading victim/hello (/../) 1015 { 1016 Name: "slash-dotdot", 1017 Typeflag: tar.TypeLink, 1018 // Note the leading slash 1019 Linkname: "/../victim/hello", 1020 Mode: 0644, 1021 }, 1022 }, 1023 { // try writing victim/file 1024 { 1025 Name: "loophole-victim", 1026 Typeflag: tar.TypeLink, 1027 Linkname: "../victim", 1028 Mode: 0755, 1029 }, 1030 { 1031 Name: "loophole-victim/file", 1032 Typeflag: tar.TypeReg, 1033 Mode: 0644, 1034 }, 1035 }, 1036 { // try reading victim/hello (hardlink, symlink) 1037 { 1038 Name: "loophole-victim", 1039 Typeflag: tar.TypeLink, 1040 Linkname: "../victim", 1041 Mode: 0755, 1042 }, 1043 { 1044 Name: "symlink", 1045 Typeflag: tar.TypeSymlink, 1046 Linkname: "loophole-victim/hello", 1047 Mode: 0644, 1048 }, 1049 }, 1050 { // Try reading victim/hello (hardlink, hardlink) 1051 { 1052 Name: "loophole-victim", 1053 Typeflag: tar.TypeLink, 1054 Linkname: "../victim", 1055 Mode: 0755, 1056 }, 1057 { 1058 Name: "hardlink", 1059 Typeflag: tar.TypeLink, 1060 Linkname: "loophole-victim/hello", 1061 Mode: 0644, 1062 }, 1063 }, 1064 { // Try removing victim directory (hardlink) 1065 { 1066 Name: "loophole-victim", 1067 Typeflag: tar.TypeLink, 1068 Linkname: "../victim", 1069 Mode: 0755, 1070 }, 1071 { 1072 Name: "loophole-victim", 1073 Typeflag: tar.TypeReg, 1074 Mode: 0644, 1075 }, 1076 }, 1077 } { 1078 if err := testBreakout("untar", "docker-TestUntarInvalidHardlink", headers); err != nil { 1079 t.Fatalf("i=%d. %v", i, err) 1080 } 1081 } 1082 } 1083 1084 func TestUntarInvalidSymlink(t *testing.T) { 1085 // TODO Windows. There may be a way of running this, but turning off for now 1086 if runtime.GOOS == "windows" { 1087 t.Skip("hardlinks on Windows") 1088 } 1089 for i, headers := range [][]*tar.Header{ 1090 { // try reading victim/hello (../) 1091 { 1092 Name: "dotdot", 1093 Typeflag: tar.TypeSymlink, 1094 Linkname: "../victim/hello", 1095 Mode: 0644, 1096 }, 1097 }, 1098 { // try reading victim/hello (/../) 1099 { 1100 Name: "slash-dotdot", 1101 Typeflag: tar.TypeSymlink, 1102 // Note the leading slash 1103 Linkname: "/../victim/hello", 1104 Mode: 0644, 1105 }, 1106 }, 1107 { // try writing victim/file 1108 { 1109 Name: "loophole-victim", 1110 Typeflag: tar.TypeSymlink, 1111 Linkname: "../victim", 1112 Mode: 0755, 1113 }, 1114 { 1115 Name: "loophole-victim/file", 1116 Typeflag: tar.TypeReg, 1117 Mode: 0644, 1118 }, 1119 }, 1120 { // try reading victim/hello (symlink, symlink) 1121 { 1122 Name: "loophole-victim", 1123 Typeflag: tar.TypeSymlink, 1124 Linkname: "../victim", 1125 Mode: 0755, 1126 }, 1127 { 1128 Name: "symlink", 1129 Typeflag: tar.TypeSymlink, 1130 Linkname: "loophole-victim/hello", 1131 Mode: 0644, 1132 }, 1133 }, 1134 { // try reading victim/hello (symlink, hardlink) 1135 { 1136 Name: "loophole-victim", 1137 Typeflag: tar.TypeSymlink, 1138 Linkname: "../victim", 1139 Mode: 0755, 1140 }, 1141 { 1142 Name: "hardlink", 1143 Typeflag: tar.TypeLink, 1144 Linkname: "loophole-victim/hello", 1145 Mode: 0644, 1146 }, 1147 }, 1148 { // try removing victim directory (symlink) 1149 { 1150 Name: "loophole-victim", 1151 Typeflag: tar.TypeSymlink, 1152 Linkname: "../victim", 1153 Mode: 0755, 1154 }, 1155 { 1156 Name: "loophole-victim", 1157 Typeflag: tar.TypeReg, 1158 Mode: 0644, 1159 }, 1160 }, 1161 { // try writing to victim/newdir/newfile with a symlink in the path 1162 { 1163 // this header needs to be before the next one, or else there is an error 1164 Name: "dir/loophole", 1165 Typeflag: tar.TypeSymlink, 1166 Linkname: "../../victim", 1167 Mode: 0755, 1168 }, 1169 { 1170 Name: "dir/loophole/newdir/newfile", 1171 Typeflag: tar.TypeReg, 1172 Mode: 0644, 1173 }, 1174 }, 1175 } { 1176 if err := testBreakout("untar", "docker-TestUntarInvalidSymlink", headers); err != nil { 1177 t.Fatalf("i=%d. %v", i, err) 1178 } 1179 } 1180 } 1181 1182 func TestTempArchiveCloseMultipleTimes(t *testing.T) { 1183 reader := ioutil.NopCloser(strings.NewReader("hello")) 1184 tempArchive, err := NewTempArchive(reader, "") 1185 require.NoError(t, err) 1186 buf := make([]byte, 10) 1187 n, err := tempArchive.Read(buf) 1188 require.NoError(t, err) 1189 if n != 5 { 1190 t.Fatalf("Expected to read 5 bytes. Read %d instead", n) 1191 } 1192 for i := 0; i < 3; i++ { 1193 if err = tempArchive.Close(); err != nil { 1194 t.Fatalf("i=%d. Unexpected error closing temp archive: %v", i, err) 1195 } 1196 } 1197 } 1198 1199 func TestReplaceFileTarWrapper(t *testing.T) { 1200 filesInArchive := 20 1201 testcases := []struct { 1202 doc string 1203 filename string 1204 modifier TarModifierFunc 1205 expected string 1206 fileCount int 1207 }{ 1208 { 1209 doc: "Modifier creates a new file", 1210 filename: "newfile", 1211 modifier: createModifier(t), 1212 expected: "the new content", 1213 fileCount: filesInArchive + 1, 1214 }, 1215 { 1216 doc: "Modifier replaces a file", 1217 filename: "file-2", 1218 modifier: createOrReplaceModifier, 1219 expected: "the new content", 1220 fileCount: filesInArchive, 1221 }, 1222 { 1223 doc: "Modifier replaces the last file", 1224 filename: fmt.Sprintf("file-%d", filesInArchive-1), 1225 modifier: createOrReplaceModifier, 1226 expected: "the new content", 1227 fileCount: filesInArchive, 1228 }, 1229 { 1230 doc: "Modifier appends to a file", 1231 filename: "file-3", 1232 modifier: appendModifier, 1233 expected: "fooo\nnext line", 1234 fileCount: filesInArchive, 1235 }, 1236 } 1237 1238 for _, testcase := range testcases { 1239 sourceArchive, cleanup := buildSourceArchive(t, filesInArchive) 1240 defer cleanup() 1241 1242 resultArchive := ReplaceFileTarWrapper( 1243 sourceArchive, 1244 map[string]TarModifierFunc{testcase.filename: testcase.modifier}) 1245 1246 actual := readFileFromArchive(t, resultArchive, testcase.filename, testcase.fileCount, testcase.doc) 1247 assert.Equal(t, testcase.expected, actual, testcase.doc) 1248 } 1249 } 1250 1251 // TestPrefixHeaderReadable tests that files that could be created with the 1252 // version of this package that was built with <=go17 are still readable. 1253 func TestPrefixHeaderReadable(t *testing.T) { 1254 // https://gist.github.com/stevvooe/e2a790ad4e97425896206c0816e1a882#file-out-go 1255 var testFile = []byte("\x1f\x8b\x08\x08\x44\x21\x68\x59\x00\x03\x74\x2e\x74\x61\x72\x00\x4b\xcb\xcf\x67\xa0\x35\x30\x80\x00\x86\x06\x10\x47\x01\xc1\x37\x40\x00\x54\xb6\xb1\xa1\xa9\x99\x09\x48\x25\x1d\x40\x69\x71\x49\x62\x91\x02\xe5\x76\xa1\x79\x84\x21\x91\xd6\x80\x72\xaf\x8f\x82\x51\x30\x0a\x46\x36\x00\x00\xf0\x1c\x1e\x95\x00\x06\x00\x00") 1256 1257 tmpDir, err := ioutil.TempDir("", "prefix-test") 1258 require.NoError(t, err) 1259 defer os.RemoveAll(tmpDir) 1260 err = Untar(bytes.NewReader(testFile), tmpDir, nil) 1261 require.NoError(t, err) 1262 1263 baseName := "foo" 1264 pth := strings.Repeat("a", 100-len(baseName)) + "/" + baseName 1265 1266 _, err = os.Lstat(filepath.Join(tmpDir, pth)) 1267 require.NoError(t, err) 1268 } 1269 1270 func buildSourceArchive(t *testing.T, numberOfFiles int) (io.ReadCloser, func()) { 1271 srcDir, err := ioutil.TempDir("", "docker-test-srcDir") 1272 require.NoError(t, err) 1273 1274 _, err = prepareUntarSourceDirectory(numberOfFiles, srcDir, false) 1275 require.NoError(t, err) 1276 1277 sourceArchive, err := TarWithOptions(srcDir, &TarOptions{}) 1278 require.NoError(t, err) 1279 return sourceArchive, func() { 1280 os.RemoveAll(srcDir) 1281 sourceArchive.Close() 1282 } 1283 } 1284 1285 func createOrReplaceModifier(path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) { 1286 return &tar.Header{ 1287 Mode: 0600, 1288 Typeflag: tar.TypeReg, 1289 }, []byte("the new content"), nil 1290 } 1291 1292 func createModifier(t *testing.T) TarModifierFunc { 1293 return func(path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) { 1294 assert.Nil(t, content) 1295 return createOrReplaceModifier(path, header, content) 1296 } 1297 } 1298 1299 func appendModifier(path string, header *tar.Header, content io.Reader) (*tar.Header, []byte, error) { 1300 buffer := bytes.Buffer{} 1301 if content != nil { 1302 if _, err := buffer.ReadFrom(content); err != nil { 1303 return nil, nil, err 1304 } 1305 } 1306 buffer.WriteString("\nnext line") 1307 return &tar.Header{Mode: 0600, Typeflag: tar.TypeReg}, buffer.Bytes(), nil 1308 } 1309 1310 func readFileFromArchive(t *testing.T, archive io.ReadCloser, name string, expectedCount int, doc string) string { 1311 destDir, err := ioutil.TempDir("", "docker-test-destDir") 1312 require.NoError(t, err) 1313 defer os.RemoveAll(destDir) 1314 1315 err = Untar(archive, destDir, nil) 1316 require.NoError(t, err) 1317 1318 files, _ := ioutil.ReadDir(destDir) 1319 assert.Len(t, files, expectedCount, doc) 1320 1321 content, err := ioutil.ReadFile(filepath.Join(destDir, name)) 1322 assert.NoError(t, err) 1323 return string(content) 1324 } 1325 1326 func TestDisablePigz(t *testing.T) { 1327 _, err := exec.LookPath("unpigz") 1328 if err != nil { 1329 t.Log("Test will not check full path when Pigz not installed") 1330 } 1331 1332 os.Setenv("MOBY_DISABLE_PIGZ", "true") 1333 defer os.Unsetenv("MOBY_DISABLE_PIGZ") 1334 1335 r := testDecompressStream(t, "gz", "gzip -f") 1336 // For the bufio pool 1337 outsideReaderCloserWrapper := r.(*ioutils.ReadCloserWrapper) 1338 // For the context canceller 1339 contextReaderCloserWrapper := outsideReaderCloserWrapper.Reader.(*ioutils.ReadCloserWrapper) 1340 1341 assert.IsType(t, &gzip.Reader{}, contextReaderCloserWrapper.Reader) 1342 } 1343 1344 func TestPigz(t *testing.T) { 1345 r := testDecompressStream(t, "gz", "gzip -f") 1346 // For the bufio pool 1347 outsideReaderCloserWrapper := r.(*ioutils.ReadCloserWrapper) 1348 // For the context canceller 1349 contextReaderCloserWrapper := outsideReaderCloserWrapper.Reader.(*ioutils.ReadCloserWrapper) 1350 1351 _, err := exec.LookPath("unpigz") 1352 if err == nil { 1353 t.Log("Tested whether Pigz is used, as it installed") 1354 assert.IsType(t, &io.PipeReader{}, contextReaderCloserWrapper.Reader) 1355 } else { 1356 t.Log("Tested whether Pigz is not used, as it not installed") 1357 assert.IsType(t, &gzip.Reader{}, contextReaderCloserWrapper.Reader) 1358 } 1359 }