示例#1
0
func (*reflectSuite) TestValueOf(c *gc.C) {
	v := rpcreflect.ValueOf(reflect.ValueOf(nil))
	c.Check(v.IsValid(), jc.IsFalse)
	c.Check(func() { v.FindMethod("foo", 0, "bar") }, gc.PanicMatches, "FindMethod 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) TestFindMethod(c *gc.C) {
	// FindMethod 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.FindMethod("foo", 0, "bar")
	c.Assert(err, gc.ErrorMatches, `unknown object type "foo"`)
	c.Assert(err, gc.FitsTypeOf, (*rpcreflect.CallNotImplementedError)(nil))
	c.Assert(m, gc.IsNil)

	m, err = v.FindMethod("SimpleMethods", 0, "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.IsNil)

	m, err = v.FindMethod("SimpleMethods", 0, "Call1r1e")
	c.Assert(err, jc.ErrorIsNil)
	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, jc.ErrorIsNil)
	c.Assert(ret.Interface(), gc.Equals, stringVal{"Call1r1e ret"})
}
示例#3
0
文件: server.go 项目: bac/juju
// 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() {
		conn.serve(rootValue, transformErrors)
	} else {
		conn.serve(nil, transformErrors)
	}
}
示例#4
0
文件: root_test.go 项目: imoapps/juju
func (s *errRootSuite) TestErrorRootViaRPC(c *gc.C) {
	origErr := fmt.Errorf("my custom error")
	errRoot := apiserver.NewErrRoot(origErr)
	val := rpcreflect.ValueOf(reflect.ValueOf(errRoot))
	caller, err := val.FindMethod("Admin", 0, "Login")
	c.Assert(err, jc.ErrorIsNil)
	resp, err := caller.Call("", reflect.Value{})
	c.Check(err, gc.Equals, origErr)
	c.Check(resp.IsValid(), jc.IsFalse)
}
示例#5
0
文件: server.go 项目: rogpeppe/juju
// 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
}
示例#6
0
文件: fakeapi.go 项目: bac/juju
func (srv *Server) serveConn(wsConn *websocket.Conn, modelUUID string) {
	codec := jsoncodec.NewWebsocket(wsConn)
	conn := rpc.NewConn(codec, &fakeobserver.Instance{})

	root := allVersions{
		rpcreflect.ValueOf(reflect.ValueOf(srv.newRoot(modelUUID))),
	}
	conn.ServeRoot(root, nil)
	conn.Start()
	<-conn.Dead()
	conn.Close()
}
示例#7
0
文件: root.go 项目: bac/juju
func (r *anonRoot) FindMethod(rootName string, version int, methodName string) (rpcreflect.MethodCaller, error) {
	if rootName != "Admin" {
		return nil, &rpcreflect.CallNotImplementedError{
			RootMethod: rootName,
			Version:    version,
		}
	}
	if api, ok := r.adminAPIs[version]; ok {
		return rpcreflect.ValueOf(reflect.ValueOf(api)).FindMethod(rootName, 0, methodName)
	}
	return nil, &rpc.RequestError{
		Code:    params.CodeNotSupported,
		Message: "this version of Juju does not support login from old clients",
	}
}
示例#8
0
func (*reflectSuite) TestFindMethodRefusesVersionsNot0(c *gc.C) {
	root := &Root{
		simple: make(map[string]*SimpleMethods),
	}
	root.simple["a99"] = &SimpleMethods{root: root, id: "a99"}
	v := rpcreflect.ValueOf(reflect.ValueOf(root))

	m, err := v.FindMethod("SimpleMethods", 0, "Call1r1e")
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(m.ParamsType(), gc.Equals, reflect.TypeOf(stringVal{}))
	c.Assert(m.ResultType(), gc.Equals, reflect.TypeOf(stringVal{}))

	m, err = v.FindMethod("SimpleMethods", 1, "Call1r1e")
	c.Assert(err, gc.FitsTypeOf, (*rpcreflect.CallNotImplementedError)(nil))
	c.Assert(err, gc.ErrorMatches, `unknown version \(1\) of interface "SimpleMethods"`)
}
示例#9
0
文件: root.go 项目: pmatulis/juju
func (r *anonRoot) FindMethod(rootName string, version int, methodName string) (rpcreflect.MethodCaller, error) {
	if rootName != "Admin" {
		return nil, &rpcreflect.CallNotImplementedError{
			RootMethod: rootName,
			Version:    version,
		}
	}
	if api, ok := r.adminApis[version]; ok {
		return rpcreflect.ValueOf(reflect.ValueOf(api)).FindMethod(rootName, 0, methodName)
	}
	return nil, &rpcreflect.CallNotImplementedError{
		RootMethod: rootName,
		Method:     methodName,
		Version:    version,
	}
}