github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/uniter/operation/runaction_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package operation_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 "gopkg.in/juju/charm.v4/hooks" 12 13 "github.com/juju/juju/worker/uniter/hook" 14 "github.com/juju/juju/worker/uniter/operation" 15 "github.com/juju/juju/worker/uniter/runner" 16 ) 17 18 type RunActionSuite struct { 19 testing.IsolationSuite 20 } 21 22 var _ = gc.Suite(&RunActionSuite{}) 23 24 func (s *RunActionSuite) TestPrepareErrorBadActionAndFailSucceeds(c *gc.C) { 25 errBadAction := runner.NewBadActionError("some-action-id", "splat") 26 runnerFactory := &MockRunnerFactory{ 27 MockNewActionRunner: &MockNewActionRunner{err: errBadAction}, 28 } 29 callbacks := &RunActionCallbacks{ 30 MockFailAction: &MockFailAction{err: errors.New("squelch")}, 31 } 32 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 33 op, err := factory.NewAction(someActionId) 34 c.Assert(err, jc.ErrorIsNil) 35 36 newState, err := op.Prepare(operation.State{}) 37 c.Assert(newState, gc.IsNil) 38 c.Assert(err, gc.ErrorMatches, "squelch") 39 c.Assert(*runnerFactory.MockNewActionRunner.gotActionId, gc.Equals, someActionId) 40 c.Assert(*callbacks.MockFailAction.gotActionId, gc.Equals, someActionId) 41 c.Assert(*callbacks.MockFailAction.gotMessage, gc.Equals, errBadAction.Error()) 42 } 43 44 func (s *RunActionSuite) TestPrepareErrorBadActionAndFailErrors(c *gc.C) { 45 errBadAction := runner.NewBadActionError("some-action-id", "foof") 46 runnerFactory := &MockRunnerFactory{ 47 MockNewActionRunner: &MockNewActionRunner{err: errBadAction}, 48 } 49 callbacks := &RunActionCallbacks{ 50 MockFailAction: &MockFailAction{}, 51 } 52 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 53 op, err := factory.NewAction(someActionId) 54 c.Assert(err, jc.ErrorIsNil) 55 56 newState, err := op.Prepare(operation.State{}) 57 c.Assert(newState, gc.IsNil) 58 c.Assert(err, gc.Equals, operation.ErrSkipExecute) 59 c.Assert(*runnerFactory.MockNewActionRunner.gotActionId, gc.Equals, someActionId) 60 c.Assert(*callbacks.MockFailAction.gotActionId, gc.Equals, someActionId) 61 c.Assert(*callbacks.MockFailAction.gotMessage, gc.Equals, errBadAction.Error()) 62 } 63 64 func (s *RunActionSuite) TestPrepareErrorActionNotAvailable(c *gc.C) { 65 runnerFactory := &MockRunnerFactory{ 66 MockNewActionRunner: &MockNewActionRunner{err: runner.ErrActionNotAvailable}, 67 } 68 factory := operation.NewFactory(nil, runnerFactory, nil, nil) 69 op, err := factory.NewAction(someActionId) 70 c.Assert(err, jc.ErrorIsNil) 71 72 newState, err := op.Prepare(operation.State{}) 73 c.Assert(newState, gc.IsNil) 74 c.Assert(err, gc.Equals, operation.ErrSkipExecute) 75 c.Assert(*runnerFactory.MockNewActionRunner.gotActionId, gc.Equals, someActionId) 76 } 77 78 func (s *RunActionSuite) TestPrepareErrorOther(c *gc.C) { 79 runnerFactory := &MockRunnerFactory{ 80 MockNewActionRunner: &MockNewActionRunner{err: errors.New("foop")}, 81 } 82 factory := operation.NewFactory(nil, runnerFactory, nil, nil) 83 op, err := factory.NewAction(someActionId) 84 c.Assert(err, jc.ErrorIsNil) 85 86 newState, err := op.Prepare(operation.State{}) 87 c.Assert(newState, gc.IsNil) 88 c.Assert(err, gc.ErrorMatches, `cannot create runner for action ".*": foop`) 89 c.Assert(*runnerFactory.MockNewActionRunner.gotActionId, gc.Equals, someActionId) 90 } 91 92 func (s *RunActionSuite) TestPrepareSuccessCleanState(c *gc.C) { 93 runnerFactory := NewRunActionRunnerFactory(errors.New("should not call")) 94 factory := operation.NewFactory(nil, runnerFactory, nil, nil) 95 op, err := factory.NewAction(someActionId) 96 c.Assert(err, jc.ErrorIsNil) 97 98 newState, err := op.Prepare(operation.State{}) 99 c.Assert(err, jc.ErrorIsNil) 100 c.Assert(newState, gc.NotNil) 101 c.Assert(*newState, gc.DeepEquals, operation.State{ 102 Kind: operation.RunAction, 103 Step: operation.Pending, 104 ActionId: &someActionId, 105 }) 106 c.Assert(*runnerFactory.MockNewActionRunner.gotActionId, gc.Equals, someActionId) 107 } 108 109 func (s *RunActionSuite) TestPrepareSuccessDirtyState(c *gc.C) { 110 runnerFactory := NewRunActionRunnerFactory(errors.New("should not call")) 111 factory := operation.NewFactory(nil, runnerFactory, nil, nil) 112 op, err := factory.NewAction(someActionId) 113 c.Assert(err, jc.ErrorIsNil) 114 115 newState, err := op.Prepare(overwriteState) 116 c.Assert(err, jc.ErrorIsNil) 117 c.Assert(newState, gc.NotNil) 118 c.Assert(*newState, gc.DeepEquals, operation.State{ 119 Kind: operation.RunAction, 120 Step: operation.Pending, 121 ActionId: &someActionId, 122 Started: true, 123 CollectMetricsTime: 1234567, 124 Hook: &hook.Info{Kind: hooks.Install}, 125 }) 126 c.Assert(*runnerFactory.MockNewActionRunner.gotActionId, gc.Equals, someActionId) 127 } 128 129 func (s *RunActionSuite) TestExecuteLockError(c *gc.C) { 130 runnerFactory := NewRunActionRunnerFactory(errors.New("should not call")) 131 callbacks := &RunActionCallbacks{ 132 MockAcquireExecutionLock: &MockAcquireExecutionLock{err: errors.New("plonk")}, 133 } 134 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 135 op, err := factory.NewAction(someActionId) 136 c.Assert(err, jc.ErrorIsNil) 137 newState, err := op.Prepare(operation.State{}) 138 c.Assert(newState, gc.NotNil) 139 c.Assert(err, jc.ErrorIsNil) 140 141 newState, err = op.Execute(operation.State{}) 142 c.Assert(newState, gc.IsNil) 143 c.Assert(err, gc.ErrorMatches, "plonk") 144 c.Assert(*callbacks.MockAcquireExecutionLock.gotMessage, gc.Equals, "running action some-action-name") 145 } 146 147 func (s *RunActionSuite) TestExecuteRunError(c *gc.C) { 148 runnerFactory := NewRunActionRunnerFactory(errors.New("snargle")) 149 callbacks := &RunActionCallbacks{ 150 MockAcquireExecutionLock: &MockAcquireExecutionLock{}, 151 } 152 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 153 op, err := factory.NewAction(someActionId) 154 c.Assert(err, jc.ErrorIsNil) 155 newState, err := op.Prepare(operation.State{}) 156 c.Assert(newState, gc.NotNil) 157 c.Assert(err, jc.ErrorIsNil) 158 159 newState, err = op.Execute(operation.State{}) 160 c.Assert(newState, gc.IsNil) 161 c.Assert(err, gc.ErrorMatches, `running action "some-action-name": snargle`) 162 c.Assert(*callbacks.MockAcquireExecutionLock.gotMessage, gc.Equals, "running action some-action-name") 163 c.Assert(callbacks.MockAcquireExecutionLock.didUnlock, jc.IsTrue) 164 c.Assert(*runnerFactory.MockNewActionRunner.runner.MockRunAction.gotName, gc.Equals, "some-action-name") 165 } 166 167 func (s *RunActionSuite) TestExecuteSuccess(c *gc.C) { 168 var stateChangeTests = []struct { 169 description string 170 before operation.State 171 after operation.State 172 }{{ 173 description: "empty state", 174 after: operation.State{ 175 Kind: operation.RunAction, 176 Step: operation.Done, 177 ActionId: &someActionId, 178 }, 179 }, { 180 description: "preserves appropriate fields", 181 before: overwriteState, 182 after: operation.State{ 183 Kind: operation.RunAction, 184 Step: operation.Done, 185 ActionId: &someActionId, 186 Hook: &hook.Info{Kind: hooks.Install}, 187 Started: true, 188 CollectMetricsTime: 1234567, 189 }, 190 }} 191 192 for i, test := range stateChangeTests { 193 c.Logf("test %d: %s", i, test.description) 194 runnerFactory := NewRunActionRunnerFactory(nil) 195 callbacks := &RunActionCallbacks{ 196 MockAcquireExecutionLock: &MockAcquireExecutionLock{}, 197 } 198 factory := operation.NewFactory(nil, runnerFactory, callbacks, nil) 199 op, err := factory.NewAction(someActionId) 200 c.Assert(err, jc.ErrorIsNil) 201 midState, err := op.Prepare(test.before) 202 c.Assert(midState, gc.NotNil) 203 c.Assert(err, jc.ErrorIsNil) 204 205 newState, err := op.Execute(*midState) 206 c.Assert(err, jc.ErrorIsNil) 207 c.Assert(newState, gc.NotNil) 208 c.Assert(*newState, gc.DeepEquals, test.after) 209 c.Assert(*callbacks.MockAcquireExecutionLock.gotMessage, gc.Equals, "running action some-action-name") 210 c.Assert(callbacks.MockAcquireExecutionLock.didUnlock, jc.IsTrue) 211 c.Assert(*runnerFactory.MockNewActionRunner.runner.MockRunAction.gotName, gc.Equals, "some-action-name") 212 } 213 } 214 215 func (s *RunActionSuite) TestCommit(c *gc.C) { 216 var stateChangeTests = []struct { 217 description string 218 before operation.State 219 after operation.State 220 }{{ 221 description: "empty state", 222 after: operation.State{ 223 Kind: operation.Continue, 224 Step: operation.Pending, 225 }, 226 }, { 227 description: "preserves appropriate fields", 228 before: overwriteState, 229 after: operation.State{ 230 Kind: operation.Continue, 231 Step: operation.Pending, 232 Hook: &hook.Info{Kind: hooks.Install}, 233 Started: true, 234 CollectMetricsTime: 1234567, 235 }, 236 }} 237 238 for i, test := range stateChangeTests { 239 c.Logf("test %d: %s", i, test.description) 240 factory := operation.NewFactory(nil, nil, nil, nil) 241 op, err := factory.NewAction(someActionId) 242 c.Assert(err, jc.ErrorIsNil) 243 244 newState, err := op.Commit(test.before) 245 c.Assert(err, jc.ErrorIsNil) 246 c.Assert(*newState, gc.DeepEquals, test.after) 247 } 248 }