github.com/luckypickle/go-ethereum-vet@v1.14.2/rpc/json_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package rpc 18 19 import ( 20 "bufio" 21 "bytes" 22 "encoding/json" 23 "reflect" 24 "strconv" 25 "testing" 26 ) 27 28 type RWC struct { 29 *bufio.ReadWriter 30 } 31 32 func (rwc *RWC) Close() error { 33 return nil 34 } 35 36 func TestJSONRequestParsing(t *testing.T) { 37 server := NewServer() 38 service := new(Service) 39 40 if err := server.RegisterName("calc", service); err != nil { 41 t.Fatalf("%v", err) 42 } 43 44 req := bytes.NewBufferString(`{"id": 1234, "jsonrpc": "2.0", "method": "calc_add", "params": [11, 22]}`) 45 var str string 46 reply := bytes.NewBufferString(str) 47 rw := &RWC{bufio.NewReadWriter(bufio.NewReader(req), bufio.NewWriter(reply))} 48 49 codec := NewJSONCodec(rw) 50 51 requests, batch, err := codec.ReadRequestHeaders() 52 if err != nil { 53 t.Fatalf("%v", err) 54 } 55 56 if batch { 57 t.Fatalf("Request isn't a batch") 58 } 59 60 if len(requests) != 1 { 61 t.Fatalf("Expected 1 request but got %d requests - %v", len(requests), requests) 62 } 63 64 if requests[0].service != "calc" { 65 t.Fatalf("Expected service 'calc' but got '%s'", requests[0].service) 66 } 67 68 if requests[0].method != "add" { 69 t.Fatalf("Expected method 'Add' but got '%s'", requests[0].method) 70 } 71 72 if rawId, ok := requests[0].id.(*json.RawMessage); ok { 73 id, e := strconv.ParseInt(string(*rawId), 0, 64) 74 if e != nil { 75 t.Fatalf("%v", e) 76 } 77 if id != 1234 { 78 t.Fatalf("Expected id 1234 but got %d", id) 79 } 80 } else { 81 t.Fatalf("invalid request, expected *json.RawMesage got %T", requests[0].id) 82 } 83 84 var arg int 85 args := []reflect.Type{reflect.TypeOf(arg), reflect.TypeOf(arg)} 86 87 v, err := codec.ParseRequestArguments(args, requests[0].params) 88 if err != nil { 89 t.Fatalf("%v", err) 90 } 91 92 if len(v) != 2 { 93 t.Fatalf("Expected 2 argument values, got %d", len(v)) 94 } 95 96 if v[0].Int() != 11 || v[1].Int() != 22 { 97 t.Fatalf("expected %d == 11 && %d == 22", v[0].Int(), v[1].Int()) 98 } 99 } 100 101 func TestJSONRequestParamsParsing(t *testing.T) { 102 103 var ( 104 stringT = reflect.TypeOf("") 105 intT = reflect.TypeOf(0) 106 intPtrT = reflect.TypeOf(new(int)) 107 108 stringV = reflect.ValueOf("abc") 109 i = 1 110 intV = reflect.ValueOf(i) 111 intPtrV = reflect.ValueOf(&i) 112 ) 113 114 var validTests = []struct { 115 input string 116 argTypes []reflect.Type 117 expected []reflect.Value 118 }{ 119 {`[]`, []reflect.Type{}, []reflect.Value{}}, 120 {`[]`, []reflect.Type{intPtrT}, []reflect.Value{intPtrV}}, 121 {`[1]`, []reflect.Type{intT}, []reflect.Value{intV}}, 122 {`[1,"abc"]`, []reflect.Type{intT, stringT}, []reflect.Value{intV, stringV}}, 123 {`[null]`, []reflect.Type{intPtrT}, []reflect.Value{intPtrV}}, 124 {`[null,"abc"]`, []reflect.Type{intPtrT, stringT, intPtrT}, []reflect.Value{intPtrV, stringV, intPtrV}}, 125 {`[null,"abc",null]`, []reflect.Type{intPtrT, stringT, intPtrT}, []reflect.Value{intPtrV, stringV, intPtrV}}, 126 } 127 128 codec := jsonCodec{} 129 130 for _, test := range validTests { 131 params := (json.RawMessage)([]byte(test.input)) 132 args, err := codec.ParseRequestArguments(test.argTypes, params) 133 134 if err != nil { 135 t.Fatal(err) 136 } 137 138 var match []interface{} 139 json.Unmarshal([]byte(test.input), &match) 140 141 if len(args) != len(test.argTypes) { 142 t.Fatalf("expected %d parsed args, got %d", len(test.argTypes), len(args)) 143 } 144 145 for i, arg := range args { 146 expected := test.expected[i] 147 148 if arg.Kind() != expected.Kind() { 149 t.Errorf("expected type for param %d in %s", i, test.input) 150 } 151 152 if arg.Kind() == reflect.Int && arg.Int() != expected.Int() { 153 t.Errorf("expected int(%d), got int(%d) in %s", expected.Int(), arg.Int(), test.input) 154 } 155 156 if arg.Kind() == reflect.String && arg.String() != expected.String() { 157 t.Errorf("expected string(%s), got string(%s) in %s", expected.String(), arg.String(), test.input) 158 } 159 } 160 } 161 162 var invalidTests = []struct { 163 input string 164 argTypes []reflect.Type 165 }{ 166 {`[]`, []reflect.Type{intT}}, 167 {`[null]`, []reflect.Type{intT}}, 168 {`[1]`, []reflect.Type{stringT}}, 169 {`[1,2]`, []reflect.Type{stringT}}, 170 {`["abc", null]`, []reflect.Type{stringT, intT}}, 171 } 172 173 for i, test := range invalidTests { 174 if _, err := codec.ParseRequestArguments(test.argTypes, test.input); err == nil { 175 t.Errorf("expected test %d - %s to fail", i, test.input) 176 } 177 } 178 }