Commit d064eb8e authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Merge pull request #2065 from mslipper/feat/caching-itests

go/proxyd: Add additional itests for cache, changeset
parents f4903adb bb0285bc
---
'@eth-optimism/proxyd': minor
---
Add caching for block-dependent RPCs
......@@ -6,6 +6,8 @@ on:
- 'master'
- 'develop'
pull_request:
paths:
- 'go/proxyd/**'
workflow_dispatch:
defaults:
......@@ -13,7 +15,9 @@ defaults:
working-directory: ./go/proxyd
jobs:
test:
tests:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
......
......@@ -16,12 +16,14 @@ func TestCaching(t *testing.T) {
require.NoError(t, err)
defer redis.Close()
backend := NewMockBackend(RPCResponseHandler(map[string]string{
hdlr := NewRPCResponseHandler(map[string]string{
"eth_chainId": "0x420",
"net_version": "0x1234",
"eth_blockNumber": "0x64",
"eth_getBlockByNumber": "dummy_block",
}))
"eth_call": "dummy_call",
})
backend := NewMockBackend(hdlr)
defer backend.Close()
require.NoError(t, os.Setenv("GOOD_BACKEND_RPC_URL", backend.URL()))
......@@ -39,16 +41,19 @@ func TestCaching(t *testing.T) {
method string
params []interface{}
response string
backendCalls int
}{
{
"eth_chainId",
nil,
"{\"jsonrpc\": \"2.0\", \"result\": \"0x420\", \"id\": 999}",
1,
},
{
"net_version",
nil,
"{\"jsonrpc\": \"2.0\", \"result\": \"0x1234\", \"id\": 999}",
1,
},
{
"eth_getBlockByNumber",
......@@ -57,23 +62,79 @@ func TestCaching(t *testing.T) {
true,
},
"{\"jsonrpc\": \"2.0\", \"result\": \"dummy_block\", \"id\": 999}",
1,
},
{
"eth_call",
[]interface{}{
struct {
To string `json:"to"`
}{
"0x1234",
},
"0x60",
},
"{\"id\":999,\"jsonrpc\":\"2.0\",\"result\":\"dummy_call\"}",
1,
},
{
"eth_blockNumber",
nil,
"{\"id\":999,\"jsonrpc\":\"2.0\",\"result\":\"0x64\"}",
0,
},
{
"eth_call",
[]interface{}{
struct {
To string `json:"to"`
}{
"0x1234",
},
"latest",
},
"{\"id\":999,\"jsonrpc\":\"2.0\",\"result\":\"dummy_call\"}",
2,
},
{
"eth_call",
[]interface{}{
struct {
To string `json:"to"`
}{
"0x1234",
},
"pending",
},
"{\"id\":999,\"jsonrpc\":\"2.0\",\"result\":\"dummy_call\"}",
2,
},
}
for _, tt := range tests {
t.Run(tt.method, func(t *testing.T) {
_, _, err := client.SendRPC(tt.method, tt.params)
resRaw, _, err := client.SendRPC(tt.method, tt.params)
require.NoError(t, err)
res, _, err := client.SendRPC(tt.method, tt.params)
resCache, _, err := client.SendRPC(tt.method, tt.params)
require.NoError(t, err)
RequireEqualJSON(t, []byte(tt.response), res)
RequireEqualJSON(t, []byte(tt.response), resCache)
RequireEqualJSON(t, resRaw, resCache)
require.Equal(t, tt.backendCalls, countRequests(backend, tt.method))
backend.Reset()
})
}
hdlr.SetResponse("eth_blockNumber", "0x100")
time.Sleep(1500 * time.Millisecond)
resRaw, _, err := client.SendRPC("eth_blockNumber", nil)
RequireEqualJSON(t, []byte("{\"id\":999,\"jsonrpc\":\"2.0\",\"result\":\"0x100\"}"), resRaw)
}
func countRequests(backend *MockBackend, name string) int {
var count int
for _, req := range backend.Requests() {
if bytes.Contains(req.Body, []byte(tt.method)) {
if bytes.Contains(req.Body, []byte(name)) {
count++
}
}
require.Equal(t, 1, count)
backend.Reset()
})
}
return count
}
......@@ -31,8 +31,24 @@ func SingleResponseHandler(code int, response string) http.HandlerFunc {
}
}
func RPCResponseHandler(rpcResponses map[string]string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
type RPCResponseHandler struct {
mtx sync.RWMutex
rpcResponses map[string]string
}
func NewRPCResponseHandler(rpcResponses map[string]string) *RPCResponseHandler {
return &RPCResponseHandler{
rpcResponses: rpcResponses,
}
}
func (h *RPCResponseHandler) SetResponse(method, response string) {
h.mtx.Lock()
defer h.mtx.Unlock()
h.rpcResponses[method] = response
}
func (h *RPCResponseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
......@@ -41,7 +57,9 @@ func RPCResponseHandler(rpcResponses map[string]string) http.HandlerFunc {
if err != nil {
panic(err)
}
res := rpcResponses[req.Method]
h.mtx.RLock()
res := h.rpcResponses[req.Method]
h.mtx.RUnlock()
if res == "" {
w.WriteHeader(400)
return
......@@ -56,7 +74,6 @@ func RPCResponseHandler(rpcResponses map[string]string) http.HandlerFunc {
if err := enc.Encode(out); err != nil {
panic(err)
}
}
}
func NewMockBackend(handler http.Handler) *MockBackend {
......
......@@ -25,3 +25,5 @@ backends = ["good"]
eth_chainId = "main"
net_version = "main"
eth_getBlockByNumber = "main"
eth_blockNumber = "main"
eth_call = "main"
......@@ -7,7 +7,7 @@ import (
)
func TestRPCResJSON(t *testing.T) {
tests := []struct{
tests := []struct {
name string
in *RPCRes
out string
......@@ -25,7 +25,7 @@ func TestRPCResJSON(t *testing.T) {
"object result",
&RPCRes{
JSONRPC: JSONRPCVersion,
Result: struct{
Result: struct {
Str string `json:"str"`
}{
"test",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment