github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/cf/appfiles/app_files_test.go (about) 1 package appfiles_test 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "runtime" 8 "strings" 9 10 "code.cloudfoundry.org/cli/cf/appfiles" 11 "github.com/nu7hatch/gouuid" 12 13 "code.cloudfoundry.org/cli/cf/models" 14 "code.cloudfoundry.org/gofileutils/fileutils" 15 16 . "github.com/onsi/ginkgo" 17 . "github.com/onsi/gomega" 18 ) 19 20 type WalkAppFileArgs struct { 21 relativePath string 22 absolutePath string 23 } 24 25 func (a WalkAppFileArgs) RelativePath() string { 26 return filepath.Join(strings.Split(a.relativePath, "/")...) 27 } 28 29 func (a WalkAppFileArgs) AbsolutePath() string { 30 return filepath.Join(strings.Split(a.relativePath, "/")...) 31 } 32 33 func (a WalkAppFileArgs) Equal(other WalkAppFileArgs) bool { 34 return a.RelativePath() == other.RelativePath() && 35 a.AbsolutePath() == other.AbsolutePath() 36 } 37 38 var _ = Describe("AppFiles", func() { 39 var appFiles appfiles.ApplicationFiles 40 var fixturePath string 41 42 BeforeEach(func() { 43 appFiles = appfiles.ApplicationFiles{} 44 fixturePath = filepath.Join("..", "..", "fixtures", "applications") 45 }) 46 47 Describe("AppFilesInDir", func() { 48 It("all files have '/' path separators", func() { 49 files, err := appFiles.AppFilesInDir(fixturePath) 50 Expect(err).NotTo(HaveOccurred()) 51 52 for _, afile := range files { 53 Expect(afile.Path).Should(Equal(filepath.ToSlash(afile.Path))) 54 } 55 }) 56 57 Context("when .cfignore is provided", func() { 58 var paths []string 59 60 BeforeEach(func() { 61 appPath := filepath.Join(fixturePath, "app-with-cfignore") 62 files, err := appFiles.AppFilesInDir(appPath) 63 Expect(err).NotTo(HaveOccurred()) 64 65 paths = []string{} 66 for _, file := range files { 67 paths = append(paths, file.Path) 68 } 69 }) 70 71 It("excludes ignored files", func() { 72 Expect(paths).To(Equal([]string{ 73 "dir1", 74 "dir1/child-dir", 75 "dir1/child-dir/file3.txt", 76 "dir1/file1.txt", 77 "dir2", 78 79 // TODO: this should be excluded. 80 // .cfignore doesn't handle ** patterns right now 81 "dir2/child-dir2", 82 })) 83 }) 84 }) 85 86 // NB: on windows, you can never rely on the size of a directory being zero 87 // see: http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946(v=vs.85).aspx 88 // and: https://www.pivotaltracker.com/story/show/70470232 89 It("always sets the size of directories to zero bytes", func() { 90 fileutils.TempDir("something", func(tempdir string, err error) { 91 Expect(err).ToNot(HaveOccurred()) 92 93 err = os.Mkdir(filepath.Join(tempdir, "nothing"), 0600) 94 Expect(err).ToNot(HaveOccurred()) 95 96 files, err := appFiles.AppFilesInDir(tempdir) 97 Expect(err).ToNot(HaveOccurred()) 98 99 sizes := []int64{} 100 for _, file := range files { 101 sizes = append(sizes, file.Size) 102 } 103 104 Expect(sizes).To(Equal([]int64{0})) 105 }) 106 }) 107 }) 108 109 Describe("CopyFiles", func() { 110 It("copies only the files specified", func() { 111 copyDir := filepath.Join(fixturePath, "app-copy-test") 112 113 filesToCopy := []models.AppFileFields{ 114 {Path: filepath.Join("dir1")}, 115 {Path: filepath.Join("dir1", "child-dir", "file2.txt")}, 116 } 117 118 files := []string{} 119 120 fileutils.TempDir("copyToDir", func(tmpDir string, err error) { 121 copyErr := appFiles.CopyFiles(filesToCopy, copyDir, tmpDir) 122 Expect(copyErr).ToNot(HaveOccurred()) 123 124 filepath.Walk(tmpDir, func(path string, fileInfo os.FileInfo, err error) error { 125 Expect(err).ToNot(HaveOccurred()) 126 127 if !fileInfo.IsDir() { 128 files = append(files, fileInfo.Name()) 129 } 130 return nil 131 }) 132 }) 133 134 // file2.txt is in lowest subtree, thus is walked first. 135 Expect(files).To(Equal([]string{ 136 "file2.txt", 137 })) 138 }) 139 }) 140 141 Describe("WalkAppFiles", func() { 142 var cb func(string, string) error 143 var actualWalkAppFileArgs []WalkAppFileArgs 144 145 BeforeEach(func() { 146 actualWalkAppFileArgs = []WalkAppFileArgs{} 147 cb = func(fileRelativePath, fullPath string) error { 148 actualWalkAppFileArgs = append(actualWalkAppFileArgs, WalkAppFileArgs{ 149 relativePath: fileRelativePath, 150 absolutePath: fullPath, 151 }) 152 return nil 153 } 154 }) 155 156 It("calls the callback with the relative and absolute path for each file within the given dir", func() { 157 err := appFiles.WalkAppFiles(filepath.Join(fixturePath, "app-copy-test"), cb) 158 Expect(err).NotTo(HaveOccurred()) 159 expectedArgs := []WalkAppFileArgs{ 160 { 161 relativePath: "dir1", 162 absolutePath: "../../fixtures/applications/app-copy-test/dir1", 163 }, 164 { 165 relativePath: "dir1/child-dir", 166 absolutePath: "../../fixtures/applications/app-copy-test/dir1/child-dir", 167 }, 168 { 169 relativePath: "dir1/child-dir/file2.txt", 170 absolutePath: "../../fixtures/applications/app-copy-test/dir1/child-dir/file2.txt", 171 }, 172 { 173 relativePath: "dir1/child-dir/file3.txt", 174 absolutePath: "../../fixtures/applications/app-copy-test/dir1/child-dir/file3.txt", 175 }, 176 { 177 relativePath: "dir1/file1.txt", 178 absolutePath: "../../fixtures/applications/app-copy-test/dir1/file1.txt", 179 }, 180 { 181 relativePath: "dir2", 182 absolutePath: "../../fixtures/applications/app-copy-test/dir2", 183 }, 184 { 185 relativePath: "dir2/child-dir2", 186 absolutePath: "../../fixtures/applications/app-copy-test/dir2/child-dir2", 187 }, 188 { 189 relativePath: "dir2/child-dir2/grandchild-dir2", 190 absolutePath: "../../fixtures/applications/app-copy-test/dir2/child-dir2/grandchild-dir2", 191 }, 192 { 193 relativePath: "dir2/child-dir2/grandchild-dir2/file4.txt", 194 absolutePath: "../../fixtures/applications/app-copy-test/dir2/child-dir2/grandchild-dir2/file4.txt", 195 }, 196 } 197 198 for i, actual := range actualWalkAppFileArgs { 199 Expect(actual.Equal(expectedArgs[i])).To(BeTrue()) 200 } 201 }) 202 203 Context("when the given dir contains an untraversable dir", func() { 204 var ( 205 untraversableDirName string 206 tmpDir string 207 ) 208 209 BeforeEach(func() { 210 if runtime.GOOS == "windows" { 211 Skip("This test is only for non-Windows platforms") 212 } 213 214 var err error 215 tmpDir, err = ioutil.TempDir("", "untraversable-test") 216 Expect(err).NotTo(HaveOccurred()) 217 218 guid, err := uuid.NewV4() 219 Expect(err).NotTo(HaveOccurred()) 220 221 untraversableDirName = guid.String() 222 untraversableDirPath := filepath.Join(tmpDir, untraversableDirName) 223 224 err = os.Mkdir(untraversableDirPath, os.ModeDir) // untraversable without os.ModePerm 225 Expect(err).NotTo(HaveOccurred()) 226 }) 227 228 AfterEach(func() { 229 err := os.RemoveAll(tmpDir) 230 Expect(err).NotTo(HaveOccurred()) 231 }) 232 233 Context("when the untraversable dir is .cfignored", func() { 234 var cfIgnorePath string 235 236 BeforeEach(func() { 237 cfIgnorePath = filepath.Join(tmpDir, ".cfignore") 238 err := ioutil.WriteFile(cfIgnorePath, []byte(untraversableDirName+"\n"), os.ModePerm) 239 Expect(err).NotTo(HaveOccurred()) 240 }) 241 242 AfterEach(func() { 243 err := os.Remove(cfIgnorePath) 244 Expect(err).NotTo(HaveOccurred()) 245 }) 246 247 It("does not return an error", func() { 248 err := appFiles.WalkAppFiles(filepath.Join(fixturePath, "app-copy-test"), cb) 249 Expect(err).NotTo(HaveOccurred()) 250 }) 251 252 It("does not call the callback with the untraversable dir", func() { 253 appFiles.WalkAppFiles(filepath.Join(fixturePath, "app-copy-test"), cb) 254 for _, actual := range actualWalkAppFileArgs { 255 Expect(actual.RelativePath()).NotTo(Equal(untraversableDirName)) 256 } 257 }) 258 }) 259 }) 260 }) 261 })