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