github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/action/package_test.go (about)

     1  // Copyright 2014-2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package action_test
     5  
     6  import (
     7  	"errors"
     8  	"io/ioutil"
     9  	"regexp"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/juju/cmd"
    14  	jujutesting "github.com/juju/testing"
    15  	jc "github.com/juju/testing/checkers"
    16  	gc "gopkg.in/check.v1"
    17  	"gopkg.in/juju/charm.v5"
    18  
    19  	"github.com/juju/juju/apiserver/params"
    20  	"github.com/juju/juju/cmd/envcmd"
    21  	"github.com/juju/juju/cmd/juju/action"
    22  	coretesting "github.com/juju/juju/testing"
    23  )
    24  
    25  const (
    26  	validActionTagString   = "action-f47ac10b-58cc-4372-a567-0e02b2c3d479"
    27  	invalidActionTagString = "action-f47ac10b-58cc-4372-a567-0e02b2c3d47"
    28  	validActionId          = "f47ac10b-58cc-4372-a567-0e02b2c3d479"
    29  	invalidActionId        = "f47ac10b-58cc-4372-a567-0e02b2c3d47"
    30  	validUnitId            = "mysql/0"
    31  	invalidUnitId          = "something-strange-"
    32  	validServiceId         = "mysql"
    33  	invalidServiceId       = "something-strange-"
    34  )
    35  
    36  func TestPackage(t *testing.T) {
    37  	gc.TestingT(t)
    38  }
    39  
    40  type BaseActionSuite struct {
    41  	jujutesting.IsolationSuite
    42  	command cmd.Command
    43  }
    44  
    45  var _ = gc.Suite(&FetchSuite{})
    46  
    47  func (s *BaseActionSuite) SetUpTest(c *gc.C) {
    48  	s.command = action.NewSuperCommand()
    49  }
    50  
    51  func (s *BaseActionSuite) patchAPIClient(client *fakeAPIClient) func() {
    52  	return jujutesting.PatchValue(action.NewActionAPIClient,
    53  		func(c *action.ActionCommandBase) (action.APIClient, error) {
    54  			return client, nil
    55  		},
    56  	)
    57  }
    58  
    59  func (s *BaseActionSuite) checkHelp(c *gc.C, subcmd envcmd.EnvironCommand) {
    60  	ctx, err := coretesting.RunCommand(c, s.command, subcmd.Info().Name, "--help")
    61  	c.Assert(err, gc.IsNil)
    62  
    63  	expected := "(?sm).*^usage: juju action " +
    64  		regexp.QuoteMeta(subcmd.Info().Name) +
    65  		` \[options\] ` + regexp.QuoteMeta(subcmd.Info().Args) + ".+"
    66  	c.Check(coretesting.Stdout(ctx), gc.Matches, expected)
    67  
    68  	expected = "(?sm).*^purpose: " + regexp.QuoteMeta(subcmd.Info().Purpose) + "$.*"
    69  	c.Check(coretesting.Stdout(ctx), gc.Matches, expected)
    70  
    71  	expected = "(?sm).*^" + regexp.QuoteMeta(subcmd.Info().Doc) + "$.*"
    72  	c.Check(coretesting.Stdout(ctx), gc.Matches, expected)
    73  }
    74  
    75  var someCharmActions = &charm.Actions{
    76  	ActionSpecs: map[string]charm.ActionSpec{
    77  		"snapshot": {
    78  			Description: "Take a snapshot of the database.",
    79  			Params: map[string]interface{}{
    80  				"foo": map[string]interface{}{
    81  					"bar": "baz",
    82  				},
    83  				"baz": "bar",
    84  			},
    85  		},
    86  		"kill": {
    87  			Description: "Kill the database.",
    88  			Params: map[string]interface{}{
    89  				"bar": map[string]interface{}{
    90  					"baz": "foo",
    91  				},
    92  				"foo": "baz",
    93  			},
    94  		},
    95  		"no-description": {
    96  			Params: map[string]interface{}{
    97  				"bar": map[string]interface{}{
    98  					"baz": "foo",
    99  				},
   100  				"foo": "baz",
   101  			},
   102  		},
   103  		"no-params": {
   104  			Description: "An action with no parameters.",
   105  		},
   106  	},
   107  }
   108  
   109  // tagsForIdPrefix builds a params.FindTagResults for a given id prefix
   110  // and 0..n given tags. This is useful for stubbing out the API and
   111  // ensuring that the API returns expected tags for a given id prefix.
   112  func tagsForIdPrefix(prefix string, tags ...string) params.FindTagsResults {
   113  	entities := make([]params.Entity, len(tags))
   114  	for i, t := range tags {
   115  		entities[i] = params.Entity{Tag: t}
   116  	}
   117  	return params.FindTagsResults{Matches: map[string][]params.Entity{prefix: entities}}
   118  }
   119  
   120  // setupValueFile creates a file containing one value for testing.
   121  // cf. cmd/juju/set_test.go
   122  func setupValueFile(c *gc.C, dir, filename, value string) string {
   123  	ctx := coretesting.ContextForDir(c, dir)
   124  	path := ctx.AbsPath(filename)
   125  	content := []byte(value)
   126  	err := ioutil.WriteFile(path, content, 0666)
   127  	c.Assert(err, jc.ErrorIsNil)
   128  	return path
   129  }
   130  
   131  type fakeAPIClient struct {
   132  	delay              *time.Timer
   133  	timeout            *time.Timer
   134  	actionResults      []params.ActionResult
   135  	enqueuedActions    params.Actions
   136  	actionsByReceivers []params.ActionsByReceiver
   137  	actionTagMatches   params.FindTagsResults
   138  	charmActions       *charm.Actions
   139  	apiErr             error
   140  }
   141  
   142  var _ action.APIClient = (*fakeAPIClient)(nil)
   143  
   144  // EnqueuedActions is a testing method which shows what Actions got enqueued
   145  // by our Enqueue stub.
   146  func (c *fakeAPIClient) EnqueuedActions() params.Actions {
   147  	return c.enqueuedActions
   148  }
   149  
   150  func (c *fakeAPIClient) Close() error {
   151  	return nil
   152  }
   153  
   154  func (c *fakeAPIClient) Enqueue(args params.Actions) (params.ActionResults, error) {
   155  	c.enqueuedActions = args
   156  	return params.ActionResults{Results: c.actionResults}, c.apiErr
   157  }
   158  
   159  func (c *fakeAPIClient) ListAll(args params.Entities) (params.ActionsByReceivers, error) {
   160  	return params.ActionsByReceivers{
   161  		Actions: c.actionsByReceivers,
   162  	}, c.apiErr
   163  }
   164  
   165  func (c *fakeAPIClient) ListPending(args params.Entities) (params.ActionsByReceivers, error) {
   166  	return params.ActionsByReceivers{
   167  		Actions: c.actionsByReceivers,
   168  	}, c.apiErr
   169  }
   170  
   171  func (c *fakeAPIClient) ListCompleted(args params.Entities) (params.ActionsByReceivers, error) {
   172  	return params.ActionsByReceivers{
   173  		Actions: c.actionsByReceivers,
   174  	}, c.apiErr
   175  }
   176  
   177  func (c *fakeAPIClient) Cancel(args params.Actions) (params.ActionResults, error) {
   178  	return params.ActionResults{
   179  		Results: c.actionResults,
   180  	}, c.apiErr
   181  }
   182  
   183  func (c *fakeAPIClient) ServiceCharmActions(params.Entity) (*charm.Actions, error) {
   184  	return c.charmActions, c.apiErr
   185  }
   186  
   187  func (c *fakeAPIClient) Actions(args params.Entities) (params.ActionResults, error) {
   188  	// If the test supplies a delay time too long, we'll return an error
   189  	// to prevent the test hanging.  If the given wait is up, then return
   190  	// the results; otherwise, return a pending status.
   191  
   192  	// First, sync.
   193  	_ = <-time.NewTimer(0 * time.Second).C
   194  
   195  	select {
   196  	case _ = <-c.delay.C:
   197  		// The API delay timer is up.  Pass pre-canned results back.
   198  		return params.ActionResults{Results: c.actionResults}, c.apiErr
   199  	case _ = <-c.timeout.C:
   200  		// Timeout to prevent tests from hanging.
   201  		return params.ActionResults{}, errors.New("test timed out before wait time")
   202  	default:
   203  		// Timeout should only be nonzero in case we want to test
   204  		// pending behavior with a --wait flag on FetchCommand.
   205  		return params.ActionResults{Results: []params.ActionResult{{
   206  			Status:   params.ActionPending,
   207  			Output:   map[string]interface{}{},
   208  			Started:  time.Date(2015, time.February, 14, 8, 15, 0, 0, time.UTC),
   209  			Enqueued: time.Date(2015, time.February, 14, 8, 13, 0, 0, time.UTC),
   210  		}}}, nil
   211  	}
   212  }
   213  
   214  func (c *fakeAPIClient) FindActionTagsByPrefix(arg params.FindTags) (params.FindTagsResults, error) {
   215  	return c.actionTagMatches, c.apiErr
   216  }