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  })