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: ¶ms.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: ¶ms.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: ¶ms.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 }