You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

503 lines
17 KiB

package jsonrpc
import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"
"time"
"github.com/onsi/gomega"
)
// needed to retrieve requests that arrived at httpServer for further investigation
var requestChan = make(chan *RequestData, 1)
// the request datastructure that can be retrieved for test assertions
type RequestData struct {
request *http.Request
body string
}
// set the response body the httpServer should return for the next request
var responseBody = ""
var httpServer *httptest.Server
// start the testhttp server and stop it when tests are finished
func TestMain(m *testing.M) {
httpServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, _ := ioutil.ReadAll(r.Body)
defer r.Body.Close()
// put request and body to channel for the client to investigate them
requestChan <- &RequestData{r, string(data)}
fmt.Fprintf(w, responseBody)
}))
defer httpServer.Close()
os.Exit(m.Run())
}
func TestSimpleRpcCallHeaderCorrect(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.Call("add", 1, 2)
req := (<-requestChan).request
gomega.Expect(req.Method).To(gomega.Equal("POST"))
gomega.Expect(req.Header.Get("Content-Type")).To(gomega.Equal("application/json"))
gomega.Expect(req.Header.Get("Accept")).To(gomega.Equal("application/json"))
}
// test if the structure of an rpc request is built correctly validate the data that arrived on the server
func TestRpcJsonRequestStruct(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetAutoIncrementID(false)
rpcClient.Call("add", 1, 2)
body := (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"add","params":[1,2],"id":0}`))
rpcClient.Call("setName", "alex")
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"setName","params":["alex"],"id":0}`))
rpcClient.Call("setPerson", "alex", 33, "Germany")
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"setPerson","params":["alex",33,"Germany"],"id":0}`))
rpcClient.Call("setPersonObject", Person{"alex", 33, "Germany"})
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"setPersonObject","params":[{"name":"alex","age":33,"country":"Germany"}],"id":0}`))
rpcClient.Call("getDate")
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"getDate","id":0}`))
rpcClient.Call("setAnonymStruct", struct {
Name string `json:"name"`
Age int `json:"age"`
}{"Alex", 33})
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"setAnonymStruct","params":[{"name":"Alex","age":33}],"id":0}`))
}
// test if the structure of an rpc request is built correctly validate the data that arrived on the server
func TestRpcJsonRequestStructWithNamedParams(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetAutoIncrementID(false)
rpcClient.CallNamed("myMethod", map[string]interface{}{
"arrayOfInts": []int{1, 2, 3},
"arrayOfStrings": []string{"A", "B", "C"},
"bool": true,
"int": 1,
"number": 1.2,
"string": "boogaloo",
"subObject": map[string]interface{}{"foo": "bar"},
})
body := (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"myMethod","params":{"arrayOfInts":[1,2,3],"arrayOfStrings":["A","B","C"],"bool":true,"int":1,"number":1.2,"string":"boogaloo","subObject":{"foo":"bar"}},"id":0}`))
}
func TestRpcJsonResponseStruct(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetAutoIncrementID(false)
responseBody = `{"jsonrpc":"2.0","result":3,"id":0}`
response, _ := rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var int64Result int64
int64Result, _ = response.GetInt64()
gomega.Expect(int64Result).To(gomega.Equal(int64(3)))
responseBody = `{"jsonrpc":"2.0","result":3,"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var intResult int
intResult, _ = response.GetInt()
gomega.Expect(intResult).To(gomega.Equal(3))
responseBody = `{"jsonrpc":"2.0","result":3.3,"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
_, err := response.GetInt()
gomega.Expect(err).To(gomega.Not(gomega.Equal(nil)))
responseBody = `{"jsonrpc":"2.0","result":false,"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
_, err = response.GetInt()
gomega.Expect(err).To(gomega.Not(gomega.Equal(nil)))
responseBody = `{"jsonrpc":"2.0","result": 3.7,"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var float64Result float64
float64Result, _ = response.GetFloat64()
gomega.Expect(float64Result).To(gomega.Equal(3.7))
responseBody = `{"jsonrpc":"2.0","result": "1.3","id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
_, err = response.GetFloat64()
gomega.Expect(err).To(gomega.Not(gomega.Equal(nil)))
responseBody = `{"jsonrpc":"2.0","result": true,"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var boolResult bool
boolResult, _ = response.GetBool()
gomega.Expect(boolResult).To(gomega.Equal(true))
responseBody = `{"jsonrpc":"2.0","result": 0,"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
_, err = response.GetBool()
gomega.Expect(err).To(gomega.Not(gomega.Equal(nil)))
responseBody = `{"jsonrpc":"2.0","result": "alex","id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var stringResult string
stringResult, _ = response.GetString()
gomega.Expect(stringResult).To(gomega.Equal("alex"))
responseBody = `{"jsonrpc":"2.0","result": 123,"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
_, err = response.GetString()
gomega.Expect(err).To(gomega.Not(gomega.Equal(nil)))
responseBody = `{"jsonrpc":"2.0","result": {"name": "alex", "age": 33, "country": "Germany"},"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var person Person
response.GetObject(&person)
gomega.Expect(person).To(gomega.Equal(Person{"alex", 33, "Germany"}))
responseBody = `{"jsonrpc":"2.0","result": 3,"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var number int
response.GetObject(&number)
gomega.Expect(int(number)).To(gomega.Equal(3))
responseBody = `{"jsonrpc":"2.0","result": [{"name": "alex", "age": 33, "country": "Germany"}, {"name": "Ferolaz", "age": 333, "country": "Azeroth"}],"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var personArray = []Person{}
response.GetObject(&personArray)
gomega.Expect(personArray).To(gomega.Equal([]Person{{"alex", 33, "Germany"}, {"Ferolaz", 333, "Azeroth"}}))
responseBody = `{"jsonrpc":"2.0","result": [1, 2, 3],"id":0}`
response, _ = rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
var intArray []int
response.GetObject(&intArray)
gomega.Expect(intArray).To(gomega.Equal([]int{1, 2, 3}))
}
func TestResponseErrorWorks(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetAutoIncrementID(false)
responseBody = `{"jsonrpc":"2.0","error": {"code": -123, "message": "something wrong"},"id":0}`
response, _ := rpcClient.Call("test") // Call param does not matter, since response does not depend on request
<-requestChan
gomega.Expect(*response.Error).To(gomega.Equal(RPCError{-123, "something wrong", nil}))
}
func TestNotifyWorks(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.Notification("test", 10)
<-requestChan
rpcClient.Notification("test", Person{"alex", 33, "Germany"})
<-requestChan
rpcClient.Notification("test", 10, 20, "alex")
body := (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"test","params":[10,20,"alex"]}`))
}
func TestNewRPCRequestObject(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
req := rpcClient.NewRPCRequestObject("add", 1, 2)
gomega.Expect(req).To(gomega.Equal(&RPCRequest{
JSONRPC: "2.0",
ID: 0,
Method: "add",
Params: []interface{}{1, 2},
}))
req = rpcClient.NewRPCRequestObject("getDate")
gomega.Expect(req).To(gomega.Equal(&RPCRequest{
JSONRPC: "2.0",
ID: 1,
Method: "getDate",
Params: nil,
}))
req = rpcClient.NewRPCRequestObject("getPerson", Person{"alex", 33, "germany"})
gomega.Expect(req).To(gomega.Equal(&RPCRequest{
JSONRPC: "2.0",
ID: 2,
Method: "getPerson",
Params: []interface{}{Person{"alex", 33, "germany"}},
}))
}
func TestNewRPCNotificationObject(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
req := rpcClient.NewRPCNotificationObject("add", 1, 2)
gomega.Expect(req).To(gomega.Equal(&RPCNotification{
JSONRPC: "2.0",
Method: "add",
Params: []interface{}{1, 2},
}))
req = rpcClient.NewRPCNotificationObject("getDate")
gomega.Expect(req).To(gomega.Equal(&RPCNotification{
JSONRPC: "2.0",
Method: "getDate",
Params: nil,
}))
req = rpcClient.NewRPCNotificationObject("getPerson", Person{"alex", 33, "germany"})
gomega.Expect(req).To(gomega.Equal(&RPCNotification{
JSONRPC: "2.0",
Method: "getPerson",
Params: []interface{}{Person{"alex", 33, "germany"}},
}))
}
func TestBatchRequestWorks(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetCustomHeader("Test", "test")
req1 := rpcClient.NewRPCRequestObject("test1", "alex")
rpcClient.Batch(req1)
req := <-requestChan
body := req.body
gomega.Expect(req.request.Header.Get("Test")).To(gomega.Equal("test"))
gomega.Expect(body).To(gomega.Equal(`[{"jsonrpc":"2.0","method":"test1","params":["alex"],"id":0}]`))
notify1 := rpcClient.NewRPCNotificationObject("test2", "alex")
rpcClient.Batch(notify1)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`[{"jsonrpc":"2.0","method":"test2","params":["alex"]}]`))
rpcClient.Batch(req1, notify1)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`[{"jsonrpc":"2.0","method":"test1","params":["alex"],"id":0},{"jsonrpc":"2.0","method":"test2","params":["alex"]}]`))
requests := []interface{}{req1, notify1}
rpcClient.Batch(requests...)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`[{"jsonrpc":"2.0","method":"test1","params":["alex"],"id":0},{"jsonrpc":"2.0","method":"test2","params":["alex"]}]`))
invalid := &Person{"alex", 33, "germany"}
_, err := rpcClient.Batch(invalid, notify1)
gomega.Expect(err).To(gomega.Not(gomega.Equal(nil)))
}
func TestBatchResponseWorks(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
responseBody = `[{"jsonrpc":"2.0","result": 1,"id":0},{"jsonrpc":"2.0","result": 2,"id":1},{"jsonrpc":"2.0","result": 3,"id":3}]`
req1 := rpcClient.NewRPCRequestObject("test1", 1)
req2 := rpcClient.NewRPCRequestObject("test2", 2)
req3 := rpcClient.NewRPCRequestObject("test3", 3)
responses, _ := rpcClient.Batch(req1, req2, req3)
<-requestChan
resp2, _ := responses.GetResponseOf(req2)
res2, _ := resp2.GetInt()
gomega.Expect(res2).To(gomega.Equal(2))
}
func TestIDIncremtWorks(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetAutoIncrementID(true) // default
rpcClient.Call("test1", 1, 2)
body := (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"test1","params":[1,2],"id":0}`))
rpcClient.Call("test2", 1, 2)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"test2","params":[1,2],"id":1}`))
rpcClient.SetNextID(10)
rpcClient.Call("test3", 1, 2)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"test3","params":[1,2],"id":10}`))
rpcClient.Call("test4", 1, 2)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"test4","params":[1,2],"id":11}`))
rpcClient.SetAutoIncrementID(false)
rpcClient.Call("test5", 1, 2)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"test5","params":[1,2],"id":12}`))
rpcClient.Call("test6", 1, 2)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"test6","params":[1,2],"id":12}`))
}
func TestRequestIDUpdateWorks(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetAutoIncrementID(true) // default
req1 := rpcClient.NewRPCRequestObject("test", 1, 2, 3)
req2 := rpcClient.NewRPCRequestObject("test", 1, 2, 3)
gomega.Expect(int(req1.ID)).To(gomega.Equal(0))
gomega.Expect(int(req2.ID)).To(gomega.Equal(1))
rpcClient.UpdateRequestID(req1)
rpcClient.UpdateRequestID(req2)
gomega.Expect(int(req1.ID)).To(gomega.Equal(2))
gomega.Expect(int(req2.ID)).To(gomega.Equal(3))
rpcClient.UpdateRequestID(req2)
rpcClient.UpdateRequestID(req1)
gomega.Expect(int(req1.ID)).To(gomega.Equal(5))
gomega.Expect(int(req2.ID)).To(gomega.Equal(4))
rpcClient.UpdateRequestID(req1)
rpcClient.UpdateRequestID(req1)
gomega.Expect(int(req1.ID)).To(gomega.Equal(7))
gomega.Expect(int(req2.ID)).To(gomega.Equal(4))
rpcClient.SetAutoIncrementID(false)
rpcClient.UpdateRequestID(req2)
rpcClient.UpdateRequestID(req1)
gomega.Expect(int(req1.ID)).To(gomega.Equal(8))
gomega.Expect(int(req2.ID)).To(gomega.Equal(8))
rpcClient.SetAutoIncrementID(false)
}
func TestBasicAuthentication(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetBasicAuth("alex", "secret")
rpcClient.Call("add", 1, 2)
req := (<-requestChan).request
gomega.Expect(req.Header.Get("Authorization")).To(gomega.Equal("Basic YWxleDpzZWNyZXQ="))
rpcClient.SetBasicAuth("", "")
rpcClient.Call("add", 1, 2)
req = (<-requestChan).request
gomega.Expect(req.Header.Get("Authorization")).NotTo(gomega.Equal("Basic YWxleDpzZWNyZXQ="))
}
func TestCustomHeaders(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetCustomHeader("Test", "success")
rpcClient.Call("add", 1, 2)
req := (<-requestChan).request
gomega.Expect(req.Header.Get("Test")).To(gomega.Equal("success"))
rpcClient.SetCustomHeader("Test2", "success2")
rpcClient.Call("add", 1, 2)
req = (<-requestChan).request
gomega.Expect(req.Header.Get("Test")).To(gomega.Equal("success"))
gomega.Expect(req.Header.Get("Test2")).To(gomega.Equal("success2"))
rpcClient.UnsetCustomHeader("Test")
rpcClient.Call("add", 1, 2)
req = (<-requestChan).request
gomega.Expect(req.Header.Get("Test")).NotTo(gomega.Equal("success"))
gomega.Expect(req.Header.Get("Test2")).To(gomega.Equal("success2"))
}
func TestCustomHTTPClient(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
proxyURL, _ := url.Parse("http://proxy:8080")
transport := &http.Transport{Proxy: http.ProxyURL(proxyURL)}
httpClient := &http.Client{
Timeout: 5 * time.Second,
Transport: transport,
}
rpcClient.SetHTTPClient(httpClient)
rpcClient.Call("add", 1, 2)
// req := (<-requestChan).request
// TODO: what to test here?
}
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Country string `json:"country"`
}
func TestReadmeExamples(t *testing.T) {
gomega.RegisterTestingT(t)
rpcClient := NewRPCClient(httpServer.URL)
rpcClient.SetAutoIncrementID(false)
rpcClient.Call("getDate")
body := (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"getDate","id":0}`))
rpcClient.Call("addNumbers", 1, 2)
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"addNumbers","params":[1,2],"id":0}`))
rpcClient.Call("createPerson", "Alex", 33, "Germany")
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"createPerson","params":["Alex",33,"Germany"],"id":0}`))
rpcClient.Call("createPerson", Person{"Alex", 33, "Germany"})
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"createPerson","params":[{"name":"Alex","age":33,"country":"Germany"}],"id":0}`))
rpcClient.Call("createPersonsWithRole", []Person{{"Alex", 33, "Germany"}, {"Barney", 38, "Germany"}}, []string{"Admin", "User"})
body = (<-requestChan).body
gomega.Expect(body).To(gomega.Equal(`{"jsonrpc":"2.0","method":"createPersonsWithRole","params":[[{"name":"Alex","age":33,"country":"Germany"},{"name":"Barney","age":38,"country":"Germany"}],["Admin","User"]],"id":0}`))
}