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