Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package main |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "fmt" |
|
| 4 | 5 |
"os/exec" |
| 5 | 6 |
"runtime" |
| 6 | 7 |
"strings" |
| ... | ... |
@@ -13,6 +14,7 @@ import ( |
| 13 | 13 |
|
| 14 | 14 |
func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
|
| 15 | 15 |
testRequires(c, DaemonIsLinux) |
| 16 |
+ |
|
| 16 | 17 |
// Make sure main help text fits within 80 chars and that |
| 17 | 18 |
// on non-windows system we use ~ when possible (to shorten things). |
| 18 | 19 |
// Test for HOME set to its default value and set to "/" on linux |
| ... | ... |
@@ -40,6 +42,7 @@ func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
|
| 40 | 40 |
} |
| 41 | 41 |
|
| 42 | 42 |
for _, home := range homes {
|
| 43 |
+ |
|
| 43 | 44 |
// Dup baseEnvs and add our new HOME value |
| 44 | 45 |
newEnvs := make([]string, len(baseEnvs)+1) |
| 45 | 46 |
copy(newEnvs, baseEnvs) |
| ... | ... |
@@ -117,114 +120,22 @@ func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
|
| 117 | 117 |
cmdsToTest = append(cmdsToTest, "volume ls") |
| 118 | 118 |
cmdsToTest = append(cmdsToTest, "volume rm") |
| 119 | 119 |
|
| 120 |
- for _, cmd := range cmdsToTest {
|
|
| 121 |
- var stderr string |
|
| 122 |
- |
|
| 123 |
- args := strings.Split(cmd+" --help", " ") |
|
| 124 |
- |
|
| 125 |
- // Check the full usage text |
|
| 126 |
- helpCmd := exec.Command(dockerBinary, args...) |
|
| 127 |
- helpCmd.Env = newEnvs |
|
| 128 |
- out, stderr, _, err = runCommandWithStdoutStderr(helpCmd) |
|
| 129 |
- c.Assert(len(stderr), checker.Equals, 0, check.Commentf("Error on %q help. non-empty stderr:%q", cmd, stderr))
|
|
| 130 |
- c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have blank line on %q\n", cmd))
|
|
| 131 |
- c.Assert(out, checker.Contains, "--help", check.Commentf("All commands should mention '--help'. Command '%v' did not.\n", cmd))
|
|
| 132 |
- |
|
| 133 |
- c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 134 |
- |
|
| 135 |
- // Check each line for lots of stuff |
|
| 136 |
- lines := strings.Split(out, "\n") |
|
| 137 |
- for _, line := range lines {
|
|
| 138 |
- c.Assert(len(line), checker.LessOrEqualThan, 107, check.Commentf("Help for %q is too long:\n%s", cmd, line))
|
|
| 139 |
- |
|
| 140 |
- if scanForHome && strings.Contains(line, `"`+home) {
|
|
| 141 |
- c.Fatalf("Help for %q should use ~ instead of %q on:\n%s",
|
|
| 142 |
- cmd, home, line) |
|
| 143 |
- } |
|
| 144 |
- i := strings.Index(line, "~") |
|
| 145 |
- if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
|
|
| 146 |
- c.Fatalf("Help for %q should not have used ~:\n%s", cmd, line)
|
|
| 147 |
- } |
|
| 148 |
- |
|
| 149 |
- // If a line starts with 4 spaces then assume someone |
|
| 150 |
- // added a multi-line description for an option and we need |
|
| 151 |
- // to flag it |
|
| 152 |
- c.Assert(line, checker.Not(checker.HasPrefix), " ", check.Commentf("Help for %q should not have a multi-line option", cmd))
|
|
| 153 |
- |
|
| 154 |
- // Options should NOT end with a period |
|
| 155 |
- if strings.HasPrefix(line, " -") && strings.HasSuffix(line, ".") {
|
|
| 156 |
- c.Fatalf("Help for %q should not end with a period: %s", cmd, line)
|
|
| 157 |
- } |
|
| 158 |
- |
|
| 159 |
- // Options should NOT end with a space |
|
| 160 |
- c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Help for %q should not end with a space", cmd))
|
|
| 161 |
- |
|
| 162 |
- } |
|
| 163 |
- |
|
| 164 |
- // For each command make sure we generate an error |
|
| 165 |
- // if we give a bad arg |
|
| 166 |
- args = strings.Split(cmd+" --badArg", " ") |
|
| 167 |
- |
|
| 168 |
- out, _, err = dockerCmdWithError(args...) |
|
| 169 |
- c.Assert(err, checker.NotNil, check.Commentf(out)) |
|
| 170 |
- // Be really picky |
|
| 171 |
- c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker rm'\n"))
|
|
| 172 |
- |
|
| 173 |
- // Now make sure that each command will print a short-usage |
|
| 174 |
- // (not a full usage - meaning no opts section) if we |
|
| 175 |
- // are missing a required arg or pass in a bad arg |
|
| 176 |
- |
|
| 177 |
- // These commands will never print a short-usage so don't test |
|
| 178 |
- noShortUsage := map[string]string{
|
|
| 179 |
- "images": "", |
|
| 180 |
- "login": "", |
|
| 181 |
- "logout": "", |
|
| 182 |
- "network": "", |
|
| 183 |
- "stats": "", |
|
| 184 |
- } |
|
| 120 |
+ // Divide the list of commands into go routines and run the func testcommand on the commands in parallel |
|
| 121 |
+ // to save runtime of test |
|
| 185 | 122 |
|
| 186 |
- if _, ok := noShortUsage[cmd]; !ok {
|
|
| 187 |
- // For each command run it w/o any args. It will either return |
|
| 188 |
- // valid output or print a short-usage |
|
| 189 |
- var dCmd *exec.Cmd |
|
| 190 |
- var stdout, stderr string |
|
| 191 |
- var args []string |
|
| 192 |
- |
|
| 193 |
- // skipNoArgs are ones that we don't want to try w/o |
|
| 194 |
- // any args. Either because it'll hang the test or |
|
| 195 |
- // lead to incorrect test result (like false negative). |
|
| 196 |
- // Whatever the reason, skip trying to run w/o args and |
|
| 197 |
- // jump to trying with a bogus arg. |
|
| 198 |
- skipNoArgs := map[string]struct{}{
|
|
| 199 |
- "daemon": {},
|
|
| 200 |
- "events": {},
|
|
| 201 |
- "load": {},
|
|
| 202 |
- } |
|
| 123 |
+ errChan := make(chan error) |
|
| 203 | 124 |
|
| 204 |
- ec := 0 |
|
| 205 |
- if _, ok := skipNoArgs[cmd]; !ok {
|
|
| 206 |
- args = strings.Split(cmd, " ") |
|
| 207 |
- dCmd = exec.Command(dockerBinary, args...) |
|
| 208 |
- stdout, stderr, ec, err = runCommandWithStdoutStderr(dCmd) |
|
| 209 |
- } |
|
| 210 |
- |
|
| 211 |
- // If its ok w/o any args then try again with an arg |
|
| 212 |
- if ec == 0 {
|
|
| 213 |
- args = strings.Split(cmd+" badArg", " ") |
|
| 214 |
- dCmd = exec.Command(dockerBinary, args...) |
|
| 215 |
- stdout, stderr, ec, err = runCommandWithStdoutStderr(dCmd) |
|
| 216 |
- } |
|
| 125 |
+ for index := 0; index < len(cmdsToTest); index++ {
|
|
| 126 |
+ go func(index int) {
|
|
| 127 |
+ errChan <- testCommand(cmdsToTest[index], newEnvs, scanForHome, home) |
|
| 128 |
+ }(index) |
|
| 129 |
+ } |
|
| 217 | 130 |
|
| 218 |
- if len(stdout) != 0 || len(stderr) == 0 || ec == 0 || err == nil {
|
|
| 219 |
- c.Fatalf("Bad output from %q\nstdout:%q\nstderr:%q\nec:%d\nerr:%q", args, stdout, stderr, ec, err)
|
|
| 220 |
- } |
|
| 221 |
- // Should have just short usage |
|
| 222 |
- c.Assert(stderr, checker.Contains, "\nUsage:\t", check.Commentf("Missing short usage on %q\n", args))
|
|
| 223 |
- // But shouldn't have full usage |
|
| 224 |
- c.Assert(stderr, checker.Not(checker.Contains), "--help=false", check.Commentf("Should not have full usage on %q\n", args))
|
|
| 225 |
- c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line on %q\n", args))
|
|
| 131 |
+ for index := 0; index < len(cmdsToTest); index++ {
|
|
| 132 |
+ err := <-errChan |
|
| 133 |
+ if err != nil {
|
|
| 134 |
+ c.Fatal(err) |
|
| 226 | 135 |
} |
| 227 |
- |
|
| 228 | 136 |
} |
| 229 | 137 |
|
| 230 | 138 |
// Number of commands for standard release and experimental release |
| ... | ... |
@@ -296,3 +207,136 @@ func (s *DockerSuite) TestHelpExitCodesHelpOutput(c *check.C) {
|
| 296 | 296 |
c.Assert(stdout, checker.Equals, "") |
| 297 | 297 |
c.Assert(stderr, checker.Equals, "docker: 'BadCmd' is not a docker command.\nSee 'docker --help'.\n", check.Commentf("Unexcepted output for 'docker badCmd'\n"))
|
| 298 | 298 |
} |
| 299 |
+ |
|
| 300 |
+func testCommand(cmd string, newEnvs []string, scanForHome bool, home string) error {
|
|
| 301 |
+ |
|
| 302 |
+ args := strings.Split(cmd+" --help", " ") |
|
| 303 |
+ |
|
| 304 |
+ // Check the full usage text |
|
| 305 |
+ helpCmd := exec.Command(dockerBinary, args...) |
|
| 306 |
+ helpCmd.Env = newEnvs |
|
| 307 |
+ out, stderr, _, err := runCommandWithStdoutStderr(helpCmd) |
|
| 308 |
+ if len(stderr) != 0 {
|
|
| 309 |
+ return fmt.Errorf("Error on %q help. non-empty stderr:%q\n", cmd, stderr)
|
|
| 310 |
+ } |
|
| 311 |
+ if strings.HasSuffix(out, "\n\n") {
|
|
| 312 |
+ return fmt.Errorf("Should not have blank line on %q\n", cmd)
|
|
| 313 |
+ } |
|
| 314 |
+ if !strings.Contains(out, "--help") {
|
|
| 315 |
+ return fmt.Errorf("All commands should mention '--help'. Command '%v' did not.\n", cmd)
|
|
| 316 |
+ } |
|
| 317 |
+ |
|
| 318 |
+ if err != nil {
|
|
| 319 |
+ return fmt.Errorf(out) |
|
| 320 |
+ } |
|
| 321 |
+ |
|
| 322 |
+ // Check each line for lots of stuff |
|
| 323 |
+ lines := strings.Split(out, "\n") |
|
| 324 |
+ for _, line := range lines {
|
|
| 325 |
+ if len(line) > 107 {
|
|
| 326 |
+ return fmt.Errorf("Help for %q is too long:\n%s\n", cmd, line)
|
|
| 327 |
+ } |
|
| 328 |
+ |
|
| 329 |
+ if scanForHome && strings.Contains(line, `"`+home) {
|
|
| 330 |
+ return fmt.Errorf("Help for %q should use ~ instead of %q on:\n%s\n",
|
|
| 331 |
+ cmd, home, line) |
|
| 332 |
+ } |
|
| 333 |
+ i := strings.Index(line, "~") |
|
| 334 |
+ if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
|
|
| 335 |
+ return fmt.Errorf("Help for %q should not have used ~:\n%s", cmd, line)
|
|
| 336 |
+ } |
|
| 337 |
+ |
|
| 338 |
+ // If a line starts with 4 spaces then assume someone |
|
| 339 |
+ // added a multi-line description for an option and we need |
|
| 340 |
+ // to flag it |
|
| 341 |
+ if strings.HasPrefix(line, " ") {
|
|
| 342 |
+ return fmt.Errorf("Help for %q should not have a multi-line option", cmd)
|
|
| 343 |
+ } |
|
| 344 |
+ |
|
| 345 |
+ // Options should NOT end with a period |
|
| 346 |
+ if strings.HasPrefix(line, " -") && strings.HasSuffix(line, ".") {
|
|
| 347 |
+ return fmt.Errorf("Help for %q should not end with a period: %s", cmd, line)
|
|
| 348 |
+ } |
|
| 349 |
+ |
|
| 350 |
+ // Options should NOT end with a space |
|
| 351 |
+ if strings.HasSuffix(line, " ") {
|
|
| 352 |
+ return fmt.Errorf("Help for %q should not end with a space", cmd)
|
|
| 353 |
+ } |
|
| 354 |
+ |
|
| 355 |
+ } |
|
| 356 |
+ |
|
| 357 |
+ // For each command make sure we generate an error |
|
| 358 |
+ // if we give a bad arg |
|
| 359 |
+ args = strings.Split(cmd+" --badArg", " ") |
|
| 360 |
+ |
|
| 361 |
+ out, _, err = dockerCmdWithError(args...) |
|
| 362 |
+ if err == nil {
|
|
| 363 |
+ return fmt.Errorf(out) |
|
| 364 |
+ } |
|
| 365 |
+ |
|
| 366 |
+ // Be really picky |
|
| 367 |
+ if strings.HasSuffix(stderr, "\n\n") {
|
|
| 368 |
+ return fmt.Errorf("Should not have a blank line at the end of 'docker rm'\n")
|
|
| 369 |
+ } |
|
| 370 |
+ |
|
| 371 |
+ // Now make sure that each command will print a short-usage |
|
| 372 |
+ // (not a full usage - meaning no opts section) if we |
|
| 373 |
+ // are missing a required arg or pass in a bad arg |
|
| 374 |
+ |
|
| 375 |
+ // These commands will never print a short-usage so don't test |
|
| 376 |
+ noShortUsage := map[string]string{
|
|
| 377 |
+ "images": "", |
|
| 378 |
+ "login": "", |
|
| 379 |
+ "logout": "", |
|
| 380 |
+ "network": "", |
|
| 381 |
+ "stats": "", |
|
| 382 |
+ } |
|
| 383 |
+ |
|
| 384 |
+ if _, ok := noShortUsage[cmd]; !ok {
|
|
| 385 |
+ // For each command run it w/o any args. It will either return |
|
| 386 |
+ // valid output or print a short-usage |
|
| 387 |
+ var dCmd *exec.Cmd |
|
| 388 |
+ |
|
| 389 |
+ // skipNoArgs are ones that we don't want to try w/o |
|
| 390 |
+ // any args. Either because it'll hang the test or |
|
| 391 |
+ // lead to incorrect test result (like false negative). |
|
| 392 |
+ // Whatever the reason, skip trying to run w/o args and |
|
| 393 |
+ // jump to trying with a bogus arg. |
|
| 394 |
+ skipNoArgs := map[string]struct{}{
|
|
| 395 |
+ "daemon": {},
|
|
| 396 |
+ "events": {},
|
|
| 397 |
+ "load": {},
|
|
| 398 |
+ } |
|
| 399 |
+ |
|
| 400 |
+ ec := 0 |
|
| 401 |
+ if _, ok := skipNoArgs[cmd]; !ok {
|
|
| 402 |
+ args = strings.Split(cmd, " ") |
|
| 403 |
+ dCmd = exec.Command(dockerBinary, args...) |
|
| 404 |
+ out, stderr, ec, err = runCommandWithStdoutStderr(dCmd) |
|
| 405 |
+ } |
|
| 406 |
+ |
|
| 407 |
+ // If its ok w/o any args then try again with an arg |
|
| 408 |
+ if ec == 0 {
|
|
| 409 |
+ args = strings.Split(cmd+" badArg", " ") |
|
| 410 |
+ dCmd = exec.Command(dockerBinary, args...) |
|
| 411 |
+ out, stderr, ec, err = runCommandWithStdoutStderr(dCmd) |
|
| 412 |
+ } |
|
| 413 |
+ |
|
| 414 |
+ if len(out) != 0 || len(stderr) == 0 || ec == 0 || err == nil {
|
|
| 415 |
+ return fmt.Errorf("Bad output from %q\nstdout:%q\nstderr:%q\nec:%d\nerr:%q\n", args, out, stderr, ec, err)
|
|
| 416 |
+ } |
|
| 417 |
+ // Should have just short usage |
|
| 418 |
+ if !strings.Contains(stderr, "\nUsage:\t") {
|
|
| 419 |
+ return fmt.Errorf("Missing short usage on %q\n", args)
|
|
| 420 |
+ } |
|
| 421 |
+ // But shouldn't have full usage |
|
| 422 |
+ if strings.Contains(stderr, "--help=false") {
|
|
| 423 |
+ return fmt.Errorf("Should not have full usage on %q\n", args)
|
|
| 424 |
+ } |
|
| 425 |
+ if strings.HasSuffix(stderr, "\n\n") {
|
|
| 426 |
+ return fmt.Errorf("Should not have a blank line on %q\n", args)
|
|
| 427 |
+ } |
|
| 428 |
+ } |
|
| 429 |
+ |
|
| 430 |
+ return nil |
|
| 431 |
+} |