mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 21:56:43 +00:00
updated tests
This commit is contained in:
parent
d87ba43a5d
commit
b3c89562b9
6 changed files with 221 additions and 20 deletions
|
|
@ -23,8 +23,9 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ func TestJSONRequestParsing(t *testing.T) {
|
||||||
t.Fatalf("%v", err)
|
t.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req := bytes.NewBufferString(`{"id": 1234, "jsonrpc": "2.0", "method": "calc_Add", "params": [11, 22]}`)
|
req := bytes.NewBufferString(`{"id": 1234, "jsonrpc": "2.0", "method": "calc_add", "params": [11, 22]}`)
|
||||||
var str string
|
var str string
|
||||||
reply := bytes.NewBufferString(str)
|
reply := bytes.NewBufferString(str)
|
||||||
rw := &RWC{bufio.NewReadWriter(bufio.NewReader(req), bufio.NewWriter(reply))}
|
rw := &RWC{bufio.NewReadWriter(bufio.NewReader(req), bufio.NewWriter(reply))}
|
||||||
|
|
@ -47,7 +47,7 @@ func TestJSONRequestParsing(t *testing.T) {
|
||||||
t.Fatalf("Expected service 'calc' but got '%s'", requests[0].service)
|
t.Fatalf("Expected service 'calc' but got '%s'", requests[0].service)
|
||||||
}
|
}
|
||||||
|
|
||||||
if requests[0].method != "Add" {
|
if requests[0].method != "add" {
|
||||||
t.Fatalf("Expected method 'Add' but got '%s'", requests[0].method)
|
t.Fatalf("Expected method 'Add' but got '%s'", requests[0].method)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,19 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewServer will create a new server instance with no registered handlers.
|
// NewServer will create a new server instance with no registered handlers.
|
||||||
func NewServer() *Server {
|
func NewServer() *Server {
|
||||||
server := &Server{services: make(serviceRegistry), subscriptions: make(subscriptionRegistry)}
|
server := &Server{services: make(serviceRegistry), subscriptions: make(subscriptionRegistry)}
|
||||||
|
|
||||||
|
// register a default service which will provide meta information about the RPC service such as the services and
|
||||||
|
// methods it offers.
|
||||||
rpcService := &RPCService{server}
|
rpcService := &RPCService{server}
|
||||||
server.RegisterName("rpc", rpcService)
|
server.RegisterName("rpc", rpcService)
|
||||||
|
|
||||||
|
|
@ -87,6 +90,9 @@ func (s *Server) register(rcvr interface{}, name string, useName bool) error {
|
||||||
if !isExported(sname) && !useName {
|
if !isExported(sname) && !useName {
|
||||||
return fmt.Errorf("%s is not exported", sname)
|
return fmt.Errorf("%s is not exported", sname)
|
||||||
}
|
}
|
||||||
|
if !useName {
|
||||||
|
sname = formatName(sname)
|
||||||
|
}
|
||||||
|
|
||||||
// already a previous service register under given sname, merge methods/subscriptions
|
// already a previous service register under given sname, merge methods/subscriptions
|
||||||
if regsvc, present := s.services[sname]; present {
|
if regsvc, present := s.services[sname]; present {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
package v2
|
package v2
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type Service struct{}
|
type Service struct{}
|
||||||
|
|
||||||
|
|
@ -11,7 +17,14 @@ type Args struct {
|
||||||
func (s *Service) NoArgsRets() {
|
func (s *Service) NoArgsRets() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Args(str string, i int, args *Args) {
|
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) Rets() (string, error) {
|
func (s *Service) Rets() (string, error) {
|
||||||
|
|
@ -30,16 +43,46 @@ func (s *Service) InvalidRets3() (string, string, error) {
|
||||||
return "", "", nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) Subscription() (Subscription, error) {
|
||||||
|
return NewSubscription(nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestServerRegister(t *testing.T) {
|
func TestServerRegister(t *testing.T) {
|
||||||
server := NewServer()
|
server := NewServer()
|
||||||
service := new(Service)
|
service := new(Service)
|
||||||
|
|
||||||
|
if err := server.Register(service); err != nil {
|
||||||
|
t.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(server.services) != 2 {
|
||||||
|
t.Fatalf("Expected 2 services entries, got %d", len(server.services))
|
||||||
|
}
|
||||||
|
|
||||||
|
svc, ok := server.services["service"]
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Unable to locate 'service' service after registration")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(svc.callbacks) != 3 {
|
||||||
|
t.Errorf("Expected 3 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 TestServerRegisterName(t *testing.T) {
|
||||||
|
server := NewServer()
|
||||||
|
service := new(Service)
|
||||||
|
|
||||||
if err := server.RegisterName("calc", service); err != nil {
|
if err := server.RegisterName("calc", service); err != nil {
|
||||||
t.Fatalf("%v", err)
|
t.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(server.services) != 1 {
|
if len(server.services) != 2 {
|
||||||
t.Fatalf("Expected 1 service entry but got %d", len(server.services))
|
t.Fatalf("Expected 2 service entries, got %d", len(server.services))
|
||||||
}
|
}
|
||||||
|
|
||||||
svc, ok := server.services["calc"]
|
svc, ok := server.services["calc"]
|
||||||
|
|
@ -48,6 +91,154 @@ func TestServerRegister(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(svc.callbacks) != 3 {
|
if len(svc.callbacks) != 3 {
|
||||||
t.Fatalf("Expected 3 callbacks for service 'calc', got %d", len(svc.callbacks))
|
t.Errorf("Expected 3 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dummy codec used for testing RPC method execution
|
||||||
|
type ServerTestCodec struct {
|
||||||
|
counter int
|
||||||
|
input []byte
|
||||||
|
output string
|
||||||
|
closer chan interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) ReadRequestHeaders() ([]rpcRequest, bool, RPCError) {
|
||||||
|
c.counter += 1
|
||||||
|
|
||||||
|
if c.counter == 1 {
|
||||||
|
var req jsonRequest
|
||||||
|
json.Unmarshal(c.input, &req)
|
||||||
|
return []rpcRequest{rpcRequest{id: req.Id, isPubSub: false, service: "test", method: req.Method, params: req.Payload}}, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// requests are executes in parallel, wait a bit before returning an error so that the previous request has time to
|
||||||
|
// be executed
|
||||||
|
timer := time.NewTimer(time.Duration(2) * time.Second)
|
||||||
|
<-timer.C
|
||||||
|
|
||||||
|
return nil, false, &invalidRequestError{"connection closed"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) ParseRequestArguments(argTypes []reflect.Type, payload interface{}) ([]reflect.Value, RPCError) {
|
||||||
|
|
||||||
|
args, _ := payload.(json.RawMessage)
|
||||||
|
|
||||||
|
argValues := make([]reflect.Value, len(argTypes))
|
||||||
|
params := make([]interface{}, len(argTypes))
|
||||||
|
|
||||||
|
n, err := countArguments(args)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &invalidParamsError{err.Error()}
|
||||||
|
}
|
||||||
|
if n != len(argTypes) {
|
||||||
|
return nil, &invalidParamsError{fmt.Sprintf("insufficient params, want %d have %d", len(argTypes), n)}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, t := range argTypes {
|
||||||
|
if t.Kind() == reflect.Ptr {
|
||||||
|
// values must be pointers for the Unmarshal method, reflect.
|
||||||
|
// Dereference otherwise reflect.New would create **SomeType
|
||||||
|
argValues[i] = reflect.New(t.Elem())
|
||||||
|
params[i] = argValues[i].Interface()
|
||||||
|
|
||||||
|
// when not specified blockNumbers are by default latest (-1)
|
||||||
|
if blockNumber, ok := params[i].(*BlockNumber); ok {
|
||||||
|
*blockNumber = BlockNumber(-1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
argValues[i] = reflect.New(t)
|
||||||
|
params[i] = argValues[i].Interface()
|
||||||
|
|
||||||
|
// when not specified blockNumbers are by default latest (-1)
|
||||||
|
if blockNumber, ok := params[i].(*BlockNumber); ok {
|
||||||
|
*blockNumber = BlockNumber(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(args, ¶ms); err != nil {
|
||||||
|
return nil, &invalidParamsError{err.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert pointers back to values where necessary
|
||||||
|
for i, a := range argValues {
|
||||||
|
if a.Kind() != argTypes[i].Kind() {
|
||||||
|
argValues[i] = reflect.Indirect(argValues[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return argValues, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) CreateResponse(id int64, reply interface{}) interface{} {
|
||||||
|
return &jsonSuccessResponse{Version: jsonRPCVersion, Id: id, Result: reply}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) CreateErrorResponse(id *int64, err RPCError) interface{} {
|
||||||
|
return &jsonErrResponse{Version: jsonRPCVersion, Id: id, Error: jsonError{Code: err.Code(), Message: err.Error()}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) CreateErrorResponseWithInfo(id *int64, err RPCError, info interface{}) interface{} {
|
||||||
|
return &jsonErrResponse{Version: jsonRPCVersion, Id: id,
|
||||||
|
Error: jsonError{Code: err.Code(), Message: err.Error(), Data: info}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) CreateNotification(subid string, event interface{}) interface{} {
|
||||||
|
return &jsonNotification{Version: jsonRPCVersion, Method: notificationMethod,
|
||||||
|
Params: jsonSubscription{Subscription: subid, Result: event}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) Write(msg interface{}) error {
|
||||||
|
if len(c.output) == 0 { // only capture first response
|
||||||
|
if o, err := json.Marshal(msg); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
c.output = string(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) Close() {
|
||||||
|
close(c.closer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerTestCodec) Closed() <-chan interface{} {
|
||||||
|
return c.closer
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServerMethodExecution(t *testing.T) {
|
||||||
|
server := NewServer()
|
||||||
|
service := new(Service)
|
||||||
|
|
||||||
|
if err := server.RegisterName("test", service); err != nil {
|
||||||
|
t.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req := jsonRequest{
|
||||||
|
Method: "echo",
|
||||||
|
Version: "2.0",
|
||||||
|
Id: 12345,
|
||||||
|
}
|
||||||
|
args := []interface{}{"string arg", 1122, &Args{"qwerty"}}
|
||||||
|
req.Payload, _ = json.Marshal(&args)
|
||||||
|
|
||||||
|
input, _ := json.Marshal(&req)
|
||||||
|
codec := &ServerTestCodec{input: input, closer: make(chan interface{})}
|
||||||
|
go server.ServeCodec(codec)
|
||||||
|
|
||||||
|
<-codec.closer
|
||||||
|
|
||||||
|
expected := `{"jsonrpc":"2.0","id":12345,"result":{"String":"string arg","Int":1122,"Args":{"S":"qwerty"}}}`
|
||||||
|
|
||||||
|
if expected != codec.output {
|
||||||
|
t.Fatalf("expected %s, got %s\n", expected, codec.output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,8 +190,8 @@ func NewHexNumber(val interface{}) *HexNumber {
|
||||||
|
|
||||||
func (h *HexNumber) UnmarshalJSON(input []byte) error {
|
func (h *HexNumber) UnmarshalJSON(input []byte) error {
|
||||||
length := len(input)
|
length := len(input)
|
||||||
if length >= 2 && input[0] == '"' && input[length - 1] == '"' {
|
if length >= 2 && input[0] == '"' && input[length-1] == '"' {
|
||||||
input = input[1 : length - 1]
|
input = input[1 : length-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
hn := (*big.Int)(h)
|
hn := (*big.Int)(h)
|
||||||
|
|
@ -239,11 +239,12 @@ func (h *HexNumber) BigInt() *big.Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Number int64
|
type Number int64
|
||||||
|
|
||||||
func (n *Number) UnmarshalJSON(data []byte) error {
|
func (n *Number) UnmarshalJSON(data []byte) error {
|
||||||
input := strings.TrimSpace(string(data))
|
input := strings.TrimSpace(string(data))
|
||||||
|
|
||||||
if len(input) >= 2 && input[0] == '"' && input[len(input) - 1] == '"' {
|
if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
|
||||||
input = input[1 : len(input) - 1]
|
input = input[1 : len(input)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
|
|
@ -271,17 +272,17 @@ func (n *Number) Int64() int64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
pendingBlockNumber = big.NewInt(-2)
|
pendingBlockNumber = big.NewInt(-2)
|
||||||
latestBlockNumber = big.NewInt(-1)
|
latestBlockNumber = big.NewInt(-1)
|
||||||
earliestBlockNumber = big.NewInt(0)
|
earliestBlockNumber = big.NewInt(0)
|
||||||
maxBlockNumber = big.NewInt(math.MaxInt64)
|
maxBlockNumber = big.NewInt(math.MaxInt64)
|
||||||
)
|
)
|
||||||
|
|
||||||
type BlockNumber int64
|
type BlockNumber int64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PendingBlockNumber = BlockNumber(-2)
|
PendingBlockNumber = BlockNumber(-2)
|
||||||
LatestBlockNumber = BlockNumber(-1)
|
LatestBlockNumber = BlockNumber(-1)
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnmarshalJSON parses the given JSON fragement into a BlockNumber. It supports:
|
// UnmarshalJSON parses the given JSON fragement into a BlockNumber. It supports:
|
||||||
|
|
@ -294,8 +295,8 @@ const (
|
||||||
func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
|
func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
|
||||||
input := strings.TrimSpace(string(data))
|
input := strings.TrimSpace(string(data))
|
||||||
|
|
||||||
if len(input) >= 2 && input[0] == '"' && input[len(input) - 1] == '"' {
|
if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
|
||||||
input = input[1 : len(input) - 1]
|
input = input[1 : len(input)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,9 @@ func (s *WhisperService) GetFilterChanges(filterId rpc.HexNumber) []WhisperMessa
|
||||||
defer s.messagesMu.RUnlock()
|
defer s.messagesMu.RUnlock()
|
||||||
|
|
||||||
if s.messages[filterId.Int()] != nil {
|
if s.messages[filterId.Int()] != nil {
|
||||||
return s.messages[filterId.Int()].retrieve()
|
if changes := s.messages[filterId.Int()].retrieve(); changes != nil {
|
||||||
|
return changes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return returnWhisperMessages(nil)
|
return returnWhisperMessages(nil)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue