github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/command/flag/path_test.go (about)

     1  package flag_test
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
    10  	. "code.cloudfoundry.org/cli/command/flag"
    11  	flags "github.com/jessevdk/go-flags"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("path types", func() {
    17  	var (
    18  		currentDir string
    19  		tempDir    string
    20  	)
    21  
    22  	BeforeEach(func() {
    23  		var err error
    24  		currentDir, err = os.Getwd()
    25  		Expect(err).ToNot(HaveOccurred())
    26  
    27  		tempDir, err = ioutil.TempDir("", "")
    28  		Expect(err).ToNot(HaveOccurred())
    29  
    30  		err = os.Chdir(tempDir)
    31  		Expect(err).ToNot(HaveOccurred())
    32  
    33  		for _, filename := range []string{"abc", "abd", "~abd", "tfg", "ABCD"} {
    34  			err = ioutil.WriteFile(filename, []byte{}, 0400)
    35  			Expect(err).ToNot(HaveOccurred())
    36  		}
    37  
    38  		for _, dir := range []string{"~add", "add", "aee"} {
    39  			err := os.Mkdir(dir, 0700)
    40  			Expect(err).ToNot(HaveOccurred())
    41  		}
    42  	})
    43  
    44  	AfterEach(func() {
    45  		err := os.Chdir(currentDir)
    46  		Expect(err).ToNot(HaveOccurred())
    47  		err = os.RemoveAll(tempDir)
    48  		Expect(err).ToNot(HaveOccurred())
    49  	})
    50  
    51  	Describe("Path", func() {
    52  		var path Path
    53  
    54  		Describe("Complete", func() {
    55  			When("the prefix is empty", func() {
    56  				It("returns all files and directories", func() {
    57  					matches := path.Complete("")
    58  					Expect(matches).To(ConsistOf(
    59  						flags.Completion{Item: "abc"},
    60  						flags.Completion{Item: "abd"},
    61  						flags.Completion{Item: fmt.Sprintf("~add%c", os.PathSeparator)},
    62  						flags.Completion{Item: "~abd"},
    63  						flags.Completion{Item: fmt.Sprintf("add%c", os.PathSeparator)},
    64  						flags.Completion{Item: fmt.Sprintf("aee%c", os.PathSeparator)},
    65  						flags.Completion{Item: "tfg"},
    66  						flags.Completion{Item: "ABCD"},
    67  					))
    68  				})
    69  			})
    70  
    71  			When("the prefix is not empty", func() {
    72  				When("there are matching paths", func() {
    73  					It("returns the matching paths", func() {
    74  						matches := path.Complete("a")
    75  						Expect(matches).To(ConsistOf(
    76  							flags.Completion{Item: "abc"},
    77  							flags.Completion{Item: "abd"},
    78  							flags.Completion{Item: fmt.Sprintf("add%c", os.PathSeparator)},
    79  							flags.Completion{Item: fmt.Sprintf("aee%c", os.PathSeparator)},
    80  						))
    81  					})
    82  
    83  					It("is case sensitive", func() {
    84  						matches := path.Complete("A")
    85  						Expect(matches).To(ConsistOf(
    86  							flags.Completion{Item: "ABCD"},
    87  						))
    88  					})
    89  
    90  					It("finds files starting with '~'", func() {
    91  						matches := path.Complete("~")
    92  						Expect(matches).To(ConsistOf(
    93  							flags.Completion{Item: "~abd"},
    94  							flags.Completion{Item: fmt.Sprintf("~add%c", os.PathSeparator)},
    95  						))
    96  					})
    97  				})
    98  
    99  				When("there are no matching paths", func() {
   100  					It("returns no matches", func() {
   101  						Expect(path.Complete("z")).To(BeEmpty())
   102  					})
   103  				})
   104  			})
   105  
   106  			When("the prefix is ~/", func() {
   107  				var prevHome string
   108  
   109  				BeforeEach(func() {
   110  					prevHome = os.Getenv("HOME")
   111  				})
   112  
   113  				AfterEach(func() {
   114  					os.Setenv("HOME", prevHome)
   115  				})
   116  
   117  				When("$HOME is set", func() {
   118  					var (
   119  						tempDir string
   120  						err     error
   121  					)
   122  
   123  					BeforeEach(func() {
   124  						tempDir, err = ioutil.TempDir("", "")
   125  						Expect(err).ToNot(HaveOccurred())
   126  						os.Setenv("HOME", tempDir)
   127  
   128  						for _, filename := range []string{"abc", "def"} {
   129  							err = ioutil.WriteFile(filepath.Join(tempDir, filename), []byte{}, 0400)
   130  							Expect(err).ToNot(HaveOccurred())
   131  						}
   132  
   133  						for _, dir := range []string{"adir", "bdir"} {
   134  							err = os.Mkdir(filepath.Join(tempDir, dir), 0700)
   135  							Expect(err).ToNot(HaveOccurred())
   136  						}
   137  					})
   138  
   139  					AfterEach(func() {
   140  						err = os.RemoveAll(tempDir)
   141  						Expect(err).ToNot(HaveOccurred())
   142  					})
   143  
   144  					It("returns matching paths in $HOME", func() {
   145  						matches := path.Complete(fmt.Sprintf("~%c", os.PathSeparator))
   146  						Expect(matches).To(ConsistOf(
   147  							flags.Completion{Item: fmt.Sprintf("~%cabc", os.PathSeparator)},
   148  							flags.Completion{Item: fmt.Sprintf("~%cdef", os.PathSeparator)},
   149  							flags.Completion{Item: fmt.Sprintf("~%cadir%c", os.PathSeparator, os.PathSeparator)},
   150  							flags.Completion{Item: fmt.Sprintf("~%cbdir%c", os.PathSeparator, os.PathSeparator)},
   151  						))
   152  					})
   153  				})
   154  			})
   155  
   156  			When("the prefix starts with ~/", func() {
   157  				var prevHome string
   158  
   159  				BeforeEach(func() {
   160  					prevHome = os.Getenv("HOME")
   161  				})
   162  
   163  				AfterEach(func() {
   164  					os.Setenv("HOME", prevHome)
   165  				})
   166  
   167  				When("$HOME is set", func() {
   168  					var (
   169  						tempDir string
   170  						err     error
   171  					)
   172  
   173  					BeforeEach(func() {
   174  						tempDir, err = ioutil.TempDir("", "")
   175  						Expect(err).ToNot(HaveOccurred())
   176  						os.Setenv("HOME", tempDir)
   177  
   178  						for _, filename := range []string{"abc", "def"} {
   179  							err = ioutil.WriteFile(filepath.Join(tempDir, filename), []byte{}, 0400)
   180  							Expect(err).ToNot(HaveOccurred())
   181  						}
   182  
   183  						for _, dir := range []string{"adir", "bdir"} {
   184  							err = os.Mkdir(filepath.Join(tempDir, dir), 0700)
   185  							Expect(err).ToNot(HaveOccurred())
   186  						}
   187  					})
   188  
   189  					AfterEach(func() {
   190  						err = os.RemoveAll(tempDir)
   191  						Expect(err).ToNot(HaveOccurred())
   192  					})
   193  
   194  					It("returns matching paths in $HOME", func() {
   195  						matches := path.Complete(fmt.Sprintf("~%ca", os.PathSeparator))
   196  						Expect(matches).To(ConsistOf(
   197  							flags.Completion{Item: fmt.Sprintf("~%cabc", os.PathSeparator)},
   198  							flags.Completion{Item: fmt.Sprintf("~%cadir%c", os.PathSeparator, os.PathSeparator)},
   199  						))
   200  					})
   201  				})
   202  			})
   203  		})
   204  	})
   205  
   206  	Describe("PathWithExistenceCheck", func() {
   207  		var pathWithExistenceCheck PathWithExistenceCheck
   208  
   209  		BeforeEach(func() {
   210  			pathWithExistenceCheck = PathWithExistenceCheck("")
   211  		})
   212  
   213  		// The Complete method is not tested because it shares the same code as
   214  		// Path.Complete().
   215  
   216  		Describe("UnmarshalFlag", func() {
   217  			When("the path does not exist", func() {
   218  				It("returns a path does not exist error", func() {
   219  					err := pathWithExistenceCheck.UnmarshalFlag("./some-dir/some-file")
   220  					Expect(err).To(MatchError(&flags.Error{
   221  						Type:    flags.ErrRequired,
   222  						Message: "The specified path './some-dir/some-file' does not exist.",
   223  					}))
   224  				})
   225  			})
   226  
   227  			When("the path exists", func() {
   228  				When("the path is relative", func() {
   229  					It("expands the path", func() {
   230  						fullPath := filepath.Join(tempDir, "abc")
   231  						err := pathWithExistenceCheck.UnmarshalFlag("abc")
   232  						Expect(err).ToNot(HaveOccurred())
   233  						Expect(string(pathWithExistenceCheck)).To(matchers.MatchPath(fullPath))
   234  					})
   235  				})
   236  
   237  				When("the path is absolute", func() {
   238  					It("preserves the path", func() {
   239  						err := pathWithExistenceCheck.UnmarshalFlag(filepath.Join(tempDir, "abc"))
   240  						Expect(err).ToNot(HaveOccurred())
   241  						Expect(pathWithExistenceCheck).To(BeEquivalentTo(filepath.Join(tempDir, "abc")))
   242  					})
   243  				})
   244  			})
   245  		})
   246  	})
   247  
   248  	Describe("ManifestPathWithExistenceCheck", func() {
   249  		var manifestPathWithExistenceCheck ManifestPathWithExistenceCheck
   250  
   251  		BeforeEach(func() {
   252  			manifestPathWithExistenceCheck = ManifestPathWithExistenceCheck("")
   253  		})
   254  
   255  		// The Complete method is not tested because it shares the same code as
   256  		// Path.Complete().
   257  
   258  		Describe("UnmarshalFlag", func() {
   259  			When("the path does not exist", func() {
   260  				It("returns a path does not exist error", func() {
   261  					err := manifestPathWithExistenceCheck.UnmarshalFlag("./some-dir/some-file")
   262  					Expect(err).To(MatchError(&flags.Error{
   263  						Type:    flags.ErrRequired,
   264  						Message: "The specified path './some-dir/some-file' does not exist.",
   265  					}))
   266  				})
   267  			})
   268  
   269  			When("the path is a directory, and exists, but does not contain a manifest.{yml,yaml} file", func() {
   270  				It("returns a path does not exist error", func() {
   271  					err := manifestPathWithExistenceCheck.UnmarshalFlag(tempDir)
   272  					Expect(err).To(MatchError(&flags.Error{
   273  						Type:    flags.ErrRequired,
   274  						Message: "The specified directory '" + tempDir + "' does not contain a file named 'manifest.yml'.",
   275  					}))
   276  				})
   277  			})
   278  
   279  			When("the path exists", func() {
   280  				It("sets the path", func() {
   281  					err := manifestPathWithExistenceCheck.UnmarshalFlag("abc")
   282  					Expect(err).ToNot(HaveOccurred())
   283  					Expect(manifestPathWithExistenceCheck).To(BeEquivalentTo("abc"))
   284  				})
   285  			})
   286  		})
   287  	})
   288  
   289  	Describe("JSONOrFileWithValidation", func() {
   290  		var jsonOrFile JSONOrFileWithValidation
   291  
   292  		BeforeEach(func() {
   293  			jsonOrFile = JSONOrFileWithValidation(nil)
   294  		})
   295  
   296  		// The Complete method is not tested because it shares the same code as
   297  		// Path.Complete().
   298  
   299  		Describe("UnmarshalFlag", func() {
   300  			When("the file exists", func() {
   301  				var tempPath string
   302  
   303  				When("the file has valid JSON", func() {
   304  					BeforeEach(func() {
   305  						tempPath = tempFile(`{"this is":"valid JSON"}`)
   306  					})
   307  
   308  					It("reads and unmarshals the JSON from the file", func() {
   309  						err := jsonOrFile.UnmarshalFlag(tempPath)
   310  						Expect(err).ToNot(HaveOccurred())
   311  						Expect(jsonOrFile).To(BeEquivalentTo(map[string]interface{}{
   312  							"this is": "valid JSON",
   313  						}))
   314  					})
   315  				})
   316  
   317  				When("the file has invalid JSON", func() {
   318  					BeforeEach(func() {
   319  						tempPath = tempFile(`{"this is":"invalid JSON"`)
   320  					})
   321  
   322  					It("errors with the invalid configuration error", func() {
   323  						err := jsonOrFile.UnmarshalFlag(tempPath)
   324  						Expect(err).To(Equal(&flags.Error{
   325  							Type:    flags.ErrRequired,
   326  							Message: "Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object.",
   327  						}))
   328  					})
   329  				})
   330  			})
   331  
   332  			When("the JSON is invalid", func() {
   333  				It("errors with the invalid configuration error", func() {
   334  					err := jsonOrFile.UnmarshalFlag(`{"this is":"invalid JSON"`)
   335  					Expect(err).To(Equal(&flags.Error{
   336  						Type:    flags.ErrRequired,
   337  						Message: "Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object.",
   338  					}))
   339  				})
   340  			})
   341  
   342  			When("the JSON is valid", func() {
   343  				It("reads and unmarshals the JSON", func() {
   344  					err := jsonOrFile.UnmarshalFlag(`{"this is":"valid JSON"}`)
   345  					Expect(err).ToNot(HaveOccurred())
   346  					Expect(jsonOrFile).To(BeEquivalentTo(map[string]interface{}{
   347  						"this is": "valid JSON",
   348  					}))
   349  				})
   350  			})
   351  		})
   352  	})
   353  
   354  	Describe("PathWithExistenceCheckOrURL", func() {
   355  		var pathWithExistenceCheckOrURL PathWithExistenceCheckOrURL
   356  
   357  		BeforeEach(func() {
   358  			pathWithExistenceCheckOrURL = PathWithExistenceCheckOrURL("")
   359  		})
   360  
   361  		// The Complete method is not tested because it shares the same code as
   362  		// Path.Complete().
   363  
   364  		Describe("UnmarshalFlag", func() {
   365  			When("the path is a URL", func() {
   366  				It("sets the path if it starts with 'http://'", func() {
   367  					err := pathWithExistenceCheckOrURL.UnmarshalFlag("http://example.com/payload.tgz")
   368  					Expect(err).ToNot(HaveOccurred())
   369  					Expect(pathWithExistenceCheckOrURL).To(BeEquivalentTo("http://example.com/payload.tgz"))
   370  				})
   371  
   372  				It("sets the path if it starts with 'https://'", func() {
   373  					err := pathWithExistenceCheckOrURL.UnmarshalFlag("https://example.com/payload.tgz")
   374  					Expect(err).ToNot(HaveOccurred())
   375  					Expect(pathWithExistenceCheckOrURL).To(BeEquivalentTo("https://example.com/payload.tgz"))
   376  				})
   377  			})
   378  
   379  			When("the path does not exist", func() {
   380  				It("returns a path does not exist error", func() {
   381  					err := pathWithExistenceCheckOrURL.UnmarshalFlag("./some-dir/some-file")
   382  					Expect(err).To(MatchError(&flags.Error{
   383  						Type:    flags.ErrRequired,
   384  						Message: "The specified path './some-dir/some-file' does not exist.",
   385  					}))
   386  				})
   387  			})
   388  
   389  			When("the path exists", func() {
   390  				It("sets the path", func() {
   391  					err := pathWithExistenceCheckOrURL.UnmarshalFlag("abc")
   392  					Expect(err).ToNot(HaveOccurred())
   393  					Expect(pathWithExistenceCheckOrURL).To(BeEquivalentTo("abc"))
   394  				})
   395  			})
   396  		})
   397  	})
   398  
   399  	Describe("PathWithAt", func() {
   400  		var pathWithAt PathWithAt
   401  
   402  		Describe("Complete", func() {
   403  			When("the prefix is empty", func() {
   404  				It("returns no matches", func() {
   405  					Expect(pathWithAt.Complete("")).To(BeEmpty())
   406  				})
   407  			})
   408  
   409  			When("the prefix doesn't start with @", func() {
   410  				It("returns no matches", func() {
   411  					Expect(pathWithAt.Complete("a@b")).To(BeEmpty())
   412  				})
   413  			})
   414  
   415  			When("the prefix starts with @", func() {
   416  				When("there are no characters after the @", func() {
   417  					It("returns all files and directories", func() {
   418  						matches := pathWithAt.Complete("@")
   419  						Expect(matches).To(ConsistOf(
   420  							flags.Completion{Item: "@abc"},
   421  							flags.Completion{Item: "@abd"},
   422  							flags.Completion{Item: fmt.Sprintf("@~add%c", os.PathSeparator)},
   423  							flags.Completion{Item: "@~abd"},
   424  							flags.Completion{Item: fmt.Sprintf("@add%c", os.PathSeparator)},
   425  							flags.Completion{Item: fmt.Sprintf("@aee%c", os.PathSeparator)},
   426  							flags.Completion{Item: "@tfg"},
   427  							flags.Completion{Item: "@ABCD"},
   428  						))
   429  					})
   430  				})
   431  
   432  				When("there are characters after the @", func() {
   433  					When("there are matching paths", func() {
   434  						It("returns the matching paths", func() {
   435  							matches := pathWithAt.Complete("@a")
   436  							Expect(matches).To(ConsistOf(
   437  								flags.Completion{Item: "@abc"},
   438  								flags.Completion{Item: "@abd"},
   439  								flags.Completion{Item: fmt.Sprintf("@add%c", os.PathSeparator)},
   440  								flags.Completion{Item: fmt.Sprintf("@aee%c", os.PathSeparator)},
   441  							))
   442  						})
   443  
   444  						It("is case sensitive", func() {
   445  							matches := pathWithAt.Complete("@A")
   446  							Expect(matches).To(ConsistOf(
   447  								flags.Completion{Item: "@ABCD"},
   448  							))
   449  						})
   450  					})
   451  
   452  					When("there are no matching paths", func() {
   453  						It("returns no matches", func() {
   454  							Expect(pathWithAt.Complete("@z")).To(BeEmpty())
   455  						})
   456  					})
   457  				})
   458  			})
   459  
   460  			When("the prefix is @~/", func() {
   461  				var prevHome string
   462  
   463  				BeforeEach(func() {
   464  					prevHome = os.Getenv("HOME")
   465  				})
   466  
   467  				AfterEach(func() {
   468  					os.Setenv("HOME", prevHome)
   469  				})
   470  
   471  				When("$HOME is set", func() {
   472  					var (
   473  						tempDir string
   474  						err     error
   475  					)
   476  
   477  					BeforeEach(func() {
   478  						tempDir, err = ioutil.TempDir("", "")
   479  						Expect(err).ToNot(HaveOccurred())
   480  						os.Setenv("HOME", tempDir)
   481  
   482  						for _, filename := range []string{"abc", "def"} {
   483  							err = ioutil.WriteFile(filepath.Join(tempDir, filename), []byte{}, 0400)
   484  							Expect(err).ToNot(HaveOccurred())
   485  						}
   486  
   487  						for _, dir := range []string{"adir", "bdir"} {
   488  							err = os.Mkdir(filepath.Join(tempDir, dir), 0700)
   489  							Expect(err).ToNot(HaveOccurred())
   490  						}
   491  					})
   492  
   493  					AfterEach(func() {
   494  						err = os.RemoveAll(tempDir)
   495  						Expect(err).ToNot(HaveOccurred())
   496  					})
   497  
   498  					It("returns matching paths in $HOME", func() {
   499  						matches := pathWithAt.Complete(fmt.Sprintf("@~%c", os.PathSeparator))
   500  						Expect(matches).To(ConsistOf(
   501  							flags.Completion{Item: fmt.Sprintf("@~%cabc", os.PathSeparator)},
   502  							flags.Completion{Item: fmt.Sprintf("@~%cdef", os.PathSeparator)},
   503  							flags.Completion{Item: fmt.Sprintf("@~%cadir%c", os.PathSeparator, os.PathSeparator)},
   504  							flags.Completion{Item: fmt.Sprintf("@~%cbdir%c", os.PathSeparator, os.PathSeparator)},
   505  						))
   506  					})
   507  				})
   508  			})
   509  
   510  			When("the prefix starts with @~/", func() {
   511  				var prevHome string
   512  
   513  				BeforeEach(func() {
   514  					prevHome = os.Getenv("HOME")
   515  				})
   516  
   517  				AfterEach(func() {
   518  					os.Setenv("HOME", prevHome)
   519  				})
   520  
   521  				When("$HOME is set", func() {
   522  					var (
   523  						tempDir string
   524  						err     error
   525  					)
   526  
   527  					BeforeEach(func() {
   528  						tempDir, err = ioutil.TempDir("", "")
   529  						Expect(err).ToNot(HaveOccurred())
   530  						os.Setenv("HOME", tempDir)
   531  
   532  						for _, filename := range []string{"abc", "def"} {
   533  							err = ioutil.WriteFile(filepath.Join(tempDir, filename), []byte{}, 0400)
   534  							Expect(err).ToNot(HaveOccurred())
   535  						}
   536  
   537  						for _, dir := range []string{"adir", "bdir"} {
   538  							err = os.Mkdir(filepath.Join(tempDir, dir), 0700)
   539  							Expect(err).ToNot(HaveOccurred())
   540  						}
   541  					})
   542  
   543  					AfterEach(func() {
   544  						err = os.RemoveAll(tempDir)
   545  						Expect(err).ToNot(HaveOccurred())
   546  					})
   547  
   548  					It("returns matching paths in $HOME", func() {
   549  						matches := pathWithAt.Complete(fmt.Sprintf("@~%ca", os.PathSeparator))
   550  						Expect(matches).To(ConsistOf(
   551  							flags.Completion{Item: fmt.Sprintf("@~%cabc", os.PathSeparator)},
   552  							flags.Completion{Item: fmt.Sprintf("@~%cadir%c", os.PathSeparator, os.PathSeparator)},
   553  						))
   554  					})
   555  				})
   556  			})
   557  		})
   558  	})
   559  
   560  	Describe("PathWithBool", func() {
   561  		var pathWithBool PathWithBool
   562  
   563  		Describe("Complete", func() {
   564  			When("the prefix is empty", func() {
   565  				It("returns bool choices and all files and directories", func() {
   566  					matches := pathWithBool.Complete("")
   567  					Expect(matches).To(ConsistOf(
   568  						flags.Completion{Item: "true"},
   569  						flags.Completion{Item: "false"},
   570  						flags.Completion{Item: "abc"},
   571  						flags.Completion{Item: "abd"},
   572  						flags.Completion{Item: fmt.Sprintf("add%c", os.PathSeparator)},
   573  						flags.Completion{Item: "~abd"},
   574  						flags.Completion{Item: fmt.Sprintf("~add%c", os.PathSeparator)},
   575  						flags.Completion{Item: fmt.Sprintf("aee%c", os.PathSeparator)},
   576  						flags.Completion{Item: "tfg"},
   577  						flags.Completion{Item: "ABCD"},
   578  					))
   579  				})
   580  			})
   581  
   582  			When("the prefix is not empty", func() {
   583  				When("there are matching bool/paths", func() {
   584  					It("returns the matching bool/paths", func() {
   585  						matches := pathWithBool.Complete("t")
   586  						Expect(matches).To(ConsistOf(
   587  							flags.Completion{Item: "true"},
   588  							flags.Completion{Item: "tfg"},
   589  						))
   590  					})
   591  
   592  					It("paths are case sensitive", func() {
   593  						matches := pathWithBool.Complete("A")
   594  						Expect(matches).To(ConsistOf(
   595  							flags.Completion{Item: "ABCD"},
   596  						))
   597  					})
   598  
   599  					It("bools are not case sensitive", func() {
   600  						matches := pathWithBool.Complete("Tr")
   601  						Expect(matches).To(ConsistOf(
   602  							flags.Completion{Item: "true"},
   603  						))
   604  					})
   605  				})
   606  
   607  				When("there are no matching bool/paths", func() {
   608  					It("returns no matches", func() {
   609  						Expect(pathWithBool.Complete("z")).To(BeEmpty())
   610  					})
   611  				})
   612  			})
   613  		})
   614  	})
   615  })