github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/rpc/reflect_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  	"context"
     8  	"reflect"
     9  
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/rpc/rpcreflect"
    14  	"github.com/juju/juju/testing"
    15  )
    16  
    17  // We test rpcreflect in this package, so that the
    18  // tests can all share the same testing Root type.
    19  
    20  type reflectSuite struct {
    21  	testing.BaseSuite
    22  }
    23  
    24  var _ = gc.Suite(&reflectSuite{})
    25  
    26  func (*reflectSuite) TestTypeOf(c *gc.C) {
    27  	rtype := rpcreflect.TypeOf(reflect.TypeOf(&Root{}))
    28  	c.Assert(rtype.DiscardedMethods(), gc.DeepEquals, []string{
    29  		"Discard1",
    30  		"Discard2",
    31  		"Discard3",
    32  	})
    33  	expect := map[string]reflect.Type{
    34  		"CallbackMethods":  reflect.TypeOf(&CallbackMethods{}),
    35  		"ChangeAPIMethods": reflect.TypeOf(&ChangeAPIMethods{}),
    36  		"DelayedMethods":   reflect.TypeOf(&DelayedMethods{}),
    37  		"ErrorMethods":     reflect.TypeOf(&ErrorMethods{}),
    38  		"InterfaceMethods": reflect.TypeOf((*InterfaceMethods)(nil)).Elem(),
    39  		"SimpleMethods":    reflect.TypeOf(&SimpleMethods{}),
    40  		"ContextMethods":   reflect.TypeOf(&ContextMethods{}),
    41  	}
    42  	c.Assert(rtype.MethodNames(), gc.HasLen, len(expect))
    43  	for name, expectGoType := range expect {
    44  		m, err := rtype.Method(name)
    45  		c.Assert(err, jc.ErrorIsNil)
    46  		c.Assert(m, gc.NotNil)
    47  		c.Assert(m.Call, gc.NotNil)
    48  		c.Assert(m.ObjType, gc.Equals, rpcreflect.ObjTypeOf(expectGoType))
    49  		c.Assert(m.ObjType.GoType(), gc.Equals, expectGoType)
    50  	}
    51  	m, err := rtype.Method("not found")
    52  	c.Assert(err, gc.Equals, rpcreflect.ErrMethodNotFound)
    53  	c.Assert(m, gc.DeepEquals, rpcreflect.RootMethod{})
    54  }
    55  
    56  func (*reflectSuite) TestObjTypeOf(c *gc.C) {
    57  	objType := rpcreflect.ObjTypeOf(reflect.TypeOf(&SimpleMethods{}))
    58  	c.Check(objType.DiscardedMethods(), gc.DeepEquals, []string{
    59  		"Discard1",
    60  		"Discard2",
    61  		"Discard3",
    62  		"Discard4",
    63  	})
    64  	expect := map[string]*rpcreflect.ObjMethod{
    65  		"SliceArg": {
    66  			Params: reflect.TypeOf(struct{ X []string }{}),
    67  			Result: reflect.TypeOf(stringVal{}),
    68  		},
    69  	}
    70  	for narg := 0; narg < 2; narg++ {
    71  		for nret := 0; nret < 2; nret++ {
    72  			for nerr := 0; nerr < 2; nerr++ {
    73  				retErr := nerr != 0
    74  				var m rpcreflect.ObjMethod
    75  				if narg > 0 {
    76  					m.Params = reflect.TypeOf(stringVal{})
    77  				}
    78  				if nret > 0 {
    79  					m.Result = reflect.TypeOf(stringVal{})
    80  				}
    81  				expect[callName(narg, nret, retErr)] = &m
    82  			}
    83  		}
    84  	}
    85  	c.Assert(objType.MethodNames(), gc.HasLen, len(expect))
    86  	for name, expectMethod := range expect {
    87  		m, err := objType.Method(name)
    88  		c.Check(err, jc.ErrorIsNil)
    89  		c.Assert(m, gc.NotNil)
    90  		c.Check(m.Call, gc.NotNil)
    91  		c.Check(m.Params, gc.Equals, expectMethod.Params)
    92  		c.Check(m.Result, gc.Equals, expectMethod.Result)
    93  	}
    94  	m, err := objType.Method("not found")
    95  	c.Check(err, gc.Equals, rpcreflect.ErrMethodNotFound)
    96  	c.Check(m, gc.DeepEquals, rpcreflect.ObjMethod{})
    97  }
    98  
    99  func (*reflectSuite) TestValueOf(c *gc.C) {
   100  	v := rpcreflect.ValueOf(reflect.ValueOf(nil))
   101  	c.Check(v.IsValid(), jc.IsFalse)
   102  	c.Check(func() { v.FindMethod("foo", 0, "bar") }, gc.PanicMatches, "FindMethod called on invalid Value")
   103  
   104  	root := &Root{}
   105  	v = rpcreflect.ValueOf(reflect.ValueOf(root))
   106  	c.Check(v.IsValid(), jc.IsTrue)
   107  	c.Check(v.GoValue().Interface(), gc.Equals, root)
   108  }
   109  
   110  func (*reflectSuite) TestFindMethod(c *gc.C) {
   111  	// FindMethod is actually extensively tested because it's
   112  	// used in the implementation of the rpc server,
   113  	// so just a simple sanity check test here.
   114  	root := &Root{
   115  		simple: make(map[string]*SimpleMethods),
   116  	}
   117  	root.simple["a99"] = &SimpleMethods{root: root, id: "a99"}
   118  	v := rpcreflect.ValueOf(reflect.ValueOf(root))
   119  
   120  	m, err := v.FindMethod("foo", 0, "bar")
   121  	c.Assert(err, gc.ErrorMatches, `unknown object type "foo"`)
   122  	c.Assert(err, gc.FitsTypeOf, (*rpcreflect.CallNotImplementedError)(nil))
   123  	c.Assert(m, gc.IsNil)
   124  
   125  	m, err = v.FindMethod("SimpleMethods", 0, "bar")
   126  	c.Assert(err, gc.ErrorMatches, "no such request - method SimpleMethods.bar is not implemented")
   127  	c.Assert(err, gc.FitsTypeOf, (*rpcreflect.CallNotImplementedError)(nil))
   128  	c.Assert(m, gc.IsNil)
   129  
   130  	m, err = v.FindMethod("SimpleMethods", 0, "Call1r1e")
   131  	c.Assert(err, jc.ErrorIsNil)
   132  	c.Assert(m.ParamsType(), gc.Equals, reflect.TypeOf(stringVal{}))
   133  	c.Assert(m.ResultType(), gc.Equals, reflect.TypeOf(stringVal{}))
   134  
   135  	ret, err := m.Call(context.TODO(), "a99", reflect.ValueOf(stringVal{"foo"}))
   136  	c.Assert(err, jc.ErrorIsNil)
   137  	c.Assert(ret.Interface(), gc.Equals, stringVal{"Call1r1e ret"})
   138  }
   139  
   140  func (*reflectSuite) TestFindMethodAcceptsAnyVersion(c *gc.C) {
   141  	root := &Root{
   142  		simple: make(map[string]*SimpleMethods),
   143  	}
   144  	root.simple["a99"] = &SimpleMethods{root: root, id: "a99"}
   145  	v := rpcreflect.ValueOf(reflect.ValueOf(root))
   146  
   147  	m, err := v.FindMethod("SimpleMethods", 0, "Call1r1e")
   148  	c.Assert(err, jc.ErrorIsNil)
   149  	c.Assert(m.ParamsType(), gc.Equals, reflect.TypeOf(stringVal{}))
   150  	c.Assert(m.ResultType(), gc.Equals, reflect.TypeOf(stringVal{}))
   151  
   152  	m, err = v.FindMethod("SimpleMethods", 1, "Call1r1e")
   153  	c.Assert(err, jc.ErrorIsNil)
   154  	c.Assert(m.ParamsType(), gc.Equals, reflect.TypeOf(stringVal{}))
   155  	c.Assert(m.ResultType(), gc.Equals, reflect.TypeOf(stringVal{}))
   156  }