github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/rpc/rpc_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package rpc_test
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"net"
    10  	"reflect"
    11  	"regexp"
    12  	"sync"
    13  	stdtesting "testing"
    14  	"time"
    15  
    16  	"github.com/juju/loggo"
    17  	jc "github.com/juju/testing/checkers"
    18  	gc "gopkg.in/check.v1"
    19  
    20  	"github.com/juju/juju/rpc"
    21  	"github.com/juju/juju/rpc/jsoncodec"
    22  	"github.com/juju/juju/rpc/rpcreflect"
    23  	"github.com/juju/juju/testing"
    24  )
    25  
    26  var logger = loggo.GetLogger("juju.rpc")
    27  
    28  type rpcSuite struct {
    29  	testing.BaseSuite
    30  }
    31  
    32  var _ = gc.Suite(&rpcSuite{})
    33  
    34  func TestAll(t *stdtesting.T) {
    35  	gc.TestingT(t)
    36  }
    37  
    38  type callInfo struct {
    39  	rcvr   interface{}
    40  	method string
    41  	arg    interface{}
    42  }
    43  
    44  type callError callInfo
    45  
    46  func (e *callError) Error() string {
    47  	return fmt.Sprintf("error calling %s", e.method)
    48  }
    49  
    50  type stringVal struct {
    51  	Val string
    52  }
    53  
    54  type Root struct {
    55  	mu        sync.Mutex
    56  	conn      *rpc.Conn
    57  	calls     []*callInfo
    58  	returnErr bool
    59  	simple    map[string]*SimpleMethods
    60  	delayed   map[string]*DelayedMethods
    61  	errorInst *ErrorMethods
    62  }
    63  
    64  func (r *Root) callError(rcvr interface{}, name string, arg interface{}) error {
    65  	if r.returnErr {
    66  		return &callError{rcvr, name, arg}
    67  	}
    68  	return nil
    69  }
    70  
    71  func (r *Root) SimpleMethods(id string) (*SimpleMethods, error) {
    72  	r.mu.Lock()
    73  	defer r.mu.Unlock()
    74  	if a := r.simple[id]; a != nil {
    75  		return a, nil
    76  	}
    77  	return nil, fmt.Errorf("unknown SimpleMethods id")
    78  }
    79  
    80  func (r *Root) DelayedMethods(id string) (*DelayedMethods, error) {
    81  	r.mu.Lock()
    82  	defer r.mu.Unlock()
    83  	if a := r.delayed[id]; a != nil {
    84  		return a, nil
    85  	}
    86  	return nil, fmt.Errorf("unknown DelayedMethods id")
    87  }
    88  
    89  func (r *Root) ErrorMethods(id string) (*ErrorMethods, error) {
    90  	if r.errorInst == nil {
    91  		return nil, fmt.Errorf("no error methods")
    92  	}
    93  	return r.errorInst, nil
    94  }
    95  
    96  func (r *Root) Discard1() {}
    97  
    98  func (r *Root) Discard2(id string) error { return nil }
    99  
   100  func (r *Root) Discard3(id string) int { return 0 }
   101  
   102  func (r *Root) CallbackMethods(string) (*CallbackMethods, error) {
   103  	return &CallbackMethods{r}, nil
   104  }
   105  
   106  func (r *Root) InterfaceMethods(id string) (InterfaceMethods, error) {
   107  	logger.Infof("interface methods called")
   108  	m, err := r.SimpleMethods(id)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	return m, nil
   113  }
   114  
   115  type InterfaceMethods interface {
   116  	Call1r1e(s stringVal) (stringVal, error)
   117  }
   118  
   119  type ChangeAPIMethods struct {
   120  	r *Root
   121  }
   122  
   123  func (r *Root) ChangeAPIMethods(string) (*ChangeAPIMethods, error) {
   124  	return &ChangeAPIMethods{r}, nil
   125  }
   126  
   127  func (t *Root) called(rcvr interface{}, method string, arg interface{}) {
   128  	t.mu.Lock()
   129  	t.calls = append(t.calls, &callInfo{rcvr, method, arg})
   130  	t.mu.Unlock()
   131  }
   132  
   133  type SimpleMethods struct {
   134  	root *Root
   135  	id   string
   136  }
   137  
   138  // Each Call method is named in this standard form:
   139  //
   140  //     Call<narg>r<nret><e>
   141  //
   142  // where narg is the number of arguments, nret is the number of returned
   143  // values (not including the error) and e is the letter 'e' if the
   144  // method returns an error.
   145  
   146  func (a *SimpleMethods) Call0r0() {
   147  	a.root.called(a, "Call0r0", nil)
   148  }
   149  
   150  func (a *SimpleMethods) Call0r1() stringVal {
   151  	a.root.called(a, "Call0r1", nil)
   152  	return stringVal{"Call0r1 ret"}
   153  }
   154  
   155  func (a *SimpleMethods) Call0r1e() (stringVal, error) {
   156  	a.root.called(a, "Call0r1e", nil)
   157  	return stringVal{"Call0r1e ret"}, a.root.callError(a, "Call0r1e", nil)
   158  }
   159  
   160  func (a *SimpleMethods) Call0r0e() error {
   161  	a.root.called(a, "Call0r0e", nil)
   162  	return a.root.callError(a, "Call0r0e", nil)
   163  }
   164  
   165  func (a *SimpleMethods) Call1r0(s stringVal) {
   166  	a.root.called(a, "Call1r0", s)
   167  }
   168  
   169  func (a *SimpleMethods) Call1r1(s stringVal) stringVal {
   170  	a.root.called(a, "Call1r1", s)
   171  	return stringVal{"Call1r1 ret"}
   172  }
   173  
   174  func (a *SimpleMethods) Call1r1e(s stringVal) (stringVal, error) {
   175  	a.root.called(a, "Call1r1e", s)
   176  	return stringVal{"Call1r1e ret"}, a.root.callError(a, "Call1r1e", s)
   177  }
   178  
   179  func (a *SimpleMethods) Call1r0e(s stringVal) error {
   180  	a.root.called(a, "Call1r0e", s)
   181  	return a.root.callError(a, "Call1r0e", s)
   182  }
   183  
   184  func (a *SimpleMethods) SliceArg(struct{ X []string }) stringVal {
   185  	return stringVal{"SliceArg ret"}
   186  }
   187  
   188  func (a *SimpleMethods) Discard1(int) {}
   189  
   190  func (a *SimpleMethods) Discard2(struct{}, struct{}) {}
   191  
   192  func (a *SimpleMethods) Discard3() int { return 0 }
   193  
   194  func (a *SimpleMethods) Discard4() (_, _ struct{}) { return }
   195  
   196  type DelayedMethods struct {
   197  	ready     chan struct{}
   198  	done      chan string
   199  	doneError chan error
   200  }
   201  
   202  func (a *DelayedMethods) Delay() (stringVal, error) {
   203  	if a.ready != nil {
   204  		a.ready <- struct{}{}
   205  	}
   206  	select {
   207  	case s := <-a.done:
   208  		return stringVal{s}, nil
   209  	case err := <-a.doneError:
   210  		return stringVal{}, err
   211  	}
   212  }
   213  
   214  type ErrorMethods struct {
   215  	err error
   216  }
   217  
   218  func (e *ErrorMethods) Call() error {
   219  	return e.err
   220  }
   221  
   222  type CallbackMethods struct {
   223  	root *Root
   224  }
   225  
   226  type int64val struct {
   227  	I int64
   228  }
   229  
   230  func (a *CallbackMethods) Factorial(x int64val) (int64val, error) {
   231  	if x.I <= 1 {
   232  		return int64val{1}, nil
   233  	}
   234  	var r int64val
   235  	err := a.root.conn.Call(rpc.Request{"CallbackMethods", 0, "", "Factorial"}, int64val{x.I - 1}, &r)
   236  	if err != nil {
   237  		return int64val{}, err
   238  	}
   239  	return int64val{x.I * r.I}, nil
   240  }
   241  
   242  func (a *ChangeAPIMethods) ChangeAPI() {
   243  	a.r.conn.Serve(&changedAPIRoot{}, nil)
   244  }
   245  
   246  func (a *ChangeAPIMethods) RemoveAPI() {
   247  	a.r.conn.Serve(nil, nil)
   248  }
   249  
   250  type changedAPIRoot struct{}
   251  
   252  func (r *changedAPIRoot) NewlyAvailable(string) (newlyAvailableMethods, error) {
   253  	return newlyAvailableMethods{}, nil
   254  }
   255  
   256  type newlyAvailableMethods struct{}
   257  
   258  func (newlyAvailableMethods) NewMethod() stringVal {
   259  	return stringVal{"new method result"}
   260  }
   261  
   262  type VariableMethods1 struct {
   263  	sm *SimpleMethods
   264  }
   265  
   266  func (vm *VariableMethods1) Call0r1() stringVal {
   267  	return vm.sm.Call0r1()
   268  }
   269  
   270  type VariableMethods2 struct {
   271  	sm *SimpleMethods
   272  }
   273  
   274  func (vm *VariableMethods2) Call1r1(s stringVal) stringVal {
   275  	return vm.sm.Call1r1(s)
   276  }
   277  
   278  type RestrictedMethods struct {
   279  	InterfaceMethods
   280  }
   281  
   282  type CustomMethodFinder struct {
   283  	root *Root
   284  }
   285  
   286  type wrapper func(*SimpleMethods) reflect.Value
   287  
   288  type customMethodCaller struct {
   289  	wrap         wrapper
   290  	root         *Root
   291  	objMethod    rpcreflect.ObjMethod
   292  	expectedType reflect.Type
   293  }
   294  
   295  func (c customMethodCaller) ParamsType() reflect.Type {
   296  	return c.objMethod.Params
   297  }
   298  
   299  func (c customMethodCaller) ResultType() reflect.Type {
   300  	return c.objMethod.Result
   301  }
   302  
   303  func (c customMethodCaller) Call(objId string, arg reflect.Value) (reflect.Value, error) {
   304  	sm, err := c.root.SimpleMethods(objId)
   305  	if err != nil {
   306  		return reflect.Value{}, err
   307  	}
   308  	obj := c.wrap(sm)
   309  	if reflect.TypeOf(obj) != c.expectedType {
   310  		logger.Errorf("got the wrong type back, expected %s got %T", c.expectedType, obj)
   311  	}
   312  	logger.Debugf("calling: %T %v %#v", obj, obj, c.objMethod)
   313  	return c.objMethod.Call(obj, arg)
   314  }
   315  
   316  func (cc *CustomMethodFinder) FindMethod(
   317  	rootMethodName string, version int, objMethodName string,
   318  ) (
   319  	rpcreflect.MethodCaller, error,
   320  ) {
   321  	logger.Debugf("got to FindMethod: %q %d %q", rootMethodName, version, objMethodName)
   322  	if rootMethodName != "MultiVersion" {
   323  		return nil, &rpcreflect.CallNotImplementedError{
   324  			RootMethod: rootMethodName,
   325  		}
   326  	}
   327  	var goType reflect.Type
   328  	var wrap wrapper
   329  	switch version {
   330  	case 0:
   331  		goType = reflect.TypeOf((*VariableMethods1)(nil))
   332  		wrap = func(sm *SimpleMethods) reflect.Value {
   333  			return reflect.ValueOf(&VariableMethods1{sm})
   334  		}
   335  	case 1:
   336  		goType = reflect.TypeOf((*VariableMethods2)(nil))
   337  		wrap = func(sm *SimpleMethods) reflect.Value {
   338  			return reflect.ValueOf(&VariableMethods2{sm})
   339  		}
   340  	case 2:
   341  		goType = reflect.TypeOf((*RestrictedMethods)(nil))
   342  		wrap = func(sm *SimpleMethods) reflect.Value {
   343  			methods := &RestrictedMethods{InterfaceMethods: sm}
   344  			return reflect.ValueOf(methods)
   345  		}
   346  	default:
   347  		return nil, &rpcreflect.CallNotImplementedError{
   348  			RootMethod: rootMethodName,
   349  			Version:    version,
   350  		}
   351  	}
   352  	logger.Debugf("found type: %s", goType)
   353  	objType := rpcreflect.ObjTypeOf(goType)
   354  	objMethod, err := objType.Method(objMethodName)
   355  	if err != nil {
   356  		return nil, &rpcreflect.CallNotImplementedError{
   357  			RootMethod: rootMethodName,
   358  			Version:    version,
   359  			Method:     objMethodName,
   360  		}
   361  	}
   362  	return customMethodCaller{
   363  		objMethod:    objMethod,
   364  		root:         cc.root,
   365  		wrap:         wrap,
   366  		expectedType: goType,
   367  	}, nil
   368  }
   369  
   370  func SimpleRoot() *Root {
   371  	root := &Root{
   372  		simple: make(map[string]*SimpleMethods),
   373  	}
   374  	root.simple["a99"] = &SimpleMethods{root: root, id: "a99"}
   375  	return root
   376  }
   377  
   378  func (*rpcSuite) TestRPC(c *gc.C) {
   379  	root := SimpleRoot()
   380  	client, srvDone, clientNotifier, serverNotifier := newRPCClientServer(c, root, nil, false)
   381  	defer closeClient(c, client, srvDone)
   382  	for narg := 0; narg < 2; narg++ {
   383  		for nret := 0; nret < 2; nret++ {
   384  			for nerr := 0; nerr < 2; nerr++ {
   385  				retErr := nerr != 0
   386  				p := testCallParams{
   387  					client:         client,
   388  					clientNotifier: clientNotifier,
   389  					serverNotifier: serverNotifier,
   390  					entry:          "SimpleMethods",
   391  					narg:           narg,
   392  					nret:           nret,
   393  					retErr:         retErr,
   394  					testErr:        false,
   395  				}
   396  				root.testCall(c, p)
   397  				if retErr {
   398  					p.testErr = true
   399  					root.testCall(c, p)
   400  				}
   401  			}
   402  		}
   403  	}
   404  }
   405  
   406  func callName(narg, nret int, retErr bool) string {
   407  	e := ""
   408  	if retErr {
   409  		e = "e"
   410  	}
   411  	return fmt.Sprintf("Call%dr%d%s", narg, nret, e)
   412  }
   413  
   414  type testCallParams struct {
   415  	// client holds the client-side of the rpc connection that
   416  	// will be used to make the call.
   417  	client *rpc.Conn
   418  
   419  	// clientNotifier holds the notifier for the client side.
   420  	clientNotifier *notifier
   421  
   422  	// serverNotifier holds the notifier for the server side.
   423  	serverNotifier *notifier
   424  
   425  	// entry holds the top-level type that will be invoked
   426  	// (e.g. "SimpleMethods").
   427  	entry string
   428  
   429  	// narg holds the number of arguments accepted by the
   430  	// call (0 or 1).
   431  	narg int
   432  
   433  	// nret holds the number of values returned by the
   434  	// call (0 or 1).
   435  	nret int
   436  
   437  	// retErr specifies whether the call returns an error.
   438  	retErr bool
   439  
   440  	// testErr specifies whether the call should be made to return an error.
   441  	testErr bool
   442  
   443  	// version specifies what version of the interface to call, defaults to 0.
   444  	version int
   445  }
   446  
   447  // request returns the RPC request for the test call.
   448  func (p testCallParams) request() rpc.Request {
   449  	return rpc.Request{
   450  		Type:    p.entry,
   451  		Version: p.version,
   452  		Id:      "a99",
   453  		Action:  callName(p.narg, p.nret, p.retErr),
   454  	}
   455  }
   456  
   457  // error message returns the error message that the test call
   458  // should return if it returns an error.
   459  func (p testCallParams) errorMessage() string {
   460  	return fmt.Sprintf("error calling %s", p.request().Action)
   461  }
   462  
   463  func (root *Root) testCall(c *gc.C, p testCallParams) {
   464  	p.clientNotifier.reset()
   465  	p.serverNotifier.reset()
   466  	root.calls = nil
   467  	root.returnErr = p.testErr
   468  	c.Logf("test call %s", p.request().Action)
   469  	var r stringVal
   470  	err := p.client.Call(p.request(), stringVal{"arg"}, &r)
   471  	switch {
   472  	case p.retErr && p.testErr:
   473  		c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   474  			Message: p.errorMessage(),
   475  		})
   476  		c.Assert(r, gc.Equals, stringVal{})
   477  	case p.nret > 0:
   478  		c.Check(r, gc.Equals, stringVal{p.request().Action + " ret"})
   479  	}
   480  	if !p.testErr {
   481  		c.Check(err, jc.ErrorIsNil)
   482  	}
   483  
   484  	// Check that the call was actually made, the right
   485  	// parameters were received and the right result returned.
   486  	root.mu.Lock()
   487  	defer root.mu.Unlock()
   488  
   489  	root.assertCallMade(c, p)
   490  
   491  	requestId := root.assertClientNotified(c, p, &r)
   492  
   493  	root.assertServerNotified(c, p, requestId)
   494  }
   495  
   496  func (root *Root) assertCallMade(c *gc.C, p testCallParams) {
   497  	expectCall := callInfo{
   498  		rcvr:   root.simple["a99"],
   499  		method: p.request().Action,
   500  	}
   501  	if p.narg > 0 {
   502  		expectCall.arg = stringVal{"arg"}
   503  	}
   504  	c.Assert(root.calls, gc.HasLen, 1)
   505  	c.Assert(*root.calls[0], gc.Equals, expectCall)
   506  }
   507  
   508  // assertClientNotified asserts that the right client notifications
   509  // were made for the given test call parameters. The value of r
   510  // holds the result parameter passed to the call.
   511  // It returns the request id.
   512  func (root *Root) assertClientNotified(c *gc.C, p testCallParams, r interface{}) uint64 {
   513  	c.Assert(p.clientNotifier.serverRequests, gc.HasLen, 0)
   514  	c.Assert(p.clientNotifier.serverReplies, gc.HasLen, 0)
   515  
   516  	// Test that there was a notification for the request.
   517  	c.Assert(p.clientNotifier.clientRequests, gc.HasLen, 1)
   518  	clientReq := p.clientNotifier.clientRequests[0]
   519  	requestId := clientReq.hdr.RequestId
   520  	clientReq.hdr.RequestId = 0 // Ignore the exact value of the request id to start with.
   521  	c.Assert(clientReq.hdr, gc.DeepEquals, rpc.Header{
   522  		Request: p.request(),
   523  	})
   524  	c.Assert(clientReq.body, gc.Equals, stringVal{"arg"})
   525  
   526  	// Test that there was a notification for the reply.
   527  	c.Assert(p.clientNotifier.clientReplies, gc.HasLen, 1)
   528  	clientReply := p.clientNotifier.clientReplies[0]
   529  	c.Assert(clientReply.req, gc.Equals, p.request())
   530  	if p.retErr && p.testErr {
   531  		c.Assert(clientReply.body, gc.Equals, nil)
   532  	} else {
   533  		c.Assert(clientReply.body, gc.Equals, r)
   534  	}
   535  	if p.retErr && p.testErr {
   536  		c.Assert(clientReply.hdr, gc.DeepEquals, rpc.Header{
   537  			RequestId: requestId,
   538  			Error:     p.errorMessage(),
   539  		})
   540  	} else {
   541  		c.Assert(clientReply.hdr, gc.DeepEquals, rpc.Header{
   542  			RequestId: requestId,
   543  		})
   544  	}
   545  	return requestId
   546  }
   547  
   548  // assertServerNotified asserts that the right server notifications
   549  // were made for the given test call parameters. The id of the request
   550  // is held in requestId.
   551  func (root *Root) assertServerNotified(c *gc.C, p testCallParams, requestId uint64) {
   552  	// Check that the right server notifications were made.
   553  	c.Assert(p.serverNotifier.clientRequests, gc.HasLen, 0)
   554  	c.Assert(p.serverNotifier.clientReplies, gc.HasLen, 0)
   555  
   556  	// Test that there was a notification for the request.
   557  	c.Assert(p.serverNotifier.serverRequests, gc.HasLen, 1)
   558  	serverReq := p.serverNotifier.serverRequests[0]
   559  	c.Assert(serverReq.hdr, gc.DeepEquals, rpc.Header{
   560  		RequestId: requestId,
   561  		Request:   p.request(),
   562  	})
   563  	if p.narg > 0 {
   564  		c.Assert(serverReq.body, gc.Equals, stringVal{"arg"})
   565  	} else {
   566  		c.Assert(serverReq.body, gc.Equals, struct{}{})
   567  	}
   568  
   569  	// Test that there was a notification for the reply.
   570  	c.Assert(p.serverNotifier.serverReplies, gc.HasLen, 1)
   571  	serverReply := p.serverNotifier.serverReplies[0]
   572  	c.Assert(serverReply.req, gc.Equals, p.request())
   573  	if p.retErr && p.testErr || p.nret == 0 {
   574  		c.Assert(serverReply.body, gc.Equals, struct{}{})
   575  	} else {
   576  		c.Assert(serverReply.body, gc.Equals, stringVal{p.request().Action + " ret"})
   577  	}
   578  	if p.retErr && p.testErr {
   579  		c.Assert(serverReply.hdr, gc.Equals, rpc.Header{
   580  			RequestId: requestId,
   581  			Error:     p.errorMessage(),
   582  		})
   583  	} else {
   584  		c.Assert(serverReply.hdr, gc.Equals, rpc.Header{
   585  			RequestId: requestId,
   586  		})
   587  	}
   588  }
   589  
   590  func (*rpcSuite) TestInterfaceMethods(c *gc.C) {
   591  	root := SimpleRoot()
   592  	client, srvDone, clientNotifier, serverNotifier := newRPCClientServer(c, root, nil, false)
   593  	defer closeClient(c, client, srvDone)
   594  	p := testCallParams{
   595  		client:         client,
   596  		clientNotifier: clientNotifier,
   597  		serverNotifier: serverNotifier,
   598  		entry:          "InterfaceMethods",
   599  		narg:           1,
   600  		nret:           1,
   601  		retErr:         true,
   602  		testErr:        false,
   603  	}
   604  
   605  	root.testCall(c, p)
   606  	p.testErr = true
   607  	root.testCall(c, p)
   608  	// Call0r0 is defined on the underlying SimpleMethods, but is not
   609  	// exposed at the InterfaceMethods level, so this call should fail with
   610  	// CodeNotImplemented.
   611  	var r stringVal
   612  	err := client.Call(rpc.Request{"InterfaceMethods", 0, "a99", "Call0r0"}, stringVal{"arg"}, &r)
   613  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   614  		Message: "no such request - method InterfaceMethods.Call0r0 is not implemented",
   615  		Code:    rpc.CodeNotImplemented,
   616  	})
   617  }
   618  
   619  func (*rpcSuite) TestCustomMethodFinderV0(c *gc.C) {
   620  	root := &CustomMethodFinder{SimpleRoot()}
   621  	client, srvDone, clientNotifier, serverNotifier := newRPCClientServer(c, root, nil, false)
   622  	defer closeClient(c, client, srvDone)
   623  	// V0 of MultiVersion implements only VariableMethods1.Call0r1.
   624  	p := testCallParams{
   625  		client:         client,
   626  		clientNotifier: clientNotifier,
   627  		serverNotifier: serverNotifier,
   628  		entry:          "MultiVersion",
   629  		version:        0,
   630  		narg:           0,
   631  		nret:           1,
   632  		retErr:         false,
   633  		testErr:        false,
   634  	}
   635  
   636  	root.root.testCall(c, p)
   637  	// Call1r1 is exposed in version 1, but not in version 0.
   638  	var r stringVal
   639  	err := client.Call(rpc.Request{"MultiVersion", 0, "a99", "Call1r1"}, stringVal{"arg"}, &r)
   640  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   641  		Message: "no such request - method MultiVersion.Call1r1 is not implemented",
   642  		Code:    rpc.CodeNotImplemented,
   643  	})
   644  }
   645  
   646  func (*rpcSuite) TestCustomMethodFinderV1(c *gc.C) {
   647  	root := &CustomMethodFinder{SimpleRoot()}
   648  	client, srvDone, clientNotifier, serverNotifier := newRPCClientServer(c, root, nil, false)
   649  	defer closeClient(c, client, srvDone)
   650  	// V1 of MultiVersion implements only VariableMethods2.Call1r1.
   651  	p := testCallParams{
   652  		client:         client,
   653  		clientNotifier: clientNotifier,
   654  		serverNotifier: serverNotifier,
   655  		entry:          "MultiVersion",
   656  		version:        1,
   657  		narg:           1,
   658  		nret:           1,
   659  		retErr:         false,
   660  		testErr:        false,
   661  	}
   662  
   663  	root.root.testCall(c, p)
   664  	// Call0r1 is exposed in version 0, but not in version 1.
   665  	var r stringVal
   666  	err := client.Call(rpc.Request{"MultiVersion", 1, "a99", "Call0r1"}, nil, &r)
   667  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   668  		Message: "no such request - method MultiVersion(1).Call0r1 is not implemented",
   669  		Code:    rpc.CodeNotImplemented,
   670  	})
   671  }
   672  
   673  func (*rpcSuite) TestCustomMethodFinderV2(c *gc.C) {
   674  	root := &CustomMethodFinder{SimpleRoot()}
   675  	client, srvDone, clientNotifier, serverNotifier := newRPCClientServer(c, root, nil, false)
   676  	defer closeClient(c, client, srvDone)
   677  	p := testCallParams{
   678  		client:         client,
   679  		clientNotifier: clientNotifier,
   680  		serverNotifier: serverNotifier,
   681  		entry:          "MultiVersion",
   682  		version:        2,
   683  		narg:           1,
   684  		nret:           1,
   685  		retErr:         true,
   686  		testErr:        false,
   687  	}
   688  
   689  	root.root.testCall(c, p)
   690  	// By embedding the InterfaceMethods inside a concrete
   691  	// RestrictedMethods type, we actually only expose the methods defined
   692  	// in InterfaceMethods.
   693  	var r stringVal
   694  	err := client.Call(rpc.Request{"MultiVersion", 2, "a99", "Call0r1e"}, nil, &r)
   695  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   696  		Message: `no such request - method MultiVersion(2).Call0r1e is not implemented`,
   697  		Code:    rpc.CodeNotImplemented,
   698  	})
   699  }
   700  
   701  func (*rpcSuite) TestCustomMethodFinderUnknownVersion(c *gc.C) {
   702  	root := &CustomMethodFinder{SimpleRoot()}
   703  	client, srvDone, _, _ := newRPCClientServer(c, root, nil, false)
   704  	defer closeClient(c, client, srvDone)
   705  	var r stringVal
   706  	// Unknown version 5
   707  	err := client.Call(rpc.Request{"MultiVersion", 5, "a99", "Call0r1"}, nil, &r)
   708  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   709  		Message: `unknown version (5) of interface "MultiVersion"`,
   710  		Code:    rpc.CodeNotImplemented,
   711  	})
   712  }
   713  
   714  func (*rpcSuite) TestConcurrentCalls(c *gc.C) {
   715  	start1 := make(chan string)
   716  	start2 := make(chan string)
   717  	ready1 := make(chan struct{})
   718  	ready2 := make(chan struct{})
   719  
   720  	root := &Root{
   721  		delayed: map[string]*DelayedMethods{
   722  			"1": {ready: ready1, done: start1},
   723  			"2": {ready: ready2, done: start2},
   724  		},
   725  	}
   726  
   727  	client, srvDone, _, _ := newRPCClientServer(c, root, nil, false)
   728  	defer closeClient(c, client, srvDone)
   729  	call := func(id string, done chan<- struct{}) {
   730  		var r stringVal
   731  		err := client.Call(rpc.Request{"DelayedMethods", 0, id, "Delay"}, nil, &r)
   732  		c.Check(err, jc.ErrorIsNil)
   733  		c.Check(r.Val, gc.Equals, "return "+id)
   734  		done <- struct{}{}
   735  	}
   736  	done1 := make(chan struct{})
   737  	done2 := make(chan struct{})
   738  	go call("1", done1)
   739  	go call("2", done2)
   740  
   741  	// Check that both calls are running concurrently.
   742  	chanRead(c, ready1, "method 1 ready")
   743  	chanRead(c, ready2, "method 2 ready")
   744  
   745  	// Let the requests complete.
   746  	start1 <- "return 1"
   747  	start2 <- "return 2"
   748  	chanRead(c, done1, "method 1 done")
   749  	chanRead(c, done2, "method 2 done")
   750  }
   751  
   752  type codedError struct {
   753  	m    string
   754  	code string
   755  }
   756  
   757  func (e *codedError) Error() string {
   758  	return e.m
   759  }
   760  
   761  func (e *codedError) ErrorCode() string {
   762  	return e.code
   763  }
   764  
   765  func (*rpcSuite) TestErrorCode(c *gc.C) {
   766  	root := &Root{
   767  		errorInst: &ErrorMethods{&codedError{"message", "code"}},
   768  	}
   769  	client, srvDone, _, _ := newRPCClientServer(c, root, nil, false)
   770  	defer closeClient(c, client, srvDone)
   771  	err := client.Call(rpc.Request{"ErrorMethods", 0, "", "Call"}, nil, nil)
   772  	c.Assert(err, gc.ErrorMatches, `request error: message \(code\)`)
   773  	c.Assert(err.(rpc.ErrorCoder).ErrorCode(), gc.Equals, "code")
   774  }
   775  
   776  func (*rpcSuite) TestTransformErrors(c *gc.C) {
   777  	root := &Root{
   778  		errorInst: &ErrorMethods{&codedError{"message", "code"}},
   779  	}
   780  	tfErr := func(err error) error {
   781  		c.Check(err, gc.NotNil)
   782  		if e, ok := err.(*codedError); ok {
   783  			return &codedError{
   784  				m:    "transformed: " + e.m,
   785  				code: "transformed: " + e.code,
   786  			}
   787  		}
   788  		return fmt.Errorf("transformed: %v", err)
   789  	}
   790  	client, srvDone, _, _ := newRPCClientServer(c, root, tfErr, false)
   791  	defer closeClient(c, client, srvDone)
   792  	// First, we don't transform methods we can't find.
   793  	err := client.Call(rpc.Request{"foo", 0, "", "bar"}, nil, nil)
   794  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   795  		Message: `unknown object type "foo"`,
   796  		Code:    rpc.CodeNotImplemented,
   797  	})
   798  
   799  	err = client.Call(rpc.Request{"ErrorMethods", 0, "", "NoMethod"}, nil, nil)
   800  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   801  		Message: "no such request - method ErrorMethods.NoMethod is not implemented",
   802  		Code:    rpc.CodeNotImplemented,
   803  	})
   804  
   805  	// We do transform any errors that happen from calling the RootMethod
   806  	// and beyond.
   807  	err = client.Call(rpc.Request{"ErrorMethods", 0, "", "Call"}, nil, nil)
   808  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   809  		Message: "transformed: message",
   810  		Code:    "transformed: code",
   811  	})
   812  
   813  	root.errorInst.err = nil
   814  	err = client.Call(rpc.Request{"ErrorMethods", 0, "", "Call"}, nil, nil)
   815  	c.Assert(err, jc.ErrorIsNil)
   816  
   817  	root.errorInst = nil
   818  	err = client.Call(rpc.Request{"ErrorMethods", 0, "", "Call"}, nil, nil)
   819  	c.Assert(err, gc.DeepEquals, &rpc.RequestError{
   820  		Message: "transformed: no error methods",
   821  	})
   822  
   823  }
   824  
   825  func (*rpcSuite) TestServerWaitsForOutstandingCalls(c *gc.C) {
   826  	ready := make(chan struct{})
   827  	start := make(chan string)
   828  	root := &Root{
   829  		delayed: map[string]*DelayedMethods{
   830  			"1": {
   831  				ready: ready,
   832  				done:  start,
   833  			},
   834  		},
   835  	}
   836  	client, srvDone, _, _ := newRPCClientServer(c, root, nil, false)
   837  	defer closeClient(c, client, srvDone)
   838  	done := make(chan struct{})
   839  	go func() {
   840  		var r stringVal
   841  		err := client.Call(rpc.Request{"DelayedMethods", 0, "1", "Delay"}, nil, &r)
   842  		c.Check(err, gc.Equals, rpc.ErrShutdown)
   843  		done <- struct{}{}
   844  	}()
   845  	chanRead(c, ready, "DelayedMethods.Delay ready")
   846  	client.Close()
   847  	select {
   848  	case err := <-srvDone:
   849  		c.Fatalf("server returned while outstanding operation in progress: %v", err)
   850  		<-done
   851  	case <-time.After(25 * time.Millisecond):
   852  	}
   853  	start <- "xxx"
   854  }
   855  
   856  func chanRead(c *gc.C, ch <-chan struct{}, what string) {
   857  	select {
   858  	case <-ch:
   859  		return
   860  	case <-time.After(3 * time.Second):
   861  		c.Fatalf("timeout on channel read %s", what)
   862  	}
   863  }
   864  
   865  func (*rpcSuite) TestCompatibility(c *gc.C) {
   866  	root := &Root{
   867  		simple: make(map[string]*SimpleMethods),
   868  	}
   869  	a0 := &SimpleMethods{root: root, id: "a0"}
   870  	root.simple["a0"] = a0
   871  
   872  	client, srvDone, _, _ := newRPCClientServer(c, root, nil, false)
   873  	defer closeClient(c, client, srvDone)
   874  	call := func(method string, arg, ret interface{}) (passedArg interface{}) {
   875  		root.calls = nil
   876  		err := client.Call(rpc.Request{"SimpleMethods", 0, "a0", method}, arg, ret)
   877  		c.Assert(err, jc.ErrorIsNil)
   878  		c.Assert(root.calls, gc.HasLen, 1)
   879  		info := root.calls[0]
   880  		c.Assert(info.rcvr, gc.Equals, a0)
   881  		c.Assert(info.method, gc.Equals, method)
   882  		return info.arg
   883  	}
   884  	type extra struct {
   885  		Val   string
   886  		Extra string
   887  	}
   888  	// Extra fields in request and response.
   889  	var r extra
   890  	arg := call("Call1r1", extra{"x", "y"}, &r)
   891  	c.Assert(arg, gc.Equals, stringVal{"x"})
   892  
   893  	// Nil argument as request.
   894  	r = extra{}
   895  	arg = call("Call1r1", nil, &r)
   896  	c.Assert(arg, gc.Equals, stringVal{})
   897  
   898  	// Nil argument as response.
   899  	arg = call("Call1r1", stringVal{"x"}, nil)
   900  	c.Assert(arg, gc.Equals, stringVal{"x"})
   901  
   902  	// Non-nil argument for no response.
   903  	r = extra{}
   904  	arg = call("Call1r0", stringVal{"x"}, &r)
   905  	c.Assert(arg, gc.Equals, stringVal{"x"})
   906  	c.Assert(r, gc.Equals, extra{})
   907  }
   908  
   909  func (*rpcSuite) TestBadCall(c *gc.C) {
   910  	root := &Root{
   911  		simple: make(map[string]*SimpleMethods),
   912  	}
   913  	a0 := &SimpleMethods{root: root, id: "a0"}
   914  	root.simple["a0"] = a0
   915  	client, srvDone, clientNotifier, serverNotifier := newRPCClientServer(c, root, nil, false)
   916  	defer closeClient(c, client, srvDone)
   917  
   918  	testBadCall(c, client, clientNotifier, serverNotifier,
   919  		rpc.Request{"BadSomething", 0, "a0", "No"},
   920  		`unknown object type "BadSomething"`,
   921  		rpc.CodeNotImplemented,
   922  		false,
   923  	)
   924  	testBadCall(c, client, clientNotifier, serverNotifier,
   925  		rpc.Request{"SimpleMethods", 0, "xx", "No"},
   926  		"no such request - method SimpleMethods.No is not implemented",
   927  		rpc.CodeNotImplemented,
   928  		false,
   929  	)
   930  	testBadCall(c, client, clientNotifier, serverNotifier,
   931  		rpc.Request{"SimpleMethods", 0, "xx", "Call0r0"},
   932  		`unknown SimpleMethods id`,
   933  		"",
   934  		true,
   935  	)
   936  }
   937  
   938  func testBadCall(
   939  	c *gc.C,
   940  	client *rpc.Conn,
   941  	clientNotifier, serverNotifier *notifier,
   942  	req rpc.Request,
   943  	expectedErr string,
   944  	expectedErrCode string,
   945  	requestKnown bool,
   946  ) {
   947  	clientNotifier.reset()
   948  	serverNotifier.reset()
   949  	err := client.Call(req, nil, nil)
   950  	msg := expectedErr
   951  	if expectedErrCode != "" {
   952  		msg += " (" + expectedErrCode + ")"
   953  	}
   954  	c.Assert(err, gc.ErrorMatches, regexp.QuoteMeta("request error: "+msg))
   955  
   956  	// Test that there was a notification for the client request.
   957  	c.Assert(clientNotifier.clientRequests, gc.HasLen, 1)
   958  	clientReq := clientNotifier.clientRequests[0]
   959  	requestId := clientReq.hdr.RequestId
   960  	c.Assert(clientReq, gc.DeepEquals, requestEvent{
   961  		hdr: rpc.Header{
   962  			RequestId: requestId,
   963  			Request:   req,
   964  		},
   965  		body: struct{}{},
   966  	})
   967  	// Test that there was a notification for the client reply.
   968  	c.Assert(clientNotifier.clientReplies, gc.HasLen, 1)
   969  	clientReply := clientNotifier.clientReplies[0]
   970  	c.Assert(clientReply, gc.DeepEquals, replyEvent{
   971  		req: req,
   972  		hdr: rpc.Header{
   973  			RequestId: requestId,
   974  			Error:     expectedErr,
   975  			ErrorCode: expectedErrCode,
   976  		},
   977  	})
   978  
   979  	// Test that there was a notification for the server request.
   980  	c.Assert(serverNotifier.serverRequests, gc.HasLen, 1)
   981  	serverReq := serverNotifier.serverRequests[0]
   982  
   983  	// From docs on ServerRequest:
   984  	// 	If the request was not recognized or there was
   985  	//	an error reading the body, body will be nil.
   986  	var expectBody interface{}
   987  	if requestKnown {
   988  		expectBody = struct{}{}
   989  	}
   990  	c.Assert(serverReq, gc.DeepEquals, requestEvent{
   991  		hdr: rpc.Header{
   992  			RequestId: requestId,
   993  			Request:   req,
   994  		},
   995  		body: expectBody,
   996  	})
   997  
   998  	// Test that there was a notification for the server reply.
   999  	c.Assert(serverNotifier.serverReplies, gc.HasLen, 1)
  1000  	serverReply := serverNotifier.serverReplies[0]
  1001  	c.Assert(serverReply, gc.DeepEquals, replyEvent{
  1002  		hdr: rpc.Header{
  1003  			RequestId: requestId,
  1004  			Error:     expectedErr,
  1005  			ErrorCode: expectedErrCode,
  1006  		},
  1007  		req:  req,
  1008  		body: struct{}{},
  1009  	})
  1010  }
  1011  
  1012  func (*rpcSuite) TestContinueAfterReadBodyError(c *gc.C) {
  1013  	root := &Root{
  1014  		simple: make(map[string]*SimpleMethods),
  1015  	}
  1016  	a0 := &SimpleMethods{root: root, id: "a0"}
  1017  	root.simple["a0"] = a0
  1018  	client, srvDone, _, _ := newRPCClientServer(c, root, nil, false)
  1019  	defer closeClient(c, client, srvDone)
  1020  
  1021  	var ret stringVal
  1022  	arg0 := struct {
  1023  		X map[string]int
  1024  	}{
  1025  		X: map[string]int{"hello": 65},
  1026  	}
  1027  	err := client.Call(rpc.Request{"SimpleMethods", 0, "a0", "SliceArg"}, arg0, &ret)
  1028  	c.Assert(err, gc.ErrorMatches, `request error: json: cannot unmarshal object into Go value of type \[\]string`)
  1029  
  1030  	err = client.Call(rpc.Request{"SimpleMethods", 0, "a0", "SliceArg"}, arg0, &ret)
  1031  	c.Assert(err, gc.ErrorMatches, `request error: json: cannot unmarshal object into Go value of type \[\]string`)
  1032  
  1033  	arg1 := struct {
  1034  		X []string
  1035  	}{
  1036  		X: []string{"one"},
  1037  	}
  1038  	err = client.Call(rpc.Request{"SimpleMethods", 0, "a0", "SliceArg"}, arg1, &ret)
  1039  	c.Assert(err, jc.ErrorIsNil)
  1040  	c.Assert(ret.Val, gc.Equals, "SliceArg ret")
  1041  }
  1042  
  1043  func (*rpcSuite) TestErrorAfterClientClose(c *gc.C) {
  1044  	client, srvDone, _, _ := newRPCClientServer(c, &Root{}, nil, false)
  1045  	err := client.Close()
  1046  	c.Assert(err, jc.ErrorIsNil)
  1047  	err = client.Call(rpc.Request{"Foo", 0, "", "Bar"}, nil, nil)
  1048  	c.Assert(err, gc.Equals, rpc.ErrShutdown)
  1049  	err = chanReadError(c, srvDone, "server done")
  1050  	c.Assert(err, jc.ErrorIsNil)
  1051  }
  1052  
  1053  func (*rpcSuite) TestClientCloseIdempotent(c *gc.C) {
  1054  	client, _, _, _ := newRPCClientServer(c, &Root{}, nil, false)
  1055  	err := client.Close()
  1056  	c.Assert(err, jc.ErrorIsNil)
  1057  	err = client.Close()
  1058  	c.Assert(err, jc.ErrorIsNil)
  1059  	err = client.Close()
  1060  	c.Assert(err, jc.ErrorIsNil)
  1061  }
  1062  
  1063  type KillerCleanerRoot struct {
  1064  	events []string
  1065  	Root
  1066  }
  1067  
  1068  func (r *KillerCleanerRoot) Kill() {
  1069  	r.events = append(r.events, "kill")
  1070  }
  1071  
  1072  func (r *KillerCleanerRoot) Cleanup() {
  1073  	r.events = append(r.events, "cleanup")
  1074  }
  1075  
  1076  func (*rpcSuite) TestRootIsKilledAndCleaned(c *gc.C) {
  1077  	root := &KillerCleanerRoot{}
  1078  	client, srvDone, _, _ := newRPCClientServer(c, root, nil, false)
  1079  	err := client.Close()
  1080  	c.Assert(err, jc.ErrorIsNil)
  1081  	err = chanReadError(c, srvDone, "server done")
  1082  	c.Assert(err, jc.ErrorIsNil)
  1083  	// Kill should happen first.
  1084  	c.Assert(root.events, jc.DeepEquals, []string{"kill", "cleanup"})
  1085  }
  1086  
  1087  func (*rpcSuite) TestBidirectional(c *gc.C) {
  1088  	srvRoot := &Root{}
  1089  	client, srvDone, _, _ := newRPCClientServer(c, srvRoot, nil, true)
  1090  	defer closeClient(c, client, srvDone)
  1091  	clientRoot := &Root{conn: client}
  1092  	client.Serve(clientRoot, nil)
  1093  	var r int64val
  1094  	err := client.Call(rpc.Request{"CallbackMethods", 0, "", "Factorial"}, int64val{12}, &r)
  1095  	c.Assert(err, jc.ErrorIsNil)
  1096  	c.Assert(r.I, gc.Equals, int64(479001600))
  1097  }
  1098  
  1099  func (*rpcSuite) TestServerRequestWhenNotServing(c *gc.C) {
  1100  	srvRoot := &Root{}
  1101  	client, srvDone, _, _ := newRPCClientServer(c, srvRoot, nil, true)
  1102  	defer closeClient(c, client, srvDone)
  1103  	var r int64val
  1104  	err := client.Call(rpc.Request{"CallbackMethods", 0, "", "Factorial"}, int64val{12}, &r)
  1105  	c.Assert(err, gc.ErrorMatches, "request error: request error: no service")
  1106  }
  1107  
  1108  func (*rpcSuite) TestChangeAPI(c *gc.C) {
  1109  	srvRoot := &Root{}
  1110  	client, srvDone, _, _ := newRPCClientServer(c, srvRoot, nil, true)
  1111  	defer closeClient(c, client, srvDone)
  1112  	var s stringVal
  1113  	err := client.Call(rpc.Request{"NewlyAvailable", 0, "", "NewMethod"}, nil, &s)
  1114  	c.Assert(err, gc.ErrorMatches, `request error: unknown object type "NewlyAvailable" \(not implemented\)`)
  1115  	err = client.Call(rpc.Request{"ChangeAPIMethods", 0, "", "ChangeAPI"}, nil, nil)
  1116  	c.Assert(err, jc.ErrorIsNil)
  1117  	err = client.Call(rpc.Request{"ChangeAPIMethods", 0, "", "ChangeAPI"}, nil, nil)
  1118  	c.Assert(err, gc.ErrorMatches, `request error: unknown object type "ChangeAPIMethods" \(not implemented\)`)
  1119  	err = client.Call(rpc.Request{"NewlyAvailable", 0, "", "NewMethod"}, nil, &s)
  1120  	c.Assert(err, jc.ErrorIsNil)
  1121  	c.Assert(s, gc.Equals, stringVal{"new method result"})
  1122  }
  1123  
  1124  func (*rpcSuite) TestChangeAPIToNil(c *gc.C) {
  1125  	srvRoot := &Root{}
  1126  	client, srvDone, _, _ := newRPCClientServer(c, srvRoot, nil, true)
  1127  	defer closeClient(c, client, srvDone)
  1128  
  1129  	err := client.Call(rpc.Request{"ChangeAPIMethods", 0, "", "RemoveAPI"}, nil, nil)
  1130  	c.Assert(err, jc.ErrorIsNil)
  1131  
  1132  	err = client.Call(rpc.Request{"ChangeAPIMethods", 0, "", "RemoveAPI"}, nil, nil)
  1133  	c.Assert(err, gc.ErrorMatches, "request error: no service")
  1134  }
  1135  
  1136  func (*rpcSuite) TestChangeAPIWhileServingRequest(c *gc.C) {
  1137  	ready := make(chan struct{})
  1138  	done := make(chan error)
  1139  	srvRoot := &Root{
  1140  		delayed: map[string]*DelayedMethods{
  1141  			"1": {ready: ready, doneError: done},
  1142  		},
  1143  	}
  1144  	transform := func(err error) error {
  1145  		return fmt.Errorf("transformed: %v", err)
  1146  	}
  1147  	client, srvDone, _, _ := newRPCClientServer(c, srvRoot, transform, true)
  1148  	defer closeClient(c, client, srvDone)
  1149  
  1150  	result := make(chan error)
  1151  	go func() {
  1152  		result <- client.Call(rpc.Request{"DelayedMethods", 0, "1", "Delay"}, nil, nil)
  1153  	}()
  1154  	chanRead(c, ready, "method ready")
  1155  
  1156  	err := client.Call(rpc.Request{"ChangeAPIMethods", 0, "", "ChangeAPI"}, nil, nil)
  1157  	c.Assert(err, jc.ErrorIsNil)
  1158  
  1159  	// Ensure that not only does the request in progress complete,
  1160  	// but that the original transformErrors function is called.
  1161  	done <- fmt.Errorf("an error")
  1162  	select {
  1163  	case r := <-result:
  1164  		c.Assert(r, gc.ErrorMatches, "request error: transformed: an error")
  1165  	case <-time.After(3 * time.Second):
  1166  		c.Fatalf("timeout on channel read")
  1167  	}
  1168  }
  1169  
  1170  func chanReadError(c *gc.C, ch <-chan error, what string) error {
  1171  	select {
  1172  	case e := <-ch:
  1173  		return e
  1174  	case <-time.After(3 * time.Second):
  1175  		c.Fatalf("timeout on channel read %s", what)
  1176  	}
  1177  	panic("unreachable")
  1178  }
  1179  
  1180  // newRPCClientServer starts an RPC server serving a connection from a
  1181  // single client.  When the server has finished serving the connection,
  1182  // it sends a value on the returned channel.
  1183  // If bidir is true, requests can flow in both directions.
  1184  func newRPCClientServer(c *gc.C, root interface{}, tfErr func(error) error, bidir bool) (client *rpc.Conn, srvDone chan error, clientNotifier, serverNotifier *notifier) {
  1185  	l, err := net.Listen("tcp", "127.0.0.1:0")
  1186  	c.Assert(err, jc.ErrorIsNil)
  1187  
  1188  	srvDone = make(chan error, 1)
  1189  	clientNotifier = new(notifier)
  1190  	serverNotifier = new(notifier)
  1191  	go func() {
  1192  		conn, err := l.Accept()
  1193  		if err != nil {
  1194  			srvDone <- nil
  1195  			return
  1196  		}
  1197  		defer l.Close()
  1198  		role := roleServer
  1199  		if bidir {
  1200  			role = roleBoth
  1201  		}
  1202  		rpcConn := rpc.NewConn(NewJSONCodec(conn, role), serverNotifier)
  1203  		if custroot, ok := root.(*CustomMethodFinder); ok {
  1204  			rpcConn.ServeFinder(custroot, tfErr)
  1205  			custroot.root.conn = rpcConn
  1206  		} else {
  1207  			rpcConn.Serve(root, tfErr)
  1208  		}
  1209  		if root, ok := root.(*Root); ok {
  1210  			root.conn = rpcConn
  1211  		}
  1212  		rpcConn.Start()
  1213  		<-rpcConn.Dead()
  1214  		srvDone <- rpcConn.Close()
  1215  	}()
  1216  	conn, err := net.Dial("tcp", l.Addr().String())
  1217  	c.Assert(err, jc.ErrorIsNil)
  1218  	role := roleClient
  1219  	if bidir {
  1220  		role = roleBoth
  1221  	}
  1222  	client = rpc.NewConn(NewJSONCodec(conn, role), clientNotifier)
  1223  	client.Start()
  1224  	return client, srvDone, clientNotifier, serverNotifier
  1225  }
  1226  
  1227  func closeClient(c *gc.C, client *rpc.Conn, srvDone <-chan error) {
  1228  	err := client.Close()
  1229  	c.Assert(err, jc.ErrorIsNil)
  1230  	err = chanReadError(c, srvDone, "server done")
  1231  	c.Assert(err, jc.ErrorIsNil)
  1232  }
  1233  
  1234  type encoder interface {
  1235  	Encode(e interface{}) error
  1236  }
  1237  
  1238  type decoder interface {
  1239  	Decode(e interface{}) error
  1240  }
  1241  
  1242  // testCodec wraps an rpc.Codec with extra error checking code.
  1243  type testCodec struct {
  1244  	role connRole
  1245  	rpc.Codec
  1246  }
  1247  
  1248  func (c *testCodec) WriteMessage(hdr *rpc.Header, x interface{}) error {
  1249  	if reflect.ValueOf(x).Kind() != reflect.Struct {
  1250  		panic(fmt.Errorf("WriteRequest bad param; want struct got %T (%#v)", x, x))
  1251  	}
  1252  	if c.role != roleBoth && hdr.IsRequest() != (c.role == roleClient) {
  1253  		panic(fmt.Errorf("codec role %v; header wrong type %#v", c.role, hdr))
  1254  	}
  1255  	logger.Infof("send header: %#v; body: %#v", hdr, x)
  1256  	return c.Codec.WriteMessage(hdr, x)
  1257  }
  1258  
  1259  func (c *testCodec) ReadHeader(hdr *rpc.Header) error {
  1260  	err := c.Codec.ReadHeader(hdr)
  1261  	if err != nil {
  1262  		return err
  1263  	}
  1264  	logger.Infof("got header %#v", hdr)
  1265  	if c.role != roleBoth && hdr.IsRequest() == (c.role == roleClient) {
  1266  		panic(fmt.Errorf("codec role %v; read wrong type %#v", c.role, hdr))
  1267  	}
  1268  	return nil
  1269  }
  1270  
  1271  func (c *testCodec) ReadBody(r interface{}, isRequest bool) error {
  1272  	if v := reflect.ValueOf(r); v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
  1273  		panic(fmt.Errorf("ReadResponseBody bad destination; want *struct got %T", r))
  1274  	}
  1275  	if c.role != roleBoth && isRequest == (c.role == roleClient) {
  1276  		panic(fmt.Errorf("codec role %v; read wrong body type %#v", c.role, r))
  1277  	}
  1278  	// Note: this will need to change if we want to test a non-JSON codec.
  1279  	var m json.RawMessage
  1280  	err := c.Codec.ReadBody(&m, isRequest)
  1281  	if err != nil {
  1282  		return err
  1283  	}
  1284  	logger.Infof("got response body: %q", m)
  1285  	err = json.Unmarshal(m, r)
  1286  	logger.Infof("unmarshalled into %#v", r)
  1287  	return err
  1288  }
  1289  
  1290  type connRole string
  1291  
  1292  const (
  1293  	roleBoth   connRole = "both"
  1294  	roleClient connRole = "client"
  1295  	roleServer connRole = "server"
  1296  )
  1297  
  1298  func NewJSONCodec(c net.Conn, role connRole) rpc.Codec {
  1299  	return &testCodec{
  1300  		role:  role,
  1301  		Codec: jsoncodec.NewNet(c),
  1302  	}
  1303  }
  1304  
  1305  type requestEvent struct {
  1306  	hdr  rpc.Header
  1307  	body interface{}
  1308  }
  1309  
  1310  type replyEvent struct {
  1311  	req  rpc.Request
  1312  	hdr  rpc.Header
  1313  	body interface{}
  1314  }
  1315  
  1316  type notifier struct {
  1317  	mu             sync.Mutex
  1318  	serverRequests []requestEvent
  1319  	serverReplies  []replyEvent
  1320  	clientRequests []requestEvent
  1321  	clientReplies  []replyEvent
  1322  }
  1323  
  1324  func (n *notifier) reset() {
  1325  	n.mu.Lock()
  1326  	defer n.mu.Unlock()
  1327  	n.serverRequests = nil
  1328  	n.serverReplies = nil
  1329  	n.clientRequests = nil
  1330  	n.clientReplies = nil
  1331  }
  1332  
  1333  func (n *notifier) ServerRequest(hdr *rpc.Header, body interface{}) {
  1334  	n.mu.Lock()
  1335  	defer n.mu.Unlock()
  1336  	n.serverRequests = append(n.serverRequests, requestEvent{
  1337  		hdr:  *hdr,
  1338  		body: body,
  1339  	})
  1340  }
  1341  
  1342  func (n *notifier) ServerReply(req rpc.Request, hdr *rpc.Header, body interface{}, timeSpent time.Duration) {
  1343  	n.mu.Lock()
  1344  	defer n.mu.Unlock()
  1345  	n.serverReplies = append(n.serverReplies, replyEvent{
  1346  		req:  req,
  1347  		hdr:  *hdr,
  1348  		body: body,
  1349  	})
  1350  }
  1351  
  1352  func (n *notifier) ClientRequest(hdr *rpc.Header, body interface{}) {
  1353  	n.mu.Lock()
  1354  	defer n.mu.Unlock()
  1355  	n.clientRequests = append(n.clientRequests, requestEvent{
  1356  		hdr:  *hdr,
  1357  		body: body,
  1358  	})
  1359  }
  1360  
  1361  func (n *notifier) ClientReply(req rpc.Request, hdr *rpc.Header, body interface{}) {
  1362  	n.mu.Lock()
  1363  	defer n.mu.Unlock()
  1364  	n.clientReplies = append(n.clientReplies, replyEvent{
  1365  		req:  req,
  1366  		hdr:  *hdr,
  1367  		body: body,
  1368  	})
  1369  }