github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/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  
    10  	"github.com/juju/cmd"
    11  	"launchpad.net/gnuflag"
    12  	gc "launchpad.net/gocheck"
    13  )
    14  
    15  // NewFlagSet creates a new flag set using the standard options, particularly
    16  // the option to stop the gnuflag methods from writing to StdErr or StdOut.
    17  func NewFlagSet() *gnuflag.FlagSet {
    18  	fs := gnuflag.NewFlagSet("", gnuflag.ContinueOnError)
    19  	fs.SetOutput(ioutil.Discard)
    20  	return fs
    21  }
    22  
    23  // InitCommand will create a new flag set, and call the Command's SetFlags and
    24  // Init methods with the appropriate args.
    25  func InitCommand(c cmd.Command, args []string) error {
    26  	f := NewFlagSet()
    27  	c.SetFlags(f)
    28  	if err := f.Parse(c.AllowInterspersedFlags(), args); err != nil {
    29  		return err
    30  	}
    31  	return c.Init(f.Args())
    32  }
    33  
    34  // Context creates a simple command execution context with the current
    35  // dir set to a newly created directory within the test directory.
    36  func Context(c *gc.C) *cmd.Context {
    37  	return &cmd.Context{
    38  		Dir:    c.MkDir(),
    39  		Stdin:  &bytes.Buffer{},
    40  		Stdout: &bytes.Buffer{},
    41  		Stderr: &bytes.Buffer{},
    42  	}
    43  }
    44  
    45  // ContextForDir creates a simple command execution context with the current
    46  // dir set to the specified directory.
    47  func ContextForDir(c *gc.C, dir string) *cmd.Context {
    48  	return &cmd.Context{
    49  		Dir:    dir,
    50  		Stdin:  &bytes.Buffer{},
    51  		Stdout: &bytes.Buffer{},
    52  		Stderr: &bytes.Buffer{},
    53  	}
    54  }
    55  
    56  // Stdout takes a command Context that we assume has been created in this
    57  // package, and gets the content of the Stdout buffer as a string.
    58  func Stdout(ctx *cmd.Context) string {
    59  	return ctx.Stdout.(*bytes.Buffer).String()
    60  }
    61  
    62  // Stderr takes a command Context that we assume has been created in this
    63  // package, and gets the content of the Stderr buffer as a string.
    64  func Stderr(ctx *cmd.Context) string {
    65  	return ctx.Stderr.(*bytes.Buffer).String()
    66  }
    67  
    68  // RunCommand runs a command with the specified args.  The returned error
    69  // may come from either the parsing of the args, the command initialisation, or
    70  // the actual running of the command.  Access to the resulting output streams
    71  // is provided through the returned context instance.
    72  func RunCommand(c *gc.C, com cmd.Command, args ...string) (*cmd.Context, error) {
    73  	if err := InitCommand(com, args); err != nil {
    74  		return nil, err
    75  	}
    76  	var context = Context(c)
    77  	return context, com.Run(context)
    78  }
    79  
    80  // RunCommandInDir works like RunCommand, but runs with a context that uses dir.
    81  func RunCommandInDir(c *gc.C, com cmd.Command, args []string, dir string) (*cmd.Context, error) {
    82  	if err := InitCommand(com, args); err != nil {
    83  		return nil, err
    84  	}
    85  	var context = ContextForDir(c, dir)
    86  	return context, com.Run(context)
    87  }
    88  
    89  // TestInit checks that a command initialises correctly with the given set of
    90  // arguments.
    91  func TestInit(c *gc.C, com cmd.Command, args []string, errPat string) {
    92  	err := InitCommand(com, args)
    93  	if errPat != "" {
    94  		c.Assert(err, gc.ErrorMatches, errPat)
    95  	} else {
    96  		c.Assert(err, gc.IsNil)
    97  	}
    98  }