// Copyright 2015 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package rpc import ( "context" "encoding/json" "net" "reflect" "testing" "time" ) type Service struct{} type Args struct { S string } func (s *Service) NoArgsRets() { } type Result struct { String string Int int Args *Args } func (s *Service) Echo(str string, i int, args *Args) Result { return Result{str, i, args} } func (s *Service) EchoWithCtx(ctx context.Context, str string, i int, args *Args) Result { return Result{str, i, args} } func (s *Service) Sleep(ctx context.Context, duration time.Duration) { select { case <-time.After(duration): case <-ctx.Done(): } } func (s *Service) Rets() (string, error) { return "", nil } func (s *Service) InvalidRets1() (error, string) { return nil, "" } func (s *Service) InvalidRets2() (string, string) { return "", "" } func (s *Service) InvalidRets3() (string, string, error) { return "", "", nil } func (s *Service) Subscription(ctx context.Context) (*Subscription, error) { return nil, nil } func TestServerRegisterName(t *testing.T) { server := NewServer() service := new(Service) if err := server.RegisterName("calc", service); err != nil { t.Fatalf("%v", err) } if len(server.services) != 2 { t.Fatalf("Expected 2 service entries, got %d", len(server.services)) } svc, ok := server.services["calc"] if !ok { t.Fatalf("Expected service calc to be registered") } if len(svc.callbacks) != 5 { t.Errorf("Expected 5 callbacks for service 'calc', got %d", len(svc.callbacks)) } if len(svc.subscriptions) != 1 { t.Errorf("Expected 1 subscription for service 'calc', got %d", len(svc.subscriptions)) } } func testServerMethodExecution(t *testing.T, method string) { server := NewServer() service := new(Service) if err := server.RegisterName("test", service); err != nil { t.Fatalf("%v", err) } stringArg := "string arg" intArg := 1122 argsArg := &Args{"abcde"} params := []interface{}{stringArg, intArg, argsArg} request := map[string]interface{}{ "id": 12345, "method": "test_" + method, "version": "2.0", "params": params, } clientConn, serverConn := net.Pipe() defer clientConn.Close() go server.ServeCodec(NewJSONCodec(serverConn), OptionMethodInvocation) out := json.NewEncoder(clientConn) in := json.NewDecoder(clientConn) if err := out.Encode(request); err != nil { t.Fatal(err) } response := jsonSuccessResponse{Result: &Result{}} if err := in.Decode(&response); err != nil { t.Fatal(err) } if result, ok := response.Result.(*Result); ok { if result.String != stringArg { t.Errorf("expected %s, got : %s\n", stringArg, result.String) } if result.Int != intArg { t.Errorf("expected %d, got %d\n", intArg, result.Int) } if !reflect.DeepEqual(result.Args, argsArg) { t.Errorf("expected %v, got %v\n", argsArg, result) } } else { t.Fatalf("invalid response: expected *Result - got: %T", response.Result) } } func TestServerMethodExecution(t *testing.T) { testServerMethodExecution(t, "echo") } func TestServerMethodWithCtx(t *testing.T) { testServerMethodExecution(t, "echoWithCtx") }