github.com/asifdxtreme/cli@v6.1.3-0.20150123051144-9ead8700b4ae+incompatible/main/main_test.go (about) 1 package main_test 2 3 import ( 4 "bufio" 5 "os" 6 "os/exec" 7 "path/filepath" 8 "time" 9 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 . "github.com/onsi/gomega/gbytes" 13 . "github.com/onsi/gomega/gexec" 14 ) 15 16 var _ = Describe("main", func() { 17 var ( 18 old_PLUGINS_HOME string 19 ) 20 21 BeforeEach(func() { 22 old_PLUGINS_HOME = os.Getenv("CF_PLUGIN_HOME") 23 24 dir, err := os.Getwd() 25 Expect(err).NotTo(HaveOccurred()) 26 27 fullDir := filepath.Join(dir, "..", "fixtures", "config", "main-plugin-test-config") 28 err = os.Setenv("CF_PLUGIN_HOME", fullDir) 29 Expect(err).NotTo(HaveOccurred()) 30 }) 31 32 AfterEach(func() { 33 err := os.Setenv("CF_PLUGIN_HOME", old_PLUGINS_HOME) 34 Expect(err).NotTo(HaveOccurred()) 35 }) 36 37 Describe("exit codes", func() { 38 It("exits non-zero when an unknown command is invoked", func() { 39 result := Cf("some-command-that-should-never-actually-be-a-real-thing-i-can-use") 40 41 Eventually(result, 3*time.Second).Should(Say("not a registered command")) 42 Eventually(result).Should(Exit(1)) 43 }) 44 45 It("exits non-zero when known command is invoked with invalid option", func() { 46 result := Cf("push", "--crazy") 47 Eventually(result).Should(Exit(1)) 48 }) 49 }) 50 51 It("can print help for all core commands by executing only the command `cf`", func() { 52 output := Cf().Wait(3 * time.Second) 53 Eventually(output.Out.Contents).Should(ContainSubstring("A command line tool to interact with Cloud Foundry")) 54 }) 55 56 Describe("Flag verification", func() { 57 It("informs user for any incorrect provided flags", func() { 58 result := Cf("push", "--no-hostname", "--bad-flag") 59 Eventually(result.Out).Should(Say("\"--bad-flag\"")) 60 Consistently(result.Out).ShouldNot(Say("\"--no-hostname\"")) 61 }) 62 63 It("checks flags with prefix '--'", func() { 64 result := Cf("push", "not-a-flag", "--invalid-flag") 65 Eventually(result.Out).Should(Say("Unknown flag \"--invalid-flag\"")) 66 Consistently(result.Out).ShouldNot(Say("Unknown flag \"not-a-flag\"")) 67 }) 68 69 It("checks flags with prefix '-'", func() { 70 result := Cf("push", "not-a-flag", "-invalid-flag") 71 Eventually(result.Out).Should(Say("\"-invalid-flag\"")) 72 Consistently(result.Out).ShouldNot(Say("\"not-a-flag\"")) 73 }) 74 75 It("checks flags but ignores the value after '=' ", func() { 76 result := Cf("push", "-p=./", "-invalid-flag=blarg") 77 Eventually(result.Out).Should(Say("\"-invalid-flag\"")) 78 Consistently(result.Out).ShouldNot(Say("Unknown flag \"-p\"")) 79 }) 80 81 It("outputs all unknown flags in single sentence", func() { 82 result := Cf("push", "--bad-flag1", "--bad-flag2", "--bad-flag3") 83 Eventually(result.Out).Should(Say("\"--bad-flag1\", \"--bad-flag2\", \"--bad-flag3\"")) 84 }) 85 86 It("only checks input flags against flags from the provided command", func() { 87 result := Cf("push", "--no-hostname", "--skip-ssl-validation") 88 Eventually(result.Out).Should(Say("\"--skip-ssl-validation\"")) 89 }) 90 91 It("accepts -h and --h flags for all commands", func() { 92 result := Cf("push", "-h") 93 Consistently(result.Out).ShouldNot(Say("Unknown flag \"-h\"")) 94 95 result = Cf("target", "--h") 96 Consistently(result.Out).ShouldNot(Say("Unknown flag \"--h\"")) 97 }) 98 99 Context("When TotalArgs is set in the metadata for a command", func() { 100 It("will only validate flags in the argument position after position <TotalArgs>", func() { 101 result := Cf("create-buildpack", "buildpack_name", "location/to/nowhere", "-100", "-bad_flag") 102 Eventually(result.Out).ShouldNot(Say("\"-100\"")) 103 Eventually(result.Out).Should(Say("\"-bad_flag\"")) 104 }) 105 106 It("will not validate arguments before the position <TotalArgs>", func() { 107 result := Cf("create-buildpack", "-bad-flag", "--bad-flag2") 108 Eventually(result.Out).ShouldNot(Say("\"-bad-flag\"")) 109 Eventually(result.Out).ShouldNot(Say("\"--bad_flag2\"")) 110 }) 111 }) 112 113 Context("When a negative integer is preceeded by a valid flag", func() { 114 It("skips validation for negative integer flag values", func() { 115 result := Cf("update-space-quota", "-i", "-10") 116 Eventually(result.Out).ShouldNot(Say("\"-10\"")) 117 }) 118 }) 119 120 Context("When a negative integer is preceeded by a invalid flag", func() { 121 It("validates the negative integer as a flag", func() { 122 result := Cf("update-space-quota", "-badflag", "-10") 123 Eventually(result.Out).Should(Say("\"-badflag\"")) 124 Eventually(result.Out).Should(Say("\"-10\"")) 125 }) 126 }) 127 }) 128 129 Describe("Plugins", func() { 130 It("Can call a plugin command from the Plugins configuration if it does not exist as a cf command", func() { 131 output := Cf("test_1_cmd1").Wait(3 * time.Second) 132 Eventually(output.Out).Should(Say("You called cmd1 in test_1")) 133 }) 134 135 It("Can call a plugin command via alias if it does not exist as a cf command", func() { 136 output := Cf("test_1_cmd1_alias").Wait(3 * time.Second) 137 Eventually(output.Out).Should(Say("You called cmd1 in test_1")) 138 }) 139 140 It("Can call another plugin command when more than one plugin is installed", func() { 141 output := Cf("test_2_cmd1").Wait(3 * time.Second) 142 Eventually(output.Out).Should(Say("You called cmd1 in test_2")) 143 }) 144 145 It("informs user for any invalid commands", func() { 146 output := Cf("foo-bar") 147 Eventually(output.Out, 3*time.Second).Should(Say("'foo-bar' is not a registered command")) 148 }) 149 150 It("Calls help if the plugin shares the same name", func() { 151 output := Cf("help") 152 Consistently(output.Out, 1).ShouldNot(Say("You called help in test_with_help")) 153 }) 154 155 It("Can call help for a plugin command", func() { 156 output := Cf("help", "test_1_cmd1").Wait(3 * time.Second) 157 Eventually(output.Out).ShouldNot(Say("You called cmd1 in test_1")) 158 Eventually(output.Out.Contents).Should(ContainSubstring("USAGE:")) 159 Eventually(output.Out.Contents).Should(ContainSubstring("cf test_1_cmd1 [-a] [-b] [--no-ouput]")) 160 Eventually(output.Out.Contents).Should(ContainSubstring("OPTIONS:")) 161 Eventually(output.Out.Contents).Should(ContainSubstring("----no-output example option with no use")) 162 }) 163 164 It("shows help with a '-h' or '--help' flag in plugin command", func() { 165 output := Cf("test_1_cmd1", "-h").Wait(3 * time.Second) 166 Eventually(output.Out).ShouldNot(Say("You called cmd1 in test_1")) 167 Eventually(output.Out.Contents).Should(ContainSubstring("USAGE:")) 168 Eventually(output.Out.Contents).Should(ContainSubstring("OPTIONS:")) 169 }) 170 171 It("Calls the core push command if the plugin shares the same name", func() { 172 output := Cf("push") 173 Consistently(output.Out, 1).ShouldNot(Say("You called push in test_with_push")) 174 }) 175 176 It("Calls the core short name if a plugin shares the same name", func() { 177 output := Cf("p") 178 Consistently(output.Out, 1).ShouldNot(Say("You called p within the plugin")) 179 }) 180 181 It("Passes all arguments to a plugin", func() { 182 output := Cf("my-say", "foo").Wait(3 * time.Second) 183 Eventually(output.Out).Should(Say("foo")) 184 }) 185 186 It("Passes all arguments and flags to a plugin", func() { 187 output := Cf("my-say", "foo", "--loud").Wait(3 * time.Second) 188 Eventually(output.Out).Should(Say("FOO")) 189 }) 190 191 It("Calls a plugin that calls core commands", func() { 192 output := Cf("awesomeness").Wait(3 * time.Second) 193 Eventually(output.Out).Should(Say("my-say")) //look for another plugin 194 }) 195 196 It("Sends stdoutput to the plugin to echo", func() { 197 output := Cf("core-command", "plugins").Wait(3 * time.Second) 198 Eventually(output.Out.Contents).Should(MatchRegexp("Command output from the plugin(.*\\W)*awesomeness(.*\\W)*FIN")) 199 }) 200 201 It("Can call a core commmand from a plugin without terminal output", func() { 202 output := Cf("core-command-quiet", "plugins").Wait(3 * time.Second) 203 Eventually(output.Out.Contents).Should(MatchRegexp("^\n---------- Command output from the plugin")) 204 }) 205 206 It("Can call a plugin that requires stdin (interactive)", func() { 207 session := CfWithIo("input", "silly\n").Wait(5 * time.Second) 208 Eventually(session.Out).Should(Say("silly")) 209 }) 210 211 It("exits 1 when a plugin panics", func() { 212 session := Cf("panic").Wait(5 * time.Second) 213 Eventually(session).Should(Exit(1)) 214 }) 215 216 It("exits 1 when a plugin exits 1", func() { 217 session := Cf("exit1").Wait(5 * time.Second) 218 Eventually(session).Should(Exit(1)) 219 }) 220 }) 221 }) 222 223 func Cf(args ...string) *Session { 224 path, err := Build("github.com/cloudfoundry/cli/main") 225 Expect(err).NotTo(HaveOccurred()) 226 227 session, err := Start(exec.Command(path, args...), GinkgoWriter, GinkgoWriter) 228 Expect(err).NotTo(HaveOccurred()) 229 230 return session 231 } 232 func CfWithIo(command string, args string) *Session { 233 path, err := Build("github.com/cloudfoundry/cli/main") 234 Expect(err).NotTo(HaveOccurred()) 235 236 cmd := exec.Command(path, command) 237 238 stdin, err := cmd.StdinPipe() 239 Expect(err).ToNot(HaveOccurred()) 240 241 buffer := bufio.NewWriter(stdin) 242 buffer.WriteString(args) 243 buffer.Flush() 244 245 session, err := Start(cmd, GinkgoWriter, GinkgoWriter) 246 Expect(err).NotTo(HaveOccurred()) 247 248 return session 249 } 250 251 // gexec.Build leaves a compiled binary behind in /tmp. 252 var _ = AfterSuite(func() { 253 CleanupBuildArtifacts() 254 })