github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/payload/api/private/client/unitfacade_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package client_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/names.v2" 12 13 "github.com/juju/juju/apiserver/common" 14 "github.com/juju/juju/apiserver/params" 15 "github.com/juju/juju/payload" 16 "github.com/juju/juju/payload/api" 17 internal "github.com/juju/juju/payload/api/private" 18 "github.com/juju/juju/payload/api/private/client" 19 ) 20 21 type clientSuite struct { 22 testing.IsolationSuite 23 24 stub *testing.Stub 25 facade *stubFacade 26 payload api.Payload 27 } 28 29 var _ = gc.Suite(&clientSuite{}) 30 31 func (s *clientSuite) SetUpTest(c *gc.C) { 32 s.IsolationSuite.SetUpTest(c) 33 34 s.stub = &testing.Stub{} 35 s.facade = &stubFacade{stub: s.stub} 36 s.facade.methods = &unitMethods{} 37 s.payload = api.Payload{ 38 Class: "foobar", 39 Type: "type", 40 ID: "idfoo", 41 Status: payload.StateRunning, 42 } 43 44 } 45 46 func (s *clientSuite) TestTrack(c *gc.C) { 47 id := "ce5bc2a7-65d8-4800-8199-a7c3356ab309" 48 numStubCalls := 0 49 s.facade.FacadeCallFn = func(name string, args, response interface{}) error { 50 numStubCalls++ 51 c.Check(name, gc.Equals, "Track") 52 53 typedResponse, ok := response.(*internal.PayloadResults) 54 c.Assert(ok, gc.Equals, true) 55 typedResponse.Results = []internal.PayloadResult{{ 56 Entity: params.Entity{ 57 Tag: names.NewPayloadTag(id).String(), 58 }, 59 Payload: nil, 60 NotFound: false, 61 Error: nil, 62 }} 63 return nil 64 } 65 66 pclient := client.NewUnitFacadeClient(s.facade) 67 68 pl, err := api.API2Payload(s.payload) 69 c.Assert(err, jc.ErrorIsNil) 70 results, err := pclient.Track(pl.Payload) 71 c.Assert(err, jc.ErrorIsNil) 72 73 c.Check(numStubCalls, gc.Equals, 1) 74 c.Check(results, jc.DeepEquals, []payload.Result{{ 75 ID: id, 76 Payload: nil, 77 NotFound: false, 78 Error: nil, 79 }}) 80 } 81 82 func (s *clientSuite) TestList(c *gc.C) { 83 id := "ce5bc2a7-65d8-4800-8199-a7c3356ab309" 84 responses := []interface{}{ 85 &internal.PayloadResults{ 86 Results: []internal.PayloadResult{{ 87 Entity: params.Entity{ 88 Tag: names.NewPayloadTag(id).String(), 89 }, 90 Payload: nil, 91 NotFound: false, 92 Error: nil, 93 }}, 94 }, 95 &internal.PayloadResults{ 96 Results: []internal.PayloadResult{{ 97 Entity: params.Entity{ 98 Tag: names.NewPayloadTag(id).String(), 99 }, 100 Payload: &s.payload, 101 NotFound: false, 102 Error: nil, 103 }}, 104 }, 105 } 106 s.facade.responses = append(s.facade.responses, responses...) 107 108 pclient := client.NewUnitFacadeClient(s.facade) 109 110 results, err := pclient.List("idfoo/bar") 111 c.Assert(err, jc.ErrorIsNil) 112 113 expected, err := api.API2Payload(s.payload) 114 c.Assert(err, jc.ErrorIsNil) 115 c.Check(results, jc.DeepEquals, []payload.Result{{ 116 ID: id, 117 Payload: &expected, 118 NotFound: false, 119 Error: nil, 120 }}) 121 s.stub.CheckCalls(c, []testing.StubCall{{ 122 FuncName: "FacadeCall", 123 Args: []interface{}{ 124 "LookUp", 125 &internal.LookUpArgs{ 126 Args: []internal.LookUpArg{{ 127 Name: "idfoo", 128 ID: "bar", 129 }}, 130 }, 131 responses[0], 132 }, 133 }, { 134 FuncName: "FacadeCall", 135 Args: []interface{}{ 136 "List", 137 ¶ms.Entities{ 138 Entities: []params.Entity{{ 139 Tag: names.NewPayloadTag(id).String(), 140 }}, 141 }, 142 responses[1], 143 }, 144 }}) 145 } 146 147 func (s *clientSuite) TestLookUpOkay(c *gc.C) { 148 id := "ce5bc2a7-65d8-4800-8199-a7c3356ab309" 149 response := &internal.PayloadResults{ 150 Results: []internal.PayloadResult{{ 151 Entity: params.Entity{ 152 Tag: names.NewPayloadTag(id).String(), 153 }, 154 Payload: nil, 155 NotFound: false, 156 Error: nil, 157 }}, 158 } 159 s.facade.responses = append(s.facade.responses, response) 160 161 pclient := client.NewUnitFacadeClient(s.facade) 162 results, err := pclient.LookUp("idfoo/bar") 163 c.Assert(err, jc.ErrorIsNil) 164 165 c.Check(results, jc.DeepEquals, []payload.Result{{ 166 ID: id, 167 Payload: nil, 168 NotFound: false, 169 Error: nil, 170 }}) 171 s.stub.CheckCalls(c, []testing.StubCall{{ 172 FuncName: "FacadeCall", 173 Args: []interface{}{ 174 "LookUp", 175 &internal.LookUpArgs{ 176 Args: []internal.LookUpArg{{ 177 Name: "idfoo", 178 ID: "bar", 179 }}, 180 }, 181 response, 182 }, 183 }}) 184 } 185 186 func (s *clientSuite) TestLookUpMulti(c *gc.C) { 187 id1 := "ce5bc2a7-65d8-4800-8199-a7c3356ab309" 188 id2 := "ce5bc2a7-65d8-4800-8199-a7c3356ab311" 189 response := &internal.PayloadResults{ 190 Results: []internal.PayloadResult{{ 191 Entity: params.Entity{ 192 Tag: names.NewPayloadTag(id1).String(), 193 }, 194 Payload: nil, 195 NotFound: false, 196 Error: nil, 197 }, { 198 Entity: params.Entity{ 199 Tag: "", 200 }, 201 Payload: nil, 202 NotFound: true, 203 Error: common.ServerError(errors.NotFoundf("payload")), 204 }, { 205 Entity: params.Entity{ 206 Tag: names.NewPayloadTag(id2).String(), 207 }, 208 Payload: nil, 209 NotFound: false, 210 Error: nil, 211 }}, 212 } 213 s.facade.responses = append(s.facade.responses, response) 214 215 pclient := client.NewUnitFacadeClient(s.facade) 216 results, err := pclient.LookUp("idfoo/bar", "idbaz/bam", "spam/eggs") 217 c.Assert(err, jc.ErrorIsNil) 218 219 c.Assert(results, gc.HasLen, 3) 220 c.Assert(results[1].Error, gc.NotNil) 221 results[1].Error = nil 222 c.Check(results, jc.DeepEquals, []payload.Result{{ 223 ID: id1, 224 Payload: nil, 225 NotFound: false, 226 Error: nil, 227 }, { 228 ID: "", 229 Payload: nil, 230 NotFound: true, 231 Error: nil, 232 }, { 233 ID: id2, 234 Payload: nil, 235 NotFound: false, 236 Error: nil, 237 }}) 238 s.stub.CheckCalls(c, []testing.StubCall{{ 239 FuncName: "FacadeCall", 240 Args: []interface{}{ 241 "LookUp", 242 &internal.LookUpArgs{ 243 Args: []internal.LookUpArg{{ 244 Name: "idfoo", 245 ID: "bar", 246 }, { 247 Name: "idbaz", 248 ID: "bam", 249 }, { 250 Name: "spam", 251 ID: "eggs", 252 }}, 253 }, 254 response, 255 }, 256 }}) 257 } 258 259 func (s *clientSuite) TestSetStatus(c *gc.C) { 260 id := "ce5bc2a7-65d8-4800-8199-a7c3356ab309" 261 responses := []interface{}{ 262 &internal.PayloadResults{ 263 Results: []internal.PayloadResult{{ 264 Entity: params.Entity{ 265 Tag: names.NewPayloadTag(id).String(), 266 }, 267 Payload: nil, 268 NotFound: false, 269 Error: nil, 270 }}, 271 }, 272 &internal.PayloadResults{ 273 Results: []internal.PayloadResult{{ 274 Entity: params.Entity{ 275 Tag: names.NewPayloadTag(id).String(), 276 }, 277 Payload: nil, 278 NotFound: false, 279 Error: nil, 280 }}, 281 }, 282 } 283 s.facade.responses = append(s.facade.responses, responses...) 284 285 pclient := client.NewUnitFacadeClient(s.facade) 286 results, err := pclient.SetStatus(payload.StateRunning, "idfoo/bar") 287 c.Assert(err, jc.ErrorIsNil) 288 289 c.Check(results, jc.DeepEquals, []payload.Result{{ 290 ID: id, 291 Payload: nil, 292 NotFound: false, 293 Error: nil, 294 }}) 295 s.stub.CheckCalls(c, []testing.StubCall{{ 296 FuncName: "FacadeCall", 297 Args: []interface{}{ 298 "LookUp", 299 &internal.LookUpArgs{ 300 Args: []internal.LookUpArg{{ 301 Name: "idfoo", 302 ID: "bar", 303 }}, 304 }, 305 responses[0], 306 }, 307 }, { 308 FuncName: "FacadeCall", 309 Args: []interface{}{ 310 "SetStatus", 311 &internal.SetStatusArgs{ 312 Args: []internal.SetStatusArg{{ 313 Entity: params.Entity{ 314 Tag: names.NewPayloadTag(id).String(), 315 }, 316 Status: "running", 317 }}, 318 }, 319 responses[1], 320 }, 321 }}) 322 } 323 324 func (s *clientSuite) TestUntrack(c *gc.C) { 325 id := "ce5bc2a7-65d8-4800-8199-a7c3356ab309" 326 responses := []interface{}{ 327 &internal.PayloadResults{ 328 Results: []internal.PayloadResult{{ 329 Entity: params.Entity{ 330 Tag: names.NewPayloadTag(id).String(), 331 }, 332 Payload: nil, 333 NotFound: false, 334 Error: nil, 335 }}, 336 }, 337 &internal.PayloadResults{ 338 Results: []internal.PayloadResult{{ 339 Entity: params.Entity{ 340 Tag: names.NewPayloadTag(id).String(), 341 }, 342 Payload: nil, 343 NotFound: false, 344 Error: nil, 345 }}, 346 }, 347 } 348 s.facade.responses = append(s.facade.responses, responses...) 349 350 pclient := client.NewUnitFacadeClient(s.facade) 351 results, err := pclient.Untrack("idfoo/bar") 352 c.Assert(err, jc.ErrorIsNil) 353 354 c.Check(results, jc.DeepEquals, []payload.Result{{ 355 ID: id, 356 Payload: nil, 357 NotFound: false, 358 Error: nil, 359 }}) 360 s.stub.CheckCalls(c, []testing.StubCall{{ 361 FuncName: "FacadeCall", 362 Args: []interface{}{ 363 "LookUp", 364 &internal.LookUpArgs{ 365 Args: []internal.LookUpArg{{ 366 Name: "idfoo", 367 ID: "bar", 368 }}, 369 }, 370 responses[0], 371 }, 372 }, { 373 FuncName: "FacadeCall", 374 Args: []interface{}{ 375 "Untrack", 376 ¶ms.Entities{ 377 Entities: []params.Entity{{ 378 Tag: names.NewPayloadTag(id).String(), 379 }}, 380 }, 381 responses[1], 382 }, 383 }}) 384 } 385 386 type apiMethods interface { 387 Handler(name string) (func(target, response interface{}), bool) 388 } 389 390 type stubFacade struct { 391 stub *testing.Stub 392 responses []interface{} 393 methods apiMethods 394 395 // TODO(ericsnow) Eliminate this. 396 FacadeCallFn func(name string, params, response interface{}) error 397 } 398 399 func (s *stubFacade) nextResponse() interface{} { 400 if len(s.responses) == 0 { 401 return nil 402 } 403 resp := s.responses[0] 404 s.responses = s.responses[1:] 405 return resp 406 } 407 408 func (s *stubFacade) FacadeCall(request string, params, response interface{}) error { 409 s.stub.AddCall("FacadeCall", request, params, response) 410 resp := s.nextResponse() 411 if err := s.stub.NextErr(); err != nil { 412 return errors.Trace(err) 413 } 414 415 if s.FacadeCallFn != nil { 416 return s.FacadeCallFn(request, params, response) 417 } 418 419 if resp == nil { 420 // TODO(ericsnow) Fail? 421 return nil 422 } 423 handler, ok := s.methods.Handler(request) 424 if !ok { 425 return errors.Errorf("unknown request %q", request) 426 } 427 handler(response, resp) 428 return nil 429 } 430 431 func (s *stubFacade) Close() error { 432 s.stub.AddCall("Close") 433 if err := s.stub.NextErr(); err != nil { 434 return errors.Trace(err) 435 } 436 437 return nil 438 } 439 440 type unitMethods struct{} 441 442 func (m unitMethods) Handler(name string) (func(target, response interface{}), bool) { 443 switch name { 444 case "List", "LookUp", "SetStatus", "Untrack": 445 return m.generic, true 446 default: 447 return nil, false 448 } 449 } 450 451 func (unitMethods) generic(target, response interface{}) { 452 typedTarget := target.(*internal.PayloadResults) 453 typedResponse := response.(*internal.PayloadResults) 454 *typedTarget = *typedResponse 455 }