diff options
author | Ian Lance Taylor <iant@golang.org> | 2017-09-14 17:11:35 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-09-14 17:11:35 +0000 |
commit | bc998d034f45d1828a8663b2eed928faf22a7d01 (patch) | |
tree | 8d262a22ca7318f4bcd64269fe8fe9e45bcf8d0f /libgo/go/net/rpc | |
parent | a41a6142df74219f596e612d3a7775f68ca6e96f (diff) | |
download | gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.zip gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.tar.gz gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.tar.bz2 |
libgo: update to go1.9
Reviewed-on: https://go-review.googlesource.com/63753
From-SVN: r252767
Diffstat (limited to 'libgo/go/net/rpc')
-rw-r--r-- | libgo/go/net/rpc/debug.go | 23 | ||||
-rw-r--r-- | libgo/go/net/rpc/jsonrpc/all_test.go | 58 | ||||
-rw-r--r-- | libgo/go/net/rpc/jsonrpc/client.go | 3 | ||||
-rw-r--r-- | libgo/go/net/rpc/server.go | 36 | ||||
-rw-r--r-- | libgo/go/net/rpc/server_test.go | 67 |
5 files changed, 153 insertions, 34 deletions
diff --git a/libgo/go/net/rpc/debug.go b/libgo/go/net/rpc/debug.go index 98b2c1c..a1d799f 100644 --- a/libgo/go/net/rpc/debug.go +++ b/libgo/go/net/rpc/debug.go @@ -71,20 +71,17 @@ type debugHTTP struct { // Runs at /debug/rpc func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) { // Build a sorted version of the data. - var services = make(serviceArray, len(server.serviceMap)) - i := 0 - server.mu.Lock() - for sname, service := range server.serviceMap { - services[i] = debugService{service, sname, make(methodArray, len(service.method))} - j := 0 - for mname, method := range service.method { - services[i].Method[j] = debugMethod{method, mname} - j++ + var services serviceArray + server.serviceMap.Range(func(snamei, svci interface{}) bool { + svc := svci.(*service) + ds := debugService{svc, snamei.(string), make(methodArray, 0, len(svc.method))} + for mname, method := range svc.method { + ds.Method = append(ds.Method, debugMethod{method, mname}) } - sort.Sort(services[i].Method) - i++ - } - server.mu.Unlock() + sort.Sort(ds.Method) + services = append(services, ds) + return true + }) sort.Sort(services) err := debug.Execute(w, services) if err != nil { diff --git a/libgo/go/net/rpc/jsonrpc/all_test.go b/libgo/go/net/rpc/jsonrpc/all_test.go index b811d3c..bbb8eb0 100644 --- a/libgo/go/net/rpc/jsonrpc/all_test.go +++ b/libgo/go/net/rpc/jsonrpc/all_test.go @@ -13,6 +13,7 @@ import ( "io/ioutil" "net" "net/rpc" + "reflect" "strings" "testing" ) @@ -55,8 +56,26 @@ func (t *Arith) Error(args *Args, reply *Reply) error { panic("ERROR") } +type BuiltinTypes struct{} + +func (BuiltinTypes) Map(i int, reply *map[int]int) error { + (*reply)[i] = i + return nil +} + +func (BuiltinTypes) Slice(i int, reply *[]int) error { + *reply = append(*reply, i) + return nil +} + +func (BuiltinTypes) Array(i int, reply *[1]int) error { + (*reply)[0] = i + return nil +} + func init() { rpc.Register(new(Arith)) + rpc.Register(BuiltinTypes{}) } func TestServerNoParams(t *testing.T) { @@ -182,6 +201,45 @@ func TestClient(t *testing.T) { } } +func TestBuiltinTypes(t *testing.T) { + cli, srv := net.Pipe() + go ServeConn(srv) + + client := NewClient(cli) + defer client.Close() + + // Map + arg := 7 + replyMap := map[int]int{} + err := client.Call("BuiltinTypes.Map", arg, &replyMap) + if err != nil { + t.Errorf("Map: expected no error but got string %q", err.Error()) + } + if replyMap[arg] != arg { + t.Errorf("Map: expected %d got %d", arg, replyMap[arg]) + } + + // Slice + replySlice := []int{} + err = client.Call("BuiltinTypes.Slice", arg, &replySlice) + if err != nil { + t.Errorf("Slice: expected no error but got string %q", err.Error()) + } + if e := []int{arg}; !reflect.DeepEqual(replySlice, e) { + t.Errorf("Slice: expected %v got %v", e, replySlice) + } + + // Array + replyArray := [1]int{} + err = client.Call("BuiltinTypes.Array", arg, &replyArray) + if err != nil { + t.Errorf("Array: expected no error but got string %q", err.Error()) + } + if e := [1]int{arg}; !reflect.DeepEqual(replyArray, e) { + t.Errorf("Array: expected %v got %v", e, replyArray) + } +} + func TestMalformedInput(t *testing.T) { cli, srv := net.Pipe() go cli.Write([]byte(`{id:1}`)) // invalid json diff --git a/libgo/go/net/rpc/jsonrpc/client.go b/libgo/go/net/rpc/jsonrpc/client.go index da1b816..e6359be 100644 --- a/libgo/go/net/rpc/jsonrpc/client.go +++ b/libgo/go/net/rpc/jsonrpc/client.go @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package jsonrpc implements a JSON-RPC ClientCodec and ServerCodec +// Package jsonrpc implements a JSON-RPC 1.0 ClientCodec and ServerCodec // for the rpc package. +// For JSON-RPC 2.0 support, see https://godoc.org/?q=json-rpc+2.0 package jsonrpc import ( diff --git a/libgo/go/net/rpc/server.go b/libgo/go/net/rpc/server.go index 18ea629..29aae7e 100644 --- a/libgo/go/net/rpc/server.go +++ b/libgo/go/net/rpc/server.go @@ -187,8 +187,7 @@ type Response struct { // Server represents an RPC Server. type Server struct { - mu sync.RWMutex // protects the serviceMap - serviceMap map[string]*service + serviceMap sync.Map // map[string]*service reqLock sync.Mutex // protects freeReq freeReq *Request respLock sync.Mutex // protects freeResp @@ -197,7 +196,7 @@ type Server struct { // NewServer returns a new Server. func NewServer() *Server { - return &Server{serviceMap: make(map[string]*service)} + return &Server{} } // DefaultServer is the default instance of *Server. @@ -240,11 +239,6 @@ func (server *Server) RegisterName(name string, rcvr interface{}) error { } func (server *Server) register(rcvr interface{}, name string, useName bool) error { - server.mu.Lock() - defer server.mu.Unlock() - if server.serviceMap == nil { - server.serviceMap = make(map[string]*service) - } s := new(service) s.typ = reflect.TypeOf(rcvr) s.rcvr = reflect.ValueOf(rcvr) @@ -262,9 +256,6 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro log.Print(s) return errors.New(s) } - if _, present := server.serviceMap[sname]; present { - return errors.New("rpc: service already defined: " + sname) - } s.name = sname // Install the methods @@ -283,7 +274,10 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro log.Print(str) return errors.New(str) } - server.serviceMap[s.name] = s + + if _, dup := server.serviceMap.LoadOrStore(sname, s); dup { + return errors.New("rpc: service already defined: " + sname) + } return nil } @@ -571,10 +565,17 @@ func (server *Server) readRequest(codec ServerCodec) (service *service, mtype *m } replyv = reflect.New(mtype.ReplyType.Elem()) + + switch mtype.ReplyType.Elem().Kind() { + case reflect.Map: + replyv.Elem().Set(reflect.MakeMap(mtype.ReplyType.Elem())) + case reflect.Slice: + replyv.Elem().Set(reflect.MakeSlice(mtype.ReplyType.Elem(), 0, 0)) + } return } -func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mtype *methodType, req *Request, keepReading bool, err error) { +func (server *Server) readRequestHeader(codec ServerCodec) (svc *service, mtype *methodType, req *Request, keepReading bool, err error) { // Grab the request header. req = server.getRequest() err = codec.ReadRequestHeader(req) @@ -600,14 +601,13 @@ func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mt methodName := req.ServiceMethod[dot+1:] // Look up the request. - server.mu.RLock() - service = server.serviceMap[serviceName] - server.mu.RUnlock() - if service == nil { + svci, ok := server.serviceMap.Load(serviceName) + if !ok { err = errors.New("rpc: can't find service " + req.ServiceMethod) return } - mtype = service.method[methodName] + svc = svci.(*service) + mtype = svc.method[methodName] if mtype == nil { err = errors.New("rpc: can't find method " + req.ServiceMethod) } diff --git a/libgo/go/net/rpc/server_test.go b/libgo/go/net/rpc/server_test.go index 8369c9d..fb97f82 100644 --- a/libgo/go/net/rpc/server_test.go +++ b/libgo/go/net/rpc/server_test.go @@ -11,6 +11,7 @@ import ( "log" "net" "net/http/httptest" + "reflect" "runtime" "strings" "sync" @@ -85,6 +86,24 @@ type Embed struct { hidden } +type BuiltinTypes struct{} + +func (BuiltinTypes) Map(args *Args, reply *map[int]int) error { + (*reply)[args.A] = args.B + return nil +} + +func (BuiltinTypes) Slice(args *Args, reply *[]int) error { + *reply = append(*reply, args.A, args.B) + return nil +} + +func (BuiltinTypes) Array(args *Args, reply *[2]int) error { + (*reply)[0] = args.A + (*reply)[1] = args.B + return nil +} + func listenTCP() (net.Listener, string) { l, e := net.Listen("tcp", "127.0.0.1:0") // any available address if e != nil { @@ -97,6 +116,7 @@ func startServer() { Register(new(Arith)) Register(new(Embed)) RegisterName("net.rpc.Arith", new(Arith)) + Register(BuiltinTypes{}) var l net.Listener l, serverAddr = listenTCP() @@ -326,6 +346,49 @@ func testHTTPRPC(t *testing.T, path string) { } } +func TestBuiltinTypes(t *testing.T) { + once.Do(startServer) + + client, err := DialHTTP("tcp", httpServerAddr) + if err != nil { + t.Fatal("dialing", err) + } + defer client.Close() + + // Map + args := &Args{7, 8} + replyMap := map[int]int{} + err = client.Call("BuiltinTypes.Map", args, &replyMap) + if err != nil { + t.Errorf("Map: expected no error but got string %q", err.Error()) + } + if replyMap[args.A] != args.B { + t.Errorf("Map: expected %d got %d", args.B, replyMap[args.A]) + } + + // Slice + args = &Args{7, 8} + replySlice := []int{} + err = client.Call("BuiltinTypes.Slice", args, &replySlice) + if err != nil { + t.Errorf("Slice: expected no error but got string %q", err.Error()) + } + if e := []int{args.A, args.B}; !reflect.DeepEqual(replySlice, e) { + t.Errorf("Slice: expected %v got %v", e, replySlice) + } + + // Array + args = &Args{7, 8} + replyArray := [2]int{} + err = client.Call("BuiltinTypes.Array", args, &replyArray) + if err != nil { + t.Errorf("Array: expected no error but got string %q", err.Error()) + } + if e := [2]int{args.A, args.B}; !reflect.DeepEqual(replyArray, e) { + t.Errorf("Array: expected %v got %v", e, replyArray) + } +} + // CodecEmulator provides a client-like api and a ServerCodec interface. // Can be used to test ServeRequest. type CodecEmulator struct { @@ -619,13 +682,13 @@ func TestErrorAfterClientClose(t *testing.T) { // Tests the fix to issue 11221. Without the fix, this loops forever or crashes. func TestAcceptExitAfterListenerClose(t *testing.T) { - newServer = NewServer() + newServer := NewServer() newServer.Register(new(Arith)) newServer.RegisterName("net.rpc.Arith", new(Arith)) newServer.RegisterName("newServer.Arith", new(Arith)) var l net.Listener - l, newServerAddr = listenTCP() + l, _ = listenTCP() l.Close() newServer.Accept(l) } |