Added command test.

- cmd/micromdm now has a simple test.
- changed flagset defaults to support testing and remove default side
effects. Go flags write to os.Stderr and call os.Exit(2) when parsing
usage.
This commit is contained in:
Victor Vrantchan
2020-07-10 08:31:29 -04:00
parent b5c0644ff5
commit dc6fa6fb53
2 changed files with 91 additions and 3 deletions

View File

@@ -33,11 +33,15 @@ func micromdm(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
ctx = context.Background()
logger = log.New()
ffOptions = []ff.Option{ff.WithConfigFileParser(ff.PlainParser), ff.WithConfigFileFlag("config")}
rootfs = flag.NewFlagSet("micromdm", flag.ExitOnError)
rootfs = flag.NewFlagSet("micromdm", flag.ContinueOnError)
pidfile = rootfs.String("pidfile", "/tmp/micromdm.pid", "Path to server pidfile")
_ = rootfs.String("config", "", "Path to config file (optional)")
)
// default output is os.Stderr.
// setting the output and flag.ContinueOnError overrides allows testing usage.
rootfs.SetOutput(stderr)
version := &ffcli.Command{
Name: "version",
ShortUsage: "version [<arg> ...]",
@@ -48,11 +52,21 @@ func micromdm(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
},
}
// add a help subcommand to make usage more discoverable.
helpCmd := &ffcli.Command{
Name: "help",
UsageFunc: func(c *ffcli.Command) string { return "" },
Exec: func(_ context.Context, args []string) error {
rootfs.Usage()
return flag.ErrHelp
},
}
root := &ffcli.Command{
ShortUsage: "micromdm [flags] <subcommand>",
FlagSet: rootfs,
Options: ffOptions,
Subcommands: []*ffcli.Command{version},
Subcommands: []*ffcli.Command{helpCmd, version},
Exec: func(context.Context, []string) error {
if err := writePID(*pidfile); err != nil {
return err
@@ -107,8 +121,10 @@ func micromdm(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
}
switch err := root.ParseAndRun(ctx, args[1:]); {
case err == nil, errors.Is(err, flag.ErrHelp):
case err == nil:
return 0
case errors.Is(err, flag.ErrHelp):
return 2
default:
fmt.Fprintln(stderr) // when Ctrl+C is used, avoid messing up the logger line
log.Info(logger).Log("exit", err)

View File

@@ -0,0 +1,72 @@
package main
import (
"bytes"
"strings"
"testing"
)
type mainIOFunc func(t *testing.T, stdin, stdout, stderr *bytes.Buffer)
func mainUsage(t *testing.T, stdin, stdout, stderr *bytes.Buffer) {
output := stderr.String()
words := []string{"USAGE", "pidfile"}
for _, word := range words {
if !strings.Contains(output, word) {
t.Errorf("expected %q in output, got:\n%s", word, output)
}
}
}
func TestMain(t *testing.T) {
tests := []struct {
name string
stdin *bytes.Buffer
stdout *bytes.Buffer
stderr *bytes.Buffer
args []string
exit int
check mainIOFunc
}{
{
name: "short usage",
stdin: new(bytes.Buffer),
stdout: new(bytes.Buffer),
stderr: new(bytes.Buffer),
args: []string{"micromdm", "-h"},
exit: 2,
check: mainUsage,
},
{
name: "long usage",
stdin: new(bytes.Buffer),
stdout: new(bytes.Buffer),
stderr: new(bytes.Buffer),
args: []string{"micromdm", "-help"},
exit: 2,
check: mainUsage,
},
{
name: "subcommand help usage",
stdin: new(bytes.Buffer),
stdout: new(bytes.Buffer),
stderr: new(bytes.Buffer),
args: []string{"micromdm", "help"},
exit: 2,
check: mainUsage,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got, want := micromdm(tt.args, tt.stdin, tt.stdout, tt.stderr), tt.exit; got != want {
t.Fatalf("exit code: got %d, want %d", got, want)
}
tt.check(t, tt.stdin, tt.stdout, tt.stderr)
})
}
}