github.com/paketo-buildpacks/packit@v1.3.2-0.20211206231111-86b75c657449/fs/checksum_calculator_test.go (about)

     1  package fs_test
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  
    10  	"github.com/paketo-buildpacks/packit/fs"
    11  	"github.com/sclevine/spec"
    12  
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  func testChecksumCalculator(t *testing.T, context spec.G, it spec.S) {
    17  	var (
    18  		Expect = NewWithT(t).Expect
    19  
    20  		calculator fs.ChecksumCalculator
    21  		workingDir string
    22  	)
    23  
    24  	context("Sum", func() {
    25  		it.Before(func() {
    26  			var err error
    27  			workingDir, err = os.MkdirTemp("", "working-dir")
    28  			Expect(err).NotTo(HaveOccurred())
    29  
    30  			calculator = fs.NewChecksumCalculator()
    31  		})
    32  
    33  		it.After(func() {
    34  			Expect(os.RemoveAll(workingDir)).To(Succeed())
    35  		})
    36  
    37  		context("when given a single file", func() {
    38  			var path string
    39  
    40  			it.Before(func() {
    41  				path = filepath.Join(workingDir, "some-file")
    42  				Expect(os.WriteFile(path, []byte{}, os.ModePerm)).To(Succeed())
    43  			})
    44  
    45  			it("generates the SHA256 checksum for that file", func() {
    46  				sum, err := calculator.Sum(path)
    47  				Expect(err).ToNot(HaveOccurred())
    48  				Expect(sum).To(Equal("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"))
    49  			})
    50  		})
    51  
    52  		context("when given an empty directory", func() {
    53  			var path string
    54  			it.Before(func() {
    55  				path = filepath.Join(workingDir, "some-dir")
    56  				Expect(os.MkdirAll(path, os.ModePerm)).To(Succeed())
    57  			})
    58  
    59  			it("generates the SHA256 checksum for that directory", func() {
    60  				sum, err := calculator.Sum(path)
    61  				Expect(err).ToNot(HaveOccurred())
    62  				Expect(sum).To(Equal("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"))
    63  			})
    64  
    65  		})
    66  
    67  		context("when given multiple files", func() {
    68  			var path1 string
    69  			var path2 string
    70  			var paths []string
    71  
    72  			it.Before(func() {
    73  				path1 = filepath.Join(workingDir, "some-file1")
    74  				Expect(os.WriteFile(path1, []byte{}, os.ModePerm)).To(Succeed())
    75  				path2 = filepath.Join(workingDir, "some-file2")
    76  				Expect(os.WriteFile(path2, []byte{}, os.ModePerm)).To(Succeed())
    77  			})
    78  
    79  			it("generates the SHA256 checksum for multiple files", func() {
    80  				sum, err := calculator.Sum(path1, path2)
    81  				Expect(err).ToNot(HaveOccurred())
    82  				Expect(sum).To(Equal("2dba5dbc339e7316aea2683faf839c1b7b1ee2313db792112588118df066aa35"))
    83  			})
    84  
    85  			context("when the files are different", func() {
    86  				it.Before(func() {
    87  					// Generate a bunch of files and shuffle input order to ensure test fails consistently without sorting implemented
    88  					for i := 0; i < 10; i++ {
    89  						path := filepath.Join(workingDir, fmt.Sprintf("some-file-%d", i))
    90  						Expect(os.WriteFile(path, []byte(fmt.Sprintf("some-file-contents-%d", i)), os.ModePerm)).To(Succeed())
    91  						paths = append(paths, path)
    92  					}
    93  				})
    94  
    95  				it("generates the same checksum no matter the order of the inputs", func() {
    96  					var shuffledPaths []string
    97  					sum1, err := calculator.Sum(paths...)
    98  					Expect(err).NotTo(HaveOccurred())
    99  
   100  					for _, value := range rand.Perm(len(paths)) {
   101  						shuffledPaths = append(shuffledPaths, paths[value])
   102  					}
   103  
   104  					sum2, err := calculator.Sum(shuffledPaths...)
   105  					Expect(err).NotTo(HaveOccurred())
   106  					Expect(sum1).To(Equal(sum2))
   107  				})
   108  			})
   109  
   110  			context("failure cases", func() {
   111  				context("either of the files cannot be read", func() {
   112  					it.Before(func() {
   113  						Expect(os.Chmod(path2, 0222)).To(Succeed())
   114  					})
   115  
   116  					it("returns an error", func() {
   117  						_, err := calculator.Sum(path1, path2)
   118  						Expect(err).To(MatchError(ContainSubstring("failed to calculate checksum")))
   119  						Expect(err).To(MatchError(ContainSubstring("permission denied")))
   120  					})
   121  				})
   122  			})
   123  		})
   124  
   125  		context("when given multiple directories", func() {
   126  			var dir1 string
   127  			var dir2 string
   128  
   129  			it.Before(func() {
   130  				dir1 = filepath.Join(workingDir, "some-dir")
   131  				Expect(os.MkdirAll(dir1, os.ModePerm)).To(Succeed())
   132  
   133  				dir2 = filepath.Join(workingDir, "some-other-dir")
   134  				Expect(os.MkdirAll(dir2, os.ModePerm)).To(Succeed())
   135  
   136  				Expect(os.WriteFile(filepath.Join(dir1, "some-file"), []byte{}, os.ModePerm)).To(Succeed())
   137  				Expect(os.WriteFile(filepath.Join(dir1, "some-other-file"), []byte{}, os.ModePerm)).To(Succeed())
   138  
   139  				Expect(os.WriteFile(filepath.Join(dir2, "some-file"), []byte{}, os.ModePerm)).To(Succeed())
   140  				Expect(os.WriteFile(filepath.Join(dir2, "some-other-file"), []byte{}, os.ModePerm)).To(Succeed())
   141  			})
   142  
   143  			it("returns the 256 sha sum of a directory containing the directories", func() {
   144  				sum, err := calculator.Sum(dir1, dir2)
   145  				Expect(err).ToNot(HaveOccurred())
   146  				Expect(sum).To(Equal("9fb03d22515ca48e57b578de80bbc1e75d5126dbb2de6db177947c3da3b2276f"))
   147  			})
   148  
   149  			context("failure cases", func() {
   150  				context("when one of the directories cannot be read", func() {
   151  					it.Before(func() {
   152  						Expect(os.Chmod(dir2, 0222)).To(Succeed())
   153  					})
   154  
   155  					it.After(func() {
   156  						Expect(os.Chmod(dir2, os.ModePerm)).To(Succeed())
   157  					})
   158  
   159  					it("returns an error", func() {
   160  						_, err := calculator.Sum(dir1, dir2)
   161  						Expect(err).To(MatchError(ContainSubstring("failed to calculate checksum")))
   162  						Expect(err).To(MatchError(ContainSubstring("permission denied")))
   163  					})
   164  				})
   165  
   166  				context("when a file in the directory cannot be read", func() {
   167  					it.Before(func() {
   168  						Expect(os.Chmod(filepath.Join(dir2, "some-file"), 0222)).To(Succeed())
   169  					})
   170  
   171  					it("returns an error", func() {
   172  						_, err := calculator.Sum(dir1, dir2)
   173  						Expect(err).To(MatchError(ContainSubstring("failed to calculate checksum")))
   174  						Expect(err).To(MatchError(ContainSubstring("permission denied")))
   175  					})
   176  				})
   177  			})
   178  		})
   179  
   180  		context("when given a combination of files and directories", func() {
   181  			var dir string
   182  			var path string
   183  
   184  			it.Before(func() {
   185  				dir = filepath.Join(workingDir, "some-dir")
   186  				path = filepath.Join(workingDir, "some-filepath")
   187  				Expect(os.MkdirAll(dir, os.ModePerm)).To(Succeed())
   188  
   189  				Expect(os.WriteFile(filepath.Join(dir, "some-file"), []byte{}, os.ModePerm)).To(Succeed())
   190  				Expect(os.WriteFile(filepath.Join(dir, "some-other-file"), []byte{}, os.ModePerm)).To(Succeed())
   191  				Expect(os.WriteFile(path, []byte{}, os.ModePerm)).To(Succeed())
   192  			})
   193  
   194  			it("returns the 256 sha sum of a directory containing the file and directory", func() {
   195  				sum, err := calculator.Sum(dir, path)
   196  				Expect(err).ToNot(HaveOccurred())
   197  				Expect(sum).To(Equal("1a03c02fb531d7e1ce353b2f20711c79af2b66730d6de865fb130734973ccd2c"))
   198  			})
   199  		})
   200  
   201  		context("when given multiple items with same base name", func() {
   202  			var dir string
   203  			var path string
   204  
   205  			it.Before(func() {
   206  				dir = filepath.Join(workingDir, "some-dir", "the-item")
   207  				path = filepath.Join(workingDir, "the-item")
   208  				Expect(os.MkdirAll(dir, os.ModePerm)).To(Succeed())
   209  
   210  				Expect(os.WriteFile(filepath.Join(dir, "some-file"), []byte{}, os.ModePerm)).To(Succeed())
   211  				Expect(os.WriteFile(filepath.Join(dir, "some-other-file"), []byte{}, os.ModePerm)).To(Succeed())
   212  				Expect(os.WriteFile(path, []byte{}, os.ModePerm)).To(Succeed())
   213  
   214  			})
   215  
   216  			it("returns the 256 sha sum of the items", func() {
   217  				sum, err := calculator.Sum(dir, path)
   218  				Expect(err).ToNot(HaveOccurred())
   219  				Expect(sum).To(Equal("1a03c02fb531d7e1ce353b2f20711c79af2b66730d6de865fb130734973ccd2c"))
   220  			})
   221  		})
   222  
   223  		context("failure cases", func() {
   224  			context("when any of the given paths do not exist", func() {
   225  				it("returns an error", func() {
   226  					_, err := calculator.Sum("not a real path")
   227  					Expect(err).To(MatchError(ContainSubstring("failed to calculate checksum")))
   228  					Expect(err).To(MatchError(ContainSubstring("no such file or directory")))
   229  				})
   230  			})
   231  		})
   232  	})
   233  }