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 }