diff --git a/cmd/inspect.go b/cmd/inspect.go index f1bbd41dc..b3d19d013 100644 --- a/cmd/inspect.go +++ b/cmd/inspect.go @@ -22,18 +22,17 @@ func NewInspectCommand(stdin io.Reader, stdout, stderr io.Writer) *cobra.Command Long: ` Inspects a data file and provides stats. `, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { - fmt.Println("path required") - return + return fmt.Errorf("path required") } else if len(args) > 1 { - fmt.Println("only one path allowed") - return + return fmt.Errorf("only one path allowed") } Inspector.Path = args[0] if err := Inspector.Run(context.Background()); err != nil { - fmt.Println(err) + return err } + return nil }, } return inspectCmd diff --git a/cmd/inspect_test.go b/cmd/inspect_test.go index b81078a8a..619f6fbe9 100644 --- a/cmd/inspect_test.go +++ b/cmd/inspect_test.go @@ -6,9 +6,23 @@ import ( ) func TestInspectHelp(t *testing.T) { - output := ExecNewRootCommand(t, "inspect", "--help") + output, err := ExecNewRootCommand(t, "inspect", "--help") if !strings.Contains(output, "Usage:") || - !strings.Contains(output, "pilosa inspect") { - t.Fatalf("Command 'inspect --help' not working, got: %s", output) + !strings.Contains(output, "pilosa inspect") || err != nil { + t.Fatalf("Command 'inspect --help' not working, err: '%v', output: '%s'", err, output) + } +} + +func TestInspectNoPath(t *testing.T) { + output, err := ExecNewRootCommand(t, "inspect") + if !strings.Contains(err.Error(), "path required") { + t.Fatalf("Command 'inspect' without args should error but: err: '%v', output: '%v'", err, output) + } +} + +func TestInspectMultiPath(t *testing.T) { + output, err := ExecNewRootCommand(t, "inspect", "one", "two") + if !strings.Contains(err.Error(), "only one path") { + t.Fatalf("Command 'inspect' without args should error but: err: '%v', output: '%v'", err, output) } } diff --git a/cmd/root_test.go b/cmd/root_test.go index 113815e45..a19db932a 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -5,6 +5,7 @@ import ( "io" "io/ioutil" "os" + "reflect" "strings" "testing" @@ -24,48 +25,99 @@ func failErr(t *testing.T, err error, context ...string) { // tExec executes the given `cmd`, which will be writing its output to `w`, and // can be read from `out`. It will fail the test if the command does not return // within 1 second. Useful for testing help messages and such. -func tExec(t *testing.T, cmd *cobra.Command, out io.Reader, w io.WriteCloser) (output []byte) { +func tExec(t *testing.T, cmd *cobra.Command, out io.Reader, w io.WriteCloser) (output []byte, err error) { done := make(chan struct{}) + var readErr error go func() { - var err error - output, err = ioutil.ReadAll(out) - if err != nil { - t.Fatal(err) - } + output, readErr = ioutil.ReadAll(out) close(done) }() fmt.Println("executing") - err := cmd.Execute() + err = cmd.Execute() if err != nil { - t.Fatal(err) + return output, err } if err := w.Close(); err != nil { - t.Fatalf("closing cmd's stdout: %v", err) + return output, fmt.Errorf("closing cmd's stdout: %v", err) } select { case <-done: case <-time.After(time.Second * 1): t.Fatal("Test failed due to command execution timeout") } - return output + return output, readErr } // ExecNewRootCommand executes the pilosa root command with the given arguments // and returns it's output. It will fail if the command does not complete within // 1 second. -func ExecNewRootCommand(t *testing.T, args ...string) string { +func ExecNewRootCommand(t *testing.T, args ...string) (string, error) { out, w := io.Pipe() rc := cmd.NewRootCommand(os.Stdin, w, w) rc.SetArgs(args) - output := tExec(t, rc, out, w) - return string(output) + output, err := tExec(t, rc, out, w) + return string(output), err +} + +type validator struct { + err error +} + +func (v *validator) Check(actual, expected interface{}) { + if v.err != nil { + return + } + if !reflect.DeepEqual(actual, expected) { + v.err = fmt.Errorf("Actual: '%v' is not equal to '%v'", actual, expected) + } +} +func (v *validator) Error() error { return v.err } + +type commandTest struct { + args []string + env map[string]string + cfgFileContent string + validation func() error +} + +func (ct commandTest) setupCommand(t *testing.T) *cobra.Command { + // make config file + cfgFile, err := ioutil.TempFile("", "") + failErr(t, err, "making temp file") + _, err = cfgFile.WriteString(ct.cfgFileContent) + failErr(t, err, "writing config to temp file") + + // set up config file args/env + ct.env["PILOSA_CONFIG"] = cfgFile.Name() + ct.args = append(ct.args[:1], append([]string{"--config=" + cfgFile.Name()}, ct.args[1:]...)...) + + // set up env + for name, val := range ct.env { + err = os.Setenv(name, val) + failErr(t, err, fmt.Sprintf("setting environment variable '%s' to '%s'", name, val)) + } + + // make command and set args + rc := cmd.NewRootCommand(strings.NewReader(""), ioutil.Discard, ioutil.Discard) + rc.SetArgs(ct.args) + + err = cfgFile.Close() + failErr(t, err, "closing config file") + + return rc +} + +func (ct commandTest) reset() { + for name, _ := range ct.env { + os.Setenv(name, "") + } } func TestRootCommand(t *testing.T) { - outStr := ExecNewRootCommand(t, "--help") + outStr, err := ExecNewRootCommand(t, "--help") if !strings.Contains(outStr, "Usage:") || !strings.Contains(outStr, "Available Commands:") || - !strings.Contains(outStr, "--help") { - t.Fatalf("Expected standard usage message from RootCommand, but got: %s", outStr) + !strings.Contains(outStr, "--help") || err != nil { + t.Fatalf("Expected standard usage message from RootCommand, but err: '%v', output: '%s'", err, outStr) } } diff --git a/cmd/server_test.go b/cmd/server_test.go index 807f957ec..c73fbf7c6 100644 --- a/cmd/server_test.go +++ b/cmd/server_test.go @@ -1,49 +1,23 @@ package cmd_test import ( - "fmt" "io/ioutil" - "reflect" "strings" "testing" "time" - "os" - "github.com/pilosa/pilosa" "github.com/pilosa/pilosa/cmd" - "github.com/spf13/cobra" ) func TestServerHelp(t *testing.T) { - output := ExecNewRootCommand(t, "server", "--help") + output, err := ExecNewRootCommand(t, "server", "--help") if !strings.Contains(output, "Usage:") || - !strings.Contains(output, "Flags:") { - t.Fatalf("Command 'server --help' not working, got: %s", output) + !strings.Contains(output, "Flags:") || err != nil { + t.Fatalf("Command 'server --help' not working, err: '%v', output: '%s'", err, output) } } -type validator struct { - err error -} - -func (v *validator) Check(actual, expected interface{}) { - if v.err != nil { - return - } - if !reflect.DeepEqual(actual, expected) { - v.err = fmt.Errorf("Actual: '%v' is not equal to '%v'", actual, expected) - } -} -func (v *validator) Error() error { return v.err } - -type commandTest struct { - args []string - env map[string]string - cfgFileContent string - validation func() error -} - func TestServerConfig(t *testing.T) { actualDataDir, err := ioutil.TempDir("", "") failErr(t, err, "making data dir") @@ -123,6 +97,7 @@ bind = "localhost:0" }, } + // run server tests for i, test := range tests { com := test.setupCommand(t) executed := make(chan struct{}) @@ -146,36 +121,3 @@ bind = "localhost:0" test.reset() } } - -func (ct commandTest) setupCommand(t *testing.T) *cobra.Command { - // make config file - cfgFile, err := ioutil.TempFile("", "") - failErr(t, err, "making temp file") - _, err = cfgFile.WriteString(ct.cfgFileContent) - failErr(t, err, "writing config to temp file") - - // set up config file args/env - ct.env["PILOSA_CONFIG"] = cfgFile.Name() - ct.args = append(ct.args[:1], append([]string{"--config=" + cfgFile.Name()}, ct.args[1:]...)...) - - // set up env - for name, val := range ct.env { - err = os.Setenv(name, val) - failErr(t, err, fmt.Sprintf("setting environment variable '%s' to '%s'", name, val)) - } - - // make command and set args - rc := cmd.NewRootCommand(strings.NewReader(""), ioutil.Discard, ioutil.Discard) - rc.SetArgs(ct.args) - - err = cfgFile.Close() - failErr(t, err, "closing config file") - - return rc -} - -func (ct commandTest) reset() { - for name, _ := range ct.env { - os.Setenv(name, "") - } -}