github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/actor/sharedaction/resource_test.go (about)

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