github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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/names"
     9  	"github.com/juju/testing"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    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  			&params.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  			&params.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  }