caching_test.go 3.66 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
package integration_tests

import (
	"bytes"
	"fmt"
	"github.com/alicebob/miniredis"
	"github.com/ethereum-optimism/optimism/go/proxyd"
	"github.com/stretchr/testify/require"
	"os"
	"testing"
	"time"
)

func TestCaching(t *testing.T) {
	redis, err := miniredis.Run()
	require.NoError(t, err)
	defer redis.Close()

19
	hdlr := NewRPCResponseHandler(map[string]interface{}{
20 21 22 23
		"eth_chainId":          "0x420",
		"net_version":          "0x1234",
		"eth_blockNumber":      "0x64",
		"eth_getBlockByNumber": "dummy_block",
24 25 26
		"eth_call":             "dummy_call",
	})
	backend := NewMockBackend(hdlr)
27 28 29 30 31 32 33 34 35 36 37 38 39 40
	defer backend.Close()

	require.NoError(t, os.Setenv("GOOD_BACKEND_RPC_URL", backend.URL()))
	require.NoError(t, os.Setenv("REDIS_URL", fmt.Sprintf("redis://127.0.0.1:%s", redis.Port())))
	config := ReadConfig("caching")
	client := NewProxydClient("http://127.0.0.1:8545")
	shutdown, err := proxyd.Start(config)
	require.NoError(t, err)
	defer shutdown()

	// allow time for the block number fetcher to fire
	time.Sleep(1500 * time.Millisecond)

	tests := []struct {
41 42 43 44
		method       string
		params       []interface{}
		response     string
		backendCalls int
45 46 47 48 49
	}{
		{
			"eth_chainId",
			nil,
			"{\"jsonrpc\": \"2.0\", \"result\": \"0x420\", \"id\": 999}",
50
			1,
51 52 53 54 55
		},
		{
			"net_version",
			nil,
			"{\"jsonrpc\": \"2.0\", \"result\": \"0x1234\", \"id\": 999}",
56
			1,
57 58 59 60 61 62 63 64
		},
		{
			"eth_getBlockByNumber",
			[]interface{}{
				"0x1",
				true,
			},
			"{\"jsonrpc\": \"2.0\", \"result\": \"dummy_block\", \"id\": 999}",
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
			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,
111 112 113 114
		},
	}
	for _, tt := range tests {
		t.Run(tt.method, func(t *testing.T) {
115
			resRaw, _, err := client.SendRPC(tt.method, tt.params)
116
			require.NoError(t, err)
117
			resCache, _, err := client.SendRPC(tt.method, tt.params)
118
			require.NoError(t, err)
119 120 121
			RequireEqualJSON(t, []byte(tt.response), resCache)
			RequireEqualJSON(t, resRaw, resCache)
			require.Equal(t, tt.backendCalls, countRequests(backend, tt.method))
122 123 124
			backend.Reset()
		})
	}
125

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
	t.Run("block numbers update", func(t *testing.T) {
		hdlr.SetResponse("eth_blockNumber", "0x100")
		time.Sleep(1500 * time.Millisecond)
		resRaw, _, err := client.SendRPC("eth_blockNumber", nil)
		require.NoError(t, err)
		RequireEqualJSON(t, []byte("{\"id\":999,\"jsonrpc\":\"2.0\",\"result\":\"0x100\"}"), resRaw)
		backend.Reset()
	})

	t.Run("nil responses should not be cached", func(t *testing.T) {
		hdlr.SetResponse("eth_getBlockByNumber", nil)
		resRaw, _, err := client.SendRPC("eth_getBlockByNumber", []interface{}{"0x123"})
		require.NoError(t, err)
		resCache, _, err := client.SendRPC("eth_getBlockByNumber", []interface{}{"0x123"})
		require.NoError(t, err)
		RequireEqualJSON(t, []byte("{\"id\":999,\"jsonrpc\":\"2.0\",\"result\":null}"), resRaw)
		RequireEqualJSON(t, resRaw, resCache)
		require.Equal(t, 2, countRequests(backend, "eth_getBlockByNumber"))
	})
145 146 147 148 149 150 151 152 153 154
}

func countRequests(backend *MockBackend, name string) int {
	var count int
	for _, req := range backend.Requests() {
		if bytes.Contains(req.Body, []byte(name)) {
			count++
		}
	}
	return count
155
}