github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/pkg/archive/archive_test.go (about) 1 package archive_test 2 3 import ( 4 "archive/tar" 5 "net" 6 "os" 7 "path/filepath" 8 "runtime" 9 "strings" 10 "testing" 11 12 "github.com/pkg/errors" 13 14 "github.com/heroku/color" 15 "github.com/sclevine/spec" 16 "github.com/sclevine/spec/report" 17 18 "github.com/buildpacks/pack/pkg/archive" 19 h "github.com/buildpacks/pack/testhelpers" 20 ) 21 22 func TestArchive(t *testing.T) { 23 color.Disable(true) 24 defer color.Disable(false) 25 spec.Run(t, "Archive", testArchive, spec.Sequential(), spec.Report(report.Terminal{})) 26 } 27 28 func testArchive(t *testing.T, when spec.G, it spec.S) { 29 var ( 30 tmpDir string 31 ) 32 33 it.Before(func() { 34 var err error 35 tmpDir, err = os.MkdirTemp("", "create-tar-test") 36 if err != nil { 37 t.Fatalf("failed to create tmp dir %s: %s", tmpDir, err) 38 } 39 }) 40 41 it.After(func() { 42 if err := os.RemoveAll(tmpDir); err != nil { 43 if runtime.GOOS != "windows" { 44 // skip "The process cannot access the file because it is being used by another process" on windows 45 t.Fatalf("failed to clean up tmp dir %s: %s", tmpDir, err) 46 } 47 } 48 }) 49 50 when("#ReadDirAsTar", func() { 51 var src string 52 it.Before(func() { 53 src = filepath.Join("testdata", "dir-to-tar") 54 }) 55 56 it("returns a TarReader of the dir", func() { 57 rc := archive.ReadDirAsTar(src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, false, nil) 58 59 tr := tar.NewReader(rc) 60 verify := h.NewTarVerifier(t, tr, 1234, 2345) 61 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", int64(os.ModePerm)) 62 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", int64(os.ModePerm)) 63 if runtime.GOOS != "windows" { 64 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 65 verify.NoMoreFilesExist() 66 h.AssertNil(t, rc.Close()) 67 } 68 }) 69 when("includeRoot", func() { 70 it("includes a modified root entry", func() { 71 rc := archive.ReadDirAsTar(src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, true, nil) 72 tr := tar.NewReader(rc) 73 verify := h.NewTarVerifier(t, tr, 1234, 2345) 74 verify.NextDirectory("/nested/dir/dir-in-archive", int64(os.ModePerm)) 75 }) 76 }) 77 }) 78 79 when("#ReadZipAsTar", func() { 80 var src string 81 it.Before(func() { 82 src = filepath.Join("testdata", "zip-to-tar.zip") 83 }) 84 85 it("returns a TarReader of the dir", func() { 86 rc := archive.ReadZipAsTar(src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, nil) 87 88 tr := tar.NewReader(rc) 89 verify := h.NewTarVerifier(t, tr, 1234, 2345) 90 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", int64(os.ModePerm)) 91 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", int64(os.ModePerm)) 92 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 93 94 verify.NoMoreFilesExist() 95 h.AssertNil(t, rc.Close()) 96 }) 97 }) 98 99 when("#ReadTarEntry", func() { 100 var ( 101 err error 102 tarFile *os.File 103 ) 104 it.Before(func() { 105 tarFile, err = os.CreateTemp(tmpDir, "file.tgz") 106 h.AssertNil(t, err) 107 }) 108 109 it.After(func() { 110 _ = tarFile.Close() 111 }) 112 113 when("tgz has the path", func() { 114 it.Before(func() { 115 err = archive.CreateSingleFileTar(tarFile.Name(), "file1", "file-1 content") 116 h.AssertNil(t, err) 117 }) 118 119 it("returns the file contents", func() { 120 _, contents, err := archive.ReadTarEntry(tarFile, "file1") 121 h.AssertNil(t, err) 122 h.AssertEq(t, string(contents), "file-1 content") 123 }) 124 }) 125 126 when("tgz has ./path", func() { 127 it.Before(func() { 128 err = archive.CreateSingleFileTar(tarFile.Name(), "./file1", "file-1 content") 129 h.AssertNil(t, err) 130 }) 131 132 it("returns the file contents", func() { 133 _, contents, err := archive.ReadTarEntry(tarFile, "file1") 134 h.AssertNil(t, err) 135 h.AssertEq(t, string(contents), "file-1 content") 136 }) 137 }) 138 139 when("path doesn't exist", func() { 140 it.Before(func() { 141 err = archive.CreateSingleFileTar(tarFile.Name(), "file1", "file-1 content") 142 h.AssertNil(t, err) 143 }) 144 145 it("returns the file contents", func() { 146 _, _, err := archive.ReadTarEntry(tarFile, "file2") 147 h.AssertError(t, err, "could not find entry path") 148 h.AssertTrue(t, archive.IsEntryNotExist(err)) 149 }) 150 }) 151 152 when("reader isn't tar", func() { 153 it("returns the file contents", func() { 154 reader := strings.NewReader("abcde") 155 _, _, err := archive.ReadTarEntry(reader, "file1") 156 h.AssertError(t, err, "get next tar entry") 157 }) 158 }) 159 }) 160 161 when("#CreateSingleFileTarReader", func() { 162 it("returns the file contents", func() { 163 rc := archive.CreateSingleFileTarReader("file1", "file-1 content") 164 _, contents, err := archive.ReadTarEntry(rc, "file1") 165 h.AssertNil(t, err) 166 h.AssertEq(t, string(contents), "file-1 content") 167 }) 168 }) 169 170 when("#IsEntryNotExist", func() { 171 it("works", func() { 172 h.AssertTrue(t, archive.IsEntryNotExist(errors.Wrap(archive.ErrEntryNotExist, "something"))) 173 h.AssertFalse(t, archive.IsEntryNotExist(errors.New("something not err not exist"))) 174 }) 175 }) 176 177 when("#WriteDirToTar", func() { 178 var src string 179 it.Before(func() { 180 src = filepath.Join("testdata", "dir-to-tar") 181 }) 182 183 when("mode is set to 0777", func() { 184 it("writes a tar to the dest dir with 0777", func() { 185 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 186 h.AssertNil(t, err) 187 188 tw := tar.NewWriter(fh) 189 190 err = archive.WriteDirToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, false, nil) 191 h.AssertNil(t, err) 192 h.AssertNil(t, tw.Close()) 193 h.AssertNil(t, fh.Close()) 194 195 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 196 h.AssertNil(t, err) 197 defer file.Close() 198 199 tr := tar.NewReader(file) 200 201 verify := h.NewTarVerifier(t, tr, 1234, 2345) 202 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", int64(os.ModePerm)) 203 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", int64(os.ModePerm)) 204 if runtime.GOOS != "windows" { 205 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 206 } 207 }) 208 }) 209 210 when("mode is set to 0755", func() { 211 it("writes a tar to the dest dir with 0755", func() { 212 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 213 h.AssertNil(t, err) 214 215 tw := tar.NewWriter(fh) 216 217 err = archive.WriteDirToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, 0755, true, false, nil) 218 h.AssertNil(t, err) 219 h.AssertNil(t, tw.Close()) 220 h.AssertNil(t, fh.Close()) 221 222 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 223 h.AssertNil(t, err) 224 defer file.Close() 225 226 tr := tar.NewReader(file) 227 228 verify := h.NewTarVerifier(t, tr, 1234, 2345) 229 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", 0755) 230 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", 0755) 231 if runtime.GOOS != "windows" { 232 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 233 } 234 }) 235 }) 236 237 when("includeRoot is true", func() { 238 it("writes a tar to the root dir with the provided mode", func() { 239 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 240 h.AssertNil(t, err) 241 242 tw := tar.NewWriter(fh) 243 244 err = archive.WriteDirToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, true, nil) 245 h.AssertNil(t, err) 246 h.AssertNil(t, tw.Close()) 247 h.AssertNil(t, fh.Close()) 248 249 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 250 h.AssertNil(t, err) 251 defer file.Close() 252 253 tr := tar.NewReader(file) 254 255 verify := h.NewTarVerifier(t, tr, 1234, 2345) 256 verify.NextDirectory("/nested/dir/dir-in-archive", int64(os.ModePerm)) 257 }) 258 when("mode is set to -1", func() { 259 it("writes a tar to the root dir with default (0777) dir mode", func() { 260 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 261 h.AssertNil(t, err) 262 263 tw := tar.NewWriter(fh) 264 265 err = archive.WriteDirToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, -1, true, true, nil) 266 h.AssertNil(t, err) 267 h.AssertNil(t, tw.Close()) 268 h.AssertNil(t, fh.Close()) 269 270 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 271 h.AssertNil(t, err) 272 defer file.Close() 273 274 tr := tar.NewReader(file) 275 276 verify := h.NewTarVerifier(t, tr, 1234, 2345) 277 verify.NextDirectory("/nested/dir/dir-in-archive", 0777) 278 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", fileMode(t, filepath.Join(src, "some-file.txt"))) 279 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", fileMode(t, filepath.Join(src, "sub-dir"))) 280 if runtime.GOOS != "windows" { 281 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 282 } 283 }) 284 }) 285 }) 286 287 when("has file filter", func() { 288 it("does not add files against the file filter", func() { 289 tarFile := filepath.Join(tmpDir, "some.tar") 290 fh, err := os.Create(tarFile) 291 h.AssertNil(t, err) 292 293 tw := tar.NewWriter(fh) 294 295 err = archive.WriteDirToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, false, func(path string) bool { 296 return !strings.Contains(path, "some-file.txt") 297 }) 298 h.AssertNil(t, err) 299 h.AssertNil(t, tw.Close()) 300 h.AssertNil(t, fh.Close()) 301 302 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 303 h.AssertNil(t, err) 304 defer file.Close() 305 306 tr := tar.NewReader(file) 307 308 verify := h.NewTarVerifier(t, tr, 1234, 2345) 309 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", int64(os.ModePerm)) 310 if runtime.GOOS != "windows" { 311 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 312 } 313 }) 314 315 it("filter is only handed relevant section of the filepath", func() { 316 tarFile := filepath.Join(tmpDir, "some.tar") 317 fh, err := os.Create(tarFile) 318 h.AssertNil(t, err) 319 320 tw := tar.NewWriter(fh) 321 322 err = archive.WriteDirToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, false, func(path string) bool { 323 return !strings.Contains(path, "dir-to-tar") 324 }) 325 h.AssertNil(t, err) 326 h.AssertNil(t, tw.Close()) 327 h.AssertNil(t, fh.Close()) 328 329 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 330 h.AssertNil(t, err) 331 defer file.Close() 332 333 tr := tar.NewReader(file) 334 335 verify := h.NewTarVerifier(t, tr, 1234, 2345) 336 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", int64(os.ModePerm)) 337 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", int64(os.ModePerm)) 338 if runtime.GOOS != "windows" { 339 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 340 } 341 }) 342 }) 343 344 when("normalize mod time is false", func() { 345 it("does not normalize mod times", func() { 346 tarFile := filepath.Join(tmpDir, "some.tar") 347 fh, err := os.Create(tarFile) 348 h.AssertNil(t, err) 349 350 tw := tar.NewWriter(fh) 351 352 err = archive.WriteDirToTar(tw, src, "/foo", 1234, 2345, 0777, false, false, nil) 353 h.AssertNil(t, err) 354 h.AssertNil(t, tw.Close()) 355 h.AssertNil(t, fh.Close()) 356 357 h.AssertOnTarEntry(t, tarFile, "/foo/some-file.txt", 358 h.DoesNotHaveModTime(archive.NormalizedDateTime), 359 ) 360 }) 361 }) 362 363 when("normalize mod time is true", func() { 364 it("normalizes mod times", func() { 365 tarFile := filepath.Join(tmpDir, "some.tar") 366 fh, err := os.Create(tarFile) 367 h.AssertNil(t, err) 368 369 tw := tar.NewWriter(fh) 370 371 err = archive.WriteDirToTar(tw, src, "/foo", 1234, 2345, 0777, true, false, nil) 372 h.AssertNil(t, err) 373 h.AssertNil(t, tw.Close()) 374 h.AssertNil(t, fh.Close()) 375 376 h.AssertOnTarEntry(t, tarFile, "/foo/some-file.txt", 377 h.HasModTime(archive.NormalizedDateTime), 378 ) 379 }) 380 }) 381 382 when("is posix", func() { 383 it.Before(func() { 384 h.SkipIf(t, runtime.GOOS == "windows", "Skipping on windows") 385 }) 386 387 when("socket is present", func() { 388 var ( 389 err error 390 tmpSrcDir string 391 fakeSocket net.Listener 392 ) 393 394 it.Before(func() { 395 tmpSrcDir, err = os.MkdirTemp("", "socket-test") 396 h.AssertNil(t, err) 397 398 fakeSocket, err = net.Listen( 399 "unix", 400 filepath.Join(tmpSrcDir, "fake-socket"), 401 ) 402 403 err = os.WriteFile(filepath.Join(tmpSrcDir, "fake-file"), []byte("some-content"), 0777) 404 h.AssertNil(t, err) 405 }) 406 407 it.After(func() { 408 os.RemoveAll(tmpSrcDir) 409 fakeSocket.Close() 410 }) 411 412 it("silently ignore socket", func() { 413 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 414 h.AssertNil(t, err) 415 416 tw := tar.NewWriter(fh) 417 418 err = archive.WriteDirToTar(tw, tmpSrcDir, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, false, nil) 419 h.AssertNil(t, err) 420 h.AssertNil(t, tw.Close()) 421 h.AssertNil(t, fh.Close()) 422 423 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 424 h.AssertNil(t, err) 425 defer file.Close() 426 427 tr := tar.NewReader(file) 428 429 verify := h.NewTarVerifier(t, tr, 1234, 2345) 430 verify.NextFile( 431 "/nested/dir/dir-in-archive/fake-file", 432 "some-content", 433 0777, 434 ) 435 verify.NoMoreFilesExist() 436 }) 437 }) 438 }) 439 440 when("hard link files are present", func() { 441 it.Before(func() { 442 src = filepath.Join("testdata", "dir-to-tar-with-hardlink") 443 // create a hard link 444 err := os.Link(filepath.Join(src, "original-file"), filepath.Join(src, "original-file-2")) 445 h.AssertNil(t, err) 446 }) 447 448 it.After(func() { 449 os.RemoveAll(filepath.Join(src, "original-file-2")) 450 }) 451 452 it("tar file file doesn't include duplicated data", func() { 453 outputFilename := filepath.Join(tmpDir, "file-with-hard-links.tar") 454 fh, err := os.Create(outputFilename) 455 h.AssertNil(t, err) 456 457 tw := tar.NewWriter(fh) 458 err = archive.WriteDirToTar(tw, src, "/nested/dir", 1234, 2345, 0777, true, false, nil) 459 460 h.AssertNil(t, err) 461 h.AssertNil(t, tw.Close()) 462 h.AssertNil(t, fh.Close()) 463 h.AssertOnTarEntries(t, outputFilename, 464 "/nested/dir/original-file", 465 "/nested/dir/original-file-2", 466 h.AreEquivalentHardLinks(), 467 ) 468 }) 469 }) 470 }) 471 472 when("#WriteZipToTar", func() { 473 var src string 474 it.Before(func() { 475 src = filepath.Join("testdata", "zip-to-tar.zip") 476 }) 477 478 when("mode is set to 0777", func() { 479 it("writes a tar to the dest dir with 0777", func() { 480 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 481 h.AssertNil(t, err) 482 483 tw := tar.NewWriter(fh) 484 485 err = archive.WriteZipToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, nil) 486 h.AssertNil(t, err) 487 h.AssertNil(t, tw.Close()) 488 h.AssertNil(t, fh.Close()) 489 490 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 491 h.AssertNil(t, err) 492 defer file.Close() 493 494 tr := tar.NewReader(file) 495 496 verify := h.NewTarVerifier(t, tr, 1234, 2345) 497 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", 0777) 498 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", 0777) 499 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 500 }) 501 }) 502 503 when("mode is set to -1", func() { 504 it("writes a tar to the dest dir with preexisting file mode", func() { 505 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 506 h.AssertNil(t, err) 507 508 tw := tar.NewWriter(fh) 509 510 err = archive.WriteZipToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, -1, true, nil) 511 h.AssertNil(t, err) 512 h.AssertNil(t, tw.Close()) 513 h.AssertNil(t, fh.Close()) 514 515 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 516 h.AssertNil(t, err) 517 defer file.Close() 518 519 tr := tar.NewReader(file) 520 521 verify := h.NewTarVerifier(t, tr, 1234, 2345) 522 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", 0644) 523 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", 0755) 524 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 525 }) 526 527 when("files are compressed in fat (MSDOS) format", func() { 528 it.Before(func() { 529 src = filepath.Join("testdata", "fat-zip-to-tar.zip") 530 }) 531 532 it("writes a tar to the dest dir with 0777", func() { 533 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 534 h.AssertNil(t, err) 535 536 tw := tar.NewWriter(fh) 537 538 err = archive.WriteZipToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, -1, true, nil) 539 h.AssertNil(t, err) 540 h.AssertNil(t, tw.Close()) 541 h.AssertNil(t, fh.Close()) 542 543 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 544 h.AssertNil(t, err) 545 defer file.Close() 546 547 tr := tar.NewReader(file) 548 549 verify := h.NewTarVerifier(t, tr, 1234, 2345) 550 verify.NextFile("/nested/dir/dir-in-archive/some-file.txt", "some-content", 0777) 551 verify.NoMoreFilesExist() 552 }) 553 }) 554 }) 555 556 when("has file filter", func() { 557 it("follows it when adding files", func() { 558 fh, err := os.Create(filepath.Join(tmpDir, "some.tar")) 559 h.AssertNil(t, err) 560 561 tw := tar.NewWriter(fh) 562 563 err = archive.WriteZipToTar(tw, src, "/nested/dir/dir-in-archive", 1234, 2345, 0777, true, func(path string) bool { 564 return !strings.Contains(path, "some-file.txt") 565 }) 566 h.AssertNil(t, err) 567 h.AssertNil(t, tw.Close()) 568 h.AssertNil(t, fh.Close()) 569 570 file, err := os.Open(filepath.Join(tmpDir, "some.tar")) 571 h.AssertNil(t, err) 572 defer file.Close() 573 574 tr := tar.NewReader(file) 575 576 verify := h.NewTarVerifier(t, tr, 1234, 2345) 577 verify.NextDirectory("/nested/dir/dir-in-archive/sub-dir", 0777) 578 verify.NextSymLink("/nested/dir/dir-in-archive/sub-dir/link-file", "../some-file.txt") 579 }) 580 }) 581 582 when("normalize mod time is false", func() { 583 it("does not normalize mod times", func() { 584 tarFile := filepath.Join(tmpDir, "some.tar") 585 fh, err := os.Create(tarFile) 586 h.AssertNil(t, err) 587 588 tw := tar.NewWriter(fh) 589 590 err = archive.WriteZipToTar(tw, src, "/foo", 1234, 2345, 0777, false, nil) 591 h.AssertNil(t, err) 592 h.AssertNil(t, tw.Close()) 593 h.AssertNil(t, fh.Close()) 594 595 h.AssertOnTarEntry(t, tarFile, "/foo/some-file.txt", 596 h.DoesNotHaveModTime(archive.NormalizedDateTime), 597 ) 598 }) 599 }) 600 601 when("normalize mod time is true", func() { 602 it("normalizes mod times", func() { 603 tarFile := filepath.Join(tmpDir, "some.tar") 604 fh, err := os.Create(tarFile) 605 h.AssertNil(t, err) 606 607 tw := tar.NewWriter(fh) 608 609 err = archive.WriteZipToTar(tw, src, "/foo", 1234, 2345, 0777, true, nil) 610 h.AssertNil(t, err) 611 h.AssertNil(t, tw.Close()) 612 h.AssertNil(t, fh.Close()) 613 614 h.AssertOnTarEntry(t, tarFile, "/foo/some-file.txt", 615 h.HasModTime(archive.NormalizedDateTime), 616 ) 617 }) 618 }) 619 }) 620 621 when("#IsZip", func() { 622 when("file is a zip file", func() { 623 it("returns true", func() { 624 path := filepath.Join("testdata", "zip-to-tar.zip") 625 isZip, err := archive.IsZip(path) 626 h.AssertNil(t, err) 627 h.AssertTrue(t, isZip) 628 }) 629 }) 630 631 when("file is a jar file", func() { 632 it("returns true", func() { 633 path := filepath.Join("testdata", "jar-file.jar") 634 isZip, err := archive.IsZip(path) 635 h.AssertNil(t, err) 636 h.AssertTrue(t, isZip) 637 }) 638 }) 639 640 when("file is not a zip file", func() { 641 when("file has some content", func() { 642 it("returns false", func() { 643 file, err := os.CreateTemp(tmpDir, "file.txt") 644 h.AssertNil(t, err) 645 defer file.Close() 646 647 err = os.WriteFile(file.Name(), []byte("content"), os.ModePerm) 648 h.AssertNil(t, err) 649 650 isZip, err := archive.IsZip(file.Name()) 651 h.AssertNil(t, err) 652 h.AssertFalse(t, isZip) 653 }) 654 }) 655 656 when("file doesn't have content", func() { 657 it("returns false", func() { 658 file, err := os.CreateTemp(tmpDir, "file.txt") 659 h.AssertNil(t, err) 660 defer file.Close() 661 662 isZip, err := archive.IsZip(file.Name()) 663 h.AssertNil(t, err) 664 h.AssertFalse(t, isZip) 665 }) 666 }) 667 }) 668 }) 669 } 670 671 func fileMode(t *testing.T, path string) int64 { 672 t.Helper() 673 info, err := os.Stat(path) 674 if err != nil { 675 t.Fatalf("failed to stat %s", path) 676 } 677 mode := int64(info.Mode() & os.ModePerm) 678 return mode 679 }