github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/testing/cmd.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package testing
     5  
     6  import (
     7  	"bytes"
     8  	"io/ioutil"
     9  	"strings"
    10  
    11  	"github.com/juju/cmd"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  	"launchpad.net/gnuflag"
    15  )
    16  
    17  // NewFlagSet creates a new flag set using the standard options, particularly
    18  // the option to stop the gnuflag methods from writing to StdErr or StdOut.
    19  func NewFlagSet() *gnuflag.FlagSet {
    20  	fs := gnuflag.NewFlagSet("", gnuflag.ContinueOnError)
    21  	fs.SetOutput(ioutil.Discard)
    22  	return fs
    23  }
    24  
    25  // InitCommand will create a new flag set, and call the Command's SetFlags and
    26  // Init methods with the appropriate args.
    27  func InitCommand(c cmd.Command, args []string) error {
    28  	f := NewFlagSet()
    29  	c.SetFlags(f)
    30  	if err := f.Parse(c.AllowInterspersedFlags(), args); err != nil {
    31  		return err
    32  	}
    33  	return c.Init(f.Args())
    34  }
    35  
    36  // Context creates a simple command execution context with the current
    37  // dir set to a newly created directory within the test directory.
    38  func Context(c *gc.C) *cmd.Context {
    39  	return &cmd.Context{
    40  		Dir:    c.MkDir(),
    41  		Stdin:  &bytes.Buffer{},
    42  		Stdout: &bytes.Buffer{},
    43  		Stderr: &bytes.Buffer{},
    44  	}
    45  }
    46  
    47  // ContextForDir creates a simple command execution context with the current
    48  // dir set to the specified directory.
    49  func ContextForDir(c *gc.C, dir string) *cmd.Context {
    50  	return &cmd.Context{
    51  		Dir:    dir,
    52  		Stdin:  &bytes.Buffer{},
    53  		Stdout: &bytes.Buffer{},
    54  		Stderr: &bytes.Buffer{},
    55  	}
    56  }
    57  
    58  // Stdout takes a command Context that we assume has been created in this
    59  // package, and gets the content of the Stdout buffer as a string.
    60  func Stdout(ctx *cmd.Context) string {
    61  	return ctx.Stdout.(*bytes.Buffer).String()
    62  }
    63  
    64  // Stderr takes a command Context that we assume has been created in this
    65  // package, and gets the content of the Stderr buffer as a string.
    66  func Stderr(ctx *cmd.Context) string {
    67  	return ctx.Stderr.(*bytes.Buffer).String()
    68  }
    69  
    70  // RunCommand runs a command with the specified args.  The returned error
    71  // may come from either the parsing of the args, the command initialisation, or
    72  // the actual running of the command.  Access to the resulting output streams
    73  // is provided through the returned context instance.
    74  func RunCommand(c *gc.C, com cmd.Command, args ...string) (*cmd.Context, error) {
    75  	if err := InitCommand(com, args); err != nil {
    76  		return nil, err
    77  	}
    78  	var context = Context(c)
    79  	return context, com.Run(context)
    80  }
    81  
    82  // RunCommandInDir works like RunCommand, but runs with a context that uses dir.
    83  func RunCommandInDir(c *gc.C, com cmd.Command, args []string, dir string) (*cmd.Context, error) {
    84  	if err := InitCommand(com, args); err != nil {
    85  		return nil, err
    86  	}
    87  	var context = ContextForDir(c, dir)
    88  	return context, com.Run(context)
    89  }
    90  
    91  // TestInit checks that a command initialises correctly with the given set of
    92  // arguments.
    93  func TestInit(c *gc.C, com cmd.Command, args []string, errPat string) {
    94  	err := InitCommand(com, args)
    95  	if errPat != "" {
    96  		c.Assert(err, gc.ErrorMatches, errPat)
    97  	} else {
    98  		c.Assert(err, jc.ErrorIsNil)
    99  	}
   100  }
   101  
   102  // ExtractCommandsFromHelpOutput takes the standard output from the
   103  // command context and looks for the "commands:" string and returns the
   104  // commands output after that.
   105  func ExtractCommandsFromHelpOutput(ctx *cmd.Context) []string {
   106  	var namesFound []string
   107  	commandHelp := strings.SplitAfter(Stdout(ctx), "commands:")[1]
   108  	commandHelp = strings.TrimSpace(commandHelp)
   109  	for _, line := range strings.Split(commandHelp, "\n") {
   110  		namesFound = append(namesFound, strings.TrimSpace(strings.Split(line, " - ")[0]))
   111  	}
   112  	return namesFound
   113  }