test coverage: 86.9% of statements

Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
diff --git a/cli/cli.go b/cli/cli.go
index 680f5f5..fdadf11 100644
--- a/cli/cli.go
+++ b/cli/cli.go
@@ -7,6 +7,7 @@
 	"fmt"
 	"os"
 	"path/filepath"
+	"sort"
 	"strings"
 	"text/tabwriter"
 )
@@ -80,9 +81,7 @@
 // Run is the entry point for the program. It parses the arguments and executes
 // the commands.
 func (p *Program) Run() {
-	// Create the context with the values we need to pass to the version command.
-	ctx := context.WithValue(context.Background(), GitCommitKey, p.GitCommit)
-	ctx = context.WithValue(ctx, VersionKey, p.Version)
+	ctx := p.defaultContext()
 
 	// Pass the os.Args through so we can more easily unit test.
 	printUsage, err := p.run(ctx, os.Args)
@@ -284,13 +283,23 @@
 type mflag struct {
 	name     string
 	defValue string
+	usage    string
+}
+
+// byName implements sort.Interface for []mflag based on the name field.
+type byName []mflag
+
+func (n byName) Len() int      { return len(n) }
+func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
+func (n byName) Less(i, j int) bool {
+	return strings.TrimPrefix(n[i].name, "-") < strings.TrimPrefix(n[j].name, "-")
 }
 
 func resetFlagUsage(fs *flag.FlagSet) {
 	var (
 		hasFlags   bool
 		flagBlock  bytes.Buffer
-		flagMap    = map[string]mflag{}
+		flagMap    = []mflag{}
 		flagWriter = tabwriter.NewWriter(&flagBlock, 0, 4, 2, ' ', 0)
 	)
 
@@ -312,32 +321,32 @@
 
 		// Try and find duplicates (or the shortcode flags and combine them.
 		// Like: -, --password
-		v, ok := flagMap[f.Usage]
-		if !ok {
-			flagMap[f.Usage] = mflag{
-				name:     name,
-				defValue: defValue,
+		for k, v := range flagMap {
+			if v.usage == f.Usage {
+				if len(v.name) <= 2 {
+					// We already had the shortcode, let's append.
+					v.name = fmt.Sprintf("%s, -%s", v.name, name)
+				} else {
+					v.name = fmt.Sprintf("%s, -%s", name, v.name)
+				}
+				flagMap[k].name = v.name
+
+				// Return here.
+				return
 			}
-
-			// Return here.
-			return
 		}
 
-		if len(v.name) <= 2 {
-			// We already had the shortcode, let's append.
-			v.name = fmt.Sprintf("%s, -%s", v.name, name)
-		} else {
-			v.name = fmt.Sprintf("%s, -%s", name, v.name)
-		}
-
-		flagMap[f.Usage] = mflag{
-			name:     v.name,
+		flagMap = append(flagMap, mflag{
+			name:     name,
 			defValue: defValue,
-		}
+			usage:    f.Usage,
+		})
 	})
 
-	for desc, fm := range flagMap {
-		fmt.Fprintf(flagWriter, "\t-%s\t%s (default: %s)\n", fm.name, desc, fm.defValue)
+	// Sort by name and preserve order on output.
+	sort.Sort(byName(flagMap))
+	for i := 0; i < len(flagMap); i++ {
+		fmt.Fprintf(flagWriter, "\t-%s\t%s (default: %s)\n", flagMap[i].name, flagMap[i].usage, flagMap[i].defValue)
 	}
 
 	flagWriter.Flush()
@@ -377,3 +386,9 @@
 	}
 	return false
 }
+
+func (p *Program) defaultContext() context.Context {
+	// Create the context with the values we need to pass to the version command.
+	ctx := context.WithValue(context.Background(), GitCommitKey, p.GitCommit)
+	return context.WithValue(ctx, VersionKey, p.Version)
+}
diff --git a/cli/cli_test.go b/cli/cli_test.go
index 75fbd20..bc30738 100644
--- a/cli/cli_test.go
+++ b/cli/cli_test.go
@@ -10,6 +10,8 @@
 	"os"
 	"strings"
 	"testing"
+
+	"github.com/genuinetools/img/version"
 )
 
 const (
@@ -202,6 +204,93 @@
 	}
 }
 
+func TestProgramUsage(t *testing.T) {
+	var (
+		debug  bool
+		token  string
+		output string
+
+		expectedOutput = `sample -  My sample command line tool.
+
+Usage: sample <command>
+
+Flags:
+
+  -d, --debug  enable debug logging (default: false)
+  -o           where to save the output (default: defaultOutput)
+  --token      API token (default: <none>)
+
+Commands:
+
+  error    Show the test information.
+  test     Show the test information.
+  version  Show the version information.
+
+`
+
+		expectedVersionOutput = `Usage: sample version` + " " + `
+
+Show the version information.
+
+Flags:
+
+  -d, --debug  enable debug logging (default: false)
+  -o           where to save the output (default: defaultOutput)
+  --token      API token (default: <none>)
+
+`
+	)
+
+	// Setup the program.
+	p := NewProgram()
+	p.Name = "sample"
+	p.Description = "My sample command line tool"
+
+	// Set the GitCommit and Version.
+	p.GitCommit = version.GITCOMMIT
+	p.Version = version.VERSION
+
+	// Setup the global flags.
+	p.FlagSet = flag.NewFlagSet("global", flag.ExitOnError)
+	p.FlagSet.StringVar(&token, "token", "", "API token")
+	p.FlagSet.StringVar(&output, "o", "defaultOutput", "where to save the output")
+	p.FlagSet.BoolVar(&debug, "d", false, "enable debug logging")
+	p.FlagSet.BoolVar(&debug, "debug", false, "enable debug logging")
+
+	p.Commands = []Command{
+		&errorCommand{},
+		&testCommand{},
+	}
+	p.Action = nilActionFunction
+
+	p.Run()
+
+	c := startCapture(t)
+	if err := p.usage(p.defaultContext()); err != nil {
+		t.Fatal(err)
+	}
+	stdout, stderr := c.finish()
+	if stderr != expectedOutput {
+		t.Fatalf("expected: %s\ngot: %s", expectedOutput, stderr)
+	}
+	if len(stdout) > 0 {
+		t.Fatalf("expected no stdout, got: %s", stdout)
+	}
+
+	// Test versionCommand.
+	vcmd := &versionCommand{}
+	c = startCapture(t)
+	p.resetCommandUsage(vcmd)
+	p.FlagSet.Usage()
+	stdout, stderr = c.finish()
+	if stderr != expectedVersionOutput {
+		t.Fatalf("expected: %q\ngot: %q", expectedVersionOutput, stderr)
+	}
+	if len(stdout) > 0 {
+		t.Fatalf("expected no stdout, got: %s", stdout)
+	}
+}
+
 func TestProgramWithNoCommandsOrFlagsOrAction(t *testing.T) {
 	p := NewProgram()
 	testCases := append(testCasesEmpty(), testCasesUndefinedCommand()...)
@@ -231,13 +320,9 @@
 
 	for _, tc := range testCases {
 		t.Run(tc.description, func(t *testing.T) {
-			// Create the context with the values we need to pass to the version command.
-			ctx := context.WithValue(context.Background(), GitCommitKey, p.GitCommit)
-			ctx = context.WithValue(ctx, VersionKey, p.Version)
-
 			c := startCapture(t)
-			printUsage, err := p.run(ctx, tc.args)
-			stdout, _ := c.finish()
+			printUsage, err := p.run(p.defaultContext(), tc.args)
+			stdout, stderr := c.finish()
 			if strings.Contains(stdout, versionExpected) {
 				t.Fatalf("did not expect version information to print, got %s", stdout)
 			}
@@ -247,6 +332,9 @@
 			if !printUsage {
 				t.Fatal("expected printUsage to be true")
 			}
+			if len(stderr) > 0 {
+				t.Fatalf("expected no stderr, got: %s", stderr)
+			}
 		})
 	}
 }
@@ -435,13 +523,12 @@
 }
 
 func (p *Program) doTestRun(t *testing.T, tc testCase) {
-	// Create the context with the values we need to pass to the version command.
-	ctx := context.WithValue(context.Background(), GitCommitKey, p.GitCommit)
-	ctx = context.WithValue(ctx, VersionKey, p.Version)
-
 	c := startCapture(t)
-	printUsage, err := p.run(ctx, tc.args)
-	stdout, _ := c.finish()
+	printUsage, err := p.run(p.defaultContext(), tc.args)
+	stdout, stderr := c.finish()
+	if len(stderr) > 0 {
+		t.Fatalf("expected no stderr, got: %s", stderr)
+	}
 
 	// IF
 	// we DON'T EXPECT and error on Before