2203b377 |
package main
import ( |
116367eb |
"os" |
2203b377 |
"os/exec" |
116367eb |
"runtime" |
2203b377 |
"strings" |
969ba5c7 |
"unicode" |
1c9b37cb |
"github.com/docker/docker/pkg/homedir" |
8845259f |
"github.com/docker/docker/pkg/integration/checker" |
dc944ea7 |
"github.com/go-check/check" |
2203b377 |
)
|
dc944ea7 |
func (s *DockerSuite) TestHelpTextVerify(c *check.C) { |
f9a3558a |
testRequires(c, DaemonIsLinux) |
2203b377 |
// Make sure main help text fits within 80 chars and that |
116367eb |
// on non-windows system we use ~ when possible (to shorten things).
// Test for HOME set to its default value and set to "/" on linux
// Yes on windows setting up an array and looping (right now) isn't
// necessary because we just have one value, but we'll need the
// array/loop on linux so we might as well set it up so that we can
// test any number of home dirs later on and all we need to do is
// modify the array - the rest of the testing infrastructure should work
homes := []string{homedir.Get()} |
2203b377 |
|
116367eb |
// Non-Windows machines need to test for this special case of $HOME
if runtime.GOOS != "windows" {
homes = append(homes, "/") |
2203b377 |
} |
1c9b37cb |
|
116367eb |
homeKey := homedir.Key()
baseEnvs := os.Environ() |
2203b377 |
|
116367eb |
// Remove HOME env var from list so we can add a new value later.
for i, env := range baseEnvs {
if strings.HasPrefix(env, homeKey+"=") {
baseEnvs = append(baseEnvs[:i], baseEnvs[i+1:]...) |
969ba5c7 |
break
} |
116367eb |
} |
969ba5c7 |
|
116367eb |
for _, home := range homes {
// Dup baseEnvs and add our new HOME value
newEnvs := make([]string, len(baseEnvs)+1)
copy(newEnvs, baseEnvs)
newEnvs[len(newEnvs)-1] = homeKey + "=" + home |
969ba5c7 |
|
116367eb |
scanForHome := runtime.GOOS != "windows" && home != "/" |
969ba5c7 |
|
116367eb |
// Check main help text to make sure its not over 80 chars
helpCmd := exec.Command(dockerBinary, "help")
helpCmd.Env = newEnvs |
8845259f |
out, _, err := runCommandWithOutput(helpCmd)
c.Assert(err, checker.IsNil, check.Commentf(out)) |
2203b377 |
lines := strings.Split(out, "\n")
for _, line := range lines { |
8845259f |
c.Assert(len(line), checker.LessOrEqualThan, 80, check.Commentf("Line is too long:\n%s", line)) |
5595da2b |
|
491b63e0 |
// All lines should not end with a space |
8845259f |
c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Line should not end with a space")) |
491b63e0 |
|
116367eb |
if scanForHome && strings.Contains(line, `=`+home) { |
dc944ea7 |
c.Fatalf("Line should use '%q' instead of %q:\n%s", homedir.GetShortcutString(), home, line) |
116367eb |
}
if runtime.GOOS != "windows" {
i := strings.Index(line, homedir.GetShortcutString())
if i >= 0 && i != len(line)-1 && line[i+1] != '/' { |
dc944ea7 |
c.Fatalf("Main help should not have used home shortcut:\n%s", line) |
116367eb |
} |
2203b377 |
}
}
|
73a6ac00 |
// Make sure each cmd's help text fits within 90 chars and that |
116367eb |
// on non-windows system we use ~ when possible (to shorten things).
// Pull the list of commands from the "Commands:" section of docker help
helpCmd = exec.Command(dockerBinary, "help")
helpCmd.Env = newEnvs |
8845259f |
out, _, err = runCommandWithOutput(helpCmd)
c.Assert(err, checker.IsNil, check.Commentf(out)) |
116367eb |
i := strings.Index(out, "Commands:") |
8845259f |
c.Assert(i, checker.GreaterOrEqualThan, 0, check.Commentf("Missing 'Commands:' in:\n%s", out)) |
116367eb |
cmds := []string{} |
e7fc6321 |
// Grab all chars starting at "Commands:"
helpOut := strings.Split(out[i:], "\n")
// First line is just "Commands:"
if isLocalDaemon {
// Replace first line with "daemon" command since it's not part of the list of commands.
helpOut[0] = " daemon"
} else {
// Skip first line
helpOut = helpOut[1:]
} |
8324d791 |
|
87255b67 |
// Create the list of commands we want to test
cmdsToTest := []string{}
for _, cmd := range helpOut { |
116367eb |
// Stop on blank line or non-idented line
if cmd == "" || !unicode.IsSpace(rune(cmd[0])) {
break
}
// Grab just the first word of each line
cmd = strings.Split(strings.TrimSpace(cmd), " ")[0] |
87255b67 |
cmds = append(cmds, cmd) // Saving count for later
cmdsToTest = append(cmdsToTest, cmd)
}
// Add some 'two word' commands - would be nice to automatically
// calculate this list - somehow
cmdsToTest = append(cmdsToTest, "volume create")
cmdsToTest = append(cmdsToTest, "volume inspect")
cmdsToTest = append(cmdsToTest, "volume ls")
cmdsToTest = append(cmdsToTest, "volume rm")
for _, cmd := range cmdsToTest {
var stderr string
args := strings.Split(cmd+" --help", " ") |
116367eb |
|
8324d791 |
// Check the full usage text |
87255b67 |
helpCmd := exec.Command(dockerBinary, args...) |
116367eb |
helpCmd.Env = newEnvs |
8845259f |
out, stderr, _, err = runCommandWithStdoutStderr(helpCmd)
c.Assert(len(stderr), checker.Equals, 0, check.Commentf("Error on %q help. non-empty stderr:%q", cmd, stderr))
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have blank line on %q\n", cmd)) |
48718a3c |
c.Assert(out, checker.Contains, "--help", check.Commentf("All commands should mention '--help'. Command '%v' did not.\n", cmd)) |
8845259f |
c.Assert(err, checker.IsNil, check.Commentf(out)) |
8324d791 |
// Check each line for lots of stuff |
116367eb |
lines := strings.Split(out, "\n")
for _, line := range lines { |
677a6b35 |
c.Assert(len(line), checker.LessOrEqualThan, 107, check.Commentf("Help for %q is too long:\n%s", cmd, line)) |
5595da2b |
|
116367eb |
if scanForHome && strings.Contains(line, `"`+home) { |
dc944ea7 |
c.Fatalf("Help for %q should use ~ instead of %q on:\n%s", |
116367eb |
cmd, home, line)
}
i := strings.Index(line, "~")
if i >= 0 && i != len(line)-1 && line[i+1] != '/' { |
dc944ea7 |
c.Fatalf("Help for %q should not have used ~:\n%s", cmd, line) |
116367eb |
} |
5595da2b |
// If a line starts with 4 spaces then assume someone
// added a multi-line description for an option and we need
// to flag it |
8845259f |
c.Assert(line, checker.Not(checker.HasPrefix), " ", check.Commentf("Help for %q should not have a multi-line option", cmd)) |
5595da2b |
// Options should NOT end with a period
if strings.HasPrefix(line, " -") && strings.HasSuffix(line, ".") { |
dc944ea7 |
c.Fatalf("Help for %q should not end with a period: %s", cmd, line) |
5595da2b |
} |
2b051bcb |
|
491b63e0 |
// Options should NOT end with a space |
8845259f |
c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Help for %q should not end with a space", cmd)) |
491b63e0 |
|
116367eb |
} |
8324d791 |
// For each command make sure we generate an error
// if we give a bad arg |
87255b67 |
args = strings.Split(cmd+" --badArg", " ")
|
8845259f |
out, _, err = dockerCmdWithError(args...)
c.Assert(err, checker.NotNil, check.Commentf(out)) |
8324d791 |
// Be really picky |
8845259f |
c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker rm'\n")) |
8324d791 |
// Now make sure that each command will print a short-usage
// (not a full usage - meaning no opts section) if we
// are missing a required arg or pass in a bad arg
// These commands will never print a short-usage so don't test
noShortUsage := map[string]string{ |
44da5c3d |
"images": "",
"login": "",
"logout": "",
"network": "", |
ae818a82 |
"stats": "", |
8324d791 |
}
if _, ok := noShortUsage[cmd]; !ok {
// For each command run it w/o any args. It will either return
// valid output or print a short-usage
var dCmd *exec.Cmd
var stdout, stderr string
var args []string
// skipNoArgs are ones that we don't want to try w/o
// any args. Either because it'll hang the test or
// lead to incorrect test result (like false negative).
// Whatever the reason, skip trying to run w/o args and
// jump to trying with a bogus arg. |
e7fc6321 |
skipNoArgs := map[string]struct{}{
"daemon": {},
"events": {},
"load": {}, |
8324d791 |
}
|
8845259f |
ec := 0 |
8324d791 |
if _, ok := skipNoArgs[cmd]; !ok { |
87255b67 |
args = strings.Split(cmd, " ") |
8324d791 |
dCmd = exec.Command(dockerBinary, args...)
stdout, stderr, ec, err = runCommandWithStdoutStderr(dCmd)
}
// If its ok w/o any args then try again with an arg
if ec == 0 { |
87255b67 |
args = strings.Split(cmd+" badArg", " ") |
8324d791 |
dCmd = exec.Command(dockerBinary, args...)
stdout, stderr, ec, err = runCommandWithStdoutStderr(dCmd)
}
if len(stdout) != 0 || len(stderr) == 0 || ec == 0 || err == nil {
c.Fatalf("Bad output from %q\nstdout:%q\nstderr:%q\nec:%d\nerr:%q", args, stdout, stderr, ec, err)
}
// Should have just short usage |
8845259f |
c.Assert(stderr, checker.Contains, "\nUsage:\t", check.Commentf("Missing short usage on %q\n", args)) |
8324d791 |
// But shouldn't have full usage |
8845259f |
c.Assert(stderr, checker.Not(checker.Contains), "--help=false", check.Commentf("Should not have full usage on %q\n", args))
c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line on %q\n", args)) |
8324d791 |
}
|
116367eb |
}
|
44da5c3d |
// Number of commands for standard release and experimental release |
8799c4fc |
standard := 41 |
44da5c3d |
experimental := 1
expected := standard + experimental |
e7fc6321 |
if isLocalDaemon {
expected++ // for the daemon command
} |
8845259f |
c.Assert(len(cmds), checker.LessOrEqualThan, expected, check.Commentf("Wrong # of cmds, it should be: %d\nThe list:\n%q", expected, cmds)) |
969ba5c7 |
}
|
2203b377 |
} |
0024935f |
|
8324d791 |
func (s *DockerSuite) TestHelpExitCodesHelpOutput(c *check.C) { |
f9a3558a |
testRequires(c, DaemonIsLinux) |
8324d791 |
// Test to make sure the exit code and output (stdout vs stderr) of
// various good and bad cases are what we expect |
0024935f |
|
8324d791 |
// docker : stdout=all, stderr=empty, rc=0 |
8845259f |
out, _, err := dockerCmdWithError()
c.Assert(err, checker.IsNil, check.Commentf(out)) |
8324d791 |
// Be really pick |
8845259f |
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker'\n")) |
0024935f |
|
8324d791 |
// docker help: stdout=all, stderr=empty, rc=0 |
8845259f |
out, _, err = dockerCmdWithError("help")
c.Assert(err, checker.IsNil, check.Commentf(out)) |
8324d791 |
// Be really pick |
8845259f |
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker help'\n")) |
0024935f |
|
8324d791 |
// docker --help: stdout=all, stderr=empty, rc=0 |
8845259f |
out, _, err = dockerCmdWithError("--help")
c.Assert(err, checker.IsNil, check.Commentf(out)) |
8324d791 |
// Be really pick |
8845259f |
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker --help'\n")) |
0024935f |
|
8324d791 |
// docker inspect busybox: stdout=all, stderr=empty, rc=0
// Just making sure stderr is empty on valid cmd |
8845259f |
out, _, err = dockerCmdWithError("inspect", "busybox")
c.Assert(err, checker.IsNil, check.Commentf(out)) |
8324d791 |
// Be really pick |
8845259f |
c.Assert(out, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker inspect busyBox'\n")) |
8324d791 |
// docker rm: stdout=empty, stderr=all, rc!=0
// testing the min arg error msg |
8845259f |
cmd := exec.Command(dockerBinary, "rm")
stdout, stderr, _, err := runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.NotNil)
c.Assert(stdout, checker.Equals, "") |
8324d791 |
// Should not contain full help text but should contain info about
// # of args and Usage line |
8845259f |
c.Assert(stderr, checker.Contains, "requires a minimum", check.Commentf("Missing # of args text from 'docker rm'\n")) |
8324d791 |
// docker rm NoSuchContainer: stdout=empty, stderr=all, rc=0
// testing to make sure no blank line on error
cmd = exec.Command(dockerBinary, "rm", "NoSuchContainer") |
8845259f |
stdout, stderr, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.NotNil)
c.Assert(len(stderr), checker.Not(checker.Equals), 0)
c.Assert(stdout, checker.Equals, "") |
8324d791 |
// Be really picky |
8845259f |
c.Assert(stderr, checker.Not(checker.HasSuffix), "\n\n", check.Commentf("Should not have a blank line at the end of 'docker rm'\n")) |
8324d791 |
// docker BadCmd: stdout=empty, stderr=all, rc=0
cmd = exec.Command(dockerBinary, "BadCmd") |
8845259f |
stdout, stderr, _, err = runCommandWithStdoutStderr(cmd)
c.Assert(err, checker.NotNil)
c.Assert(stdout, checker.Equals, "")
c.Assert(stderr, checker.Equals, "docker: 'BadCmd' is not a docker command.\nSee 'docker --help'.\n", check.Commentf("Unexcepted output for 'docker badCmd'\n")) |
0024935f |
} |