github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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/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", 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 Settings: map[string]string{ 173 "foo": "bar", 174 "baz": "qux", 175 }, 176 }}, 177 }, 178 }, 179 }} 180 } 181 182 func (s *leadershipSuite) TestMergeSuccess(c *gc.C) { 183 s.CheckCalls(c, s.expectMergeCalls(), func() { 184 s.addResponder(func(response interface{}) { 185 typed, ok := response.(*params.ErrorResults) 186 c.Assert(ok, jc.IsTrue) 187 typed.Results = []params.ErrorResult{{ 188 Error: nil, 189 }} 190 }) 191 err := s.lsa.Merge("foobar", map[string]string{ 192 "foo": "bar", 193 "baz": "qux", 194 }) 195 c.Check(err, jc.ErrorIsNil) 196 }) 197 } 198 199 func (s *leadershipSuite) TestMergeFailure(c *gc.C) { 200 s.CheckCalls(c, s.expectMergeCalls(), func() { 201 s.addResponder(func(response interface{}) { 202 typed, ok := response.(*params.ErrorResults) 203 c.Assert(ok, jc.IsTrue) 204 typed.Results = []params.ErrorResult{{ 205 Error: ¶ms.Error{Message: "zap"}, 206 }} 207 }) 208 err := s.lsa.Merge("foobar", map[string]string{ 209 "foo": "bar", 210 "baz": "qux", 211 }) 212 c.Check(err, gc.ErrorMatches, "failed to merge leadership settings: zap") 213 }) 214 } 215 216 func (s *leadershipSuite) TestMergeError(c *gc.C) { 217 s.CheckCalls(c, s.expectMergeCalls(), func() { 218 s.addResponder(nil) 219 s.stub.SetErrors(nil, errors.New("dink")) 220 err := s.lsa.Merge("foobar", map[string]string{ 221 "foo": "bar", 222 "baz": "qux", 223 }) 224 c.Check(err, gc.ErrorMatches, "failed to call leadership api: dink") 225 }) 226 } 227 228 func (s *leadershipSuite) TestMergeNoResults(c *gc.C) { 229 s.CheckCalls(c, s.expectMergeCalls(), func() { 230 s.addResponder(nil) 231 err := s.lsa.Merge("foobar", map[string]string{ 232 "foo": "bar", 233 "baz": "qux", 234 }) 235 c.Check(err, gc.ErrorMatches, "expected 1 result from leadership api, got 0") 236 }) 237 } 238 239 func (s *leadershipSuite) TestWatchBadVersion(c *gc.C) { 240 s.CheckCalls(c, []testing.StubCall{{ 241 FuncName: "CheckApiVersion", 242 Args: []interface{}{"WatchLeadershipSettings"}, 243 }}, func() { 244 s.stub.SetErrors(errors.New("splat")) 245 watcher, err := s.lsa.WatchLeadershipSettings("foobar") 246 c.Check(err, gc.ErrorMatches, "cannot access leadership api: splat") 247 c.Check(watcher, gc.IsNil) 248 }) 249 } 250 251 func (s *leadershipSuite) expectWatchCalls() []testing.StubCall { 252 return []testing.StubCall{{ 253 FuncName: "CheckApiVersion", 254 Args: []interface{}{"WatchLeadershipSettings"}, 255 }, { 256 FuncName: "FacadeCall", 257 Args: []interface{}{ 258 "WatchLeadershipSettings", 259 params.Entities{Entities: []params.Entity{{ 260 Tag: "application-foobar", 261 }}}, 262 }, 263 }} 264 } 265 266 func (s *leadershipSuite) TestWatchSuccess(c *gc.C) { 267 expectCalls := append(s.expectWatchCalls(), testing.StubCall{ 268 FuncName: "NewNotifyWatcher", 269 Args: []interface{}{ 270 params.NotifyWatchResult{ 271 NotifyWatcherId: "123", 272 }, 273 }, 274 }) 275 s.CheckCalls(c, expectCalls, func() { 276 s.addResponder(func(response interface{}) { 277 typed, ok := response.(*params.NotifyWatchResults) 278 c.Assert(ok, jc.IsTrue) 279 typed.Results = []params.NotifyWatchResult{{ 280 NotifyWatcherId: "123", 281 }} 282 }) 283 watcher, err := s.lsa.WatchLeadershipSettings("foobar") 284 c.Check(err, jc.ErrorIsNil) 285 c.Check(watcher, gc.Equals, mockWatcher) 286 }) 287 } 288 289 func (s *leadershipSuite) TestWatchFailure(c *gc.C) { 290 s.CheckCalls(c, s.expectWatchCalls(), func() { 291 s.addResponder(func(response interface{}) { 292 typed, ok := response.(*params.NotifyWatchResults) 293 c.Assert(ok, jc.IsTrue) 294 typed.Results = []params.NotifyWatchResult{{ 295 Error: ¶ms.Error{Message: "blah"}, 296 }} 297 }) 298 watcher, err := s.lsa.WatchLeadershipSettings("foobar") 299 c.Check(err, gc.ErrorMatches, "failed to watch leadership settings: blah") 300 c.Check(watcher, gc.IsNil) 301 }) 302 } 303 304 func (s *leadershipSuite) TestWatchError(c *gc.C) { 305 s.CheckCalls(c, s.expectWatchCalls(), func() { 306 s.addResponder(nil) 307 s.stub.SetErrors(nil, errors.New("snerk")) 308 watcher, err := s.lsa.WatchLeadershipSettings("foobar") 309 c.Check(err, gc.ErrorMatches, "failed to call leadership api: snerk") 310 c.Check(watcher, gc.IsNil) 311 }) 312 } 313 314 func (s *leadershipSuite) TestWatchNoResults(c *gc.C) { 315 s.CheckCalls(c, s.expectWatchCalls(), func() { 316 s.addResponder(nil) 317 watcher, err := s.lsa.WatchLeadershipSettings("foobar") 318 c.Check(err, gc.ErrorMatches, "expected 1 result from leadership api, got 0") 319 c.Check(watcher, gc.IsNil) 320 }) 321 }