|
|
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}`))
}
|