github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/actor/sharedaction/resource_test.go (about) 1 package sharedaction_test 2 3 import ( 4 "archive/zip" 5 "io" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 11 12 "code.cloudfoundry.org/cli/actor/actionerror" 13 . "code.cloudfoundry.org/cli/actor/sharedaction" 14 "code.cloudfoundry.org/cli/actor/sharedaction/sharedactionfakes" 15 "code.cloudfoundry.org/ykk" 16 . "github.com/onsi/ginkgo" 17 . "github.com/onsi/gomega" 18 ) 19 20 var _ = Describe("Resource Actions", func() { 21 var ( 22 fakeConfig *sharedactionfakes.FakeConfig 23 actor *Actor 24 srcDir string 25 ) 26 27 BeforeEach(func() { 28 fakeConfig = new(sharedactionfakes.FakeConfig) 29 actor = NewActor(fakeConfig) 30 31 // Creates the following directory structure: 32 // level1/level2/tmpFile1 33 // tmpfile2 34 // tmpfile3 35 36 var err error 37 srcDir, err = ioutil.TempDir("", "resource-actions-test") 38 Expect(err).ToNot(HaveOccurred()) 39 40 subDir := filepath.Join(srcDir, "level1", "level2") 41 err = os.MkdirAll(subDir, 0777) 42 Expect(err).ToNot(HaveOccurred()) 43 44 err = ioutil.WriteFile(filepath.Join(subDir, "tmpFile1"), []byte("why hello"), 0600) 45 Expect(err).ToNot(HaveOccurred()) 46 47 err = ioutil.WriteFile(filepath.Join(srcDir, "tmpFile2"), []byte("Hello, Binky"), 0600) 48 Expect(err).ToNot(HaveOccurred()) 49 50 err = ioutil.WriteFile(filepath.Join(srcDir, "tmpFile3"), []byte("Bananarama"), 0600) 51 Expect(err).ToNot(HaveOccurred()) 52 53 relativePath, err := filepath.Rel(srcDir, subDir) 54 Expect(err).ToNot(HaveOccurred()) 55 56 // ./symlink -> ./level1/level2/tmpfile1 57 err = os.Symlink(filepath.Join(relativePath, "tmpFile1"), filepath.Join(srcDir, "symlink1")) 58 Expect(err).ToNot(HaveOccurred()) 59 60 // ./level1/level2/symlink2 -> ../../tmpfile2 61 err = os.Symlink("../../tmpfile2", filepath.Join(subDir, "symlink2")) 62 Expect(err).ToNot(HaveOccurred()) 63 }) 64 65 AfterEach(func() { 66 Expect(os.RemoveAll(srcDir)).ToNot(HaveOccurred()) 67 }) 68 69 Describe("SharedToV3Resource", func() { 70 71 var returnedV3Resource V3Resource 72 var sharedResource = Resource{Filename: "file1", SHA1: "a43rknl", Mode: os.FileMode(644), Size: 100000} 73 74 JustBeforeEach(func() { 75 returnedV3Resource = sharedResource.ToV3Resource() 76 }) 77 78 It("returns a ccv3 Resource", func() { 79 Expect(returnedV3Resource).To(Equal(V3Resource{ 80 FilePath: "file1", 81 Checksum: ccv3.Checksum{ 82 Value: "a43rknl", 83 }, 84 SizeInBytes: 100000, 85 Mode: os.FileMode(644), 86 })) 87 }) 88 89 }) 90 91 Describe("ToSharedResource", func() { 92 93 var returnedSharedResource Resource 94 var v3Resource = V3Resource{ 95 FilePath: "file1", 96 Checksum: ccv3.Checksum{ 97 Value: "a43rknl", 98 }, 99 SizeInBytes: 100000, 100 Mode: os.FileMode(644), 101 } 102 103 JustBeforeEach(func() { 104 returnedSharedResource = v3Resource.ToV2Resource() 105 }) 106 107 It("returns a ccv3 Resource", func() { 108 Expect(returnedSharedResource).To(Equal(Resource{Filename: "file1", SHA1: "a43rknl", Mode: os.FileMode(644), Size: 100000})) 109 110 }) 111 }) 112 113 Describe("GatherArchiveResources", func() { 114 // tests are under resource_unix_test.go and resource_windows_test.go 115 }) 116 117 Describe("GatherDirectoryResources", func() { 118 // tests are under resource_unix_test.go and resource_windows_test.go 119 }) 120 121 Describe("ReadArchive", func() { 122 var ( 123 archivePath string 124 executeErr error 125 126 readCloser io.ReadCloser 127 fileSize int64 128 ) 129 130 JustBeforeEach(func() { 131 readCloser, fileSize, executeErr = actor.ReadArchive(archivePath) 132 }) 133 134 AfterEach(func() { 135 Expect(os.RemoveAll(archivePath)).ToNot(HaveOccurred()) 136 }) 137 138 When("the archive can be accessed properly", func() { 139 BeforeEach(func() { 140 tmpfile, err := ioutil.TempFile("", "fake-archive") 141 Expect(err).ToNot(HaveOccurred()) 142 _, err = tmpfile.Write([]byte("123456")) 143 Expect(err).ToNot(HaveOccurred()) 144 Expect(tmpfile.Close()).ToNot(HaveOccurred()) 145 146 archivePath = tmpfile.Name() 147 }) 148 149 It("returns zero errors", func() { 150 defer readCloser.Close() 151 152 Expect(executeErr).ToNot(HaveOccurred()) 153 Expect(fileSize).To(BeNumerically("==", 6)) 154 155 b := make([]byte, 100) 156 size, err := readCloser.Read(b) 157 Expect(err).ToNot(HaveOccurred()) 158 Expect(b[:size]).To(Equal([]byte("123456"))) 159 }) 160 }) 161 162 When("the archive returns any access errors", func() { 163 It("returns the error", func() { 164 _, ok := executeErr.(*os.PathError) 165 Expect(ok).To(BeTrue()) 166 }) 167 }) 168 }) 169 170 Describe("ZipArchiveResources", func() { 171 var ( 172 archive string 173 resultZip string 174 resources []Resource 175 executeErr error 176 ) 177 178 BeforeEach(func() { 179 tmpfile, err := ioutil.TempFile("", "zip-archive-resources") 180 Expect(err).ToNot(HaveOccurred()) 181 defer tmpfile.Close() 182 archive = tmpfile.Name() 183 184 err = zipit(srcDir, archive, "") 185 Expect(err).ToNot(HaveOccurred()) 186 }) 187 188 JustBeforeEach(func() { 189 resultZip, executeErr = actor.ZipArchiveResources(archive, resources) 190 }) 191 192 AfterEach(func() { 193 Expect(os.RemoveAll(archive)).ToNot(HaveOccurred()) 194 Expect(os.RemoveAll(resultZip)).ToNot(HaveOccurred()) 195 }) 196 197 When("the files have not been changed since scanning them", func() { 198 When("there are no symlinks", func() { 199 BeforeEach(func() { 200 resources = []Resource{ 201 {Filename: "/"}, 202 {Filename: "/level1/"}, 203 {Filename: "/level1/level2/"}, 204 {Filename: "/level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4"}, 205 {Filename: "/tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95"}, 206 // Explicitly skipping /tmpFile3 207 } 208 }) 209 210 It("zips the file and returns a populated resources list", func() { 211 Expect(executeErr).ToNot(HaveOccurred()) 212 213 Expect(resultZip).ToNot(BeEmpty()) 214 zipFile, err := os.Open(resultZip) 215 Expect(err).ToNot(HaveOccurred()) 216 defer zipFile.Close() 217 218 zipInfo, err := zipFile.Stat() 219 Expect(err).ToNot(HaveOccurred()) 220 221 reader, err := ykk.NewReader(zipFile, zipInfo.Size()) 222 Expect(err).ToNot(HaveOccurred()) 223 224 Expect(reader.File).To(HaveLen(5)) 225 226 Expect(reader.File[0].Name).To(Equal("/")) 227 228 Expect(reader.File[1].Name).To(Equal("/level1/")) 229 230 Expect(reader.File[2].Name).To(Equal("/level1/level2/")) 231 232 Expect(reader.File[3].Name).To(Equal("/level1/level2/tmpFile1")) 233 Expect(reader.File[3].Method).To(Equal(zip.Deflate)) 234 expectFileContentsToEqual(reader.File[3], "why hello") 235 236 Expect(reader.File[4].Name).To(Equal("/tmpFile2")) 237 Expect(reader.File[4].Method).To(Equal(zip.Deflate)) 238 expectFileContentsToEqual(reader.File[4], "Hello, Binky") 239 }) 240 }) 241 242 When("there are relative symlink files", func() { 243 BeforeEach(func() { 244 resources = []Resource{ 245 {Filename: "/"}, 246 {Filename: "/level1/"}, 247 {Filename: "/level1/level2/"}, 248 {Filename: "/level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4"}, 249 {Filename: "/symlink1", Mode: os.ModeSymlink | 0777}, 250 {Filename: "/level1/level2/symlink2", Mode: os.ModeSymlink | 0777}, 251 } 252 }) 253 254 It("zips the file and returns a populated resources list", func() { 255 Expect(executeErr).ToNot(HaveOccurred()) 256 257 Expect(resultZip).ToNot(BeEmpty()) 258 zipFile, err := os.Open(resultZip) 259 Expect(err).ToNot(HaveOccurred()) 260 defer zipFile.Close() 261 262 zipInfo, err := zipFile.Stat() 263 Expect(err).ToNot(HaveOccurred()) 264 265 reader, err := ykk.NewReader(zipFile, zipInfo.Size()) 266 Expect(err).ToNot(HaveOccurred()) 267 268 Expect(reader.File).To(HaveLen(6)) 269 Expect(reader.File[0].Name).To(Equal("/")) 270 Expect(reader.File[1].Name).To(Equal("/level1/")) 271 Expect(reader.File[2].Name).To(Equal("/level1/level2/")) 272 Expect(reader.File[3].Name).To(Equal("/level1/level2/symlink2")) 273 Expect(reader.File[4].Name).To(Equal("/level1/level2/tmpFile1")) 274 Expect(reader.File[5].Name).To(Equal("/symlink1")) 275 276 expectFileContentsToEqual(reader.File[4], "why hello") 277 Expect(reader.File[5].Mode() & os.ModeSymlink).To(Equal(os.ModeSymlink)) 278 expectFileContentsToEqual(reader.File[5], filepath.FromSlash("level1/level2/tmpFile1")) 279 280 Expect(reader.File[3].Mode() & os.ModeSymlink).To(Equal(os.ModeSymlink)) 281 expectFileContentsToEqual(reader.File[3], filepath.FromSlash("../../tmpfile2")) 282 }) 283 }) 284 }) 285 286 When("the files have changed since the scanning", func() { 287 BeforeEach(func() { 288 resources = []Resource{ 289 {Filename: "/"}, 290 {Filename: "/level1/"}, 291 {Filename: "/level1/level2/"}, 292 {Filename: "/level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4"}, 293 {Filename: "/tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95"}, 294 {Filename: "/tmpFile3", SHA1: "i dunno, 7?"}, 295 } 296 }) 297 298 It("returns an FileChangedError", func() { 299 Expect(executeErr).To(Equal(actionerror.FileChangedError{Filename: "/tmpFile3"})) 300 }) 301 }) 302 }) 303 304 Describe("ZipDirectoryResources", func() { 305 var ( 306 resultZip string 307 resources []Resource 308 executeErr error 309 ) 310 311 JustBeforeEach(func() { 312 resultZip, executeErr = actor.ZipDirectoryResources(srcDir, resources) 313 }) 314 315 AfterEach(func() { 316 Expect(os.RemoveAll(resultZip)).ToNot(HaveOccurred()) 317 }) 318 319 When("the files have not been changed since scanning them", func() { 320 When("there are no symlinks", func() { 321 BeforeEach(func() { 322 resources = []Resource{ 323 {Filename: "level1"}, 324 {Filename: "level1/level2"}, 325 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4"}, 326 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95"}, 327 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879"}, 328 } 329 }) 330 331 It("zips the file and returns a populated resources list", func() { 332 Expect(executeErr).ToNot(HaveOccurred()) 333 334 Expect(resultZip).ToNot(BeEmpty()) 335 zipFile, err := os.Open(resultZip) 336 Expect(err).ToNot(HaveOccurred()) 337 defer zipFile.Close() 338 339 zipInfo, err := zipFile.Stat() 340 Expect(err).ToNot(HaveOccurred()) 341 342 reader, err := ykk.NewReader(zipFile, zipInfo.Size()) 343 Expect(err).ToNot(HaveOccurred()) 344 345 Expect(reader.File).To(HaveLen(5)) 346 Expect(reader.File[0].Name).To(Equal("level1/")) 347 348 Expect(reader.File[1].Name).To(Equal("level1/level2/")) 349 350 Expect(reader.File[2].Name).To(Equal("level1/level2/tmpFile1")) 351 Expect(reader.File[2].Method).To(Equal(zip.Deflate)) 352 expectFileContentsToEqual(reader.File[2], "why hello") 353 354 Expect(reader.File[3].Name).To(Equal("tmpFile2")) 355 Expect(reader.File[3].Method).To(Equal(zip.Deflate)) 356 expectFileContentsToEqual(reader.File[3], "Hello, Binky") 357 358 Expect(reader.File[4].Name).To(Equal("tmpFile3")) 359 Expect(reader.File[4].Method).To(Equal(zip.Deflate)) 360 expectFileContentsToEqual(reader.File[4], "Bananarama") 361 }) 362 }) 363 364 When("there are relative symlink files", func() { 365 BeforeEach(func() { 366 resources = []Resource{ 367 {Filename: "level1"}, 368 {Filename: "level1/level2"}, 369 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4"}, 370 {Filename: "symlink1", Mode: os.ModeSymlink}, 371 {Filename: "level1/level2/symlink2", Mode: os.ModeSymlink}, 372 } 373 }) 374 375 It("zips the file and returns a populated resources list", func() { 376 Expect(executeErr).ToNot(HaveOccurred()) 377 378 Expect(resultZip).ToNot(BeEmpty()) 379 zipFile, err := os.Open(resultZip) 380 Expect(err).ToNot(HaveOccurred()) 381 defer zipFile.Close() 382 383 zipInfo, err := zipFile.Stat() 384 Expect(err).ToNot(HaveOccurred()) 385 386 reader, err := ykk.NewReader(zipFile, zipInfo.Size()) 387 Expect(err).ToNot(HaveOccurred()) 388 389 Expect(reader.File).To(HaveLen(5)) 390 391 Expect(reader.File[0].Name).To(Equal("level1/")) 392 393 Expect(reader.File[1].Name).To(Equal("level1/level2/")) 394 395 Expect(reader.File[2].Name).To(Equal("level1/level2/tmpFile1")) 396 expectFileContentsToEqual(reader.File[2], "why hello") 397 398 Expect(reader.File[3].Name).To(Equal("symlink1")) 399 Expect(reader.File[3].Mode() & os.ModeSymlink).To(Equal(os.ModeSymlink)) 400 expectFileContentsToEqual(reader.File[3], filepath.FromSlash("level1/level2/tmpFile1")) 401 402 Expect(reader.File[4].Name).To(Equal("level1/level2/symlink2")) 403 Expect(reader.File[4].Mode() & os.ModeSymlink).To(Equal(os.ModeSymlink)) 404 expectFileContentsToEqual(reader.File[4], filepath.FromSlash("../../tmpfile2")) 405 }) 406 }) 407 }) 408 409 When("the files have changed since the scanning", func() { 410 BeforeEach(func() { 411 resources = []Resource{ 412 {Filename: "level1"}, 413 {Filename: "level1/level2"}, 414 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4"}, 415 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95"}, 416 {Filename: "tmpFile3", SHA1: "i dunno, 7?"}, 417 } 418 }) 419 420 It("returns an FileChangedError", func() { 421 Expect(executeErr).To(Equal(actionerror.FileChangedError{Filename: filepath.Join(srcDir, "tmpFile3")})) 422 }) 423 }) 424 }) 425 }) 426 427 func expectFileContentsToEqual(file *zip.File, expectedContents string) { 428 reader, err := file.Open() 429 Expect(err).ToNot(HaveOccurred()) 430 defer reader.Close() 431 432 body, err := ioutil.ReadAll(reader) 433 Expect(err).ToNot(HaveOccurred()) 434 435 Expect(string(body)).To(Equal(expectedContents)) 436 }