github.com/loafoe/cli@v7.1.0+incompatible/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  }