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  }