Multicall testcase improvements (#39)
* feat: improve the multicall test suite to use channels to explictly control the response flow, rather than sleep functions
This commit is contained in:
parent
88c767e316
commit
c03568e408
@ -3,7 +3,6 @@ package integration_tests
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
@ -58,7 +57,6 @@ func setupMulticall(t *testing.T) (map[string]nodeContext, *proxyd.BackendGroup,
|
|||||||
|
|
||||||
// setup proxyd
|
// setup proxyd
|
||||||
config := ReadConfig("multicall")
|
config := ReadConfig("multicall")
|
||||||
fmt.Printf("[SetupMulticall] Using Timeout of %d \n", config.Server.TimeoutSeconds)
|
|
||||||
svr, shutdown, err := proxyd.Start(config)
|
svr, shutdown, err := proxyd.Start(config)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -93,6 +91,7 @@ func setupMulticall(t *testing.T) (map[string]nodeContext, *proxyd.BackendGroup,
|
|||||||
|
|
||||||
handlers := []*ms.MockedHandler{&h1, &h2, &h3}
|
handlers := []*ms.MockedHandler{&h1, &h2, &h3}
|
||||||
|
|
||||||
|
// Default Handler configurations
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandler(200, txAccepted))
|
nodes["node1"].mockBackend.SetHandler(SingleResponseHandler(200, txAccepted))
|
||||||
nodes["node2"].mockBackend.SetHandler(http.HandlerFunc(handlers[1].Handler))
|
nodes["node2"].mockBackend.SetHandler(http.HandlerFunc(handlers[1].Handler))
|
||||||
//Node 3 has no handler empty handler never respondes should always context timeout
|
//Node 3 has no handler empty handler never respondes should always context timeout
|
||||||
@ -194,16 +193,30 @@ func TestMulticall(t *testing.T) {
|
|||||||
defer nodes["node3"].mockBackend.Close()
|
defer nodes["node3"].mockBackend.Close()
|
||||||
defer shutdown()
|
defer shutdown()
|
||||||
|
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandlerWithSleep(200, txAccepted, 3*time.Second))
|
triggerBackend1 := make(chan struct{})
|
||||||
nodes["node2"].mockBackend.SetHandler(SingleResponseHandler(200, txAccepted))
|
triggerBackend2 := make(chan struct{})
|
||||||
|
triggerBackend3 := make(chan struct{})
|
||||||
|
|
||||||
|
nodes["node1"].mockBackend.SetHandler(TriggerResponseHandler(200, txAccepted, triggerBackend1))
|
||||||
|
nodes["node2"].mockBackend.SetHandler(TriggerResponseHandler(200, txAccepted, triggerBackend2))
|
||||||
|
nodes["node3"].mockBackend.SetHandler(TriggerResponseHandler(200, txAccepted, triggerBackend3))
|
||||||
|
|
||||||
localSvr := setServerBackend(svr, nodes)
|
localSvr := setServerBackend(svr, nodes)
|
||||||
|
|
||||||
body := makeSendRawTransaction(txHex1)
|
body := makeSendRawTransaction(txHex1)
|
||||||
req, _ := http.NewRequest("POST", "https://1.1.1.1:8080", bytes.NewReader(body))
|
req, _ := http.NewRequest("POST", "https://1.1.1.1:8080", bytes.NewReader(body))
|
||||||
req.Header.Set("X-Forwarded-For", "203.0.113.1")
|
req.Header.Set("X-Forwarded-For", "203.0.113.1")
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
triggerBackend2 <- struct{}{}
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
triggerBackend1 <- struct{}{}
|
||||||
|
triggerBackend3 <- struct{}{}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
localSvr.HandleRPC(rr, req)
|
localSvr.HandleRPC(rr, req)
|
||||||
|
|
||||||
resp := rr.Result()
|
resp := rr.Result()
|
||||||
@ -219,6 +232,7 @@ func TestMulticall(t *testing.T) {
|
|||||||
require.Equal(t, resp.Header["X-Served-By"], []string{"node/node2"})
|
require.Equal(t, resp.Header["X-Served-By"], []string{"node/node2"})
|
||||||
require.False(t, rpcRes.IsError())
|
require.False(t, rpcRes.IsError())
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node1"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node1"))
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node2"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node2"))
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node3"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node3"))
|
||||||
@ -232,21 +246,13 @@ func TestMulticall(t *testing.T) {
|
|||||||
|
|
||||||
defer shutdown()
|
defer shutdown()
|
||||||
|
|
||||||
shutdownChan1 := make(chan struct{})
|
triggerBackend1 := make(chan struct{})
|
||||||
shutdownChan2 := make(chan struct{})
|
triggerBackend2 := make(chan struct{})
|
||||||
|
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(200, nonceErrorResponse, shutdownChan1, 4*time.Second))
|
nodes["node1"].mockBackend.SetHandler(TriggerResponseHandler(200, nonceErrorResponse, triggerBackend1))
|
||||||
nodes["node2"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(200, nonceErrorResponse, shutdownChan2, 1*time.Second))
|
nodes["node2"].mockBackend.SetHandler(TriggerResponseHandler(200, nonceErrorResponse, triggerBackend2))
|
||||||
nodes["node3"].mockBackend.SetHandler(SingleResponseHandler(403, dummyRes))
|
nodes["node3"].mockBackend.SetHandler(SingleResponseHandler(403, dummyRes))
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
shutdownChan2 <- struct{}{}
|
|
||||||
shutdownChan1 <- struct{}{}
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
localSvr := setServerBackend(svr, nodes)
|
localSvr := setServerBackend(svr, nodes)
|
||||||
|
|
||||||
body := makeSendRawTransaction(txHex1)
|
body := makeSendRawTransaction(txHex1)
|
||||||
@ -254,6 +260,15 @@ func TestMulticall(t *testing.T) {
|
|||||||
req.Header.Set("X-Forwarded-For", "203.0.113.1")
|
req.Header.Set("X-Forwarded-For", "203.0.113.1")
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
triggerBackend2 <- struct{}{}
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
triggerBackend1 <- struct{}{}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
localSvr.HandleRPC(rr, req)
|
localSvr.HandleRPC(rr, req)
|
||||||
|
|
||||||
resp := rr.Result()
|
resp := rr.Result()
|
||||||
@ -281,8 +296,10 @@ func TestMulticall(t *testing.T) {
|
|||||||
defer nodes["node3"].mockBackend.Close()
|
defer nodes["node3"].mockBackend.Close()
|
||||||
defer shutdown()
|
defer shutdown()
|
||||||
|
|
||||||
|
triggerBackend1 := make(chan struct{})
|
||||||
|
|
||||||
// We should ignore node2 first response cause 429, and return node 1 because 200
|
// We should ignore node2 first response cause 429, and return node 1 because 200
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandlerWithSleep(200, txAccepted, 3*time.Second))
|
nodes["node1"].mockBackend.SetHandler(TriggerResponseHandler(200, txAccepted, triggerBackend1))
|
||||||
nodes["node2"].mockBackend.SetHandler(SingleResponseHandler(429, txAccepted))
|
nodes["node2"].mockBackend.SetHandler(SingleResponseHandler(429, txAccepted))
|
||||||
|
|
||||||
localSvr := setServerBackend(svr, nodes)
|
localSvr := setServerBackend(svr, nodes)
|
||||||
@ -292,6 +309,14 @@ func TestMulticall(t *testing.T) {
|
|||||||
req.Header.Set("X-Forwarded-For", "203.0.113.1")
|
req.Header.Set("X-Forwarded-For", "203.0.113.1")
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
triggerBackend1 <- struct{}{}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
localSvr.HandleRPC(rr, req)
|
localSvr.HandleRPC(rr, req)
|
||||||
|
|
||||||
resp := rr.Result()
|
resp := rr.Result()
|
||||||
@ -305,6 +330,7 @@ func TestMulticall(t *testing.T) {
|
|||||||
require.Equal(t, "2.0", rpcRes.JSONRPC)
|
require.Equal(t, "2.0", rpcRes.JSONRPC)
|
||||||
|
|
||||||
require.Equal(t, resp.Header["X-Served-By"], []string{"node/node1"})
|
require.Equal(t, resp.Header["X-Served-By"], []string{"node/node1"})
|
||||||
|
wg.Wait()
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node1"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node1"))
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node2"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node2"))
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node3"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node3"))
|
||||||
@ -317,9 +343,9 @@ func TestMulticall(t *testing.T) {
|
|||||||
defer nodes["node3"].mockBackend.Close()
|
defer nodes["node3"].mockBackend.Close()
|
||||||
defer shutdown()
|
defer shutdown()
|
||||||
|
|
||||||
shutdownChan := make(chan struct{})
|
triggerBackend := make(chan struct{})
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandler(200, dummyRes))
|
nodes["node1"].mockBackend.SetHandler(SingleResponseHandler(200, dummyRes))
|
||||||
nodes["node2"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(200, dummyRes, shutdownChan, 7*time.Second))
|
nodes["node2"].mockBackend.SetHandler(TriggerResponseHandler(200, dummyRes, triggerBackend))
|
||||||
|
|
||||||
localSvr := setServerBackend(svr, nodes)
|
localSvr := setServerBackend(svr, nodes)
|
||||||
|
|
||||||
@ -329,8 +355,14 @@ func TestMulticall(t *testing.T) {
|
|||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
localSvr.HandleRPC(rr, req)
|
localSvr.HandleRPC(rr, req)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
time.Sleep(7 * time.Second)
|
||||||
|
triggerBackend <- struct{}{}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
resp := rr.Result()
|
resp := rr.Result()
|
||||||
shutdownChan <- struct{}{}
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
require.NotNil(t, resp.Body)
|
require.NotNil(t, resp.Body)
|
||||||
@ -342,6 +374,7 @@ func TestMulticall(t *testing.T) {
|
|||||||
require.NoError(t, json.NewDecoder(resp.Body).Decode(rpcRes))
|
require.NoError(t, json.NewDecoder(resp.Body).Decode(rpcRes))
|
||||||
require.False(t, rpcRes.IsError())
|
require.False(t, rpcRes.IsError())
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node1"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node1"))
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node2"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node2"))
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node3"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node3"))
|
||||||
@ -355,10 +388,10 @@ func TestMulticall(t *testing.T) {
|
|||||||
defer nodes["node3"].mockBackend.Close()
|
defer nodes["node3"].mockBackend.Close()
|
||||||
defer shutdown()
|
defer shutdown()
|
||||||
|
|
||||||
shutdownChan1 := make(chan struct{})
|
triggerBackend1 := make(chan struct{})
|
||||||
shutdownChan2 := make(chan struct{})
|
triggerBackend2 := make(chan struct{})
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(200, dummyRes, shutdownChan1, 7*time.Second))
|
nodes["node1"].mockBackend.SetHandler(TriggerResponseHandler(200, dummyRes, triggerBackend1))
|
||||||
nodes["node2"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(200, dummyRes, shutdownChan2, 7*time.Second))
|
nodes["node2"].mockBackend.SetHandler(TriggerResponseHandler(200, dummyRes, triggerBackend2))
|
||||||
|
|
||||||
localSvr := setServerBackend(svr, nodes)
|
localSvr := setServerBackend(svr, nodes)
|
||||||
|
|
||||||
@ -370,12 +403,12 @@ func TestMulticall(t *testing.T) {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
shutdownChan1 <- struct{}{}
|
time.Sleep(7 * time.Second)
|
||||||
shutdownChan2 <- struct{}{}
|
triggerBackend1 <- struct{}{}
|
||||||
|
triggerBackend2 <- struct{}{}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
fmt.Println("sending request")
|
|
||||||
localSvr.HandleRPC(rr, req)
|
localSvr.HandleRPC(rr, req)
|
||||||
|
|
||||||
resp := rr.Result()
|
resp := rr.Result()
|
||||||
@ -388,7 +421,6 @@ func TestMulticall(t *testing.T) {
|
|||||||
require.True(t, rpcRes.IsError())
|
require.True(t, rpcRes.IsError())
|
||||||
require.Equal(t, rpcRes.Error.Code, proxyd.ErrNoBackends.Code)
|
require.Equal(t, rpcRes.Error.Code, proxyd.ErrNoBackends.Code)
|
||||||
|
|
||||||
// Wait for test response to complete before checking query count
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node1"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node1"))
|
||||||
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node2"))
|
require.Equal(t, 1, nodeBackendRequestCount(nodes, "node2"))
|
||||||
@ -403,24 +435,24 @@ func TestMulticall(t *testing.T) {
|
|||||||
defer shutdown()
|
defer shutdown()
|
||||||
|
|
||||||
for i := 1; i < 4; i++ {
|
for i := 1; i < 4; i++ {
|
||||||
shutdownChan1 := make(chan struct{})
|
triggerBackend1 := make(chan struct{})
|
||||||
shutdownChan2 := make(chan struct{})
|
triggerBackend2 := make(chan struct{})
|
||||||
shutdownChan3 := make(chan struct{})
|
triggerBackend3 := make(chan struct{})
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case i == 1:
|
case i == 1:
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(200, txAccepted, shutdownChan1, 1*time.Second))
|
nodes["node1"].mockBackend.SetHandler(TriggerResponseHandler(200, txAccepted, triggerBackend1))
|
||||||
nodes["node2"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(429, dummyRes, shutdownChan2, 1*time.Second))
|
nodes["node2"].mockBackend.SetHandler(TriggerResponseHandler(429, dummyRes, triggerBackend2))
|
||||||
nodes["node3"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(503, dummyRes, shutdownChan3, 1*time.Second))
|
nodes["node3"].mockBackend.SetHandler(TriggerResponseHandler(503, dummyRes, triggerBackend3))
|
||||||
case i == 2:
|
case i == 2:
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(404, dummyRes, shutdownChan1, 1*time.Second))
|
nodes["node1"].mockBackend.SetHandler(TriggerResponseHandler(404, dummyRes, triggerBackend1))
|
||||||
nodes["node2"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(200, nonceErrorResponse, shutdownChan2, 1*time.Second))
|
nodes["node2"].mockBackend.SetHandler(TriggerResponseHandler(200, nonceErrorResponse, triggerBackend2))
|
||||||
nodes["node3"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(405, dummyRes, shutdownChan3, 1*time.Second))
|
nodes["node3"].mockBackend.SetHandler(TriggerResponseHandler(405, dummyRes, triggerBackend3))
|
||||||
case i == 3:
|
case i == 3:
|
||||||
// Return the quickest response
|
// Return the quickest response
|
||||||
nodes["node1"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(404, dummyRes, shutdownChan1, 1*time.Second))
|
nodes["node1"].mockBackend.SetHandler(TriggerResponseHandler(404, dummyRes, triggerBackend1))
|
||||||
nodes["node2"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(500, dummyRes, shutdownChan2, 1*time.Second))
|
nodes["node2"].mockBackend.SetHandler(TriggerResponseHandler(500, dummyRes, triggerBackend2))
|
||||||
nodes["node3"].mockBackend.SetHandler(SingleResponseHandlerWithSleepShutdown(200, nonceErrorResponse, shutdownChan3, 1*time.Second))
|
nodes["node3"].mockBackend.SetHandler(TriggerResponseHandler(200, nonceErrorResponse, triggerBackend3))
|
||||||
}
|
}
|
||||||
|
|
||||||
localSvr := setServerBackend(svr, nodes)
|
localSvr := setServerBackend(svr, nodes)
|
||||||
@ -433,9 +465,9 @@ func TestMulticall(t *testing.T) {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
shutdownChan1 <- struct{}{}
|
triggerBackend1 <- struct{}{}
|
||||||
shutdownChan2 <- struct{}{}
|
triggerBackend2 <- struct{}{}
|
||||||
shutdownChan3 <- struct{}{}
|
triggerBackend3 <- struct{}{}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -475,25 +507,13 @@ func TestMulticall(t *testing.T) {
|
|||||||
require.Equal(t, i, nodeBackendRequestCount(nodes, "node3"))
|
require.Equal(t, i, nodeBackendRequestCount(nodes, "node3"))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SingleResponseHandlerWithSleep(code int, response string, duration time.Duration) http.HandlerFunc {
|
// TriggerResponseHandler uses a channel to control when a backend returns
|
||||||
|
// test cases can add an element to the triggerResponse channel to control the when a specific backend returns
|
||||||
|
func TriggerResponseHandler(code int, response string, triggerResponse chan struct{}) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Println("sleeping")
|
<-triggerResponse
|
||||||
time.Sleep(duration)
|
|
||||||
fmt.Println("Shutting down Single Response Handler")
|
|
||||||
w.WriteHeader(code)
|
|
||||||
_, _ = w.Write([]byte(response))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SingleResponseHandlerWithSleepShutdown(code int, response string, shutdownServer chan struct{}, duration time.Duration) http.HandlerFunc {
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Println("sleeping")
|
|
||||||
time.Sleep(duration)
|
|
||||||
<-shutdownServer
|
|
||||||
fmt.Println("Shutting down Single Response Handler")
|
|
||||||
w.WriteHeader(code)
|
w.WriteHeader(code)
|
||||||
_, _ = w.Write([]byte(response))
|
_, _ = w.Write([]byte(response))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user