예제 #1
0
func (*reflectSuite) TestValueOf(c *gc.C) {
	v := rpcreflect.ValueOf(reflect.ValueOf(nil))
	c.Check(v.IsValid(), jc.IsFalse)
	c.Check(func() { v.MethodCaller("foo", "bar") }, gc.PanicMatches, "MethodCaller called on invalid Value")

	root := &Root{}
	v = rpcreflect.ValueOf(reflect.ValueOf(root))
	c.Check(v.IsValid(), jc.IsTrue)
	c.Check(v.GoValue().Interface(), gc.Equals, root)
}
예제 #2
0
func (*reflectSuite) TestMethodCaller(c *gc.C) {
	// MethodCaller is actually extensively tested because it's
	// used in the implementation of the rpc server,
	// so just a simple sanity check test here.
	root := &Root{
		simple: make(map[string]*SimpleMethods),
	}
	root.simple["a99"] = &SimpleMethods{root: root, id: "a99"}
	v := rpcreflect.ValueOf(reflect.ValueOf(root))

	m, err := v.MethodCaller("foo", "bar")
	c.Assert(err, gc.ErrorMatches, `unknown object type "foo"`)
	c.Assert(err, gc.FitsTypeOf, (*rpcreflect.CallNotImplementedError)(nil))
	c.Assert(m, gc.DeepEquals, rpcreflect.MethodCaller{})

	m, err = v.MethodCaller("SimpleMethods", "bar")
	c.Assert(err, gc.ErrorMatches, "no such request - method SimpleMethods.bar is not implemented")
	c.Assert(err, gc.FitsTypeOf, (*rpcreflect.CallNotImplementedError)(nil))
	c.Assert(m, gc.DeepEquals, rpcreflect.MethodCaller{})

	m, err = v.MethodCaller("SimpleMethods", "Call1r1e")
	c.Assert(err, gc.IsNil)
	c.Assert(m.ParamsType, gc.Equals, reflect.TypeOf(stringVal{}))
	c.Assert(m.ResultType, gc.Equals, reflect.TypeOf(stringVal{}))

	ret, err := m.Call("a99", reflect.ValueOf(stringVal{"foo"}))
	c.Assert(err, gc.IsNil)
	c.Assert(ret.Interface(), gc.Equals, stringVal{"Call1r1e ret"})
}
예제 #3
0
파일: server.go 프로젝트: jameinel/core
// Serve serves RPC requests on the connection by invoking methods on
// root. Note that it does not start the connection running,
// though it may be called once the connection is already started.
//
// The server executes each client request by calling a method on root
// to obtain an object to act on; then it invokes an method on that
// object with the request parameters, possibly returning some result.
//
// Methods on the root value are of the form:
//
//      M(id string) (O, error)
//
// where M is an exported name, conventionally naming the object type,
// id is some identifier for the object and O is the type of the
// returned object.
//
// Methods defined on O may defined in one of the following forms, where
// T and R must be struct types.
//
//	Method()
//	Method() R
//	Method() (R, error)
//	Method() error
//	Method(T)
//	Method(T) R
//	Method(T) (R, error)
//	Method(T) error
//
// If transformErrors is non-nil, it will be called on all returned
// non-nil errors, for example to transform the errors into ServerErrors
// with specified codes.  There will be a panic if transformErrors
// returns nil.
//
// Serve may be called at any time on a connection to change the
// set of methods being served by the connection. This will have
// no effect on calls that are currently being services.
// If root is nil, the connection will serve no methods.
func (conn *Conn) Serve(root interface{}, transformErrors func(error) error) {
	rootValue := rpcreflect.ValueOf(reflect.ValueOf(root))
	if rootValue.IsValid() && transformErrors == nil {
		transformErrors = func(err error) error { return err }
	}
	conn.mutex.Lock()
	defer conn.mutex.Unlock()
	conn.rootValue = rootValue
	conn.transformErrors = transformErrors
}