TBR

v: renaming the v directory to go

Change-Id: I4fd9f6ee2895d8034c23b65927eb118980b3c17a
diff --git a/lib/cmdline/cmdline.go b/lib/cmdline/cmdline.go
new file mode 100644
index 0000000..d6705e6
--- /dev/null
+++ b/lib/cmdline/cmdline.go
@@ -0,0 +1,362 @@
+// Package cmdline provides a data-driven framework to simplify writing
+// command-line programs.  It includes built-in support for formatted help.
+//
+// Commands may be linked together to form a command tree.  Since commands may
+// be arbitrarily nested within other commands, it's easy to create wrapper
+// programs that invoke existing commands.
+//
+// The syntax for each command-line program is:
+//
+//   command [flags] [subcommand [flags]]* [args]
+//
+// Each sequence of flags on the command-line is associated with the command
+// that immediately precedes them.  Global flags registered with the standard
+// flags package are allowed anywhere a command-specific flag is allowed.
+package cmdline
+
+import (
+	"errors"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+)
+
+// ErrUsage is returned to indicate an error in command usage; e.g. unknown
+// flags, subcommands or args.
+var ErrUsage = errors.New("usage error")
+
+// Command represents a single command in a command-line program.  A program
+// with subcommands is represented as a root Command with children representing
+// each subcommand.  The command graph must be a tree; each command may either
+// have exactly one parent (a sub-command), or no parent (the root), and cycles
+// are not allowed.  This makes it easier to display the usage for subcommands.
+type Command struct {
+	Name     string       // Name of the command.
+	Short    string       // Short description, shown in help called on parent.
+	Long     string       // Long description, shown in help called on itself.
+	Flags    flag.FlagSet // Flags for the command.
+	ArgsName string       // Name of the args, shown in usage line.
+	ArgsLong string       // Long description of the args, shown in help.
+
+	// Children of the command.  The framework will match args[0] against each
+	// child's name, and call Run on the first matching child.
+	Children []*Command
+
+	// Run is a function that runs cmd with args.  If both Children and Run are
+	// specified, Run will only be called if none of the children match.  It is an
+	// error if neither is specified.
+	Run func(cmd *Command, args []string) error
+
+	// parent holds the parent of this Command, or nil if this is the root.
+	parent *Command
+
+	// Stdout and stderr are set through Init.
+	stdout, stderr io.Writer
+
+	// parseFlags holds the merged flags used for parsing.  Each command starts
+	// with its own Flags, and we merge in all global flags.  If the same flag is
+	// specified in both sets, the command's own flag wins.
+	parseFlags *flag.FlagSet
+
+	// TODO(toddw): If necessary we can add alias support, e.g. for abbreviations.
+	//   Alias map[string]string
+}
+
+// style describes the formatting style for usage descriptions.
+type style int
+
+const (
+	styleText  style = iota // Default style, good for cmdline output.
+	styleGoDoc              // Style good for godoc processing.
+)
+
+// String returns the human-readable representation of the style.
+func (s *style) String() string {
+	switch *s {
+	case styleText:
+		return "text"
+	case styleGoDoc:
+		return "godoc"
+	default:
+		panic(fmt.Errorf("Unhandled style %d", *s))
+	}
+}
+
+// Set implements the flag.Value interface method.
+func (s *style) Set(value string) error {
+	switch value {
+	case "text":
+		*s = styleText
+	case "godoc":
+		*s = styleGoDoc
+	default:
+		return fmt.Errorf("Unknown style %q", value)
+	}
+	return nil
+}
+
+// Stdout is where output goes.  Typically os.Stdout.
+func (cmd *Command) Stdout() io.Writer {
+	return cmd.stdout
+}
+
+// Stderr is where error messages go.  Typically os.Stderr
+func (cmd *Command) Stderr() io.Writer {
+	return cmd.stderr
+}
+
+// Errorf should be called to signal an invalid usage of the command.
+func (cmd *Command) Errorf(format string, v ...interface{}) error {
+	fmt.Fprint(cmd.stderr, "ERROR: ")
+	fmt.Fprintf(cmd.stderr, format, v...)
+	fmt.Fprint(cmd.stderr, "\n\n")
+	cmd.usage(cmd.stderr, styleText, true)
+	return ErrUsage
+}
+
+// usage prints the usage of cmd to the writer, with the given style.  The
+// firstCall boolean is set to false when printing usage for multiple commands,
+// and is used to avoid printing redundant information (e.g. section headers,
+// global flags).
+func (cmd *Command) usage(w io.Writer, style style, firstCall bool) {
+	var names []string
+	for c := cmd; c != nil; c = c.parent {
+		names = append([]string{c.Name}, names...)
+	}
+	namestr := strings.Join(names, " ")
+	if !firstCall && style == styleGoDoc {
+		// Title-case names so that godoc recognizes it as a section header.
+		fmt.Fprintf(w, "%s\n\n", strings.Title(namestr))
+	}
+	// Long description.
+	fmt.Fprint(w, strings.Trim(cmd.Long, "\n"))
+	fmt.Fprintln(w)
+	// Usage line.
+	hasFlags := false
+	cmd.Flags.VisitAll(func(*flag.Flag) {
+		hasFlags = true
+	})
+	fmt.Fprintf(w, "\nUsage:\n")
+	nameflags := "   " + namestr
+	if hasFlags {
+		nameflags += " [flags]"
+	}
+	if len(cmd.Children) > 0 {
+		fmt.Fprintf(w, "%s <command>\n", nameflags)
+	}
+	if cmd.Run != nil {
+		if cmd.ArgsName != "" {
+			fmt.Fprintf(w, "%s %s\n", nameflags, cmd.ArgsName)
+		} else {
+			fmt.Fprintf(w, "%s\n", nameflags)
+		}
+	}
+	if len(cmd.Children) == 0 && cmd.Run == nil {
+		// This is a specification error.
+		fmt.Fprintf(w, "%s [ERROR: neither Children nor Run is specified]\n", nameflags)
+	}
+	// Commands.
+	if len(cmd.Children) > 0 {
+		fmt.Fprintf(w, "\nThe %s commands are:\n", cmd.Name)
+		for _, child := range cmd.Children {
+			fmt.Fprintf(w, "   %-11s %s\n", child.Name, child.Short)
+		}
+	}
+	// Args.
+	if cmd.Run != nil && cmd.ArgsLong != "" {
+		fmt.Fprintf(w, "\n")
+		fmt.Fprint(w, strings.Trim(cmd.ArgsLong, "\n"))
+		fmt.Fprintf(w, "\n")
+	}
+	// Flags.
+	if hasFlags {
+		fmt.Fprintf(w, "\nThe %s flags are:\n", cmd.Name)
+		cmd.Flags.VisitAll(func(f *flag.Flag) {
+			fmt.Fprintf(w, "   -%s=%s: %s\n", f.Name, f.DefValue, f.Usage)
+		})
+	}
+	// Global flags.
+	hasGlobalFlags := false
+	flag.VisitAll(func(*flag.Flag) {
+		hasGlobalFlags = true
+	})
+	if firstCall && hasGlobalFlags {
+		fmt.Fprintf(w, "\nThe global flags are:\n")
+		flag.VisitAll(func(f *flag.Flag) {
+			fmt.Fprintf(w, "   -%s=%s: %s\n", f.Name, f.DefValue, f.Usage)
+		})
+	}
+}
+
+// newDefaultHelp creates a new default help command.  We need to create new
+// instances since the parent for each help command is different.
+func newDefaultHelp() *Command {
+	helpStyle := styleText
+	help := &Command{
+		Name:  helpName,
+		Short: "Display help for commands",
+		Long: `
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+`,
+		ArgsName: "<command>",
+		ArgsLong: `
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+`,
+		Run: func(cmd *Command, args []string) error {
+			// Help applies to its parent - e.g. "foo help" applies to the foo command.
+			return runHelp(cmd.parent, args, helpStyle)
+		},
+	}
+	help.Flags.Var(&helpStyle, "style", `The formatting style for help output, either "text" or "godoc".`)
+	return help
+}
+
+const helpName = "help"
+
+// runHelp runs the "help" command.
+func runHelp(cmd *Command, args []string, style style) error {
+	if len(args) == 0 {
+		cmd.usage(cmd.stdout, style, true)
+		return nil
+	}
+	if args[0] == "..." {
+		recursiveHelp(cmd, style, true)
+		return nil
+	}
+	// Find the subcommand to display help.
+	subName := args[0]
+	subArgs := args[1:]
+	for _, child := range cmd.Children {
+		if child.Name == subName {
+			return runHelp(child, subArgs, style)
+		}
+	}
+	return cmd.Errorf("%s: unknown command %q", cmd.Name, subName)
+}
+
+// recursiveHelp prints help recursively via DFS from this cmd onward.
+func recursiveHelp(cmd *Command, style style, firstCall bool) {
+	cmd.usage(cmd.stdout, style, firstCall)
+	switch style {
+	case styleText:
+		fmt.Fprintln(cmd.stdout, strings.Repeat("=", 80))
+	case styleGoDoc:
+		fmt.Fprintln(cmd.stdout)
+	}
+	for _, child := range cmd.Children {
+		recursiveHelp(child, style, false)
+	}
+}
+
+// prefixErrorWriter simply wraps a regular io.Writer and adds an "ERROR: "
+// prefix if Write is ever called.  It's used to ensure errors are clearly
+// marked when flag.FlagSet.Parse encounters errors.
+type prefixErrorWriter struct {
+	writer        io.Writer
+	prefixWritten bool
+}
+
+func (p *prefixErrorWriter) Write(b []byte) (int, error) {
+	if !p.prefixWritten {
+		io.WriteString(p.writer, "ERROR: ")
+		p.prefixWritten = true
+	}
+	return p.writer.Write(b)
+}
+
+// Init initializes all nodes in the command tree rooted at cmd.  Init must be
+// called before Execute.
+func (cmd *Command) Init(parent *Command, stdout, stderr io.Writer) {
+	cmd.parent = parent
+	cmd.stdout = stdout
+	cmd.stderr = stderr
+	// Add help command, if it doesn't already exist.
+	hasHelp := false
+	for _, child := range cmd.Children {
+		if child.Name == helpName {
+			hasHelp = true
+			break
+		}
+	}
+	if !hasHelp && cmd.Name != helpName && len(cmd.Children) > 0 {
+		cmd.Children = append(cmd.Children, newDefaultHelp())
+	}
+	// Merge command-specific and global flags into parseFlags.
+	cmd.parseFlags = flag.NewFlagSet(cmd.Name, flag.ContinueOnError)
+	cmd.parseFlags.SetOutput(&prefixErrorWriter{writer: stderr})
+	cmd.parseFlags.Usage = func() {
+		cmd.usage(stderr, styleText, true)
+	}
+	flagMerger := func(f *flag.Flag) {
+		if cmd.parseFlags.Lookup(f.Name) == nil {
+			cmd.parseFlags.Var(f.Value, f.Name, f.Usage)
+		}
+	}
+	cmd.Flags.VisitAll(flagMerger)
+	flag.VisitAll(flagMerger)
+	// Call children recursively.
+	for _, child := range cmd.Children {
+		child.Init(cmd, stdout, stderr)
+	}
+}
+
+// Execute the command with the given args.  The returned error is ErrUsage if
+// there are usage errors, otherwise it is whatever the leaf command returns
+// from its Run function.
+func (cmd *Command) Execute(args []string) error {
+	// Parse the merged flags.
+	if err := cmd.parseFlags.Parse(args); err != nil {
+		return ErrUsage
+	}
+	args = cmd.parseFlags.Args()
+	// Look for matching children.
+	if len(args) > 0 {
+		subName := args[0]
+		subArgs := args[1:]
+		for _, child := range cmd.Children {
+			if child.Name == subName {
+				return child.Execute(subArgs)
+			}
+		}
+	}
+	// No matching children, try Run.
+	if cmd.Run != nil {
+		if cmd.ArgsName == "" && len(args) > 0 {
+			if len(cmd.Children) > 0 {
+				return cmd.Errorf("%s: unknown command %q", cmd.Name, args[0])
+			} else {
+				return cmd.Errorf("%s doesn't take any arguments", cmd.Name)
+			}
+		}
+		return cmd.Run(cmd, args)
+	}
+	switch {
+	case len(cmd.Children) == 0:
+		return cmd.Errorf("%s: neither Children nor Run is specified", cmd.Name)
+	case len(args) > 0:
+		return cmd.Errorf("%s: unknown command %q", cmd.Name, args[0])
+	default:
+		return cmd.Errorf("%s: no command specified", cmd.Name)
+	}
+}
+
+// Main executes the command tree rooted at cmd, writing output to os.Stdout,
+// writing errors to os.Stderr, and getting args from os.Args.  We'll call
+// os.Exit with a non-zero exit code on errors.  It's meant as a simple
+// one-liner for the main function of command-line tools.
+func (cmd *Command) Main() {
+	cmd.Init(nil, os.Stdout, os.Stderr)
+	if err := cmd.Execute(os.Args[1:]); err != nil {
+		if err == ErrUsage {
+			os.Exit(1)
+		} else {
+			fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
+			os.Exit(2)
+		}
+	}
+}
diff --git a/lib/cmdline/cmdline_test.go b/lib/cmdline/cmdline_test.go
new file mode 100644
index 0000000..6fdf3c5
--- /dev/null
+++ b/lib/cmdline/cmdline_test.go
@@ -0,0 +1,1879 @@
+package cmdline
+
+import (
+	"bytes"
+	"errors"
+	"flag"
+	"fmt"
+	"regexp"
+	"strings"
+	"testing"
+)
+
+var (
+	errEcho           = errors.New("echo error")
+	flagExtra         bool
+	optNoNewline      bool
+	flagTopLevelExtra bool
+	globalFlag1       string
+	globalFlag2       *int64
+)
+
+// runEcho is used to implement commands for our tests.
+func runEcho(cmd *Command, args []string) error {
+	if len(args) == 1 {
+		if args[0] == "error" {
+			return errEcho
+		} else if args[0] == "bad_arg" {
+			return cmd.Errorf("Invalid argument %v", args[0])
+		}
+	}
+	if flagExtra {
+		args = append(args, "extra")
+	}
+	if flagTopLevelExtra {
+		args = append(args, "tlextra")
+	}
+	if optNoNewline {
+		fmt.Fprint(cmd.Stdout(), args)
+	} else {
+		fmt.Fprintln(cmd.Stdout(), args)
+	}
+	return nil
+}
+
+// runHello is another function for test commands.
+func runHello(cmd *Command, args []string) error {
+	if flagTopLevelExtra {
+		args = append(args, "tlextra")
+	}
+	fmt.Fprintln(cmd.Stdout(), strings.Join(append([]string{"Hello"}, args...), " "))
+	return nil
+}
+
+type testCase struct {
+	Args        []string
+	Err         error
+	Stdout      string
+	Stderr      string
+	GlobalFlag1 string
+	GlobalFlag2 int64
+}
+
+func init() {
+	flag.StringVar(&globalFlag1, "global1", "", "global test flag 1")
+	globalFlag2 = flag.Int64("global2", 0, "global test flag 2")
+}
+
+func matchOutput(actual, expect string) bool {
+	// The global flags include the flags from the testing package, so strip them
+	// out before the comparison.
+	re := regexp.MustCompile("   -test.*\n")
+	return re.ReplaceAllLiteralString(actual, "") == expect
+}
+
+func runTestCases(t *testing.T, cmd *Command, tests []testCase) {
+	for _, test := range tests {
+		// Reset global variables before running each test case.
+		var stdout bytes.Buffer
+		var stderr bytes.Buffer
+		flagExtra = false
+		flagTopLevelExtra = false
+		optNoNewline = false
+		globalFlag1 = ""
+		*globalFlag2 = 0
+
+		// Run the execute function and check against expected results.
+		cmd.Init(nil, &stdout, &stderr)
+		if err := cmd.Execute(test.Args); err != test.Err {
+			t.Errorf("Ran with args %q\nEXPECTED error:\n%q\nACTUAL error:\n%q", test.Args, test.Err, err)
+		}
+		if !matchOutput(stdout.String(), test.Stdout) {
+			t.Errorf("Ran with args %q\nEXPECTED stdout:\n%q\nACTUAL stdout:\n%q", test.Args, test.Stdout, stdout.String())
+		}
+		if !matchOutput(stderr.String(), test.Stderr) {
+			t.Errorf("Ran with args %q\nEXPECTED stderr:\n%q\nACTUAL stderr:\n%q", test.Args, test.Stderr, stderr.String())
+		}
+		if globalFlag1 != test.GlobalFlag1 {
+			t.Errorf("Value for global1 flag %q\nEXPECTED %q", globalFlag1, test.GlobalFlag1)
+		}
+		if *globalFlag2 != test.GlobalFlag2 {
+			t.Errorf("Value for global2 flag %q\nEXPECTED %q", globalFlag2, test.GlobalFlag2)
+		}
+	}
+}
+
+func TestNoCommands(t *testing.T) {
+	cmd := &Command{
+		Name:  "nocmds",
+		Short: "Nocmds is invalid.",
+		Long:  "Nocmds has no commands and no run function.",
+	}
+
+	var tests = []testCase{
+		{
+			Args: []string{},
+			Err:  ErrUsage,
+			Stderr: `ERROR: nocmds: neither Children nor Run is specified
+
+Nocmds has no commands and no run function.
+
+Usage:
+   nocmds [ERROR: neither Children nor Run is specified]
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"foo"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: nocmds: neither Children nor Run is specified
+
+Nocmds has no commands and no run function.
+
+Usage:
+   nocmds [ERROR: neither Children nor Run is specified]
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+	}
+	runTestCases(t, cmd, tests)
+}
+
+func TestOneCommand(t *testing.T) {
+	cmdEcho := &Command{
+		Name:  "echo",
+		Short: "Print strings on stdout",
+		Long: `
+Echo prints any strings passed in to stdout.
+`,
+		Run:      runEcho,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
+	}
+
+	prog := &Command{
+		Name:     "onecmd",
+		Short:    "Onecmd program.",
+		Long:     "Onecmd only has the echo command.",
+		Children: []*Command{cmdEcho},
+	}
+
+	var tests = []testCase{
+		{
+			Args: []string{},
+			Err:  ErrUsage,
+			Stderr: `ERROR: onecmd: no command specified
+
+Onecmd only has the echo command.
+
+Usage:
+   onecmd <command>
+
+The onecmd commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"foo"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: onecmd: unknown command "foo"
+
+Onecmd only has the echo command.
+
+Usage:
+   onecmd <command>
+
+The onecmd commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help"},
+			Stdout: `Onecmd only has the echo command.
+
+Usage:
+   onecmd <command>
+
+The onecmd commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "echo"},
+			Stdout: `Echo prints any strings passed in to stdout.
+
+Usage:
+   onecmd echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "help"},
+			Stdout: `Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   onecmd help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "..."},
+			Stdout: `Onecmd only has the echo command.
+
+Usage:
+   onecmd <command>
+
+The onecmd commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Echo prints any strings passed in to stdout.
+
+Usage:
+   onecmd echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   onecmd help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"help", "foo"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: onecmd: unknown command "foo"
+
+Onecmd only has the echo command.
+
+Usage:
+   onecmd <command>
+
+The onecmd commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args:   []string{"echo", "foo", "bar"},
+			Stdout: "[foo bar]\n",
+		},
+		{
+			Args: []string{"echo", "error"},
+			Err:  errEcho,
+		},
+		{
+			Args: []string{"echo", "bad_arg"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: Invalid argument bad_arg
+
+Echo prints any strings passed in to stdout.
+
+Usage:
+   onecmd echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+	}
+	runTestCases(t, prog, tests)
+}
+
+func TestMultiCommands(t *testing.T) {
+	cmdEcho := &Command{
+		Run:   runEcho,
+		Name:  "echo",
+		Short: "Print strings on stdout",
+		Long: `
+Echo prints any strings passed in to stdout.
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
+	}
+	var cmdEchoOpt = &Command{
+		Run:   runEcho,
+		Name:  "echoopt",
+		Short: "Print strings on stdout, with opts",
+		// Try varying number of header/trailer newlines around the long description.
+		Long: `Echoopt prints any args passed in to stdout.
+
+
+`,
+		ArgsName: "[args]",
+		ArgsLong: "[args] are arbitrary strings that will be echoed.",
+	}
+	cmdEchoOpt.Flags.BoolVar(&optNoNewline, "n", false, "Do not output trailing newline")
+
+	prog := &Command{
+		Name:     "multi",
+		Short:    "Multi test command",
+		Long:     "Multi has two variants of echo.",
+		Children: []*Command{cmdEcho, cmdEchoOpt},
+	}
+	prog.Flags.BoolVar(&flagExtra, "extra", false, "Print an extra arg")
+
+	var tests = []testCase{
+		{
+			Args: []string{},
+			Err:  ErrUsage,
+			Stderr: `ERROR: multi: no command specified
+
+Multi has two variants of echo.
+
+Usage:
+   multi [flags] <command>
+
+The multi commands are:
+   echo        Print strings on stdout
+   echoopt     Print strings on stdout, with opts
+   help        Display help for commands
+
+The multi flags are:
+   -extra=false: Print an extra arg
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help"},
+			Stdout: `Multi has two variants of echo.
+
+Usage:
+   multi [flags] <command>
+
+The multi commands are:
+   echo        Print strings on stdout
+   echoopt     Print strings on stdout, with opts
+   help        Display help for commands
+
+The multi flags are:
+   -extra=false: Print an extra arg
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "..."},
+			Stdout: `Multi has two variants of echo.
+
+Usage:
+   multi [flags] <command>
+
+The multi commands are:
+   echo        Print strings on stdout
+   echoopt     Print strings on stdout, with opts
+   help        Display help for commands
+
+The multi flags are:
+   -extra=false: Print an extra arg
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Echo prints any strings passed in to stdout.
+
+Usage:
+   multi echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+================================================================================
+Echoopt prints any args passed in to stdout.
+
+Usage:
+   multi echoopt [flags] [args]
+
+[args] are arbitrary strings that will be echoed.
+
+The echoopt flags are:
+   -n=false: Do not output trailing newline
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   multi help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"help", "echo"},
+			Stdout: `Echo prints any strings passed in to stdout.
+
+Usage:
+   multi echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "echoopt"},
+			Stdout: `Echoopt prints any args passed in to stdout.
+
+Usage:
+   multi echoopt [flags] [args]
+
+[args] are arbitrary strings that will be echoed.
+
+The echoopt flags are:
+   -n=false: Do not output trailing newline
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "foo"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: multi: unknown command "foo"
+
+Multi has two variants of echo.
+
+Usage:
+   multi [flags] <command>
+
+The multi commands are:
+   echo        Print strings on stdout
+   echoopt     Print strings on stdout, with opts
+   help        Display help for commands
+
+The multi flags are:
+   -extra=false: Print an extra arg
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args:   []string{"echo", "foo", "bar"},
+			Stdout: "[foo bar]\n",
+		},
+		{
+			Args:   []string{"-extra", "echo", "foo", "bar"},
+			Stdout: "[foo bar extra]\n",
+		},
+		{
+			Args: []string{"echo", "error"},
+			Err:  errEcho,
+		},
+		{
+			Args:   []string{"echoopt", "foo", "bar"},
+			Stdout: "[foo bar]\n",
+		},
+		{
+			Args:   []string{"-extra", "echoopt", "foo", "bar"},
+			Stdout: "[foo bar extra]\n",
+		},
+		{
+			Args:   []string{"echoopt", "-n", "foo", "bar"},
+			Stdout: "[foo bar]",
+		},
+		{
+			Args:   []string{"-extra", "echoopt", "-n", "foo", "bar"},
+			Stdout: "[foo bar extra]",
+		},
+		{
+			Args:        []string{"-global1=globalStringValue", "-extra", "echoopt", "-n", "foo", "bar"},
+			Stdout:      "[foo bar extra]",
+			GlobalFlag1: "globalStringValue",
+		},
+		{
+			Args:        []string{"-global2=42", "echoopt", "-n", "foo", "bar"},
+			Stdout:      "[foo bar]",
+			GlobalFlag2: 42,
+		},
+		{
+			Args:        []string{"-global1=globalStringOtherValue", "-global2=43", "-extra", "echoopt", "-n", "foo", "bar"},
+			Stdout:      "[foo bar extra]",
+			GlobalFlag1: "globalStringOtherValue",
+			GlobalFlag2: 43,
+		},
+		{
+			Args: []string{"echoopt", "error"},
+			Err:  errEcho,
+		},
+		{
+			Args: []string{"echo", "-n", "foo", "bar"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: flag provided but not defined: -n
+Echo prints any strings passed in to stdout.
+
+Usage:
+   multi echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"-nosuchflag", "echo", "foo", "bar"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: flag provided but not defined: -nosuchflag
+Multi has two variants of echo.
+
+Usage:
+   multi [flags] <command>
+
+The multi commands are:
+   echo        Print strings on stdout
+   echoopt     Print strings on stdout, with opts
+   help        Display help for commands
+
+The multi flags are:
+   -extra=false: Print an extra arg
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+	}
+	runTestCases(t, prog, tests)
+}
+
+func TestMultiLevelCommands(t *testing.T) {
+	cmdEcho := &Command{
+		Run:   runEcho,
+		Name:  "echo",
+		Short: "Print strings on stdout",
+		Long: `
+Echo prints any strings passed in to stdout.
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
+	}
+	cmdEchoOpt := &Command{
+		Run:   runEcho,
+		Name:  "echoopt",
+		Short: "Print strings on stdout, with opts",
+		// Try varying number of header/trailer newlines around the long description.
+		Long: `Echoopt prints any args passed in to stdout.
+
+
+`,
+		ArgsName: "[args]",
+		ArgsLong: "[args] are arbitrary strings that will be echoed.",
+	}
+	cmdEchoOpt.Flags.BoolVar(&optNoNewline, "n", false, "Do not output trailing newline")
+	cmdHello := &Command{
+		Run:   runHello,
+		Name:  "hello",
+		Short: "Print strings on stdout preceded by \"Hello\"",
+		Long: `
+Hello prints any strings passed in to stdout preceded by "Hello".
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be printed.",
+	}
+	echoProg := &Command{
+		Name:     "echoprog",
+		Short:    "Set of echo commands",
+		Long:     "Echoprog has two variants of echo.",
+		Children: []*Command{cmdEcho, cmdEchoOpt},
+	}
+	echoProg.Flags.BoolVar(&flagExtra, "extra", false, "Print an extra arg")
+	prog := &Command{
+		Name:     "toplevelprog",
+		Short:    "Top level prog",
+		Long:     "Toplevelprog has the echo subprogram and the hello command.",
+		Children: []*Command{echoProg, cmdHello},
+	}
+	prog.Flags.BoolVar(&flagTopLevelExtra, "tlextra", false, "Print an extra arg for all commands")
+
+	var tests = []testCase{
+		{
+			Args: []string{},
+			Err:  ErrUsage,
+			Stderr: `ERROR: toplevelprog: no command specified
+
+Toplevelprog has the echo subprogram and the hello command.
+
+Usage:
+   toplevelprog [flags] <command>
+
+The toplevelprog commands are:
+   echoprog    Set of echo commands
+   hello       Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+The toplevelprog flags are:
+   -tlextra=false: Print an extra arg for all commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help"},
+			Stdout: `Toplevelprog has the echo subprogram and the hello command.
+
+Usage:
+   toplevelprog [flags] <command>
+
+The toplevelprog commands are:
+   echoprog    Set of echo commands
+   hello       Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+The toplevelprog flags are:
+   -tlextra=false: Print an extra arg for all commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "..."},
+			Stdout: `Toplevelprog has the echo subprogram and the hello command.
+
+Usage:
+   toplevelprog [flags] <command>
+
+The toplevelprog commands are:
+   echoprog    Set of echo commands
+   hello       Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+The toplevelprog flags are:
+   -tlextra=false: Print an extra arg for all commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Echoprog has two variants of echo.
+
+Usage:
+   toplevelprog echoprog [flags] <command>
+
+The echoprog commands are:
+   echo        Print strings on stdout
+   echoopt     Print strings on stdout, with opts
+   help        Display help for commands
+
+The echoprog flags are:
+   -extra=false: Print an extra arg
+================================================================================
+Echo prints any strings passed in to stdout.
+
+Usage:
+   toplevelprog echoprog echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+================================================================================
+Echoopt prints any args passed in to stdout.
+
+Usage:
+   toplevelprog echoprog echoopt [flags] [args]
+
+[args] are arbitrary strings that will be echoed.
+
+The echoopt flags are:
+   -n=false: Do not output trailing newline
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   toplevelprog echoprog help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   toplevelprog hello [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   toplevelprog help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"help", "echoprog"},
+			Stdout: `Echoprog has two variants of echo.
+
+Usage:
+   toplevelprog echoprog [flags] <command>
+
+The echoprog commands are:
+   echo        Print strings on stdout
+   echoopt     Print strings on stdout, with opts
+   help        Display help for commands
+
+The echoprog flags are:
+   -extra=false: Print an extra arg
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"echoprog", "help", "..."},
+			Stdout: `Echoprog has two variants of echo.
+
+Usage:
+   toplevelprog echoprog [flags] <command>
+
+The echoprog commands are:
+   echo        Print strings on stdout
+   echoopt     Print strings on stdout, with opts
+   help        Display help for commands
+
+The echoprog flags are:
+   -extra=false: Print an extra arg
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Echo prints any strings passed in to stdout.
+
+Usage:
+   toplevelprog echoprog echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+================================================================================
+Echoopt prints any args passed in to stdout.
+
+Usage:
+   toplevelprog echoprog echoopt [flags] [args]
+
+[args] are arbitrary strings that will be echoed.
+
+The echoopt flags are:
+   -n=false: Do not output trailing newline
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   toplevelprog echoprog help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"echoprog", "help", "echoopt"},
+			Stdout: `Echoopt prints any args passed in to stdout.
+
+Usage:
+   toplevelprog echoprog echoopt [flags] [args]
+
+[args] are arbitrary strings that will be echoed.
+
+The echoopt flags are:
+   -n=false: Do not output trailing newline
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "hello"},
+			Stdout: `Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   toplevelprog hello [strings]
+
+[strings] are arbitrary strings that will be printed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "foo"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: toplevelprog: unknown command "foo"
+
+Toplevelprog has the echo subprogram and the hello command.
+
+Usage:
+   toplevelprog [flags] <command>
+
+The toplevelprog commands are:
+   echoprog    Set of echo commands
+   hello       Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+The toplevelprog flags are:
+   -tlextra=false: Print an extra arg for all commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args:   []string{"echoprog", "echo", "foo", "bar"},
+			Stdout: "[foo bar]\n",
+		},
+		{
+			Args:   []string{"echoprog", "-extra", "echo", "foo", "bar"},
+			Stdout: "[foo bar extra]\n",
+		},
+		{
+			Args: []string{"echoprog", "echo", "error"},
+			Err:  errEcho,
+		},
+		{
+			Args:   []string{"echoprog", "echoopt", "foo", "bar"},
+			Stdout: "[foo bar]\n",
+		},
+		{
+			Args:   []string{"echoprog", "-extra", "echoopt", "foo", "bar"},
+			Stdout: "[foo bar extra]\n",
+		},
+		{
+			Args:   []string{"echoprog", "echoopt", "-n", "foo", "bar"},
+			Stdout: "[foo bar]",
+		},
+		{
+			Args:   []string{"echoprog", "-extra", "echoopt", "-n", "foo", "bar"},
+			Stdout: "[foo bar extra]",
+		},
+		{
+			Args: []string{"echoprog", "echoopt", "error"},
+			Err:  errEcho,
+		},
+		{
+			Args:   []string{"--tlextra", "echoprog", "-extra", "echoopt", "foo", "bar"},
+			Stdout: "[foo bar extra tlextra]\n",
+		},
+		{
+			Args:   []string{"hello", "foo", "bar"},
+			Stdout: "Hello foo bar\n",
+		},
+		{
+			Args:   []string{"--tlextra", "hello", "foo", "bar"},
+			Stdout: "Hello foo bar tlextra\n",
+		},
+		{
+			Args: []string{"hello", "--extra", "foo", "bar"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: flag provided but not defined: -extra
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   toplevelprog hello [strings]
+
+[strings] are arbitrary strings that will be printed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"-extra", "echoprog", "echoopt", "foo", "bar"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: flag provided but not defined: -extra
+Toplevelprog has the echo subprogram and the hello command.
+
+Usage:
+   toplevelprog [flags] <command>
+
+The toplevelprog commands are:
+   echoprog    Set of echo commands
+   hello       Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+The toplevelprog flags are:
+   -tlextra=false: Print an extra arg for all commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+	}
+	runTestCases(t, prog, tests)
+}
+
+func TestMultiLevelCommandsOrdering(t *testing.T) {
+	cmdHello11 := &Command{
+		Name:  "hello11",
+		Short: "Print strings on stdout preceded by \"Hello\"",
+		Long: `
+Hello prints any strings passed in to stdout preceded by "Hello".
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be printed.",
+		Run:      runHello,
+	}
+	cmdHello12 := &Command{
+		Name:  "hello12",
+		Short: "Print strings on stdout preceded by \"Hello\"",
+		Long: `
+Hello prints any strings passed in to stdout preceded by "Hello".
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be printed.",
+		Run:      runHello,
+	}
+	cmdHello21 := &Command{
+		Name:  "hello21",
+		Short: "Print strings on stdout preceded by \"Hello\"",
+		Long: `
+Hello prints any strings passed in to stdout preceded by "Hello".
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be printed.",
+		Run:      runHello,
+	}
+	cmdHello22 := &Command{
+		Name:  "hello22",
+		Short: "Print strings on stdout preceded by \"Hello\"",
+		Long: `
+Hello prints any strings passed in to stdout preceded by "Hello".
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be printed.",
+		Run:      runHello,
+	}
+	cmdHello31 := &Command{
+		Name:  "hello31",
+		Short: "Print strings on stdout preceded by \"Hello\"",
+		Long: `
+Hello prints any strings passed in to stdout preceded by "Hello".
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be printed.",
+		Run:      runHello,
+	}
+	cmdHello32 := &Command{
+		Name:  "hello32",
+		Short: "Print strings on stdout preceded by \"Hello\"",
+		Long: `
+Hello prints any strings passed in to stdout preceded by "Hello".
+`,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be printed.",
+		Run:      runHello,
+	}
+	progHello3 := &Command{
+		Name:     "prog3",
+		Short:    "Set of hello commands",
+		Long:     "Prog3 has two variants of hello.",
+		Children: []*Command{cmdHello31, cmdHello32},
+	}
+	progHello2 := &Command{
+		Name:     "prog2",
+		Short:    "Set of hello commands",
+		Long:     "Prog2 has two variants of hello and a subprogram prog3.",
+		Children: []*Command{cmdHello21, progHello3, cmdHello22},
+	}
+	progHello1 := &Command{
+		Name:     "prog1",
+		Short:    "Set of hello commands",
+		Long:     "Prog1 has two variants of hello and a subprogram prog2.",
+		Children: []*Command{cmdHello11, cmdHello12, progHello2},
+	}
+
+	var tests = []testCase{
+		{
+			Args: []string{},
+			Err:  ErrUsage,
+			Stderr: `ERROR: prog1: no command specified
+
+Prog1 has two variants of hello and a subprogram prog2.
+
+Usage:
+   prog1 <command>
+
+The prog1 commands are:
+   hello11     Print strings on stdout preceded by "Hello"
+   hello12     Print strings on stdout preceded by "Hello"
+   prog2       Set of hello commands
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help"},
+			Stdout: `Prog1 has two variants of hello and a subprogram prog2.
+
+Usage:
+   prog1 <command>
+
+The prog1 commands are:
+   hello11     Print strings on stdout preceded by "Hello"
+   hello12     Print strings on stdout preceded by "Hello"
+   prog2       Set of hello commands
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "..."},
+			Stdout: `Prog1 has two variants of hello and a subprogram prog2.
+
+Usage:
+   prog1 <command>
+
+The prog1 commands are:
+   hello11     Print strings on stdout preceded by "Hello"
+   hello12     Print strings on stdout preceded by "Hello"
+   prog2       Set of hello commands
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 hello11 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 hello12 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Prog2 has two variants of hello and a subprogram prog3.
+
+Usage:
+   prog1 prog2 <command>
+
+The prog2 commands are:
+   hello21     Print strings on stdout preceded by "Hello"
+   prog3       Set of hello commands
+   hello22     Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 hello21 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Prog3 has two variants of hello.
+
+Usage:
+   prog1 prog2 prog3 <command>
+
+The prog3 commands are:
+   hello31     Print strings on stdout preceded by "Hello"
+   hello32     Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello31 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello32 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 prog2 prog3 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 hello22 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 prog2 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"prog2", "help", "..."},
+			Stdout: `Prog2 has two variants of hello and a subprogram prog3.
+
+Usage:
+   prog1 prog2 <command>
+
+The prog2 commands are:
+   hello21     Print strings on stdout preceded by "Hello"
+   prog3       Set of hello commands
+   hello22     Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 hello21 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Prog3 has two variants of hello.
+
+Usage:
+   prog1 prog2 prog3 <command>
+
+The prog3 commands are:
+   hello31     Print strings on stdout preceded by "Hello"
+   hello32     Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello31 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello32 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 prog2 prog3 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 hello22 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 prog2 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"prog2", "prog3", "help", "..."},
+			Stdout: `Prog3 has two variants of hello.
+
+Usage:
+   prog1 prog2 prog3 <command>
+
+The prog3 commands are:
+   hello31     Print strings on stdout preceded by "Hello"
+   hello32     Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello31 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello32 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 prog2 prog3 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"help", "prog2", "prog3", "..."},
+			Stdout: `Prog3 has two variants of hello.
+
+Usage:
+   prog1 prog2 prog3 <command>
+
+The prog3 commands are:
+   hello31     Print strings on stdout preceded by "Hello"
+   hello32     Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello31 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello32 [strings]
+
+[strings] are arbitrary strings that will be printed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 prog2 prog3 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"help", "-style=godoc", "..."},
+			Stdout: `Prog1 has two variants of hello and a subprogram prog2.
+
+Usage:
+   prog1 <command>
+
+The prog1 commands are:
+   hello11     Print strings on stdout preceded by "Hello"
+   hello12     Print strings on stdout preceded by "Hello"
+   prog2       Set of hello commands
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+
+Prog1 Hello11
+
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 hello11 [strings]
+
+[strings] are arbitrary strings that will be printed.
+
+Prog1 Hello12
+
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 hello12 [strings]
+
+[strings] are arbitrary strings that will be printed.
+
+Prog1 Prog2
+
+Prog2 has two variants of hello and a subprogram prog3.
+
+Usage:
+   prog1 prog2 <command>
+
+The prog2 commands are:
+   hello21     Print strings on stdout preceded by "Hello"
+   prog3       Set of hello commands
+   hello22     Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+Prog1 Prog2 Hello21
+
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 hello21 [strings]
+
+[strings] are arbitrary strings that will be printed.
+
+Prog1 Prog2 Prog3
+
+Prog3 has two variants of hello.
+
+Usage:
+   prog1 prog2 prog3 <command>
+
+The prog3 commands are:
+   hello31     Print strings on stdout preceded by "Hello"
+   hello32     Print strings on stdout preceded by "Hello"
+   help        Display help for commands
+
+Prog1 Prog2 Prog3 Hello31
+
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello31 [strings]
+
+[strings] are arbitrary strings that will be printed.
+
+Prog1 Prog2 Prog3 Hello32
+
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 prog3 hello32 [strings]
+
+[strings] are arbitrary strings that will be printed.
+
+Prog1 Prog2 Prog3 Help
+
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 prog2 prog3 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+
+Prog1 Prog2 Hello22
+
+Hello prints any strings passed in to stdout preceded by "Hello".
+
+Usage:
+   prog1 prog2 hello22 [strings]
+
+[strings] are arbitrary strings that will be printed.
+
+Prog1 Prog2 Help
+
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 prog2 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+
+Prog1 Help
+
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   prog1 help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+
+`,
+		},
+	}
+
+	runTestCases(t, progHello1, tests)
+}
+
+func TestCommandAndArgs(t *testing.T) {
+	cmdEcho := &Command{
+		Name:  "echo",
+		Short: "Print strings on stdout",
+		Long: `
+Echo prints any strings passed in to stdout.
+`,
+		Run:      runEcho,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
+	}
+
+	prog := &Command{
+		Name:     "cmdargs",
+		Short:    "Cmdargs program.",
+		Long:     "Cmdargs has the echo command and a Run function with args.",
+		Children: []*Command{cmdEcho},
+		Run:      runHello,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be printed.",
+	}
+
+	var tests = []testCase{
+		{
+			Args:   []string{},
+			Stdout: "Hello\n",
+		},
+		{
+			Args:   []string{"foo"},
+			Stdout: "Hello foo\n",
+		},
+		{
+			Args: []string{"help"},
+			Stdout: `Cmdargs has the echo command and a Run function with args.
+
+Usage:
+   cmdargs <command>
+   cmdargs [strings]
+
+The cmdargs commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+[strings] are arbitrary strings that will be printed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "echo"},
+			Stdout: `Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdargs echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "..."},
+			Stdout: `Cmdargs has the echo command and a Run function with args.
+
+Usage:
+   cmdargs <command>
+   cmdargs [strings]
+
+The cmdargs commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+[strings] are arbitrary strings that will be printed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdargs echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   cmdargs help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"help", "foo"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: cmdargs: unknown command "foo"
+
+Cmdargs has the echo command and a Run function with args.
+
+Usage:
+   cmdargs <command>
+   cmdargs [strings]
+
+The cmdargs commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+[strings] are arbitrary strings that will be printed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args:   []string{"echo", "foo", "bar"},
+			Stdout: "[foo bar]\n",
+		},
+		{
+			Args: []string{"echo", "error"},
+			Err:  errEcho,
+		},
+		{
+			Args: []string{"echo", "bad_arg"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: Invalid argument bad_arg
+
+Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdargs echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+	}
+	runTestCases(t, prog, tests)
+}
+
+func TestCommandAndRunNoArgs(t *testing.T) {
+	cmdEcho := &Command{
+		Name:  "echo",
+		Short: "Print strings on stdout",
+		Long: `
+Echo prints any strings passed in to stdout.
+`,
+		Run:      runEcho,
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
+	}
+
+	prog := &Command{
+		Name:     "cmdrun",
+		Short:    "Cmdrun program.",
+		Long:     "Cmdrun has the echo command and a Run function with no args.",
+		Children: []*Command{cmdEcho},
+		Run:      runHello,
+	}
+
+	var tests = []testCase{
+		{
+			Args:   []string{},
+			Stdout: "Hello\n",
+		},
+		{
+			Args: []string{"foo"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: cmdrun: unknown command "foo"
+
+Cmdrun has the echo command and a Run function with no args.
+
+Usage:
+   cmdrun <command>
+   cmdrun
+
+The cmdrun commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help"},
+			Stdout: `Cmdrun has the echo command and a Run function with no args.
+
+Usage:
+   cmdrun <command>
+   cmdrun
+
+The cmdrun commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "echo"},
+			Stdout: `Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdrun echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "..."},
+			Stdout: `Cmdrun has the echo command and a Run function with no args.
+
+Usage:
+   cmdrun <command>
+   cmdrun
+
+The cmdrun commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+================================================================================
+Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdrun echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+================================================================================
+Help displays usage descriptions for this command, or usage descriptions for
+sub-commands.
+
+Usage:
+   cmdrun help [flags] <command>
+
+<command> is an optional sequence of commands to display detailed per-command
+usage.  The special-case "help ..." recursively displays help for this command
+and all sub-commands.
+
+The help flags are:
+   -style=text: The formatting style for help output, either "text" or "godoc".
+================================================================================
+`,
+		},
+		{
+			Args: []string{"help", "foo"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: cmdrun: unknown command "foo"
+
+Cmdrun has the echo command and a Run function with no args.
+
+Usage:
+   cmdrun <command>
+   cmdrun
+
+The cmdrun commands are:
+   echo        Print strings on stdout
+   help        Display help for commands
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+		{
+			Args:   []string{"echo", "foo", "bar"},
+			Stdout: "[foo bar]\n",
+		},
+		{
+			Args: []string{"echo", "error"},
+			Err:  errEcho,
+		},
+		{
+			Args: []string{"echo", "bad_arg"},
+			Err:  ErrUsage,
+			Stderr: `ERROR: Invalid argument bad_arg
+
+Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdrun echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+   -global1=: global test flag 1
+   -global2=0: global test flag 2
+`,
+		},
+	}
+	runTestCases(t, prog, tests)
+}
diff --git a/lib/glob/glob.go b/lib/glob/glob.go
new file mode 100644
index 0000000..b1356c1
--- /dev/null
+++ b/lib/glob/glob.go
@@ -0,0 +1,165 @@
+// glob implements a glob language.
+//
+// Globs match a slash separated series of glob expressions.
+//
+// pattern:
+// term ['/' term]*
+// term:
+// '*'         matches any sequence of non-Separator characters
+// '?'         matches any single non-Separator character
+// '[' [ '^' ] { character-range } ']'
+// character class (must be non-empty)
+// c           matches character c (c != '*', '?', '\\', '[', '/')
+// '\\' c      matches character c
+// character-range:
+// c           matches character c (c != '\\', '-', ']')
+// '\\' c      matches character c
+// lo '-' hi   matches character c for lo <= c <= hi
+
+package glob
+
+import (
+	"path/filepath"
+	"strings"
+)
+
+// Glob represents a slash separated path glob expression.
+type Glob struct {
+	elems     []string
+	recursive bool
+}
+
+// Parse returns a new Glob.
+func Parse(pattern string) (*Glob, error) {
+	if len(pattern) > 0 && pattern[0] == '/' {
+		return nil, filepath.ErrBadPattern
+	}
+
+	g := &Glob{}
+	if pattern != "" {
+		g.elems = strings.Split(pattern, "/")
+	}
+	if last := len(g.elems) - 1; last >= 0 && g.elems[last] == "..." {
+		g.elems = g.elems[:last]
+		g.recursive = true
+	}
+
+	// The only error we can get from the filepath library is badpattern.
+	// A future implementation would most likely recognize that here, so for now
+	// I'll just check every part to make sure it's error free.
+	for _, elem := range g.elems {
+		if _, err := filepath.Match(elem, ""); err != nil {
+			return nil, err
+		}
+	}
+
+	return g, nil
+}
+
+// Len returns the number of path elements represented by the glob expression.
+func (g *Glob) Len() int {
+	return len(g.elems)
+}
+
+// Finished returns true if the pattern cannot match anything.
+func (g *Glob) Finished() bool {
+	return !g.recursive && len(g.elems) == 0
+}
+
+// Split returns the suffix of g starting at the path element corresponding to start.
+func (g *Glob) Split(start int) *Glob {
+	if start >= len(g.elems) {
+		return &Glob{elems: nil, recursive: g.recursive}
+	}
+	return &Glob{elems: g.elems[start:], recursive: g.recursive}
+}
+
+// MatchInitialSegment tries to match segment against the initial element of g.
+// Returns a boolean indicating whether the match was successful and the
+// Glob representing the unmatched remainder of g.
+func (g *Glob) MatchInitialSegment(segment string) (bool, *Glob) {
+	if len(g.elems) == 0 {
+		if !g.recursive {
+			return false, nil
+		}
+		return true, g
+	}
+
+	if matches, err := filepath.Match(g.elems[0], segment); err != nil {
+		panic("Error in glob pattern found.")
+	} else if matches {
+		return true, g.Split(1)
+	}
+	return false, nil
+}
+
+// PartialMatch tries matching elems against part of a glob pattern.
+// The first return value is true if each element e_i of elems matches
+// the (start + i)th element of the glob pattern.  If the first return
+// value is true, the second return value returns the unmatched suffix
+// of the pattern.  It will be empty if the pattern is completely
+// matched.
+//
+// Note that if the glob is recursive elems can have more elements then
+// the glob pattern and still get a true result.
+func (g *Glob) PartialMatch(start int, elems []string) (bool, *Glob) {
+	g = g.Split(start)
+	for ; len(elems) > 0; elems = elems[1:] {
+		var matched bool
+		if matched, g = g.MatchInitialSegment(elems[0]); !matched {
+			return false, nil
+		}
+	}
+	return true, g
+}
+
+// isFixed returns the unescaped string and true if 's' is a pattern specifying
+// a fixed string.  Otherwise it returns the original string and false.
+func isFixed(s string) (string, bool) {
+	// No special characters.
+	if !strings.ContainsAny(s, "*?[") {
+		return s, true
+	}
+	// Special characters and no backslash.
+	if !strings.ContainsAny(s, "\\") {
+		return "", false
+	}
+	unescaped := ""
+	escape := false
+	for _, c := range s {
+		if escape {
+			escape = false
+			unescaped += string(c)
+		} else if strings.ContainsRune("*?[", c) {
+			// S contains an unescaped special character.
+			return s, false
+		} else if c == '\\' {
+			escape = true
+		} else {
+			unescaped += string(c)
+		}
+	}
+	return unescaped, true
+}
+
+func (g *Glob) SplitFixedPrefix() ([]string, *Glob) {
+	var prefix []string
+	start := 0
+	for _, elem := range g.elems {
+		if u, q := isFixed(elem); q {
+			prefix = append(prefix, u)
+			start++
+		} else {
+			break
+		}
+	}
+	return prefix, g.Split(start)
+}
+
+func (g *Glob) String() string {
+	e := g.elems
+	if g.recursive {
+		e = append(e, "...")
+	}
+	return filepath.Join(e...)
+}
diff --git a/lib/glob/glob_test.go b/lib/glob/glob_test.go
new file mode 100644
index 0000000..bbef347
--- /dev/null
+++ b/lib/glob/glob_test.go
@@ -0,0 +1,40 @@
+package glob
+
+import (
+	"testing"
+)
+
+func same(a, b []string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i := range a {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func TestStripFixedPrefix(t *testing.T) {
+	tests := []struct {
+		pattern string
+		fixed   []string
+		rest    string
+	}{
+		{"*", nil, "*"},
+		{"a/b/c/*", []string{"a", "b", "c"}, "*"},
+		{"a/b/*/...", []string{"a", "b"}, "*/..."},
+		{"a/b/c/...", []string{"a", "b", "c"}, "..."},
+		{"a/the\\?rain.in\\*spain", []string{"a", "the?rain.in*spain"}, ""},
+	}
+	for _, test := range tests {
+		g, err := Parse(test.pattern)
+		if err != nil {
+			t.Fatalf("parsing %q: %q", test.pattern, err.Error())
+		}
+		if f, ng := g.SplitFixedPrefix(); !same(f, test.fixed) || test.rest != ng.String() {
+			t.Fatalf("SplitFixedPrefix(%q) got %q,%q, expected %q,%q", test.pattern, f, ng.String(), test.fixed, test.rest)
+		}
+	}
+}
diff --git a/lib/signals/signals.go b/lib/signals/signals.go
new file mode 100644
index 0000000..e9b88fe
--- /dev/null
+++ b/lib/signals/signals.go
@@ -0,0 +1,77 @@
+package signals
+
+import (
+	"os"
+	"os/signal"
+	"syscall"
+
+	"veyron2/rt"
+)
+
+type stopSignal string
+
+func (stopSignal) Signal()          {}
+func (s stopSignal) String() string { return string(s) }
+
+const (
+	STOP               = stopSignal("")
+	DoubleStopExitCode = 1
+)
+
+// defaultSignals returns a set of platform-specific signals that an application
+// is encouraged to listen on.
+func defaultSignals() []os.Signal {
+	return []os.Signal{syscall.SIGTERM, syscall.SIGINT, STOP}
+}
+
+// TODO(caprita): Rename this to Shutdown() and the package to shutdown since
+// it's not just signals anymore.
+
+// ShutdownOnSignals registers signal handlers for the specified signals, or, if
+// none are specified, the default signals.  The first signal received will be
+// made available on the returned channel; upon receiving a second signal, the
+// process will exit.
+func ShutdownOnSignals(signals ...os.Signal) <-chan os.Signal {
+	if len(signals) == 0 {
+		signals = defaultSignals()
+	}
+	// At least a buffer of length two so that we don't drop the first two
+	// signals we get on account of the channel being full.
+	ch := make(chan os.Signal, 2)
+	sawStop := false
+	for i := 0; i < len(signals); {
+		if s := signals[i]; s == STOP {
+			signals = append(signals[:i], signals[i+1:]...)
+			if sawStop {
+				continue
+			}
+			sawStop = true
+			if r := rt.R(); r != nil {
+				stopWaiter := make(chan string, 1)
+				r.WaitForStop(stopWaiter)
+				go func() {
+					for {
+						ch <- stopSignal(<-stopWaiter)
+					}
+				}()
+			}
+		} else {
+			i++
+		}
+	}
+	if len(signals) > 0 {
+		signal.Notify(ch, signals...)
+	}
+	// At least a buffer of length one so that we don't block on ret <- sig.
+	ret := make(chan os.Signal, 1)
+	go func() {
+		// First signal received.
+		sig := <-ch
+		ret <- sig
+		// Wait for a second signal, and force an exit if the process is
+		// still executing cleanup code.
+		<-ch
+		os.Exit(DoubleStopExitCode)
+	}()
+	return ret
+}
diff --git a/lib/signals/signals_test.go b/lib/signals/signals_test.go
new file mode 100644
index 0000000..03a480c
--- /dev/null
+++ b/lib/signals/signals_test.go
@@ -0,0 +1,212 @@
+package signals
+
+import (
+	"fmt"
+	"os"
+	"syscall"
+	"testing"
+
+	"veyron2/mgmt"
+	"veyron2/rt"
+
+	_ "veyron/lib/testutil"
+	"veyron/lib/testutil/blackbox"
+)
+
+// TestHelperProcess is boilerplate for the blackbox setup.
+func TestHelperProcess(t *testing.T) {
+	blackbox.HelperProcess(t)
+}
+
+func init() {
+	blackbox.CommandTable["handleDefaults"] = handleDefaults
+	blackbox.CommandTable["handleCustom"] = handleCustom
+	blackbox.CommandTable["handleDefaultsIgnoreChan"] = handleDefaultsIgnoreChan
+}
+
+func stopLoop(ch chan<- struct{}) {
+	for {
+		switch blackbox.ReadLineFromStdin() {
+		case "close":
+			close(ch)
+			return
+		case "stop":
+			rt.R().Stop()
+		}
+	}
+}
+
+func program(signals ...os.Signal) {
+	defer rt.Init().Shutdown()
+	closeStopLoop := make(chan struct{})
+	go stopLoop(closeStopLoop)
+	wait := ShutdownOnSignals(signals...)
+	fmt.Println("ready")
+	fmt.Println("received signal", <-wait)
+	<-closeStopLoop
+}
+
+func handleDefaults([]string) {
+	program()
+}
+
+func handleCustom([]string) {
+	program(syscall.SIGABRT)
+}
+
+func handleDefaultsIgnoreChan([]string) {
+	defer rt.Init().Shutdown()
+	closeStopLoop := make(chan struct{})
+	go stopLoop(closeStopLoop)
+	ShutdownOnSignals()
+	fmt.Println("ready")
+	<-closeStopLoop
+}
+
+func isSignalInSet(sig os.Signal, set []os.Signal) bool {
+	for _, s := range set {
+		if sig == s {
+			return true
+		}
+	}
+	return false
+}
+
+func checkSignalIsDefault(t *testing.T, sig os.Signal) {
+	if !isSignalInSet(sig, defaultSignals()) {
+		t.Errorf("signal %s not in default signal set, as expected", sig)
+	}
+}
+
+func checkSignalIsNotDefault(t *testing.T, sig os.Signal) {
+	if isSignalInSet(sig, defaultSignals()) {
+		t.Errorf("signal %s unexpectedly in default signal set", sig)
+	}
+}
+
+// TestCleanShutdownSignal verifies that sending a signal to a child that
+// handles it by default causes the child to shut down cleanly.
+func TestCleanShutdownSignal(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleDefaults")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	checkSignalIsDefault(t, syscall.SIGINT)
+	syscall.Kill(c.Cmd.Process.Pid, syscall.SIGINT)
+	c.Expect(fmt.Sprintf("received signal %s", syscall.SIGINT))
+	c.WriteLine("close")
+	c.ExpectEOFAndWait()
+}
+
+// TestCleanShutdownStop verifies that sending a stop comamnd to a child that
+// handles stop commands by default causes the child to shut down cleanly.
+func TestCleanShutdownStop(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleDefaults")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	c.WriteLine("stop")
+	c.Expect(fmt.Sprintf("received signal %s", mgmt.LocalStop))
+	c.WriteLine("close")
+	c.ExpectEOFAndWait()
+}
+
+// TestStopNoHandler verifies that sending a stop command to a child that does
+// not handle stop commands causes the child to exit immediately.
+func TestStopNoHandler(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleCustom")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	c.WriteLine("stop")
+	c.ExpectEOFAndWaitForExitCode(fmt.Errorf("exit status %d", mgmt.UnhandledStopExitCode))
+}
+
+// TestDoubleSignal verifies that sending a succession of two signals to a child
+// that handles these signals by default causes the child to exit immediately
+// upon receiving the second signal.
+func TestDoubleSignal(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleDefaults")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	checkSignalIsDefault(t, syscall.SIGTERM)
+	syscall.Kill(c.Cmd.Process.Pid, syscall.SIGTERM)
+	c.Expect(fmt.Sprintf("received signal %s", syscall.SIGTERM))
+	checkSignalIsDefault(t, syscall.SIGINT)
+	syscall.Kill(c.Cmd.Process.Pid, syscall.SIGINT)
+	c.ExpectEOFAndWaitForExitCode(fmt.Errorf("exit status %d", DoubleStopExitCode))
+}
+
+// TestSignalAndStop verifies that sending a signal followed by a stop command
+// to a child that handles these by default causes the child to exit immediately
+// upon receiving the stop command.
+func TestSignalAndStop(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleDefaults")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	checkSignalIsDefault(t, syscall.SIGTERM)
+	syscall.Kill(c.Cmd.Process.Pid, syscall.SIGTERM)
+	c.Expect(fmt.Sprintf("received signal %s", syscall.SIGTERM))
+	c.WriteLine("stop")
+	c.ExpectEOFAndWaitForExitCode(fmt.Errorf("exit status %d", DoubleStopExitCode))
+}
+
+// TestDoubleStop verifies that sending a succession of stop commands to a child
+// that handles stop commands by default causes the child to exit immediately
+// upon receiving the second stop command.
+func TestDoubleStop(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleDefaults")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	c.WriteLine("stop")
+	c.Expect(fmt.Sprintf("received signal %s", mgmt.LocalStop))
+	c.WriteLine("stop")
+	c.ExpectEOFAndWaitForExitCode(fmt.Errorf("exit status %d", DoubleStopExitCode))
+}
+
+// TestSendUnhandledSignal verifies that sending a signal that the child does
+// not handle causes the child to exit as per the signal being sent.
+func TestSendUnhandledSignal(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleDefaults")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	checkSignalIsNotDefault(t, syscall.SIGABRT)
+	syscall.Kill(c.Cmd.Process.Pid, syscall.SIGABRT)
+	c.ExpectEOFAndWaitForExitCode(fmt.Errorf("exit status 2"))
+}
+
+// TestDoubleSignalIgnoreChan verifies that, even if we ignore the channel that
+// ShutdownOnSignals returns, sending two signals should still cause the
+// process to exit (ensures that there is no dependency in ShutdownOnSignals
+// on having a goroutine read from the returned channel).
+func TestDoubleSignalIgnoreChan(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleDefaultsIgnoreChan")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	// Even if we ignore the channel that ShutdownOnSignals returns,
+	// sending two signals should still cause the process to exit.
+	checkSignalIsDefault(t, syscall.SIGTERM)
+	syscall.Kill(c.Cmd.Process.Pid, syscall.SIGTERM)
+	checkSignalIsDefault(t, syscall.SIGINT)
+	syscall.Kill(c.Cmd.Process.Pid, syscall.SIGINT)
+	c.ExpectEOFAndWaitForExitCode(fmt.Errorf("exit status %d", DoubleStopExitCode))
+}
+
+// TestHandlerCustomSignal verifies that sending a non-default signal to a
+// server that listens for that signal causes the server to shut down cleanly.
+func TestHandlerCustomSignal(t *testing.T) {
+	c := blackbox.HelperCommand(t, "handleCustom")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("ready")
+	checkSignalIsNotDefault(t, syscall.SIGABRT)
+	syscall.Kill(c.Cmd.Process.Pid, syscall.SIGABRT)
+	c.Expect(fmt.Sprintf("received signal %s", syscall.SIGABRT))
+	c.WriteLine("close")
+	c.ExpectEOFAndWait()
+}
diff --git a/lib/testutil/blackbox/doc.go b/lib/testutil/blackbox/doc.go
new file mode 100644
index 0000000..e4af049
--- /dev/null
+++ b/lib/testutil/blackbox/doc.go
@@ -0,0 +1,58 @@
+// Package blackbox provides routines to help with blackbox testing.
+//
+// Some tests need to run a subprocess.  We reuse the same test binary
+// to do so. A fake test 'TestHelperProcess' contains the code we need to
+// run in the child and we simply run this same binary with a test.run= arg
+// that runs just that test. This idea was taken from the tests for os/exec.
+//
+// To use this, you need to specify entry points to be called as subprocesses.
+//
+//     // File: mytestsubprocess.go
+//     import (
+//         "veyron/lib/testutil/blackbox"
+//     )
+//
+//     func init() {
+//         blackbox.CommandTable["myTestEntryPoint"] = myTestEntryPoint
+//     }
+//
+//     func myTestEntryPoint(argv []string) {
+//         // argv contains all non-flag arguments. Any flags should be handled
+//         // using the flag package.
+//         ...
+//         blackbox.WaitForEOFOnStdin()
+//     }
+//
+// You also need to specify a TestHelperProcess() entry point as part of your
+// test suite.  This is boilerplate; the code reads as follows.
+//
+//     // File: driver_test.go
+//     package foo
+//
+//     import (
+//         "veyron/lib/testutil/blackbox"
+//     )
+//
+//     func TestHelperProcess(t *testing.T) {
+//		   blackbox.HelperProcess(t)
+//     }
+//
+// Finally, to start a subprocess, use the HelperCommand(). defer execution
+// of the Cleanup method to ensure that logs from the child process
+// are collected, printed (if the vlog level is >= the number specified), and
+// the log files are deleted.
+//
+//     // Starts myTestEntryPoint("myTestEntryPoint", "arg1", ..., "argN")
+//     // in a subprocess.
+//     child := blackbox.HelperCommand(t, "myTestEntryPoint", "arg1", ..., "argN")
+//     child.Cmd.Start()
+//     defer child.Cleanup(2)
+//
+//     // Use the ExpectXXX() functions to examine the output.
+//     child.Expect("sometext\n")
+//     child.ExpectEOFAndWait()
+//
+//     // Close stdin when you are done.
+//     child.CloseStdin()
+//
+package blackbox
diff --git a/lib/testutil/blackbox/example_test.go b/lib/testutil/blackbox/example_test.go
new file mode 100644
index 0000000..399ff8f
--- /dev/null
+++ b/lib/testutil/blackbox/example_test.go
@@ -0,0 +1,53 @@
+package blackbox_test
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"testing"
+
+	"veyron/lib/testutil/blackbox"
+)
+
+func init() {
+	blackbox.CommandTable["print"] = print
+	blackbox.CommandTable["echo"] = echo
+}
+
+func print(args []string) {
+	for _, v := range args {
+		fmt.Printf("%s\n", v)
+	}
+	blackbox.WaitForEOFOnStdin()
+	fmt.Printf("done\n")
+}
+
+func echo(args []string) {
+	scanner := bufio.NewScanner(os.Stdin)
+	for scanner.Scan() {
+		fmt.Println(scanner.Text())
+	}
+	if err := scanner.Err(); err != nil {
+		fmt.Printf("error reading stdin: %s", err)
+	} else {
+		fmt.Printf("done\n")
+	}
+}
+
+func ExampleEcho() {
+	// Normally t is provided by testing and this example can't
+	// possible work outside of that environment.
+	t := &testing.T{}
+	c := blackbox.HelperCommand(t, "print", "a", "b", "c")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("a")
+	c.Expect("b")
+	c.Expect("c")
+	c.CloseStdin()
+	c.Expect("done")
+	c.ExpectEOFAndWait()
+	if !t.Failed() {
+		fmt.Printf("ok\n")
+	}
+}
diff --git a/lib/testutil/blackbox/faultyconn.go b/lib/testutil/blackbox/faultyconn.go
new file mode 100644
index 0000000..368068e
--- /dev/null
+++ b/lib/testutil/blackbox/faultyconn.go
@@ -0,0 +1,104 @@
+package blackbox
+
+import (
+	"io"
+	"net"
+	"sync"
+	"time"
+
+	"veyron2/vlog"
+)
+
+type syncBool struct {
+	mu    sync.Mutex
+	value bool
+}
+
+func (s *syncBool) get() bool {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	return s.value
+}
+func (s *syncBool) set(value bool) {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	s.value = value
+}
+
+// Wrap a net.Conn and to force a failure when some amount of data has been transfered.
+type faultyConn struct {
+	conn       net.Conn
+	readBytes  int
+	readMax    int
+	writeBytes int
+	writeMax   int
+	forcedErr  syncBool
+}
+
+func NewFaultyConn(conn net.Conn, readMax, writeMax int) net.Conn {
+	return &faultyConn{conn: conn, readMax: readMax, writeMax: writeMax}
+}
+
+func (conn *faultyConn) Close() error {
+	return conn.conn.Close()
+}
+
+func (conn *faultyConn) Read(buf []byte) (int, error) {
+	if conn.forcedErr.get() {
+		return 0, io.EOF
+	}
+	amount := conn.readMax - conn.readBytes
+	if amount == 0 {
+		vlog.VI(2).Info(formatLogLine("faultyConn(%p): closed", conn))
+		// subsequent Read/Write's should fail
+		conn.forcedErr.set(true)
+		return 0, io.EOF
+	}
+	if amount < len(buf) {
+		buf = buf[0:amount]
+	}
+	num, err := conn.conn.Read(buf)
+	conn.readBytes += num
+	return num, err
+}
+
+func (conn *faultyConn) Write(buf []byte) (int, error) {
+	if conn.forcedErr.get() {
+		return 0, io.EOF
+	}
+	amount := conn.writeMax - conn.writeBytes
+	shortWrite := false
+	if amount < len(buf) {
+		buf = buf[0:amount]
+		shortWrite = true
+	}
+	num, err := conn.conn.Write(buf)
+	conn.writeBytes += num
+	if shortWrite && err == nil {
+		vlog.VI(2).Info(formatLogLine("faultyConn(%p): write closed", conn))
+		// subsequent Read/Write's should fail
+		conn.forcedErr.set(true)
+		err = io.ErrShortWrite
+	}
+	return num, err
+}
+
+func (conn *faultyConn) LocalAddr() net.Addr {
+	return conn.conn.LocalAddr()
+}
+
+func (conn *faultyConn) RemoteAddr() net.Addr {
+	return conn.conn.RemoteAddr()
+}
+
+func (conn *faultyConn) SetDeadline(t time.Time) error {
+	return conn.conn.SetDeadline(t)
+}
+
+func (conn *faultyConn) SetReadDeadline(t time.Time) error {
+	return conn.conn.SetReadDeadline(t)
+}
+
+func (conn *faultyConn) SetWriteDeadline(t time.Time) error {
+	return conn.conn.SetWriteDeadline(t)
+}
diff --git a/lib/testutil/blackbox/subprocess.go b/lib/testutil/blackbox/subprocess.go
new file mode 100644
index 0000000..db4d40c
--- /dev/null
+++ b/lib/testutil/blackbox/subprocess.go
@@ -0,0 +1,472 @@
+package blackbox
+
+import (
+	"bufio"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+
+	"veyron2/vlog"
+)
+
+type mainFunc func(argv []string)
+
+type commandMap map[string]mainFunc
+
+var (
+	CommandTable = make(commandMap)
+	subcommand   string
+)
+
+func init() {
+	flag.StringVar(&subcommand, "subcommand", "", "the subcommand to run")
+}
+
+// Child represents a child process.
+type Child struct {
+	Name   string
+	Cmd    *exec.Cmd
+	ioLock sync.Mutex
+	Stdout *bufio.Reader // GUARDED_BY(ioLock)
+	Stdin  io.WriteCloser
+	stderr *os.File
+	t      *testing.T
+}
+
+// HelperCommand() takes an argument list and starts a helper subprocess.
+func HelperCommand(t *testing.T, command string, args ...string) *Child {
+	cs := []string{"-test.run=TestHelperProcess", "--subcommand=" + command}
+	for fname, fval := range vlog.Log.ExplicitlySetFlags() {
+		cs = append(cs, fmt.Sprintf("--%s=%s", fname, fval))
+	}
+	cs = append(cs, args...)
+	vlog.VI(2).Infof("running: %s %s", os.Args[0], cs)
+	cmd := exec.Command(os.Args[0], cs...)
+	stderr, err := ioutil.TempFile("", "__test__"+strings.TrimLeft(command, "-\n\t "))
+	if err != nil {
+		vlog.Errorf("Failed to open temp file, using stderr instead: err %s", err)
+		cmd.Stderr = os.Stderr
+		stderr = nil
+	} else {
+		cmd.Stderr = stderr
+	}
+	cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
+	stdout, _ := cmd.StdoutPipe()
+	stdin, _ := cmd.StdinPipe()
+	return &Child{
+		Cmd:    cmd,
+		Name:   command,
+		Stdout: bufio.NewReader(stdout),
+		Stdin:  stdin,
+		stderr: stderr,
+		t:      t,
+	}
+}
+
+// HelperProcess is the entry point for helper subprocesses.
+// Children should Write errors to stderr and test output to stdout since
+// the parent process will read from stdout a line at a time to monitor
+// the progress of the child.
+func HelperProcess(*testing.T) {
+	// Return immediately if this is not run as the child helper
+	// for the other tests.
+	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
+		return
+	}
+	if len(subcommand) == 0 {
+		vlog.Fatalf("No command found in: %s", os.Args)
+	}
+	mainFunc, ok := CommandTable[subcommand]
+	if !ok {
+		vlog.Fatalf("Unknown cmd: '%s'", subcommand)
+	}
+	mainFunc(flag.Args())
+	os.Exit(0)
+}
+
+type Reader func(r *bufio.Reader) (string, error)
+
+// ReadAll will read up to 16K of data from a buffered I/O reader, it is
+// intended to be used with ReadWithTimeout.
+func ReadAll(r *bufio.Reader) (string, error) {
+	buf := make([]byte, 4096*4)
+	n, err := r.Read(buf)
+	if err != nil {
+		return "", err
+	}
+	return string(buf[:n]), nil
+}
+
+// ReadLine will read a single line from a buffered I/O reader, it is
+// intended to be used with ReadWithTimeout.
+func ReadLine(r *bufio.Reader) (string, error) {
+	return r.ReadString('\n')
+}
+
+// ReadWithTimeout reads data from bufio.Reader instance using a function
+// of type Reader such as ReadAll or ReadLine. It will return true if it
+// times out, false otherwise. It will terminate the Child if it encounters
+// a timeout.
+func (c *Child) ReadWithTimeout(f Reader, r *bufio.Reader, timeout time.Duration) (string, bool, error) {
+	ch := make(chan string, 1)
+	ech := make(chan error, 1)
+	go func(c *Child) {
+		c.ioLock.Lock()
+		s, err := f(r)
+		c.ioLock.Unlock()
+		if err != nil {
+			if err != io.EOF {
+				vlog.VI(2).Info(formatLogLine("failed to read message: error %s: '%s'", err, s))
+			}
+			ech <- err
+			return
+		}
+		ch <- s
+	}(c)
+	select {
+	case err := <-ech:
+		return "", false, err
+	case m := <-ch:
+		return strings.TrimRight(m, "\n"), false, nil
+	case <-time.After(timeout):
+		// Kill the sub process to get the read calls running
+		// in the goroutine above to return an err.
+		c.Cmd.Process.Kill()
+		return "", true, nil
+	}
+	panic("unreachable")
+}
+
+func (c *Child) readRemaining(stream string, r *bufio.Reader) {
+	text, timedout, err := c.ReadWithTimeout(ReadAll, r, waitSeconds)
+	switch {
+	case timedout:
+		c.t.Error(formatLogLine("%s: timedout reading %s: err '%v'", c.Name, stream, err))
+	case err != nil:
+		c.t.Error(formatLogLine("%s: err reading %s", c.Name, stream))
+	default:
+		vlog.Info(formatLogLine("%s: %s: '%s'", c.Name, stream, text))
+	}
+}
+
+func (c *Child) expectLine(expected string) bool {
+	actual, timedout, err := c.ReadWithTimeout(ReadLine, c.Stdout, waitSeconds)
+	switch {
+	case timedout:
+		c.t.Error(formatLogLine("%s: timedout reading from stdout, expecting '%s'", c.Name, expected))
+		return false
+	case err != nil && err != io.EOF:
+		c.t.Error(formatLogLine("%s: unexpected error: %s, expecting '%s'", c.Name, err, expected))
+		return false
+	case actual == expected:
+		vlog.VI(2).Info(formatLogLine("%s: got: '%s'", c.Name, strings.TrimRight(actual, "")))
+		return err == io.EOF
+	default:
+		c.t.Error(formatLogLine("%s: expected '%s': got '%s'", c.Name, expected, actual))
+		return err == io.EOF
+	}
+}
+
+// removeIfFound removes the give item from the given list, if present
+// (returning if the item was present).  If several copies of the item exist,
+// removeIfFound only removes the first occurrence.
+func removeIfFound(item string, list *[]string) bool {
+	for i, e := range *list {
+		if e == item {
+			*list = append((*list)[0:i], (*list)[i+1:len(*list)]...)
+			return true
+		}
+	}
+	return false
+}
+
+func (c *Child) expectSetEventually(expected []string, timeout time.Duration) bool {
+	for {
+		actual, timedout, err := c.ReadWithTimeout(ReadLine, c.Stdout, timeout)
+		switch {
+		case timedout:
+			m := formatLogLine("%s: timedout reading from stdout", c.Name)
+			vlog.VI(2).Info(m)
+			c.t.Error(m)
+			return false
+		case err != nil && err != io.EOF:
+			m := formatLogLine("%s: unexpected error: %s", c.Name, err)
+			vlog.VI(2).Info(m)
+			c.t.Error(m)
+			return false
+		case removeIfFound(actual, &expected):
+			if len(expected) == 0 {
+				return err == io.EOF
+			}
+		case err == io.EOF:
+			m := formatLogLine("%s: eof", c.Name)
+			vlog.VI(2).Info(m)
+			c.t.Error(m)
+			return true
+		default:
+			vlog.VI(2).Info(formatLogLine("%s: got: '%s'", c.Name, strings.TrimRight(actual, "\n")))
+		}
+	}
+}
+
+// Expect the specified string to be read from the Child's stdout pipe.
+// Trailing \n's are stripped from the Child's output and hence should not
+// be included in the "expected" parameter.
+func (c *Child) Expect(expected string) {
+	if c.t.Failed() {
+		vlog.VI(2).Info(formatLogLine("Already failed"))
+		return
+	}
+	eof := c.expectLine(expected)
+	if eof {
+		c.t.Error(formatLogLine("%s: unexpected EOF when expecting '%s'", c.Name, strings.TrimRight(expected, "\n")))
+	}
+}
+
+// ExpectSet verifies whether the given set of strings (expressed as a list,
+// though order is irrelevant) matches the next len(expected) lines in stdout.
+// The set is allowed to contain repetitions if the same line is expected
+// multiple times.
+func (c *Child) ExpectSet(expected []string) {
+	if c.t.Failed() {
+		return
+	}
+	actual := make([]string, 0, len(expected))
+	for i := 0; i < len(expected); i++ {
+		str, err := c.ReadLineFromChild()
+		if err != nil {
+			c.t.Errorf("ReadLineFromChild: failed %v", err)
+			return
+		}
+		actual = append(actual, str)
+	}
+	sort.Strings(expected)
+	sort.Strings(actual)
+	for i, exp := range expected {
+		if exp != actual[i] {
+			c.t.Errorf(formatLogLine("expected %v, actual %v", expected, actual))
+			return
+		}
+	}
+}
+
+// Expect the specified string to be read from the Child's stdout pipe
+// eventually.  There may be additional output beforehand.
+func (c *Child) ExpectEventually(expected string, timeout time.Duration) {
+	if c.t.Failed() {
+		vlog.VI(2).Info(formatLogLine("Already failed"))
+		return
+	}
+	vlog.VI(2).Info(formatLogLine("Waiting for client, timeout %s", timeout))
+	eof := c.expectSetEventually([]string{expected}, timeout)
+	if eof {
+		c.t.Error(formatLogLine("%s: unexpected EOF when expecting %q", c.Name, strings.TrimRight(expected, "\n")))
+	}
+}
+
+// ExpectSetEventually verifies whether the given set of strings (expressed as a
+// list, though order is irrelevant) appear in the stdout pipe of the child
+// eventually.  The set is allowed to contain repetitions if the same line is
+// expected multiple times.
+func (c *Child) ExpectSetEventually(expected []string, timeout time.Duration) {
+	if c.t.Failed() {
+		vlog.VI(2).Info(formatLogLine("Already failed"))
+		return
+	}
+	vlog.VI(2).Info(formatLogLine("Waiting for client, timeout %s", timeout))
+	eof := c.expectSetEventually(expected, timeout)
+	if eof {
+		c.t.Error(formatLogLine("%s: unexpected EOF when expecting %q", c.Name, expected))
+	}
+}
+
+// Expect EOF to be read from the Child's stdout pipe and wait for the child
+// if it is still running to clean up process state.
+func (c *Child) ExpectEOFAndWait() {
+	c.ExpectEOFAndWaitForExitCode(nil)
+}
+
+// ExpectEOFAndWaitForExitCode is the same as ExpectEOFAndWait except that it
+// allows for a non-nil error to be returned by the child.
+func (c *Child) ExpectEOFAndWaitForExitCode(exit error) {
+	if c.t.Failed() {
+		c.t.Error(formatLogLine("%s: cleanup", c.Name))
+		c.readRemaining("stdout", c.Stdout)
+		if c.Cmd.Process != nil {
+			c.Cmd.Process.Kill()
+		}
+	} else {
+		eof := c.expectLine("")
+		if !eof {
+			c.t.Error(formatLogLine("%s: failed to exit (failed to read EOF)", c.Name))
+			c.readRemaining("stdout", c.Stdout)
+			if c.Cmd.Process != nil {
+				c.Cmd.Process.Kill()
+			}
+		}
+	}
+	c.ioLock.Lock()
+	defer c.ioLock.Unlock()
+	err := c.Cmd.Wait()
+	if exit == nil {
+		if err != nil {
+			c.t.Error(formatLogLine("Client exited with error: %s", err))
+		}
+		return
+	}
+	if err == nil {
+		c.t.Error(formatLogLine("Client exited without error: expecting %s", exit))
+		return
+	}
+	if err.Error() != exit.Error() {
+		c.t.Error(formatLogLine("Client exited with unexpected error: %q and not %q", err, exit))
+	}
+}
+
+// The WaitForXXX() functions are similar to expectations, but they do less
+// checking and for use in benchmarking.
+
+// WaitForLine reads the input until the expected line is read,
+// returning an error if EOF is reached or there is a timeout.
+func (c *Child) WaitForLine(expected string, timeout time.Duration) error {
+	if c.t.Failed() {
+		vlog.VI(2).Info(formatLogLine("Already failed"))
+		return fmt.Errorf("Already failed")
+	}
+	deadline := time.Now().Add(timeout)
+	for {
+		actual, _, err := c.ReadWithTimeout(ReadLine, c.Stdout, deadline.Sub(time.Now()))
+		if err != nil {
+			return err
+		}
+		if actual == expected {
+			return nil
+		}
+	}
+}
+
+// WaitForEOF reads the input until an EOF is reached, returning an
+// error if there is a timeout.
+func (c *Child) WaitForEOF(timeout time.Duration) error {
+	deadline := time.Now().Add(timeout)
+	for {
+		_, _, err := c.ReadWithTimeout(ReadLine, c.Stdout, deadline.Sub(time.Now()))
+		if err == io.EOF {
+			return nil
+		}
+		if err != nil {
+			return err
+		}
+	}
+}
+
+// WaitForPortFromChild waits for a line in the format "port %d" and returns the
+// port number, or an error if there is a timeout or EOF is reached.
+func (c *Child) WaitForPortFromChild() (string, error) {
+	actual, _, err := c.ReadWithTimeout(ReadLine, c.Stdout, waitSeconds)
+	if err != nil {
+		return "", err
+	}
+	last := strings.LastIndex(actual, ":")
+	if last == -1 {
+		return "", fmt.Errorf("%s", formatLogLine("%s: failed to parse port from %q - missing ':'", c.Name, actual))
+	}
+	port := actual[last+1:]
+	port = strings.TrimSuffix(port, "'\n")
+	// Check that the port is a number.
+	_, err = strconv.Atoi(port)
+	if err != nil {
+		return "", fmt.Errorf("%s", formatLogLine("%s: failed to parse port from %q: err %s", c.Name, actual, err))
+	}
+	return port, nil
+}
+
+// ReadPortFromChild reads a port number written to the child's stdout,
+// returning an error if it fails to do so and not calling t.Error internal.
+func (c *Child) ReadPortFromChild() (string, error) {
+	if c.t.Failed() {
+		return "", fmt.Errorf("%s", "Already failed")
+	}
+	actual, timedout, err := c.ReadWithTimeout(ReadLine, c.Stdout, waitSeconds)
+	if timedout {
+		return "", fmt.Errorf("%s", formatLogLine("%s: timeout reading port", c.Name))
+	}
+	if err != nil {
+		return "", fmt.Errorf("%s", formatLogLine("%s: error reading port: %s", c.Name, err))
+	}
+	last := strings.LastIndex(actual, ":")
+	if last == -1 {
+		return "", fmt.Errorf("%s", formatLogLine("%s: failed to parse port from '%s' - missing ':'", c.Name, actual))
+	}
+	port := actual[last+1:]
+	port = strings.TrimRight(port, "'\n")
+	_, err = strconv.Atoi(port)
+	if err != nil {
+		return "", fmt.Errorf("%s", formatLogLine("%s: failed to parse port from '%s': err %s", c.Name, actual, err))
+	}
+	return port, nil
+}
+
+// ReadLineFromChild reads a single line from the child's stdout,
+// returning an error if it fails to do so and not calling t.Error internal.
+func (c *Child) ReadLineFromChild() (string, error) {
+	if c.t.Failed() {
+		return "", fmt.Errorf("Already failed")
+	}
+	actual, timedout, err := c.ReadWithTimeout(ReadLine, c.Stdout, waitSeconds)
+	if timedout {
+		return "", fmt.Errorf("%s", formatLogLine("%s: timeout reading line", c.Name))
+	}
+	if err != nil {
+		return "", fmt.Errorf("%s", formatLogLine("%s: error reading line: %s", c.Name, err))
+	}
+	return strings.TrimRight(actual, "\n"), nil
+}
+
+// WriteLine writes the given line to the child's stdin, and appends a \n.
+func (c *Child) WriteLine(line string) {
+	if c.t.Failed() {
+		vlog.VI(2).Info(formatLogLine("Already failed"))
+		return
+	}
+	c.Stdin.Write([]byte(line))
+	c.Stdin.Write([]byte("\n"))
+}
+
+// CloseStding closes the stdin pipe the child is likely blocked on.
+func (c *Child) CloseStdin() {
+	// Child should exit now.
+	c.Stdin.Close()
+}
+
+// Cleanup sends a kill signal to the child, prints any stderr logs from
+// the child and deletes the log files generated by the child.
+func (c *Child) Cleanup() {
+	vlog.FlushLog()
+	if c.Cmd.Process != nil {
+		c.Cmd.Process.Kill()
+	}
+	if c.stderr != nil {
+		defer func() {
+			c.stderr.Close()
+			os.Remove(c.stderr.Name())
+		}()
+		if _, err := c.stderr.Seek(0, 0); err != nil {
+			return
+		}
+		scanner := bufio.NewScanner(c.stderr)
+		for scanner.Scan() {
+			// Avoid printing two sets of line headers
+			vlog.Info(c.Name + ": " + scanner.Text())
+		}
+	}
+}
diff --git a/lib/testutil/blackbox/subprocess_test.go b/lib/testutil/blackbox/subprocess_test.go
new file mode 100644
index 0000000..8da6ace
--- /dev/null
+++ b/lib/testutil/blackbox/subprocess_test.go
@@ -0,0 +1,128 @@
+package blackbox_test
+
+// TODO(cnicolaou): add tests for error cases that result in t.Fatalf being
+// called. We need to mock testing.T in order to be able to catch these.
+
+import (
+	"io"
+	"testing"
+	"time"
+
+	"veyron/lib/testutil"
+	"veyron/lib/testutil/blackbox"
+)
+
+func isFatalf(t *testing.T, err error, format string, args ...interface{}) {
+	if err != nil {
+		t.Fatalf(testutil.FormatLogLine(2, format, args...))
+	}
+}
+
+func TestHelperProcess(t *testing.T) {
+	blackbox.HelperProcess(t)
+}
+
+func finish(c *blackbox.Child) {
+	c.CloseStdin()
+	c.Expect("done")
+	c.ExpectEOFAndWait()
+}
+
+func TestExpect(t *testing.T) {
+	c := blackbox.HelperCommand(t, "print", "a", "b", "c")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.Expect("a")
+	c.Expect("b")
+	c.Expect("c")
+	finish(c)
+}
+
+func TestExpectSet(t *testing.T) {
+	c := blackbox.HelperCommand(t, "print", "a", "b", "c")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.ExpectSet([]string{"c", "b", "a"})
+	finish(c)
+}
+
+func TestExpectEventually(t *testing.T) {
+	c := blackbox.HelperCommand(t, "print", "a", "b", "c")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.ExpectEventually("c", time.Second)
+	finish(c)
+}
+
+func TestExpectSetEventually(t *testing.T) {
+	c := blackbox.HelperCommand(t, "print", "a", "b", "c", "d", "b")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.ExpectSetEventually([]string{"d", "b", "b"}, time.Second)
+	finish(c)
+}
+
+func TestReadPort(t *testing.T) {
+	c := blackbox.HelperCommand(t, "print", "host:1234")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	port, err := c.ReadPortFromChild()
+	if err != nil {
+		t.Fatalf("failed to read port from child: %s", err)
+	}
+	if port != "1234" {
+		t.Fatalf("unexpected port from child: %q", port)
+	}
+	finish(c)
+}
+
+func TestEcho(t *testing.T) {
+	c := blackbox.HelperCommand(t, "echo")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.WriteLine("a")
+	c.WriteLine("b")
+	c.WriteLine("c")
+	c.ExpectEventually("c", time.Second)
+	finish(c)
+}
+
+func TestTimeout(t *testing.T) {
+	c := blackbox.HelperCommand(t, "echo")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	c.WriteLine("a")
+	l, timeout, err := c.ReadWithTimeout(blackbox.ReadLine, c.Stdout, time.Second)
+	isFatalf(t, err, "unexpected error: %s", err)
+	if timeout {
+		t.Fatalf("unexpected timeout")
+	}
+	if l != "a" {
+		t.Fatalf("unexpected input: got %q", l)
+	}
+	_, timeout, _ = c.ReadWithTimeout(blackbox.ReadLine, c.Stdout, 250*time.Millisecond)
+	if !timeout {
+		t.Fatalf("failed to timeout")
+	}
+	_, _, err = c.ReadWithTimeout(blackbox.ReadLine, c.Stdout, 250*time.Millisecond)
+	// The previous call to ReadWithTimeout which timed out kills the
+	// Child, so a subsequent call will read an EOF.
+	if err != io.EOF {
+		t.Fatalf("expected EOF: got %q instead", err)
+	}
+}
+
+func TestWait(t *testing.T) {
+	c := blackbox.HelperCommand(t, "print", "a", "b:1234")
+	defer c.Cleanup()
+	c.Cmd.Start()
+	err := c.WaitForLine("a", time.Second)
+	isFatalf(t, err, "unexpected error: %s", err)
+	port, err := c.WaitForPortFromChild()
+	isFatalf(t, err, "unexpected error: %s", err)
+	if port != "1234" {
+		isFatalf(t, err, "unexpected port: %s", port)
+	}
+	c.CloseStdin()
+	c.WaitForEOF(time.Second)
+}
diff --git a/lib/testutil/blackbox/util.go b/lib/testutil/blackbox/util.go
new file mode 100644
index 0000000..4ba6790
--- /dev/null
+++ b/lib/testutil/blackbox/util.go
@@ -0,0 +1,52 @@
+package blackbox
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"time"
+)
+
+var (
+	waitSeconds = 100 * time.Second
+)
+
+// Prepend the file+lineno of the first caller from outside this package
+func formatLogLine(format string, args ...interface{}) string {
+	_, file, line, _ := runtime.Caller(1)
+	cwd := filepath.Dir(file)
+	for d := 2; d < 10; d++ {
+		_, file, line, _ = runtime.Caller(d)
+		if cwd != filepath.Dir(file) {
+			break
+		}
+	}
+	nargs := []interface{}{filepath.Base(file), line}
+	nargs = append(nargs, args...)
+	return fmt.Sprintf("%s:%d: "+format, nargs...)
+}
+
+// Wait for EOF on os.Stdin, used to signal to the Child that it should exit.
+func WaitForEOFOnStdin() {
+	var buf [1]byte
+	for {
+		_, err := os.Stdin.Read(buf[:])
+		if err != nil {
+			break
+		}
+	}
+}
+
+// ReadLineFromStdin reads a line from os.Stdin, blocking until one is available
+// or until EOF is encoutnered.  The line is returned with the newline character
+// chopped off.
+func ReadLineFromStdin() string {
+	if read, err := bufio.NewReader(os.Stdin).ReadString('\n'); err != nil {
+		return ""
+	} else {
+		return strings.TrimRight(read, "\n")
+	}
+}
diff --git a/lib/testutil/init.go b/lib/testutil/init.go
new file mode 100644
index 0000000..2d42a41
--- /dev/null
+++ b/lib/testutil/init.go
@@ -0,0 +1,34 @@
+// Package testutil provides initalization and utility routines for unit tests.
+//
+// All tests should import it, even if only for its initialization:
+//   import _ "veyron/lib/testutil"
+//
+package testutil
+
+import (
+	"flag"
+	"os"
+	"runtime"
+	// Need to import all of the packages that could possibly
+	// define flags that we care about. In practice, this is the
+	// flags defined by the testing package, the logging library
+	// and any flags defined by the blackbox package below.
+	_ "testing"
+
+	// Import blackbox to ensure that it gets to define its flags.
+	_ "veyron/lib/testutil/blackbox"
+
+	"veyron2/vlog"
+)
+
+func init() {
+	if os.Getenv("GOMAXPROCS") == "" {
+		// Set the number of logical processors to the number of CPUs,
+		// if GOMAXPROCS is not set in the environment.
+		runtime.GOMAXPROCS(runtime.NumCPU())
+	}
+	// At this point all of the flags that we're going to use for
+	// tests must be defined.
+	flag.Parse()
+	vlog.ConfigureLibraryLoggerFromFlags()
+}
diff --git a/lib/testutil/util.go b/lib/testutil/util.go
new file mode 100644
index 0000000..b6a8bf9
--- /dev/null
+++ b/lib/testutil/util.go
@@ -0,0 +1,86 @@
+package testutil
+
+import (
+	"fmt"
+	"io/ioutil"
+	"math/rand"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"time"
+
+	isecurity "veyron/runtimes/google/security"
+
+	"veyron2/security"
+)
+
+// FormatLogLine will prepend the file and line number of the caller
+// at the specificied depth (as per runtime.Caller) to the supplied
+// format and args and return a formatted string. It is useful when
+// implementing functions that factor out error handling and reporting
+// in tests.
+func FormatLogLine(depth int, format string, args ...interface{}) string {
+	_, file, line, _ := runtime.Caller(depth)
+	nargs := []interface{}{filepath.Base(file), line}
+	nargs = append(nargs, args...)
+	return fmt.Sprintf("%s:%d: "+format, nargs...)
+}
+
+// DepthToExternalCaller determines the number of stack frames to the first
+// enclosing caller that is external to the package that this function is
+// called from. Drectory name is used as a proxy for package name,
+// that is, the directory component of the file return runtime.Caller is
+// compared to that of the lowest level caller until a different one is
+// encountered as the stack is walked upwards.
+func DepthToExternalCaller() int {
+	_, file, _, _ := runtime.Caller(1)
+	cwd := filepath.Dir(file)
+	for d := 2; d < 10; d++ {
+		_, file, _, _ := runtime.Caller(d)
+		if cwd != filepath.Dir(file) {
+			return d
+		}
+	}
+	return 1
+}
+
+// SaveIdentityToFile saves the provided identity in Base64VOM format
+// to a randomly created temporary file, and returns the path to the file.
+// This function is meant to be used for testing purposes only, it panics
+// if there is an error. The caller must ensure that the created file
+// is removed once it is no longer needed.
+func SaveIdentityToFile(id security.PrivateID) string {
+	f, err := ioutil.TempFile("", strconv.Itoa(rand.Int()))
+	if err != nil {
+		panic(err)
+	}
+	defer f.Close()
+	filePath := f.Name()
+
+	if err := security.SaveIdentity(f, id); err != nil {
+		os.Remove(filePath)
+		panic(err)
+	}
+	return filePath
+}
+
+// NewBlessedIdentity creates a new identity and blesses it using the provided blesser
+// under the provided name. This function is meant to be used for testing purposes only,
+// it panics if there is an error.
+func NewBlessedIdentity(blesser security.PrivateID, name string) security.PrivateID {
+	id, err := isecurity.NewChainPrivateID("test")
+	if err != nil {
+		panic(err)
+	}
+
+	blessedID, err := blesser.Bless(id.PublicID(), name, 5*time.Minute, nil)
+	if err != nil {
+		panic(err)
+	}
+	derivedID, err := id.Derive(blessedID)
+	if err != nil {
+		panic(err)
+	}
+	return derivedID
+}
diff --git a/lib/testutil/util_test.go b/lib/testutil/util_test.go
new file mode 100644
index 0000000..2209d92
--- /dev/null
+++ b/lib/testutil/util_test.go
@@ -0,0 +1,87 @@
+package testutil_test
+
+import (
+	"fmt"
+	"os"
+	"reflect"
+	"regexp"
+	"testing"
+
+	"veyron/lib/testutil"
+	isecurity "veyron/runtimes/google/security"
+
+	"veyron2/rt"
+	"veyron2/security"
+)
+
+func TestFormatLogline(t *testing.T) {
+	depth, want := testutil.DepthToExternalCaller(), 2
+	if depth != want {
+		t.Errorf("got %v, want %v", depth, want)
+	}
+	{
+		line, want := testutil.FormatLogLine(depth, "test"), "testing.go:.*"
+		if ok, err := regexp.MatchString(want, line); !ok || err != nil {
+			t.Errorf("got %v, want %v", line, want)
+		}
+	}
+}
+
+func TestSaveIdentityToFile(t *testing.T) {
+	r, err := rt.New()
+	if err != nil {
+		t.Fatalf("rt.New failed: %v", err)
+	}
+	defer r.Shutdown()
+	id, err := r.NewIdentity("test")
+	if err != nil {
+		t.Fatalf("r.NewIdentity failed: %v", err)
+	}
+
+	filePath := testutil.SaveIdentityToFile(id)
+	defer os.Remove(filePath)
+
+	f, err := os.Open(filePath)
+	if err != nil {
+		t.Fatalf("os.Open(%v) failed: %v", filePath, err)
+	}
+	defer f.Close()
+	loadedID, err := security.LoadIdentity(f)
+	if err != nil {
+		t.Fatalf("LoadIdentity failed: %v", err)
+	}
+	if !reflect.DeepEqual(loadedID, id) {
+		t.Fatalf("Got Identity %v, but want %v", loadedID, id)
+	}
+}
+
+func TestNewBlessedIdentity(t *testing.T) {
+	r, err := rt.New()
+	if err != nil {
+		t.Fatalf("rt.New failed: %v", err)
+	}
+	defer r.Shutdown()
+	newID := func(name string) security.PrivateID {
+		id, err := r.NewIdentity(name)
+		if err != nil {
+			t.Fatalf("r.NewIdentity failed: %v", err)
+		}
+		isecurity.TrustIdentityProviders(id)
+		return id
+	}
+	testdata := []struct {
+		blesser            security.PrivateID
+		blessingName, name string
+	}{
+		{blesser: newID("google"), blessingName: "alice", name: "PrivateID:google/alice"},
+		{blesser: newID("google"), blessingName: "bob", name: "PrivateID:google/bob"},
+		{blesser: newID("veyron"), blessingName: "alice", name: "PrivateID:veyron/alice"},
+		{blesser: newID("veyron"), blessingName: "bob", name: "PrivateID:veyron/bob"},
+		{blesser: testutil.NewBlessedIdentity(newID("google"), "alice"), blessingName: "tv", name: "PrivateID:google/alice/tv"},
+	}
+	for _, d := range testdata {
+		if got, want := fmt.Sprintf("%s", testutil.NewBlessedIdentity(d.blesser, d.blessingName)), d.name; got != want {
+			t.Errorf("NewBlessedIdentity(%q, %q): Got %q, want %q", d.blesser, d.blessingName, got, want)
+		}
+	}
+}
diff --git a/lib/testutil/vtest.go b/lib/testutil/vtest.go
new file mode 100644
index 0000000..fccf74d
--- /dev/null
+++ b/lib/testutil/vtest.go
@@ -0,0 +1,12 @@
+package testutil
+
+// CallAndRecover calls the function f and returns the result of recover().
+// This minimizes the scope of the deferred recover, to ensure f is actually the
+// function that paniced.
+func CallAndRecover(f func()) (result interface{}) {
+	defer func() {
+		result = recover()
+	}()
+	f()
+	return
+}
diff --git a/lib/testutil/vtest_test.go b/lib/testutil/vtest_test.go
new file mode 100644
index 0000000..a4523ab
--- /dev/null
+++ b/lib/testutil/vtest_test.go
@@ -0,0 +1,23 @@
+package testutil
+
+import (
+	"testing"
+)
+
+func TestCallAndRecover(t *testing.T) {
+	tests := []struct {
+		f      func()
+		expect interface{}
+	}{
+		{func() {}, nil},
+		{func() { panic(nil) }, nil},
+		{func() { panic(123) }, 123},
+		{func() { panic("abc") }, "abc"},
+	}
+	for _, test := range tests {
+		got := CallAndRecover(test.f)
+		if got != test.expect {
+			t.Errorf(`CallAndRecover got "%v", want "%v"`, got, test.expect)
+		}
+	}
+}
diff --git a/lib/toposort/sort.go b/lib/toposort/sort.go
new file mode 100644
index 0000000..eadbe3a
--- /dev/null
+++ b/lib/toposort/sort.go
@@ -0,0 +1,177 @@
+/*
+A package that implements topological sort.   For details see:
+http://en.wikipedia.org/wiki/Topological_sorting
+*/
+package toposort
+
+type Sorter interface {
+	// AddNode adds a node value.  Arbitrary value types are supported, but the
+	// values must be comparable - they'll be used as map keys.  Typically this is
+	// only used to add potentially loner nodes with no incoming or outgoing edges.
+	AddNode(value interface{})
+
+	// AddEdge adds nodes corresponding to from and to, and adds an edge from -> to.
+	// You don't need to call AddNode first; the nodes will be implicitly added if
+	// they don't already exist.  The direction means that from depends on to;
+	// i.e. to will appear before from in the sorted output.  Cycles are allowed.
+	AddEdge(from, to interface{})
+
+	// Sort returns the topologically sorted values, along with cycles which
+	// represents some of the cycles (if any) that were encountered.  You're
+	// guaranteed that len(cycles)==0 iff there are no cycles in the graph,
+	// otherwise an arbitrary (but non-empty) list of cycles is returned.
+	//
+	// If there are cycles the sorting is best-effort; portions of the graph that
+	// are acyclic will still be ordered correctly, and the cyclic portions have an
+	// arbitrary ordering.
+	//
+	// Sort is deterministic; given the same sequence of inputs it will always
+	// return the same output, even if the inputs are only partially ordered.  This
+	// is useful for idl compilation where we re-order type definitions, and it's
+	// nice to get a deterministic order.
+	Sort() ([]interface{}, [][]interface{})
+}
+
+// NewSorter returns a new topological sorter.
+func NewSorter() Sorter {
+	return &topoSort{}
+}
+
+// topoSort performs a topological sort.  This is meant to be simple, not
+// high-performance.  For details see:
+// http://en.wikipedia.org/wiki/Topological_sorting
+type topoSort struct {
+	values map[interface{}]int
+	nodes  []*topoNode
+}
+
+// topoNode is a node in the graph representing the topological information.
+type topoNode struct {
+	index    int
+	value    interface{}
+	children []*topoNode
+}
+
+func (tn *topoNode) addChild(child *topoNode) {
+	tn.children = append(tn.children, child)
+}
+
+func (ts *topoSort) addOrGetNode(value interface{}) *topoNode {
+	if ts.nodes == nil {
+		ts.values = make(map[interface{}]int)
+	}
+	if index, ok := ts.values[value]; ok {
+		return ts.nodes[index]
+	}
+	index := len(ts.nodes)
+	newNode := &topoNode{index: index, value: value}
+	ts.values[value] = index
+	ts.nodes = append(ts.nodes, newNode)
+	return newNode
+}
+
+// AddNode adds a node value.  Arbitrary value types are supported, but the
+// values must be comparable - they'll be used as map keys.  Typically this is
+// only used to add potentially loner nodes with no incoming or outgoing edges.
+func (ts *topoSort) AddNode(value interface{}) {
+	ts.addOrGetNode(value)
+}
+
+// AddEdge adds nodes corresponding to from and to, and adds an edge from -> to.
+// You don't need to call AddNode first; the nodes will be implicitly added if
+// they don't already exist.  The direction means that from depends on to;
+// i.e. to will appear before from in the sorted output.  Cycles are allowed.
+func (ts *topoSort) AddEdge(from interface{}, to interface{}) {
+	fromNode := ts.addOrGetNode(from)
+	toNode := ts.addOrGetNode(to)
+	fromNode.addChild(toNode)
+}
+
+// Sort returns the topologically sorted values, along with cycles which
+// represents some of the cycles (if any) that were encountered.  You're
+// guaranteed that len(cycles)==0 iff there are no cycles in the graph,
+// otherwise an arbitrary (but non-empty) list of cycles is returned.
+//
+// If there are cycles the sorting is best-effort; portions of the graph that
+// are acyclic will still be ordered correctly, and the cyclic portions have an
+// arbitrary ordering.
+//
+// Sort is deterministic; given the same sequence of inputs it will always
+// return the same output, even if the inputs are only partially ordered.  This
+// is useful for idl compilation where we re-order type definitions, and it's
+// nice to get a deterministic order.
+func (ts *topoSort) Sort() (sorted []interface{}, cycles [][]interface{}) {
+	// The strategy is the standard simple approach of performing DFS on the
+	// graph.  Details are outlined in the above wikipedia article.
+	done := make(topoNodeSet)
+	for _, node := range ts.nodes {
+		cycles = appendCycles(cycles, node.visit(done, make(topoNodeSet), &sorted))
+	}
+	return
+}
+
+type topoNodeSet map[*topoNode]struct{}
+
+// visit performs DFS on the graph, and fills in sorted and cycles as it
+// traverses.  We use done to indicate a node has been fully explored, and
+// visiting to indicate a node is currently being explored.
+//
+// The cycle collection strategy is to wait until we've hit a repeated node in
+// visiting, and add that node to cycles and return.  Thereafter as the
+// recursive stack is unwound, nodes append themselves to the end of each cycle,
+// until we're back at the repeated node.  This guarantees that if the graph is
+// cyclic we'll return at least one of the cycles.
+func (tn *topoNode) visit(done, visiting topoNodeSet, sorted *[]interface{}) (cycles [][]interface{}) {
+	if _, ok := done[tn]; ok {
+		return
+	}
+	if _, ok := visiting[tn]; ok {
+		cycles = [][]interface{}{{tn.value}}
+		return
+	}
+	visiting[tn] = struct{}{}
+	for _, child := range tn.children {
+		cycles = appendCycles(cycles, child.visit(done, visiting, sorted))
+	}
+	done[tn] = struct{}{}
+	*sorted = append(*sorted, tn.value)
+	// Update cycles.  If it's empty none of our children detected any cycles, and
+	// there's nothing to do.  Otherwise we append ourselves to the cycle, iff the
+	// cycle hasn't completed yet.  We know the cycle has completed if the first
+	// and last item in the cycle are the same, with an exception for the single
+	// item case; self-cycles are represented as the same node appearing twice.
+	for cx := range cycles {
+		len := len(cycles[cx])
+		if len == 1 || cycles[cx][0] != cycles[cx][len-1] {
+			cycles[cx] = append(cycles[cx], tn.value)
+		}
+	}
+	return
+}
+
+// appendCycles returns the combined cycles in a and b.
+func appendCycles(a [][]interface{}, b [][]interface{}) [][]interface{} {
+	for _, bcycle := range b {
+		a = append(a, bcycle)
+	}
+	return a
+}
+
+// PrintCycles prints the cycles returned from topoSort.Sort, using f to convert
+// each node into a string.
+func PrintCycles(cycles [][]interface{}, f func(n interface{}) string) (str string) {
+	for cyclex, cycle := range cycles {
+		if cyclex > 0 {
+			str += " "
+		}
+		str += "["
+		for nodex, node := range cycle {
+			if nodex > 0 {
+				str += " <= "
+			}
+			str += f(node)
+		}
+		str += "]"
+	}
+	return
+}
diff --git a/lib/toposort/sort_test.go b/lib/toposort/sort_test.go
new file mode 100644
index 0000000..633e913
--- /dev/null
+++ b/lib/toposort/sort_test.go
@@ -0,0 +1,215 @@
+package toposort
+
+import (
+	"reflect"
+	"testing"
+)
+
+func toStringSlice(input []interface{}) (output []string) {
+	output = make([]string, len(input))
+	for ix, ival := range input {
+		output[ix] = ival.(string)
+	}
+	return
+}
+
+func toStringCycles(input [][]interface{}) (output [][]string) {
+	output = make([][]string, len(input))
+	for ix, islice := range input {
+		output[ix] = toStringSlice(islice)
+	}
+	return
+}
+
+type orderChecker struct {
+	t        *testing.T
+	original []string
+	orderMap map[string]int
+}
+
+func makeOrderChecker(t *testing.T, slice []interface{}) orderChecker {
+	result := orderChecker{t, toStringSlice(slice), make(map[string]int)}
+	for ix, val := range result.original {
+		result.orderMap[val] = ix
+	}
+	return result
+}
+
+func (oc *orderChecker) findValue(val string) int {
+	if index, ok := oc.orderMap[val]; ok {
+		return index
+	}
+	oc.t.Errorf("Couldn't find val %v in slice %v", val, oc.original)
+	return -1
+}
+
+func (oc *orderChecker) expectOrder(before, after string) {
+	if oc.findValue(before) >= oc.findValue(after) {
+		oc.t.Errorf("Expected %v before %v, slice %v", before, after, oc.original)
+	}
+}
+
+// Since sort is deterministic we can expect a particular total order, in
+// addition to the partial order checks.
+func (oc *orderChecker) expectTotalOrder(expect ...string) {
+	if !reflect.DeepEqual(oc.original, expect) {
+		oc.t.Errorf("Expected order %v, actual %v", expect, oc.original)
+	}
+}
+
+func expectCycles(t *testing.T, actual [][]interface{}, expect [][]string) {
+	actualStr := toStringCycles(actual)
+	if !reflect.DeepEqual(actualStr, expect) {
+		t.Errorf("Expected cycles %v, actual %v", expect, actualStr)
+	}
+}
+
+func TestSortDag(t *testing.T) {
+	// This is the graph:
+	// ,-->B
+	// |
+	// A-->C---->D
+	// |    \
+	// |     `-->E--.
+	// `-------------`-->F
+	var sorter topoSort
+	sorter.AddEdge("A", "B")
+	sorter.AddEdge("A", "C")
+	sorter.AddEdge("A", "F")
+	sorter.AddEdge("C", "D")
+	sorter.AddEdge("C", "E")
+	sorter.AddEdge("E", "F")
+	sorted, cycles := sorter.Sort()
+	oc := makeOrderChecker(t, sorted)
+	oc.expectOrder("B", "A")
+	oc.expectOrder("C", "A")
+	oc.expectOrder("D", "A")
+	oc.expectOrder("E", "A")
+	oc.expectOrder("F", "A")
+	oc.expectOrder("D", "C")
+	oc.expectOrder("E", "C")
+	oc.expectOrder("F", "C")
+	oc.expectOrder("F", "E")
+	oc.expectTotalOrder("B", "D", "F", "E", "C", "A")
+	expectCycles(t, cycles, [][]string{})
+}
+
+func TestSortSelfCycle(t *testing.T) {
+	// This is the graph:
+	// ,---.
+	// |   |
+	// A<--'
+	var sorter topoSort
+	sorter.AddEdge("A", "A")
+	sorted, cycles := sorter.Sort()
+	oc := makeOrderChecker(t, sorted)
+	oc.expectTotalOrder("A")
+	expectCycles(t, cycles, [][]string{{"A", "A"}})
+}
+
+func TestSortCycle(t *testing.T) {
+	// This is the graph:
+	// ,-->B-->C
+	// |       |
+	// A<------'
+	var sorter topoSort
+	sorter.AddEdge("A", "B")
+	sorter.AddEdge("B", "C")
+	sorter.AddEdge("C", "A")
+	sorted, cycles := sorter.Sort()
+	oc := makeOrderChecker(t, sorted)
+	oc.expectTotalOrder("C", "B", "A")
+	expectCycles(t, cycles, [][]string{{"A", "C", "B", "A"}})
+}
+
+func TestSortContainsCycle1(t *testing.T) {
+	// This is the graph:
+	// ,-->B
+	// |   ,-----.
+	// |   v     |
+	// A-->C---->D
+	// |    \
+	// |     `-->E--.
+	// `-------------`-->F
+	var sorter topoSort
+	sorter.AddEdge("A", "B")
+	sorter.AddEdge("A", "C")
+	sorter.AddEdge("A", "F")
+	sorter.AddEdge("C", "D")
+	sorter.AddEdge("C", "E")
+	sorter.AddEdge("D", "C") // creates the cycle
+	sorter.AddEdge("E", "F")
+	sorted, cycles := sorter.Sort()
+	oc := makeOrderChecker(t, sorted)
+	oc.expectOrder("B", "A")
+	oc.expectOrder("C", "A")
+	oc.expectOrder("D", "A")
+	oc.expectOrder("E", "A")
+	oc.expectOrder("F", "A")
+	// The difference with the dag is C, D may be in either order.
+	oc.expectOrder("E", "C")
+	oc.expectOrder("F", "C")
+	oc.expectOrder("F", "E")
+	oc.expectTotalOrder("B", "D", "F", "E", "C", "A")
+	expectCycles(t, cycles, [][]string{{"C", "D", "C"}})
+}
+
+func TestSortContainsCycle2(t *testing.T) {
+	// This is the graph:
+	// ,-->B
+	// |   ,-------------.
+	// |   v             |
+	// A-->C---->D       |
+	// |    \            |
+	// |     `-->E--.    |
+	// `-------------`-->F
+	var sorter topoSort
+	sorter.AddEdge("A", "B")
+	sorter.AddEdge("A", "C")
+	sorter.AddEdge("A", "F")
+	sorter.AddEdge("C", "D")
+	sorter.AddEdge("C", "E")
+	sorter.AddEdge("E", "F")
+	sorter.AddEdge("F", "C") // creates the cycle
+	sorted, cycles := sorter.Sort()
+	oc := makeOrderChecker(t, sorted)
+	oc.expectOrder("B", "A")
+	oc.expectOrder("C", "A")
+	oc.expectOrder("D", "A")
+	oc.expectOrder("E", "A")
+	oc.expectOrder("F", "A")
+	oc.expectOrder("D", "C")
+	// The difference with the dag is C, E, F may be in any order.
+	oc.expectTotalOrder("B", "D", "F", "E", "C", "A")
+	expectCycles(t, cycles, [][]string{{"C", "F", "E", "C"}})
+}
+
+func TestSortMultiCycles(t *testing.T) {
+	// This is the graph:
+	//    ,-->B
+	//    |   ,------------.
+	//    |   v            |
+	// .--A-->C---->D      |
+	// |  ^    \           |
+	// |  |     `-->E--.   |
+	// |  |         |  |   |
+	// |  `---------'  |   |
+	// `---------------`-->F
+	var sorter topoSort
+	sorter.AddEdge("A", "B")
+	sorter.AddEdge("A", "C")
+	sorter.AddEdge("A", "F")
+	sorter.AddEdge("C", "D")
+	sorter.AddEdge("C", "E")
+	sorter.AddEdge("E", "A") // creates a cycle
+	sorter.AddEdge("E", "F")
+	sorter.AddEdge("F", "C") // creates a cycle
+	sorted, cycles := sorter.Sort()
+	oc := makeOrderChecker(t, sorted)
+	oc.expectOrder("B", "A")
+	oc.expectOrder("D", "A")
+	oc.expectOrder("F", "A")
+	oc.expectOrder("D", "C")
+	oc.expectTotalOrder("B", "D", "F", "E", "C", "A")
+	expectCycles(t, cycles, [][]string{{"A", "E", "C", "A"}, {"C", "F", "E", "C"}})
+}