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