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