github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/uniter/leadership_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package uniter_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  
    12  	"github.com/juju/juju/api/uniter"
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/core/watcher"
    15  )
    16  
    17  type leadershipSuite struct {
    18  	testing.IsolationSuite
    19  	stub       *testing.Stub
    20  	responders []responder
    21  	lsa        *uniter.LeadershipSettingsAccessor
    22  }
    23  
    24  var _ = gc.Suite(&leadershipSuite{})
    25  
    26  type responder func(interface{})
    27  
    28  var mockWatcher = struct{ watcher.NotifyWatcher }{}
    29  
    30  func (s *leadershipSuite) SetUpTest(c *gc.C) {
    31  	s.IsolationSuite.SetUpTest(c)
    32  	s.lsa = uniter.NewLeadershipSettingsAccessor(
    33  		func(request string, params, response interface{}) error {
    34  			s.stub.AddCall("FacadeCall", request, params)
    35  			s.nextResponse(response)
    36  			return s.stub.NextErr()
    37  		},
    38  		func(result params.NotifyWatchResult) watcher.NotifyWatcher {
    39  			s.stub.AddCall("NewNotifyWatcher", result)
    40  			return mockWatcher
    41  		},
    42  		func(name string) error {
    43  			s.stub.AddCall("CheckApiVersion", name)
    44  			return s.stub.NextErr()
    45  		},
    46  	)
    47  }
    48  
    49  func (s *leadershipSuite) nextResponse(response interface{}) {
    50  	var responder responder
    51  	responder, s.responders = s.responders[0], s.responders[1:]
    52  	if responder != nil {
    53  		responder(response)
    54  	}
    55  }
    56  
    57  func (s *leadershipSuite) addResponder(responder responder) {
    58  	s.responders = append(s.responders, responder)
    59  }
    60  
    61  func (s *leadershipSuite) CheckCalls(c *gc.C, calls []testing.StubCall, f func()) {
    62  	s.stub = &testing.Stub{}
    63  	s.responders = nil
    64  	f()
    65  	s.stub.CheckCalls(c, calls)
    66  }
    67  
    68  func (s *leadershipSuite) TestReadBadVersion(c *gc.C) {
    69  	s.CheckCalls(c, []testing.StubCall{{
    70  		FuncName: "CheckApiVersion",
    71  		Args:     []interface{}{"Read"},
    72  	}}, func() {
    73  		s.stub.SetErrors(errors.New("splat"))
    74  		settings, err := s.lsa.Read("foobar")
    75  		c.Check(err, gc.ErrorMatches, "cannot access leadership api: splat")
    76  		c.Check(settings, gc.IsNil)
    77  	})
    78  }
    79  
    80  func (s *leadershipSuite) expectReadCalls() []testing.StubCall {
    81  	return []testing.StubCall{{
    82  		FuncName: "CheckApiVersion",
    83  		Args:     []interface{}{"Read"},
    84  	}, {
    85  		FuncName: "FacadeCall",
    86  		Args: []interface{}{
    87  			"Read",
    88  			params.Entities{Entities: []params.Entity{{
    89  				Tag: "application-foobar",
    90  			}}},
    91  		},
    92  	}}
    93  }
    94  
    95  func (s *leadershipSuite) TestReadSuccess(c *gc.C) {
    96  	s.CheckCalls(c, s.expectReadCalls(), func() {
    97  		s.addResponder(func(response interface{}) {
    98  			typed, ok := response.(*params.GetLeadershipSettingsBulkResults)
    99  			c.Assert(ok, jc.IsTrue)
   100  			typed.Results = []params.GetLeadershipSettingsResult{{
   101  				Settings: params.Settings{
   102  					"foo": "bar",
   103  					"baz": "qux",
   104  				},
   105  			}}
   106  		})
   107  		settings, err := s.lsa.Read("foobar")
   108  		c.Check(err, jc.ErrorIsNil)
   109  		c.Check(settings, jc.DeepEquals, map[string]string{
   110  			"foo": "bar",
   111  			"baz": "qux",
   112  		})
   113  	})
   114  }
   115  
   116  func (s *leadershipSuite) TestReadFailure(c *gc.C) {
   117  	s.CheckCalls(c, s.expectReadCalls(), func() {
   118  		s.addResponder(func(response interface{}) {
   119  			typed, ok := response.(*params.GetLeadershipSettingsBulkResults)
   120  			c.Assert(ok, jc.IsTrue)
   121  			typed.Results = []params.GetLeadershipSettingsResult{{
   122  				Error: &params.Error{Message: "pow"},
   123  			}}
   124  		})
   125  		settings, err := s.lsa.Read("foobar")
   126  		c.Check(err, gc.ErrorMatches, "failed to read leadership settings: pow")
   127  		c.Check(settings, gc.IsNil)
   128  	})
   129  }
   130  
   131  func (s *leadershipSuite) TestReadError(c *gc.C) {
   132  	s.CheckCalls(c, s.expectReadCalls(), func() {
   133  		s.addResponder(nil)
   134  		s.stub.SetErrors(nil, errors.New("blart"))
   135  		settings, err := s.lsa.Read("foobar")
   136  		c.Check(err, gc.ErrorMatches, "failed to call leadership api: blart")
   137  		c.Check(settings, gc.IsNil)
   138  	})
   139  }
   140  
   141  func (s *leadershipSuite) TestReadNoResults(c *gc.C) {
   142  	s.CheckCalls(c, s.expectReadCalls(), func() {
   143  		s.addResponder(nil)
   144  		settings, err := s.lsa.Read("foobar")
   145  		c.Check(err, gc.ErrorMatches, "expected 1 result from leadership api, got 0")
   146  		c.Check(settings, gc.IsNil)
   147  	})
   148  }
   149  
   150  func (s *leadershipSuite) TestMergeBadVersion(c *gc.C) {
   151  	s.CheckCalls(c, []testing.StubCall{{
   152  		FuncName: "CheckApiVersion",
   153  		Args:     []interface{}{"Merge"},
   154  	}}, func() {
   155  		s.stub.SetErrors(errors.New("splat"))
   156  		err := s.lsa.Merge("foobar", "foobar/0", map[string]string{"foo": "bar"})
   157  		c.Check(err, gc.ErrorMatches, "cannot access leadership api: splat")
   158  	})
   159  }
   160  
   161  func (s *leadershipSuite) expectMergeCalls() []testing.StubCall {
   162  	return []testing.StubCall{{
   163  		FuncName: "CheckApiVersion",
   164  		Args:     []interface{}{"Merge"},
   165  	}, {
   166  		FuncName: "FacadeCall",
   167  		Args: []interface{}{
   168  			"Merge",
   169  			params.MergeLeadershipSettingsBulkParams{
   170  				Params: []params.MergeLeadershipSettingsParam{{
   171  					ApplicationTag: "application-foobar",
   172  					UnitTag:        "unit-foobar-0",
   173  					Settings: map[string]string{
   174  						"foo": "bar",
   175  						"baz": "qux",
   176  					},
   177  				}},
   178  			},
   179  		},
   180  	}}
   181  }
   182  
   183  func (s *leadershipSuite) TestMergeSuccess(c *gc.C) {
   184  	s.CheckCalls(c, s.expectMergeCalls(), func() {
   185  		s.addResponder(func(response interface{}) {
   186  			typed, ok := response.(*params.ErrorResults)
   187  			c.Assert(ok, jc.IsTrue)
   188  			typed.Results = []params.ErrorResult{{
   189  				Error: nil,
   190  			}}
   191  		})
   192  		err := s.lsa.Merge("foobar", "foobar/0", map[string]string{
   193  			"foo": "bar",
   194  			"baz": "qux",
   195  		})
   196  		c.Check(err, jc.ErrorIsNil)
   197  	})
   198  }
   199  
   200  func (s *leadershipSuite) TestMergeFailure(c *gc.C) {
   201  	s.CheckCalls(c, s.expectMergeCalls(), func() {
   202  		s.addResponder(func(response interface{}) {
   203  			typed, ok := response.(*params.ErrorResults)
   204  			c.Assert(ok, jc.IsTrue)
   205  			typed.Results = []params.ErrorResult{{
   206  				Error: &params.Error{Message: "zap"},
   207  			}}
   208  		})
   209  		err := s.lsa.Merge("foobar", "foobar/0", map[string]string{
   210  			"foo": "bar",
   211  			"baz": "qux",
   212  		})
   213  		c.Check(err, gc.ErrorMatches, "failed to merge leadership settings: zap")
   214  	})
   215  }
   216  
   217  func (s *leadershipSuite) TestMergeError(c *gc.C) {
   218  	s.CheckCalls(c, s.expectMergeCalls(), func() {
   219  		s.addResponder(nil)
   220  		s.stub.SetErrors(nil, errors.New("dink"))
   221  		err := s.lsa.Merge("foobar", "foobar/0", map[string]string{
   222  			"foo": "bar",
   223  			"baz": "qux",
   224  		})
   225  		c.Check(err, gc.ErrorMatches, "failed to call leadership api: dink")
   226  	})
   227  }
   228  
   229  func (s *leadershipSuite) TestMergeNoResults(c *gc.C) {
   230  	s.CheckCalls(c, s.expectMergeCalls(), func() {
   231  		s.addResponder(nil)
   232  		err := s.lsa.Merge("foobar", "foobar/0", map[string]string{
   233  			"foo": "bar",
   234  			"baz": "qux",
   235  		})
   236  		c.Check(err, gc.ErrorMatches, "expected 1 result from leadership api, got 0")
   237  	})
   238  }
   239  
   240  func (s *leadershipSuite) TestWatchBadVersion(c *gc.C) {
   241  	s.CheckCalls(c, []testing.StubCall{{
   242  		FuncName: "CheckApiVersion",
   243  		Args:     []interface{}{"WatchLeadershipSettings"},
   244  	}}, func() {
   245  		s.stub.SetErrors(errors.New("splat"))
   246  		watcher, err := s.lsa.WatchLeadershipSettings("foobar")
   247  		c.Check(err, gc.ErrorMatches, "cannot access leadership api: splat")
   248  		c.Check(watcher, gc.IsNil)
   249  	})
   250  }
   251  
   252  func (s *leadershipSuite) expectWatchCalls() []testing.StubCall {
   253  	return []testing.StubCall{{
   254  		FuncName: "CheckApiVersion",
   255  		Args:     []interface{}{"WatchLeadershipSettings"},
   256  	}, {
   257  		FuncName: "FacadeCall",
   258  		Args: []interface{}{
   259  			"WatchLeadershipSettings",
   260  			params.Entities{Entities: []params.Entity{{
   261  				Tag: "application-foobar",
   262  			}}},
   263  		},
   264  	}}
   265  }
   266  
   267  func (s *leadershipSuite) TestWatchSuccess(c *gc.C) {
   268  	expectCalls := append(s.expectWatchCalls(), testing.StubCall{
   269  		FuncName: "NewNotifyWatcher",
   270  		Args: []interface{}{
   271  			params.NotifyWatchResult{
   272  				NotifyWatcherId: "123",
   273  			},
   274  		},
   275  	})
   276  	s.CheckCalls(c, expectCalls, func() {
   277  		s.addResponder(func(response interface{}) {
   278  			typed, ok := response.(*params.NotifyWatchResults)
   279  			c.Assert(ok, jc.IsTrue)
   280  			typed.Results = []params.NotifyWatchResult{{
   281  				NotifyWatcherId: "123",
   282  			}}
   283  		})
   284  		watcher, err := s.lsa.WatchLeadershipSettings("foobar")
   285  		c.Check(err, jc.ErrorIsNil)
   286  		c.Check(watcher, gc.Equals, mockWatcher)
   287  	})
   288  }
   289  
   290  func (s *leadershipSuite) TestWatchFailure(c *gc.C) {
   291  	s.CheckCalls(c, s.expectWatchCalls(), func() {
   292  		s.addResponder(func(response interface{}) {
   293  			typed, ok := response.(*params.NotifyWatchResults)
   294  			c.Assert(ok, jc.IsTrue)
   295  			typed.Results = []params.NotifyWatchResult{{
   296  				Error: &params.Error{Message: "blah"},
   297  			}}
   298  		})
   299  		watcher, err := s.lsa.WatchLeadershipSettings("foobar")
   300  		c.Check(err, gc.ErrorMatches, "failed to watch leadership settings: blah")
   301  		c.Check(watcher, gc.IsNil)
   302  	})
   303  }
   304  
   305  func (s *leadershipSuite) TestWatchError(c *gc.C) {
   306  	s.CheckCalls(c, s.expectWatchCalls(), func() {
   307  		s.addResponder(nil)
   308  		s.stub.SetErrors(nil, errors.New("snerk"))
   309  		watcher, err := s.lsa.WatchLeadershipSettings("foobar")
   310  		c.Check(err, gc.ErrorMatches, "failed to call leadership api: snerk")
   311  		c.Check(watcher, gc.IsNil)
   312  	})
   313  }
   314  
   315  func (s *leadershipSuite) TestWatchNoResults(c *gc.C) {
   316  	s.CheckCalls(c, s.expectWatchCalls(), func() {
   317  		s.addResponder(nil)
   318  		watcher, err := s.lsa.WatchLeadershipSettings("foobar")
   319  		c.Check(err, gc.ErrorMatches, "expected 1 result from leadership api, got 0")
   320  		c.Check(watcher, gc.IsNil)
   321  	})
   322  }