github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/bft/rpc/lib/client/http/client_test.go (about) 1 package http 2 3 import ( 4 "context" 5 "encoding/json" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 "time" 10 11 types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestClient_parseRemoteAddr(t *testing.T) { 17 t.Parallel() 18 19 testTable := []struct { 20 remoteAddr string 21 network string 22 rest string 23 }{ 24 { 25 "127.0.0.1", 26 "tcp", 27 "127.0.0.1", 28 }, 29 { 30 "https://example.com", 31 "https", 32 "example.com", 33 }, 34 { 35 "wss://[::1]", 36 "wss", 37 "[::1]", 38 }, 39 } 40 41 for _, testCase := range testTable { 42 testCase := testCase 43 44 t.Run(testCase.remoteAddr, func(t *testing.T) { 45 t.Parallel() 46 47 n, r, err := parseRemoteAddr(testCase.remoteAddr) 48 require.NoError(t, err) 49 50 assert.Equal(t, n, testCase.network) 51 assert.Equal(t, r, testCase.rest) 52 }) 53 } 54 } 55 56 // Following tests check that we correctly translate http/https to tcp, 57 // and other protocols are left intact from parseRemoteAddr() 58 59 func TestClient_makeHTTPDialer(t *testing.T) { 60 t.Parallel() 61 62 t.Run("http", func(t *testing.T) { 63 t.Parallel() 64 65 _, err := makeHTTPDialer("https://.")("hello", "world") 66 require.Error(t, err) 67 68 assert.Contains(t, err.Error(), "dial tcp:", "should convert https to tcp") 69 assert.Contains(t, err.Error(), "address .:", "should have parsed the address (as incorrect)") 70 }) 71 72 t.Run("udp", func(t *testing.T) { 73 t.Parallel() 74 75 _, err := makeHTTPDialer("udp://.")("hello", "world") 76 require.Error(t, err) 77 78 assert.Contains(t, err.Error(), "dial udp:", "udp protocol should remain the same") 79 assert.Contains(t, err.Error(), "address .:", "should have parsed the address (as incorrect)") 80 }) 81 } 82 83 // createTestServer creates a test HTTP server 84 func createTestServer( 85 t *testing.T, 86 handler http.Handler, 87 ) *httptest.Server { 88 t.Helper() 89 90 s := httptest.NewServer(handler) 91 t.Cleanup(s.Close) 92 93 return s 94 } 95 96 func TestClient_SendRequest(t *testing.T) { 97 t.Parallel() 98 99 var ( 100 request = types.RPCRequest{ 101 JSONRPC: "2.0", 102 ID: types.JSONRPCStringID("id"), 103 } 104 105 handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 106 require.Equal(t, http.MethodPost, r.Method) 107 require.Equal(t, "application/json", r.Header.Get("content-type")) 108 109 // Parse the message 110 var req types.RPCRequest 111 require.NoError(t, json.NewDecoder(r.Body).Decode(&req)) 112 require.Equal(t, request.ID.String(), req.ID.String()) 113 114 // Send an empty response back 115 response := types.RPCResponse{ 116 JSONRPC: "2.0", 117 ID: req.ID, 118 } 119 120 // Marshal the response 121 marshalledResponse, err := json.Marshal(response) 122 require.NoError(t, err) 123 124 _, err = w.Write(marshalledResponse) 125 require.NoError(t, err) 126 }) 127 128 server = createTestServer(t, handler) 129 ) 130 131 // Create the client 132 c, err := NewClient(server.URL) 133 require.NoError(t, err) 134 135 ctx, cancelFn := context.WithTimeout(context.Background(), time.Second*5) 136 defer cancelFn() 137 138 // Send the request 139 resp, err := c.SendRequest(ctx, request) 140 require.NoError(t, err) 141 142 assert.Equal(t, request.ID, resp.ID) 143 assert.Equal(t, request.JSONRPC, resp.JSONRPC) 144 assert.Nil(t, resp.Result) 145 assert.Nil(t, resp.Error) 146 } 147 148 func TestClient_SendBatchRequest(t *testing.T) { 149 t.Parallel() 150 151 var ( 152 request = types.RPCRequest{ 153 JSONRPC: "2.0", 154 ID: types.JSONRPCStringID("id"), 155 } 156 157 requests = types.RPCRequests{ 158 request, 159 request, 160 } 161 162 handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 163 require.Equal(t, http.MethodPost, r.Method) 164 require.Equal(t, "application/json", r.Header.Get("content-type")) 165 166 // Parse the message 167 var reqs types.RPCRequests 168 require.NoError(t, json.NewDecoder(r.Body).Decode(&reqs)) 169 require.Len(t, reqs, len(requests)) 170 171 for _, req := range reqs { 172 require.Equal(t, request.ID.String(), req.ID.String()) 173 } 174 175 // Send an empty response batch back 176 response := types.RPCResponse{ 177 JSONRPC: "2.0", 178 ID: request.ID, 179 } 180 181 responses := types.RPCResponses{ 182 response, 183 response, 184 } 185 186 // Marshal the responses 187 marshalledResponses, err := json.Marshal(responses) 188 require.NoError(t, err) 189 190 _, err = w.Write(marshalledResponses) 191 require.NoError(t, err) 192 }) 193 194 server = createTestServer(t, handler) 195 ) 196 197 // Create the client 198 c, err := NewClient(server.URL) 199 require.NoError(t, err) 200 201 ctx, cancelFn := context.WithTimeout(context.Background(), time.Second*5) 202 defer cancelFn() 203 204 // Send the request 205 resps, err := c.SendBatch(ctx, requests) 206 require.NoError(t, err) 207 208 require.Len(t, resps, len(requests)) 209 210 for _, resp := range resps { 211 assert.Equal(t, request.ID, resp.ID) 212 assert.Equal(t, request.JSONRPC, resp.JSONRPC) 213 assert.Nil(t, resp.Result) 214 assert.Nil(t, resp.Error) 215 } 216 }