github.com/gagliardetto/solana-go@v1.11.0/rpc/jsonrpc/jsonrpc_test.go (about)

     1  package jsonrpc
     2  
     3  import (
     4  	"context"
     5  	stdjson "encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"os"
    11  	"strconv"
    12  	"testing"
    13  
    14  	. "github.com/onsi/gomega"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  // needed to retrieve requests that arrived at httpServer for further investigation
    19  var requestChan = make(chan *RequestData, 1)
    20  
    21  // the request datastructure that can be retrieved for test assertions
    22  type RequestData struct {
    23  	request *http.Request
    24  	body    string
    25  }
    26  
    27  // set the response body the httpServer should return for the next request
    28  var responseBody = ""
    29  
    30  var httpServer *httptest.Server
    31  
    32  // start the testhttp server and stop it when tests are finished
    33  func TestMain(m *testing.M) {
    34  	httpServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    35  		data, _ := ioutil.ReadAll(r.Body)
    36  		defer r.Body.Close()
    37  		// put request and body to channel for the client to investigate them
    38  		requestChan <- &RequestData{r, string(data)}
    39  
    40  		fmt.Fprintf(w, responseBody)
    41  	}))
    42  	defer httpServer.Close()
    43  
    44  	os.Exit(m.Run())
    45  }
    46  
    47  func TestSimpleRpcCallHeaderCorrect(t *testing.T) {
    48  	RegisterTestingT(t)
    49  
    50  	rpcClient := NewClient(httpServer.URL)
    51  	rpcClient.Call(context.Background(), "add", 1, 2)
    52  
    53  	req := (<-requestChan).request
    54  
    55  	Expect(req.Method).To(Equal("POST"))
    56  	Expect(req.Header.Get("Content-Type")).To(Equal("application/json"))
    57  	Expect(req.Header.Get("Accept")).To(Equal("application/json"))
    58  }
    59  
    60  // test if the structure of an rpc request is built correctly by validating the data that arrived on the test server
    61  func TestRpcClient_Call(t *testing.T) {
    62  	RegisterTestingT(t)
    63  	rpcClient := NewClient(httpServer.URL)
    64  
    65  	person := Person{
    66  		Name:    "Alex",
    67  		Age:     35,
    68  		Country: "Germany",
    69  	}
    70  
    71  	drink := Drink{
    72  		Name:        "Cuba Libre",
    73  		Ingredients: []string{"rum", "cola"},
    74  	}
    75  
    76  	useFixedID = true
    77  
    78  	rpcClient.Call(context.Background(), "missingParam")
    79  	Expect((<-requestChan).body).To(Equal(`{"method":"missingParam","id":1,"jsonrpc":"2.0"}`))
    80  
    81  	rpcClient.Call(context.Background(), "nullParam", nil)
    82  	Expect((<-requestChan).body).To(Equal(`{"method":"nullParam","params":[null],"id":1,"jsonrpc":"2.0"}`))
    83  
    84  	rpcClient.Call(context.Background(), "nullParams", nil, nil)
    85  	Expect((<-requestChan).body).To(Equal(`{"method":"nullParams","params":[null,null],"id":1,"jsonrpc":"2.0"}`))
    86  
    87  	rpcClient.Call(context.Background(), "emptyParams", []interface{}{})
    88  	Expect((<-requestChan).body).To(Equal(`{"method":"emptyParams","params":[],"id":1,"jsonrpc":"2.0"}`))
    89  
    90  	rpcClient.Call(context.Background(), "emptyAnyParams", []string{})
    91  	Expect((<-requestChan).body).To(Equal(`{"method":"emptyAnyParams","params":[],"id":1,"jsonrpc":"2.0"}`))
    92  
    93  	rpcClient.Call(context.Background(), "emptyObject", struct{}{})
    94  	Expect((<-requestChan).body).To(Equal(`{"method":"emptyObject","params":{},"id":1,"jsonrpc":"2.0"}`))
    95  
    96  	rpcClient.Call(context.Background(), "emptyObjectList", []struct{}{{}, {}})
    97  	Expect((<-requestChan).body).To(Equal(`{"method":"emptyObjectList","params":[{},{}],"id":1,"jsonrpc":"2.0"}`))
    98  
    99  	rpcClient.Call(context.Background(), "boolParam", true)
   100  	Expect((<-requestChan).body).To(Equal(`{"method":"boolParam","params":[true],"id":1,"jsonrpc":"2.0"}`))
   101  
   102  	rpcClient.Call(context.Background(), "boolParams", true, false, true)
   103  	Expect((<-requestChan).body).To(Equal(`{"method":"boolParams","params":[true,false,true],"id":1,"jsonrpc":"2.0"}`))
   104  
   105  	rpcClient.Call(context.Background(), "stringParam", "Alex")
   106  	Expect((<-requestChan).body).To(Equal(`{"method":"stringParam","params":["Alex"],"id":1,"jsonrpc":"2.0"}`))
   107  
   108  	rpcClient.Call(context.Background(), "stringParams", "JSON", "RPC")
   109  	Expect((<-requestChan).body).To(Equal(`{"method":"stringParams","params":["JSON","RPC"],"id":1,"jsonrpc":"2.0"}`))
   110  
   111  	rpcClient.Call(context.Background(), "numberParam", 123)
   112  	Expect((<-requestChan).body).To(Equal(`{"method":"numberParam","params":[123],"id":1,"jsonrpc":"2.0"}`))
   113  
   114  	rpcClient.Call(context.Background(), "numberParams", 123, 321)
   115  	Expect((<-requestChan).body).To(Equal(`{"method":"numberParams","params":[123,321],"id":1,"jsonrpc":"2.0"}`))
   116  
   117  	rpcClient.Call(context.Background(), "floatParam", 1.23)
   118  	Expect((<-requestChan).body).To(Equal(`{"method":"floatParam","params":[1.23],"id":1,"jsonrpc":"2.0"}`))
   119  
   120  	rpcClient.Call(context.Background(), "floatParams", 1.23, 3.21)
   121  	Expect((<-requestChan).body).To(Equal(`{"method":"floatParams","params":[1.23,3.21],"id":1,"jsonrpc":"2.0"}`))
   122  
   123  	rpcClient.Call(context.Background(), "manyParams", "Alex", 35, true, nil, 2.34)
   124  	Expect((<-requestChan).body).To(Equal(`{"method":"manyParams","params":["Alex",35,true,null,2.34],"id":1,"jsonrpc":"2.0"}`))
   125  
   126  	rpcClient.Call(context.Background(), "emptyMissingPublicFieldObject", struct{ name string }{name: "Alex"})
   127  	Expect((<-requestChan).body).To(Equal(`{"method":"emptyMissingPublicFieldObject","params":{},"id":1,"jsonrpc":"2.0"}`))
   128  
   129  	rpcClient.Call(context.Background(), "singleStruct", person)
   130  	Expect((<-requestChan).body).To(Equal(`{"method":"singleStruct","params":{"name":"Alex","age":35,"country":"Germany"},"id":1,"jsonrpc":"2.0"}`))
   131  
   132  	rpcClient.Call(context.Background(), "singlePointerToStruct", &person)
   133  	Expect((<-requestChan).body).To(Equal(`{"method":"singlePointerToStruct","params":{"name":"Alex","age":35,"country":"Germany"},"id":1,"jsonrpc":"2.0"}`))
   134  
   135  	pp := &person
   136  	rpcClient.Call(context.Background(), "doublePointerStruct", &pp)
   137  	Expect((<-requestChan).body).To(Equal(`{"method":"doublePointerStruct","params":{"name":"Alex","age":35,"country":"Germany"},"id":1,"jsonrpc":"2.0"}`))
   138  
   139  	rpcClient.Call(context.Background(), "multipleStructs", person, &drink)
   140  	Expect((<-requestChan).body).To(Equal(`{"method":"multipleStructs","params":[{"name":"Alex","age":35,"country":"Germany"},{"name":"Cuba Libre","ingredients":["rum","cola"]}],"id":1,"jsonrpc":"2.0"}`))
   141  
   142  	rpcClient.Call(context.Background(), "singleStructInArray", []interface{}{person})
   143  	Expect((<-requestChan).body).To(Equal(`{"method":"singleStructInArray","params":[{"name":"Alex","age":35,"country":"Germany"}],"id":1,"jsonrpc":"2.0"}`))
   144  
   145  	rpcClient.Call(context.Background(), "namedParameters", map[string]interface{}{
   146  		"name": "Alex",
   147  		"age":  35,
   148  	})
   149  	Expect((<-requestChan).body).To(Equal(`{"method":"namedParameters","params":{"age":35,"name":"Alex"},"id":1,"jsonrpc":"2.0"}`))
   150  
   151  	rpcClient.Call(context.Background(), "anonymousStructNoTags", struct {
   152  		Name string
   153  		Age  int
   154  	}{"Alex", 33})
   155  	Expect((<-requestChan).body).To(Equal(`{"method":"anonymousStructNoTags","params":{"Name":"Alex","Age":33},"id":1,"jsonrpc":"2.0"}`))
   156  
   157  	rpcClient.Call(context.Background(), "anonymousStructWithTags", struct {
   158  		Name string `json:"name"`
   159  		Age  int    `json:"age"`
   160  	}{"Alex", 33})
   161  	Expect((<-requestChan).body).To(Equal(`{"method":"anonymousStructWithTags","params":{"name":"Alex","age":33},"id":1,"jsonrpc":"2.0"}`))
   162  
   163  	rpcClient.Call(context.Background(), "structWithNullField", struct {
   164  		Name    string  `json:"name"`
   165  		Address *string `json:"address"`
   166  	}{"Alex", nil})
   167  	Expect((<-requestChan).body).To(Equal(`{"method":"structWithNullField","params":{"name":"Alex","address":null},"id":1,"jsonrpc":"2.0"}`))
   168  }
   169  
   170  func TestRpcClient_CallBatch(t *testing.T) {
   171  	RegisterTestingT(t)
   172  	rpcClient := NewClient(httpServer.URL)
   173  
   174  	person := Person{
   175  		Name:    "Alex",
   176  		Age:     35,
   177  		Country: "Germany",
   178  	}
   179  
   180  	drink := Drink{
   181  		Name:        "Cuba Libre",
   182  		Ingredients: []string{"rum", "cola"},
   183  	}
   184  
   185  	// invalid parameters are possible by manually defining *RPCRequest
   186  	rpcClient.CallBatch(context.Background(), RPCRequests{
   187  		{
   188  			Method: "singleRequest",
   189  			Params: 3, // invalid, should be []int{3}
   190  		},
   191  	})
   192  	Expect((<-requestChan).body).To(Equal(`[{"method":"singleRequest","params":3,"id":0,"jsonrpc":"2.0"}]`))
   193  
   194  	// better use Params() unless you know what you are doing
   195  	rpcClient.CallBatch(context.Background(), RPCRequests{
   196  		{
   197  			Method: "singleRequest",
   198  			Params: Params(3), // always valid json rpc
   199  		},
   200  	})
   201  	Expect((<-requestChan).body).To(Equal(`[{"method":"singleRequest","params":[3],"id":0,"jsonrpc":"2.0"}]`))
   202  
   203  	// even better, use NewRequest()
   204  	rpcClient.CallBatch(context.Background(), RPCRequests{
   205  		NewRequest("multipleRequests1", 1),
   206  		NewRequest("multipleRequests2", 2),
   207  		NewRequest("multipleRequests3", 3),
   208  	})
   209  	Expect((<-requestChan).body).To(Equal(`[{"method":"multipleRequests1","params":[1],"id":0,"jsonrpc":"2.0"},{"method":"multipleRequests2","params":[2],"id":1,"jsonrpc":"2.0"},{"method":"multipleRequests3","params":[3],"id":2,"jsonrpc":"2.0"}]`))
   210  
   211  	// test a huge batch request
   212  	requests := RPCRequests{
   213  		NewRequest("nullParam", nil),
   214  		NewRequest("nullParams", nil, nil),
   215  		NewRequest("emptyParams", []interface{}{}),
   216  		NewRequest("emptyAnyParams", []string{}),
   217  		NewRequest("emptyObject", struct{}{}),
   218  		NewRequest("emptyObjectList", []struct{}{{}, {}}),
   219  		NewRequest("boolParam", true),
   220  		NewRequest("boolParams", true, false, true),
   221  		NewRequest("stringParam", "Alex"),
   222  		NewRequest("stringParams", "JSON", "RPC"),
   223  		NewRequest("numberParam", 123),
   224  		NewRequest("numberParams", 123, 321),
   225  		NewRequest("floatParam", 1.23),
   226  		NewRequest("floatParams", 1.23, 3.21),
   227  		NewRequest("manyParams", "Alex", 35, true, nil, 2.34),
   228  		NewRequest("emptyMissingPublicFieldObject", struct{ name string }{name: "Alex"}),
   229  		NewRequest("singleStruct", person),
   230  		NewRequest("singlePointerToStruct", &person),
   231  		NewRequest("multipleStructs", person, &drink),
   232  		NewRequest("singleStructInArray", []interface{}{person}),
   233  		NewRequest("namedParameters", map[string]interface{}{
   234  			"name": "Alex",
   235  			"age":  35,
   236  		}),
   237  		NewRequest("anonymousStructNoTags", struct {
   238  			Name string
   239  			Age  int
   240  		}{"Alex", 33}),
   241  		NewRequest("anonymousStructWithTags", struct {
   242  			Name string `json:"name"`
   243  			Age  int    `json:"age"`
   244  		}{"Alex", 33}),
   245  		NewRequest("structWithNullField", struct {
   246  			Name    string  `json:"name"`
   247  			Address *string `json:"address"`
   248  		}{"Alex", nil}),
   249  	}
   250  	rpcClient.CallBatch(context.Background(), requests)
   251  
   252  	Expect((<-requestChan).body).To(Equal(`[{"method":"nullParam","params":[null],"id":0,"jsonrpc":"2.0"},` +
   253  		`{"method":"nullParams","params":[null,null],"id":1,"jsonrpc":"2.0"},` +
   254  		`{"method":"emptyParams","params":[],"id":2,"jsonrpc":"2.0"},` +
   255  		`{"method":"emptyAnyParams","params":[],"id":3,"jsonrpc":"2.0"},` +
   256  		`{"method":"emptyObject","params":{},"id":4,"jsonrpc":"2.0"},` +
   257  		`{"method":"emptyObjectList","params":[{},{}],"id":5,"jsonrpc":"2.0"},` +
   258  		`{"method":"boolParam","params":[true],"id":6,"jsonrpc":"2.0"},` +
   259  		`{"method":"boolParams","params":[true,false,true],"id":7,"jsonrpc":"2.0"},` +
   260  		`{"method":"stringParam","params":["Alex"],"id":8,"jsonrpc":"2.0"},` +
   261  		`{"method":"stringParams","params":["JSON","RPC"],"id":9,"jsonrpc":"2.0"},` +
   262  		`{"method":"numberParam","params":[123],"id":10,"jsonrpc":"2.0"},` +
   263  		`{"method":"numberParams","params":[123,321],"id":11,"jsonrpc":"2.0"},` +
   264  		`{"method":"floatParam","params":[1.23],"id":12,"jsonrpc":"2.0"},` +
   265  		`{"method":"floatParams","params":[1.23,3.21],"id":13,"jsonrpc":"2.0"},` +
   266  		`{"method":"manyParams","params":["Alex",35,true,null,2.34],"id":14,"jsonrpc":"2.0"},` +
   267  		`{"method":"emptyMissingPublicFieldObject","params":{},"id":15,"jsonrpc":"2.0"},` +
   268  		`{"method":"singleStruct","params":{"name":"Alex","age":35,"country":"Germany"},"id":16,"jsonrpc":"2.0"},` +
   269  		`{"method":"singlePointerToStruct","params":{"name":"Alex","age":35,"country":"Germany"},"id":17,"jsonrpc":"2.0"},` +
   270  		`{"method":"multipleStructs","params":[{"name":"Alex","age":35,"country":"Germany"},{"name":"Cuba Libre","ingredients":["rum","cola"]}],"id":18,"jsonrpc":"2.0"},` +
   271  		`{"method":"singleStructInArray","params":[{"name":"Alex","age":35,"country":"Germany"}],"id":19,"jsonrpc":"2.0"},` +
   272  		`{"method":"namedParameters","params":{"age":35,"name":"Alex"},"id":20,"jsonrpc":"2.0"},` +
   273  		`{"method":"anonymousStructNoTags","params":{"Name":"Alex","Age":33},"id":21,"jsonrpc":"2.0"},` +
   274  		`{"method":"anonymousStructWithTags","params":{"name":"Alex","age":33},"id":22,"jsonrpc":"2.0"},` +
   275  		`{"method":"structWithNullField","params":{"name":"Alex","address":null},"id":23,"jsonrpc":"2.0"}]`))
   276  
   277  	// create batch manually
   278  	requests = []*RPCRequest{
   279  		{
   280  			Method:  "myMethod1",
   281  			Params:  []int{1},
   282  			ID:      123,   // will be forced to requests[i].ID == i unless you use CallBatchRaw
   283  			JSONRPC: "7.0", // will be forced to "2.0"  unless you use CallBatchRaw
   284  		},
   285  		{
   286  			Method:  "myMethod2",
   287  			Params:  &person,
   288  			ID:      321,     // will be forced to requests[i].ID == i unless you use CallBatchRaw
   289  			JSONRPC: "wrong", // will be forced to "2.0" unless you use CallBatchRaw
   290  		},
   291  	}
   292  	rpcClient.CallBatch(context.Background(), requests)
   293  
   294  	Expect((<-requestChan).body).To(Equal(`[{"method":"myMethod1","params":[1],"id":0,"jsonrpc":"2.0"},` +
   295  		`{"method":"myMethod2","params":{"name":"Alex","age":35,"country":"Germany"},"id":1,"jsonrpc":"2.0"}]`))
   296  
   297  	// use raw batch
   298  	requests = []*RPCRequest{
   299  		{
   300  			Method:  "myMethod1",
   301  			Params:  []int{1},
   302  			ID:      123,
   303  			JSONRPC: "7.0",
   304  		},
   305  		{
   306  			Method:  "myMethod2",
   307  			Params:  &person,
   308  			ID:      321,
   309  			JSONRPC: "wrong",
   310  		},
   311  	}
   312  	rpcClient.CallBatchRaw(context.Background(), requests)
   313  
   314  	Expect((<-requestChan).body).To(Equal(`[{"method":"myMethod1","params":[1],"id":123,"jsonrpc":"7.0"},` +
   315  		`{"method":"myMethod2","params":{"name":"Alex","age":35,"country":"Germany"},"id":321,"jsonrpc":"wrong"}]`))
   316  }
   317  
   318  // test if the result of an an rpc request is parsed correctly and if errors are thrown correctly
   319  func TestRpcJsonResponseStruct(t *testing.T) {
   320  	RegisterTestingT(t)
   321  	rpcClient := NewClient(httpServer.URL)
   322  
   323  	// empty return body is an error
   324  	responseBody = ``
   325  	res, err := rpcClient.Call(context.Background(), "something", 1, 2, 3)
   326  	<-requestChan
   327  	Expect(err).NotTo(BeNil())
   328  	Expect(res).To(BeNil())
   329  
   330  	// not a json body is an error
   331  	responseBody = `{ "not": "a", "json": "object"`
   332  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   333  	<-requestChan
   334  	Expect(err).NotTo(BeNil())
   335  	Expect(res).To(BeNil())
   336  
   337  	// field "anotherField" not allowed in rpc response is an error
   338  	responseBody = `{ "anotherField": "norpc"}`
   339  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   340  	<-requestChan
   341  	Expect(err).NotTo(BeNil())
   342  	Expect(res).To(BeNil())
   343  
   344  	// TODO: result must contain one of "result", "error"
   345  	// TODO: is there an efficient way to do this?
   346  	/*responseBody = `{}`
   347  	res, err = rpcClient.Call("something", 1, 2, 3)
   348  	<-requestChan
   349  	Expect(err).NotTo(BeNil())
   350  	Expect(res).To(BeNil())*/
   351  
   352  	// result null is ok
   353  	responseBody = `{"result": null}`
   354  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   355  	<-requestChan
   356  	Expect(err).To(BeNil())
   357  	Expect(res.Result).To(BeNil())
   358  	Expect(res.Error).To(BeNil())
   359  
   360  	// error null is ok
   361  	responseBody = `{"error": null}`
   362  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   363  	<-requestChan
   364  	Expect(err).To(BeNil())
   365  	Expect(res.Result).To(BeNil())
   366  	Expect(res.Error).To(BeNil())
   367  
   368  	// result and error null is ok
   369  	responseBody = `{"result": null, "error": null}`
   370  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   371  	<-requestChan
   372  	Expect(err).To(BeNil())
   373  	Expect(res.Result).To(BeNil())
   374  	Expect(res.Error).To(BeNil())
   375  
   376  	// TODO: result must not contain both of "result", "error" != null
   377  	// TODO: is there an efficient way to do this?
   378  	/*responseBody = `{ "result": 123, "error": {"code": 123, "message": "something wrong"}}`
   379  	res, err = rpcClient.Call("something", 1, 2, 3)
   380  	<-requestChan
   381  	Expect(err).NotTo(BeNil())
   382  	Expect(res).To(BeNil())*/
   383  
   384  	// result string is ok
   385  	responseBody = `{"result": "ok"}`
   386  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   387  	<-requestChan
   388  	Expect(err).To(BeNil())
   389  	Expect(res.Result).To(Equal(stdjson.RawMessage([]byte(strconv.Quote("ok")))))
   390  
   391  	// result with error null is ok
   392  	responseBody = `{"result": "ok", "error": null}`
   393  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   394  	<-requestChan
   395  	Expect(err).To(BeNil())
   396  	Expect(res.Result).To(Equal(stdjson.RawMessage([]byte(strconv.Quote("ok")))))
   397  
   398  	// error with result null is ok
   399  	responseBody = `{"error": {"code": 123, "message": "something wrong"}, "result": null}`
   400  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   401  	<-requestChan
   402  	Expect(err).To(BeNil())
   403  	Expect(res.Result).To(BeNil())
   404  	Expect(res.Error.Code).To(Equal(123))
   405  	Expect(res.Error.Message).To(Equal("something wrong"))
   406  
   407  	// TODO: empty error is not ok, must at least contain code and message
   408  	/*responseBody = `{ "error": {}}`
   409  	res, err = rpcClient.Call("something", 1, 2, 3)
   410  	<-requestChan
   411  	Expect(err).To(BeNil())
   412  	Expect(res.Result).To(BeNil())
   413  	Expect(res.Error).NotTo(BeNil())*/
   414  
   415  	// TODO: only code in error is not ok, must at least contain code and message
   416  	/*responseBody = `{ "error": {"code": 123}}`
   417  	res, err = rpcClient.Call("something", 1, 2, 3)
   418  	<-requestChan
   419  	Expect(err).To(BeNil())
   420  	Expect(res.Result).To(BeNil())
   421  	Expect(res.Error).NotTo(BeNil())*/
   422  
   423  	// TODO: only message in error is not ok, must at least contain code and message
   424  	/*responseBody = `{ "error": {"message": "something wrong"}}`
   425  	res, err = rpcClient.Call("something", 1, 2, 3)
   426  	<-requestChan
   427  	Expect(err).To(BeNil())
   428  	Expect(res.Result).To(BeNil())
   429  	Expect(res.Error).NotTo(BeNil())*/
   430  
   431  	// error with code and message is ok
   432  	responseBody = `{ "error": {"code": 123, "message": "something wrong"}}`
   433  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   434  	<-requestChan
   435  	Expect(err).To(BeNil())
   436  	Expect(res.Result).To(BeNil())
   437  	Expect(res.Error.Code).To(Equal(123))
   438  	Expect(res.Error.Message).To(Equal("something wrong"))
   439  
   440  	// check results
   441  
   442  	var p *Person
   443  	responseBody = `{ "result": {"name": "Alex", "age": 35, "anotherField": "something"} }`
   444  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   445  	<-requestChan
   446  	Expect(err).To(BeNil())
   447  	Expect(res.Error).To(BeNil())
   448  	err = res.GetObject(&p)
   449  	Expect(err).To(BeNil())
   450  	Expect(p.Name).To(Equal("Alex"))
   451  	Expect(p.Age).To(Equal(35))
   452  	Expect(p.Country).To(Equal(""))
   453  
   454  	// TODO: How to check if result could be parsed or if it is default?
   455  	p = nil
   456  	responseBody = `{ "result": {"anotherField": "something"} }`
   457  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   458  	<-requestChan
   459  	Expect(err).To(BeNil())
   460  	Expect(res.Error).To(BeNil())
   461  	err = res.GetObject(&p)
   462  	Expect(err).To(BeNil())
   463  	Expect(p).NotTo(BeNil())
   464  
   465  	// TODO: HERE######
   466  	var pp *PointerFieldPerson
   467  	responseBody = `{ "result": {"anotherField": "something", "country": "Germany"} }`
   468  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   469  	<-requestChan
   470  	Expect(err).To(BeNil())
   471  	Expect(res.Error).To(BeNil())
   472  	err = res.GetObject(&pp)
   473  	Expect(err).To(BeNil())
   474  	Expect(pp.Name).To(BeNil())
   475  	Expect(pp.Age).To(BeNil())
   476  	Expect(*pp.Country).To(Equal("Germany"))
   477  
   478  	p = nil
   479  	responseBody = `{ "result": null }`
   480  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   481  	<-requestChan
   482  	Expect(err).To(BeNil())
   483  	Expect(res.Error).To(BeNil())
   484  	err = res.GetObject(&p)
   485  	Expect(err).To(BeNil())
   486  	Expect(p).To(BeNil())
   487  
   488  	// passing nil is an error
   489  	// TODO
   490  	// p = nil
   491  	// responseBody = `{ "result": null }`
   492  	// res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   493  	// <-requestChan
   494  	// Expect(err).To(BeNil())
   495  	// Expect(res.Error).To(BeNil())
   496  	// err = res.GetObject(p)
   497  	// Expect(err).NotTo(BeNil())
   498  	// Expect(p).To(BeNil())
   499  
   500  	p2 := &Person{
   501  		Name: "Alex",
   502  	}
   503  	responseBody = `{ "result": null }`
   504  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   505  	<-requestChan
   506  	Expect(err).To(BeNil())
   507  	Expect(res.Error).To(BeNil())
   508  	err = res.GetObject(&p2)
   509  	Expect(err).To(BeNil())
   510  	Expect(p2).To(BeNil())
   511  
   512  	p2 = &Person{
   513  		Name: "Alex",
   514  	}
   515  	responseBody = `{ "result": {"age": 35} }`
   516  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   517  	<-requestChan
   518  	Expect(err).To(BeNil())
   519  	Expect(res.Error).To(BeNil())
   520  	err = res.GetObject(p2)
   521  	Expect(err).To(BeNil())
   522  	Expect(p2.Name).To(Equal("Alex"))
   523  	Expect(p2.Age).To(Equal(35))
   524  
   525  	// prefilled struct is kept on no result
   526  	p3 := Person{
   527  		Name: "Alex",
   528  	}
   529  	responseBody = `{ "result": null }`
   530  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   531  	<-requestChan
   532  	Expect(err).To(BeNil())
   533  	Expect(res.Error).To(BeNil())
   534  	err = res.GetObject(&p3)
   535  	Expect(err).To(BeNil())
   536  	Expect(p3.Name).To(Equal("Alex"))
   537  
   538  	// prefilled struct is extended / overwritten
   539  	p3 = Person{
   540  		Name: "Alex",
   541  		Age:  123,
   542  	}
   543  	responseBody = `{ "result": {"age": 35, "country": "Germany"} }`
   544  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   545  	<-requestChan
   546  	Expect(err).To(BeNil())
   547  	Expect(res.Error).To(BeNil())
   548  	err = res.GetObject(&p3)
   549  	Expect(err).To(BeNil())
   550  	Expect(p3.Name).To(Equal("Alex"))
   551  	Expect(p3.Age).To(Equal(35))
   552  	Expect(p3.Country).To(Equal("Germany"))
   553  
   554  	// nil is an error
   555  	responseBody = `{ "result": {"age": 35} }`
   556  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   557  	<-requestChan
   558  	Expect(err).To(BeNil())
   559  	Expect(res.Error).To(BeNil())
   560  	err = res.GetObject(nil)
   561  	Expect(err).NotTo(BeNil())
   562  }
   563  
   564  func TestRpcBatchJsonResponseStruct(t *testing.T) {
   565  	RegisterTestingT(t)
   566  	rpcClient := NewClient(httpServer.URL)
   567  
   568  	// empty return body is an error
   569  	responseBody = ``
   570  	res, err := rpcClient.CallBatch(context.Background(), RPCRequests{
   571  		NewRequest("something", 1, 2, 3),
   572  	})
   573  	<-requestChan
   574  	Expect(err).NotTo(BeNil())
   575  	Expect(res).To(BeNil())
   576  
   577  	// not a json body is an error
   578  	responseBody = `{ "not": "a", "json": "object"`
   579  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   580  		NewRequest("something", 1, 2, 3),
   581  	})
   582  	<-requestChan
   583  	Expect(err).NotTo(BeNil())
   584  	Expect(res).To(BeNil())
   585  
   586  	// field "anotherField" not allowed in rpc response is an error
   587  	responseBody = `{ "anotherField": "norpc"}`
   588  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   589  		NewRequest("something", 1, 2, 3),
   590  	})
   591  	<-requestChan
   592  	Expect(err).NotTo(BeNil())
   593  	Expect(res).To(BeNil())
   594  
   595  	// TODO: result must contain one of "result", "error"
   596  	// TODO: is there an efficient way to do this?
   597  	/*responseBody = `[{}]`
   598  	res, err = rpcClient.Call(context.Background(), "something", 1, 2, 3)
   599  	<-requestChan
   600  	Expect(err).NotTo(BeNil())
   601  	Expect(res).To(BeNil())*/
   602  
   603  	// result must be wrapped in array on batch request
   604  	responseBody = `{"result": null}`
   605  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   606  		NewRequest("something", 1, 2, 3),
   607  	})
   608  	<-requestChan
   609  	Expect(err.Error()).NotTo(BeNil())
   610  
   611  	// result ok since in arrary
   612  	responseBody = `[{"result": null}]`
   613  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   614  		NewRequest("something", 1, 2, 3),
   615  	})
   616  	<-requestChan
   617  	Expect(err).To(BeNil())
   618  	Expect(len(res)).To(Equal(1))
   619  	Expect(res[0].Result).To(BeNil())
   620  
   621  	// error null is ok
   622  	responseBody = `[{"error": null}]`
   623  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   624  		NewRequest("something", 1, 2, 3),
   625  	})
   626  	<-requestChan
   627  	Expect(err).To(BeNil())
   628  	Expect(res[0].Result).To(BeNil())
   629  	Expect(res[0].Error).To(BeNil())
   630  
   631  	// result and error null is ok
   632  	responseBody = `[{"result": null, "error": null}]`
   633  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   634  		NewRequest("something", 1, 2, 3),
   635  	})
   636  	<-requestChan
   637  	Expect(err).To(BeNil())
   638  	Expect(res[0].Result).To(BeNil())
   639  	Expect(res[0].Error).To(BeNil())
   640  
   641  	// TODO: result must not contain both of "result", "error" != null
   642  	// TODO: is there an efficient way to do this?
   643  	/*responseBody = `[{ "result": 123, "error": {"code": 123, "message": "something wrong"}}]`
   644  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   645  	NewRequest("something",1, 2, 3),
   646  	})
   647  	<-requestChan
   648  	Expect(err).NotTo(BeNil())
   649  	Expect(res).To(BeNil())*/
   650  
   651  	// result string is ok
   652  	responseBody = `[{"result": "ok","id":1}]`
   653  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   654  		NewRequest("something", 1, 2, 3),
   655  	})
   656  	<-requestChan
   657  	Expect(err).To(BeNil())
   658  	Expect(res[0].Result).To(Equal(stdjson.RawMessage([]byte(strconv.Quote("ok")))))
   659  	Expect(res[0].ID).To(Equal(stdjson.Number("1")))
   660  
   661  	// result with error null is ok
   662  	responseBody = `[{"result": "ok", "error": null}]`
   663  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   664  		NewRequest("something", 1, 2, 3),
   665  	})
   666  	<-requestChan
   667  	Expect(err).To(BeNil())
   668  	Expect(res[0].Result).To(Equal(stdjson.RawMessage([]byte(strconv.Quote("ok")))))
   669  
   670  	// error with result null is ok
   671  	responseBody = `[{"error": {"code": 123, "message": "something wrong"}, "result": null}]`
   672  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   673  		NewRequest("something", 1, 2, 3),
   674  	})
   675  	<-requestChan
   676  	Expect(err).To(BeNil())
   677  	Expect(res[0].Result).To(BeNil())
   678  	Expect(res[0].Error.Code).To(Equal(123))
   679  	Expect(res[0].Error.Message).To(Equal("something wrong"))
   680  
   681  	// TODO: empty error is not ok, must at least contain code and message
   682  	/*responseBody = `[{ "error": {}}]`
   683  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   684  	NewRequest("something",1, 2, 3),
   685  	})
   686  	<-requestChan
   687  	Expect(err).To(BeNil())
   688  	Expect(res[0].Result).To(BeNil())
   689  	Expect(res[0].Error).NotTo(BeNil())*/ /*
   690  
   691  		// TODO: only code in error is not ok, must at least contain code and message
   692  	*/ /*responseBody = `[{ "error": {"code": 123}}]`
   693  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   694  	NewRequest("something",1, 2, 3),
   695  	})
   696  	<-requestChan
   697  	Expect(err).To(BeNil())
   698  	Expect(res[0].Result).To(BeNil())
   699  	Expect(res[0].Error).NotTo(BeNil())*/ /*
   700  
   701  		// TODO: only message in error is not ok, must at least contain code and message
   702  	*/ /*responseBody = `[{ "error": {"message": "something wrong"}}]`
   703  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   704  	NewRequest("something",1, 2, 3),
   705  	})
   706  	<-requestChan
   707  	Expect(err).To(BeNil())
   708  	Expect(res[0].Result).To(BeNil())
   709  	Expect(res[0].Error).NotTo(BeNil())*/
   710  
   711  	// error with code and message is ok
   712  	responseBody = `[{ "error": {"code": 123, "message": "something wrong"}}]`
   713  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   714  		NewRequest("something", 1, 2, 3),
   715  	})
   716  	<-requestChan
   717  	Expect(err).To(BeNil())
   718  	Expect(res[0].Result).To(BeNil())
   719  	Expect(res[0].Error.Code).To(Equal(123))
   720  	Expect(res[0].Error.Message).To(Equal("something wrong"))
   721  
   722  	// check results
   723  
   724  	var p *Person
   725  	responseBody = `[{"id":1, "result": {"name": "Alex", "age": 35}}, {"id":2, "result": {"name": "Lena", "age": 2}}]`
   726  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   727  		NewRequest("something", 1, 2, 3),
   728  	})
   729  
   730  	<-requestChan
   731  	Expect(err).To(BeNil())
   732  
   733  	Expect(res[0].Error).To(BeNil())
   734  	Expect(res[0].ID).To(Equal(stdjson.Number("1")))
   735  
   736  	Expect(res[1].Error).To(BeNil())
   737  	Expect(res[1].ID).To(Equal(stdjson.Number("2")))
   738  
   739  	err = res[0].GetObject(&p)
   740  	require.NoError(t, err)
   741  	Expect(p.Name).To(Equal("Alex"))
   742  	Expect(p.Age).To(Equal(35))
   743  
   744  	err = res[1].GetObject(&p)
   745  	require.NoError(t, err)
   746  	Expect(p.Name).To(Equal("Lena"))
   747  	Expect(p.Age).To(Equal(2))
   748  
   749  	// check if error occurred
   750  	responseBody = `[{ "result": "someresult", "error": null}, { "result": null, "error": {"code": 123, "message": "something wrong"}}]`
   751  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   752  		NewRequest("something", 1, 2, 3),
   753  	})
   754  	<-requestChan
   755  	Expect(err).To(BeNil())
   756  	Expect(res.HasError()).To(BeTrue())
   757  
   758  	// check if error occurred
   759  	responseBody = `[{ "result": null, "error": {"code": 123, "message": "something wrong"}}]`
   760  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   761  		NewRequest("something", 1, 2, 3),
   762  	})
   763  	<-requestChan
   764  	Expect(err).To(BeNil())
   765  	Expect(res.HasError()).To(BeTrue())
   766  	// check if error occurred
   767  	responseBody = `[{ "result": null, "error": {"code": 123, "message": "something wrong"}}]`
   768  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   769  		NewRequest("something", 1, 2, 3),
   770  	})
   771  	<-requestChan
   772  	Expect(err).To(BeNil())
   773  	Expect(res.HasError()).To(BeTrue())
   774  
   775  	// check if response mapping works
   776  	responseBody = `[{ "id":123,"result": 123},{ "id":1,"result": 1}]`
   777  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   778  		NewRequest("something", 1, 2, 3),
   779  	})
   780  	<-requestChan
   781  	Expect(err).To(BeNil())
   782  	Expect(res.HasError()).To(BeFalse())
   783  	resMap := res.AsMap()
   784  
   785  	var int1 int64
   786  	require.NotNil(t, resMap[1])
   787  	resMap[1].GetObject(&int1)
   788  	var int123 int64
   789  	require.NotNil(t, resMap[123])
   790  	resMap[123].GetObject(&int123)
   791  	Expect(int1).To(Equal(int64(1)))
   792  	Expect(int123).To(Equal(int64(123)))
   793  
   794  	// check if getByID works
   795  	res.GetByID(123).GetObject(&int123)
   796  	Expect(int123).To(Equal(int64(123)))
   797  
   798  	// check if error occurred
   799  	responseBody = `[{ "result": null, "error": {"code": 123, "message": "something wrong"}}]`
   800  	res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   801  		NewRequest("something", 1, 2, 3),
   802  	})
   803  	<-requestChan
   804  	Expect(err).To(BeNil())
   805  	Expect(res.HasError()).To(BeTrue())
   806  
   807  	/*
   808  		// TODO: How to check if result could be parsed or if it is default?
   809  		p = nil
   810  		responseBody = `{ "result": {"anotherField": "something"} }`
   811  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   812  			{"something", Params(1, 2, 3)},
   813  		})
   814  		<-requestChan
   815  		Expect(err).To(BeNil())
   816  		Expect(res.Error).To(BeNil())
   817  		err = res.GetObject(&p)
   818  		Expect(err).To(BeNil())
   819  		Expect(p).NotTo(BeNil())
   820  
   821  		// TODO: HERE######
   822  		var pp *PointerFieldPerson
   823  		responseBody = `{ "result": {"anotherField": "something", "country": "Germany"} }`
   824  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   825  			{"something", Params(1, 2, 3)},
   826  		})
   827  		<-requestChan
   828  		Expect(err).To(BeNil())
   829  		Expect(res.Error).To(BeNil())
   830  		err = res.GetObject(&pp)
   831  		Expect(err).To(BeNil())
   832  		Expect(pp.Name).To(BeNil())
   833  		Expect(pp.Age).To(BeNil())
   834  		Expect(*pp.Country).To(Equal("Germany"))
   835  
   836  		p = nil
   837  		responseBody = `{ "result": null }`
   838  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   839  			{"something", Params(1, 2, 3)},
   840  		})
   841  		<-requestChan
   842  		Expect(err).To(BeNil())
   843  		Expect(res.Error).To(BeNil())
   844  		err = res.GetObject(&p)
   845  		Expect(err).To(BeNil())
   846  		Expect(p).To(BeNil())
   847  
   848  		// passing nil is an error
   849  		p = nil
   850  		responseBody = `{ "result": null }`
   851  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   852  			{"something", Params(1, 2, 3)},
   853  		})
   854  		<-requestChan
   855  		Expect(err).To(BeNil())
   856  		Expect(res.Error).To(BeNil())
   857  		err = res.GetObject(p)
   858  		Expect(err).NotTo(BeNil())
   859  		Expect(p).To(BeNil())
   860  
   861  		p2 := &Person{
   862  			Name: "Alex",
   863  		}
   864  		responseBody = `{ "result": null }`
   865  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   866  			{"something", Params(1, 2, 3)},
   867  		})
   868  		<-requestChan
   869  		Expect(err).To(BeNil())
   870  		Expect(res.Error).To(BeNil())
   871  		err = res.GetObject(&p2)
   872  		Expect(err).To(BeNil())
   873  		Expect(p2).To(BeNil())
   874  
   875  		p2 = &Person{
   876  			Name: "Alex",
   877  		}
   878  		responseBody = `{ "result": {"age": 35} }`
   879  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   880  			{"something", Params(1, 2, 3)},
   881  		})
   882  		<-requestChan
   883  		Expect(err).To(BeNil())
   884  		Expect(res.Error).To(BeNil())
   885  		err = res.GetObject(p2)
   886  		Expect(err).To(BeNil())
   887  		Expect(p2.Name).To(Equal("Alex"))
   888  		Expect(p2.Age).To(Equal(35))
   889  
   890  		// prefilled struct is kept on no result
   891  		p3 := Person{
   892  			Name: "Alex",
   893  		}
   894  		responseBody = `{ "result": null }`
   895  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   896  			{"something", Params(1, 2, 3)},
   897  		})
   898  		<-requestChan
   899  		Expect(err).To(BeNil())
   900  		Expect(res.Error).To(BeNil())
   901  		err = res.GetObject(&p3)
   902  		Expect(err).To(BeNil())
   903  		Expect(p3.Name).To(Equal("Alex"))
   904  
   905  		// prefilled struct is extended / overwritten
   906  		p3 = Person{
   907  			Name: "Alex",
   908  			Age:  123,
   909  		}
   910  		responseBody = `{ "result": {"age": 35, "country": "Germany"} }`
   911  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   912  			{"something", Params(1, 2, 3)},
   913  		})
   914  		<-requestChan
   915  		Expect(err).To(BeNil())
   916  		Expect(res.Error).To(BeNil())
   917  		err = res.GetObject(&p3)
   918  		Expect(err).To(BeNil())
   919  		Expect(p3.Name).To(Equal("Alex"))
   920  		Expect(p3.Age).To(Equal(35))
   921  		Expect(p3.Country).To(Equal("Germany"))
   922  
   923  		// nil is an error
   924  		responseBody = `{ "result": {"age": 35} }`
   925  		res, err = rpcClient.CallBatch(context.Background(), RPCRequests{
   926  			{"something", Params(1, 2, 3)},
   927  		})
   928  		<-requestChan
   929  		Expect(err).To(BeNil())
   930  		Expect(res.Error).To(BeNil())
   931  		err = res.GetObject(nil)
   932  		Expect(err).NotTo(BeNil())
   933  	*/
   934  }
   935  
   936  func TestRpcClient_CallFor(t *testing.T) {
   937  	RegisterTestingT(t)
   938  	rpcClient := NewClient(httpServer.URL)
   939  
   940  	i := 0
   941  	responseBody = `{"result":3,"id":1,"jsonrpc":"2.0"}`
   942  	err := rpcClient.CallFor(context.Background(), &i, "something", 1, 2, 3)
   943  	<-requestChan
   944  	Expect(err).To(BeNil())
   945  	Expect(i).To(Equal(3))
   946  
   947  	/*
   948  		i = 3
   949  		responseBody = `{"result":null,"id":1,"jsonrpc":"2.0"}`
   950  		err = rpcClient.CallFor(&i, "something", 1, 2, 3)
   951  		<-requestChan
   952  		Expect(err).To(BeNil())
   953  		// i is not modified when result is empty since null (nil) value cannot be stored in int
   954  		Expect(i).To(Equal(3))
   955  
   956  		var pi *int
   957  		responseBody = `{"result":4,"id":1,"jsonrpc":"2.0"}`
   958  		err = rpcClient.CallFor(pi, "something", 1, 2, 3)
   959  		<-requestChan
   960  		Expect(err).NotTo(BeNil())
   961  		Expect(pi).To(BeNil())
   962  
   963  		responseBody = `{"result":4,"id":1,"jsonrpc":"2.0"}`
   964  		err = rpcClient.CallFor(&pi, "something", 1, 2, 3)
   965  		<-requestChan
   966  		Expect(err).To(BeNil())
   967  		Expect(*pi).To(Equal(4))
   968  
   969  		*pi = 3
   970  		responseBody = `{"result":null,"id":1,"jsonrpc":"2.0"}`
   971  		err = rpcClient.CallFor(&pi, "something", 1, 2, 3)
   972  		<-requestChan
   973  		Expect(err).To(BeNil())
   974  		// since pi has a value it is not overwritten by null result
   975  		Expect(pi).To(BeNil())
   976  
   977  		p := &Person{}
   978  		responseBody = `{"result":null,"id":1,"jsonrpc":"2.0"}`
   979  		err = rpcClient.CallFor(p, "something", 1, 2, 3)
   980  		<-requestChan
   981  		Expect(err).To(BeNil())
   982  		// p is not changed since it has a value and result is null
   983  		Expect(p).NotTo(BeNil())
   984  
   985  		var p2 *Person
   986  		responseBody = `{"result":null,"id":1,"jsonrpc":"2.0"}`
   987  		err = rpcClient.CallFor(p2, "something", 1, 2, 3)
   988  		<-requestChan
   989  		Expect(err).NotTo(BeNil())
   990  		// p is not changed since it has a value and result is null
   991  		Expect(p2).To(BeNil())
   992  
   993  		p3 := Person{}
   994  		responseBody = `{"result":null,"id":1,"jsonrpc":"2.0"}`
   995  		err = rpcClient.CallFor(&p3, "something", 1, 2, 3)
   996  		<-requestChan
   997  		Expect(err).To(BeNil())
   998  		// p is not changed since it has a value and result is null
   999  		Expect(p).NotTo(BeNil())
  1000  
  1001  		p = &Person{Age: 35}
  1002  		responseBody = `{"result":{"name":"Alex"},"id":1,"jsonrpc":"2.0"}`
  1003  		err = rpcClient.CallFor(p, "something", 1, 2, 3)
  1004  		<-requestChan
  1005  		Expect(err).To(BeNil())
  1006  		// p is not changed since it has a value and result is null
  1007  		Expect(p.Name).To(Equal("Alex"))
  1008  		Expect(p.Age).To(Equal(35))
  1009  
  1010  		p2 = nil
  1011  		responseBody = `{"result":{"name":"Alex"},"id":1,"jsonrpc":"2.0"}`
  1012  		err = rpcClient.CallFor(p2, "something", 1, 2, 3)
  1013  		<-requestChan
  1014  		Expect(err).NotTo(BeNil())
  1015  		// p is not changed since it has a value and result is null
  1016  		Expect(p2).To(BeNil())
  1017  
  1018  		p2 = nil
  1019  		responseBody = `{"result":{"name":"Alex"},"id":1,"jsonrpc":"2.0"}`
  1020  		err = rpcClient.CallFor(&p2, "something", 1, 2, 3)
  1021  		<-requestChan
  1022  		Expect(err).To(BeNil())
  1023  		// p is not changed since it has a value and result is null
  1024  		Expect(p2).NotTo(BeNil())
  1025  		Expect(p2.Name).To(Equal("Alex"))
  1026  
  1027  		p3 = Person{Age: 35}
  1028  		responseBody = `{"result":{"name":"Alex"},"id":1,"jsonrpc":"2.0"}`
  1029  		err = rpcClient.CallFor(&p3, "something", 1, 2, 3)
  1030  		<-requestChan
  1031  		Expect(err).To(BeNil())
  1032  		// p is not changed since it has a value and result is null
  1033  		Expect(p.Name).To(Equal("Alex"))
  1034  		Expect(p.Age).To(Equal(35))
  1035  
  1036  		p3 = Person{Age: 35}
  1037  		responseBody = `{"result":{"name":"Alex"},"id":1,"jsonrpc":"2.0"}`
  1038  		err = rpcClient.CallFor(&p3, "something", 1, 2, 3)
  1039  		<-requestChan
  1040  		Expect(err).To(BeNil())
  1041  		// p is not changed since it has a value and result is null
  1042  		Expect(p.Name).To(Equal("Alex"))
  1043  		Expect(p.Age).To(Equal(35))
  1044  
  1045  		var intArray []int
  1046  		responseBody = `{"result":[1, 2, 3],"id":1,"jsonrpc":"2.0"}`
  1047  		err = rpcClient.CallFor(&intArray, "something", 1, 2, 3)
  1048  		<-requestChan
  1049  		Expect(err).To(BeNil())
  1050  		// p is not changed since it has a value and result is null
  1051  		Expect(intArray).To(ContainElement(1))
  1052  		Expect(intArray).To(ContainElement(2))
  1053  		Expect(intArray).To(ContainElement(3))*/
  1054  }
  1055  
  1056  type Person struct {
  1057  	Name    string `json:"name"`
  1058  	Age     int    `json:"age"`
  1059  	Country string `json:"country"`
  1060  }
  1061  
  1062  type PointerFieldPerson struct {
  1063  	Name    *string `json:"name"`
  1064  	Age     *int    `json:"age"`
  1065  	Country *string `json:"country"`
  1066  }
  1067  
  1068  type Drink struct {
  1069  	Name        string   `json:"name"`
  1070  	Ingredients []string `json:"ingredients"`
  1071  }