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 }