github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/resolver/opfactory_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package resolver_test
     5  
     6  import (
     7  	"errors"
     8  
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  	"gopkg.in/juju/charm.v6-unstable"
    12  	"gopkg.in/juju/charm.v6-unstable/hooks"
    13  
    14  	"github.com/juju/juju/testing"
    15  	"github.com/juju/juju/worker/uniter/hook"
    16  	"github.com/juju/juju/worker/uniter/operation"
    17  	"github.com/juju/juju/worker/uniter/remotestate"
    18  	"github.com/juju/juju/worker/uniter/resolver"
    19  )
    20  
    21  type ResolverOpFactorySuite struct {
    22  	testing.BaseSuite
    23  	opFactory *mockOpFactory
    24  }
    25  
    26  var _ = gc.Suite(&ResolverOpFactorySuite{})
    27  
    28  func (s *ResolverOpFactorySuite) SetUpTest(c *gc.C) {
    29  	s.BaseSuite.SetUpTest(c)
    30  	s.opFactory = &mockOpFactory{}
    31  }
    32  
    33  func (s *ResolverOpFactorySuite) TestInitialState(c *gc.C) {
    34  	f := resolver.NewResolverOpFactory(s.opFactory)
    35  	c.Assert(f.LocalState, jc.DeepEquals, &resolver.LocalState{})
    36  	c.Assert(f.RemoteState, jc.DeepEquals, remotestate.Snapshot{})
    37  }
    38  
    39  func (s *ResolverOpFactorySuite) TestUpdateStatusChanged(c *gc.C) {
    40  	s.testUpdateStatusChanged(c, resolver.ResolverOpFactory.NewRunHook)
    41  	s.testUpdateStatusChanged(c, resolver.ResolverOpFactory.NewSkipHook)
    42  }
    43  
    44  func (s *ResolverOpFactorySuite) testUpdateStatusChanged(
    45  	c *gc.C, meth func(resolver.ResolverOpFactory, hook.Info) (operation.Operation, error),
    46  ) {
    47  	f := resolver.NewResolverOpFactory(s.opFactory)
    48  	f.RemoteState.UpdateStatusVersion = 1
    49  
    50  	op, err := f.NewRunHook(hook.Info{Kind: hooks.UpdateStatus})
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	f.RemoteState.UpdateStatusVersion = 2
    53  
    54  	_, err = op.Commit(operation.State{})
    55  	c.Assert(err, jc.ErrorIsNil)
    56  
    57  	// Local state's UpdateStatusVersion should be set to what
    58  	// RemoteState's UpdateStatusVersion was when the operation
    59  	// was constructed.
    60  	c.Assert(f.LocalState.UpdateStatusVersion, gc.Equals, 1)
    61  }
    62  
    63  func (s *ResolverOpFactorySuite) TestConfigChanged(c *gc.C) {
    64  	s.testConfigChanged(c, resolver.ResolverOpFactory.NewRunHook)
    65  	s.testConfigChanged(c, resolver.ResolverOpFactory.NewSkipHook)
    66  }
    67  
    68  func (s *ResolverOpFactorySuite) TestNewHookError(c *gc.C) {
    69  	s.opFactory.SetErrors(
    70  		errors.New("NewRunHook fails"),
    71  		errors.New("NewSkipHook fails"),
    72  	)
    73  	f := resolver.NewResolverOpFactory(s.opFactory)
    74  	_, err := f.NewRunHook(hook.Info{Kind: hooks.ConfigChanged})
    75  	c.Assert(err, gc.ErrorMatches, "NewRunHook fails")
    76  	_, err = f.NewSkipHook(hook.Info{Kind: hooks.ConfigChanged})
    77  	c.Assert(err, gc.ErrorMatches, "NewSkipHook fails")
    78  }
    79  
    80  func (s *ResolverOpFactorySuite) testConfigChanged(
    81  	c *gc.C, meth func(resolver.ResolverOpFactory, hook.Info) (operation.Operation, error),
    82  ) {
    83  	f := resolver.NewResolverOpFactory(s.opFactory)
    84  	f.RemoteState.ConfigVersion = 1
    85  	f.RemoteState.UpdateStatusVersion = 3
    86  
    87  	op, err := f.NewRunHook(hook.Info{Kind: hooks.ConfigChanged})
    88  	c.Assert(err, jc.ErrorIsNil)
    89  	f.RemoteState.ConfigVersion = 2
    90  	f.RemoteState.UpdateStatusVersion = 4
    91  
    92  	_, err = op.Commit(operation.State{})
    93  	c.Assert(err, jc.ErrorIsNil)
    94  
    95  	// Local state's ConfigVersion should be set to what
    96  	// RemoteState's ConfigVersion was when the operation
    97  	// was constructed.
    98  	c.Assert(f.LocalState.ConfigVersion, gc.Equals, 1)
    99  	c.Assert(f.LocalState.UpdateStatusVersion, gc.Equals, 3)
   100  }
   101  
   102  func (s *ResolverOpFactorySuite) TestLeaderSettingsChanged(c *gc.C) {
   103  	s.testLeaderSettingsChanged(c, resolver.ResolverOpFactory.NewRunHook)
   104  	s.testLeaderSettingsChanged(c, resolver.ResolverOpFactory.NewSkipHook)
   105  }
   106  
   107  func (s *ResolverOpFactorySuite) testLeaderSettingsChanged(
   108  	c *gc.C, meth func(resolver.ResolverOpFactory, hook.Info) (operation.Operation, error),
   109  ) {
   110  	f := resolver.NewResolverOpFactory(s.opFactory)
   111  	f.RemoteState.LeaderSettingsVersion = 1
   112  	f.RemoteState.UpdateStatusVersion = 3
   113  
   114  	op, err := meth(f, hook.Info{Kind: hooks.LeaderSettingsChanged})
   115  	c.Assert(err, jc.ErrorIsNil)
   116  	f.RemoteState.LeaderSettingsVersion = 2
   117  	f.RemoteState.UpdateStatusVersion = 4
   118  
   119  	_, err = op.Commit(operation.State{})
   120  	c.Assert(err, jc.ErrorIsNil)
   121  
   122  	// Local state's LeaderSettingsVersion should be set to what
   123  	// RemoteState's LeaderSettingsVersion was when the operation
   124  	// was constructed.
   125  	c.Assert(f.LocalState.LeaderSettingsVersion, gc.Equals, 1)
   126  	c.Assert(f.LocalState.UpdateStatusVersion, gc.Equals, 3)
   127  }
   128  
   129  func (s *ResolverOpFactorySuite) TestUpgrade(c *gc.C) {
   130  	s.testUpgrade(c, resolver.ResolverOpFactory.NewUpgrade)
   131  	s.testUpgrade(c, resolver.ResolverOpFactory.NewRevertUpgrade)
   132  	s.testUpgrade(c, resolver.ResolverOpFactory.NewResolvedUpgrade)
   133  }
   134  
   135  func (s *ResolverOpFactorySuite) testUpgrade(
   136  	c *gc.C, meth func(resolver.ResolverOpFactory, *charm.URL) (operation.Operation, error),
   137  ) {
   138  	f := resolver.NewResolverOpFactory(s.opFactory)
   139  	f.LocalState.Conflicted = true
   140  	curl := charm.MustParseURL("cs:trusty/mysql")
   141  	op, err := meth(f, curl)
   142  	c.Assert(err, jc.ErrorIsNil)
   143  	_, err = op.Commit(operation.State{})
   144  	c.Assert(err, jc.ErrorIsNil)
   145  	c.Assert(f.LocalState.CharmURL, jc.DeepEquals, curl)
   146  	c.Assert(f.LocalState.Conflicted, jc.IsFalse)
   147  }
   148  
   149  func (s *ResolverOpFactorySuite) TestNewUpgradeError(c *gc.C) {
   150  	curl := charm.MustParseURL("cs:trusty/mysql")
   151  	s.opFactory.SetErrors(
   152  		errors.New("NewUpgrade fails"),
   153  		errors.New("NewRevertUpgrade fails"),
   154  		errors.New("NewResolvedUpgrade fails"),
   155  	)
   156  	f := resolver.NewResolverOpFactory(s.opFactory)
   157  	_, err := f.NewUpgrade(curl)
   158  	c.Assert(err, gc.ErrorMatches, "NewUpgrade fails")
   159  	_, err = f.NewRevertUpgrade(curl)
   160  	c.Assert(err, gc.ErrorMatches, "NewRevertUpgrade fails")
   161  	_, err = f.NewResolvedUpgrade(curl)
   162  	c.Assert(err, gc.ErrorMatches, "NewResolvedUpgrade fails")
   163  }
   164  
   165  func (s *ResolverOpFactorySuite) TestCommitError(c *gc.C) {
   166  	f := resolver.NewResolverOpFactory(s.opFactory)
   167  	curl := charm.MustParseURL("cs:trusty/mysql")
   168  	s.opFactory.op.commit = func(operation.State) (*operation.State, error) {
   169  		return nil, errors.New("Commit fails")
   170  	}
   171  	op, err := f.NewUpgrade(curl)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	_, err = op.Commit(operation.State{})
   174  	c.Assert(err, gc.ErrorMatches, "Commit fails")
   175  	// Local state should not have been updated. We use the same code
   176  	// internally for all operations, so it suffices to test just the
   177  	// upgrade case.
   178  	c.Assert(f.LocalState.CharmURL, gc.IsNil)
   179  }
   180  
   181  func (s *ResolverOpFactorySuite) TestActionsCommit(c *gc.C) {
   182  	f := resolver.NewResolverOpFactory(s.opFactory)
   183  	f.RemoteState.Actions = []string{"action 1", "action 2", "action 3"}
   184  	f.LocalState.CompletedActions = map[string]struct{}{}
   185  	op, err := f.NewAction("action 1")
   186  	c.Assert(err, jc.ErrorIsNil)
   187  	_, err = op.Commit(operation.State{})
   188  	c.Assert(err, jc.ErrorIsNil)
   189  	c.Assert(f.LocalState.CompletedActions, gc.DeepEquals, map[string]struct{}{
   190  		"action 1": struct{}{},
   191  	})
   192  }
   193  
   194  func (s *ResolverOpFactorySuite) TestActionsTrimming(c *gc.C) {
   195  	f := resolver.NewResolverOpFactory(s.opFactory)
   196  	f.RemoteState.Actions = []string{"c", "d"}
   197  	f.LocalState.CompletedActions = map[string]struct{}{
   198  		"a": struct{}{},
   199  		"b": struct{}{},
   200  		"c": struct{}{},
   201  	}
   202  	op, err := f.NewAction("d")
   203  	c.Assert(err, jc.ErrorIsNil)
   204  	_, err = op.Commit(operation.State{})
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	c.Assert(f.LocalState.CompletedActions, gc.DeepEquals, map[string]struct{}{
   207  		"c": struct{}{},
   208  		"d": struct{}{},
   209  	})
   210  }