github.com/noirx94/tendermintmp@v0.0.1/rpc/jsonrpc/server/http_server_test.go (about) 1 package server 2 3 import ( 4 "crypto/tls" 5 "errors" 6 "fmt" 7 "io/ioutil" 8 "net" 9 "net/http" 10 "net/http/httptest" 11 "sync" 12 "sync/atomic" 13 "testing" 14 "time" 15 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 19 "github.com/tendermint/tendermint/libs/log" 20 types "github.com/tendermint/tendermint/rpc/jsonrpc/types" 21 ) 22 23 type sampleResult struct { 24 Value string `json:"value"` 25 } 26 27 func TestMaxOpenConnections(t *testing.T) { 28 const max = 5 // max simultaneous connections 29 30 // Start the server. 31 var open int32 32 mux := http.NewServeMux() 33 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 34 if n := atomic.AddInt32(&open, 1); n > int32(max) { 35 t.Errorf("%d open connections, want <= %d", n, max) 36 } 37 defer atomic.AddInt32(&open, -1) 38 time.Sleep(10 * time.Millisecond) 39 fmt.Fprint(w, "some body") 40 }) 41 config := DefaultConfig() 42 config.MaxOpenConnections = max 43 l, err := Listen("tcp://127.0.0.1:0", config) 44 require.NoError(t, err) 45 defer l.Close() 46 go Serve(l, mux, log.TestingLogger(), config) //nolint:errcheck // ignore for tests 47 48 // Make N GET calls to the server. 49 attempts := max * 2 50 var wg sync.WaitGroup 51 var failed int32 52 for i := 0; i < attempts; i++ { 53 wg.Add(1) 54 go func() { 55 defer wg.Done() 56 c := http.Client{Timeout: 3 * time.Second} 57 r, err := c.Get("http://" + l.Addr().String()) 58 if err != nil { 59 atomic.AddInt32(&failed, 1) 60 return 61 } 62 defer r.Body.Close() 63 }() 64 } 65 wg.Wait() 66 67 // We expect some Gets to fail as the server's accept queue is filled, 68 // but most should succeed. 69 if int(failed) >= attempts/2 { 70 t.Errorf("%d requests failed within %d attempts", failed, attempts) 71 } 72 } 73 74 func TestServeTLS(t *testing.T) { 75 ln, err := net.Listen("tcp", "localhost:0") 76 require.NoError(t, err) 77 defer ln.Close() 78 79 mux := http.NewServeMux() 80 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 81 fmt.Fprint(w, "some body") 82 }) 83 84 chErr := make(chan error, 1) 85 go func() { 86 // FIXME This goroutine leaks 87 chErr <- ServeTLS(ln, mux, "test.crt", "test.key", log.TestingLogger(), DefaultConfig()) 88 }() 89 90 select { 91 case err := <-chErr: 92 require.NoError(t, err) 93 case <-time.After(100 * time.Millisecond): 94 } 95 96 tr := &http.Transport{ 97 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 98 } 99 c := &http.Client{Transport: tr} 100 res, err := c.Get("https://" + ln.Addr().String()) 101 require.NoError(t, err) 102 defer res.Body.Close() 103 assert.Equal(t, http.StatusOK, res.StatusCode) 104 105 body, err := ioutil.ReadAll(res.Body) 106 require.NoError(t, err) 107 assert.Equal(t, []byte("some body"), body) 108 } 109 110 func TestWriteRPCResponseHTTP(t *testing.T) { 111 id := types.JSONRPCIntID(-1) 112 113 // one argument 114 w := httptest.NewRecorder() 115 err := WriteRPCResponseHTTP(w, types.NewRPCSuccessResponse(id, &sampleResult{"hello"})) 116 require.NoError(t, err) 117 resp := w.Result() 118 body, err := ioutil.ReadAll(resp.Body) 119 _ = resp.Body.Close() 120 require.NoError(t, err) 121 assert.Equal(t, 200, resp.StatusCode) 122 assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) 123 assert.Equal(t, `{ 124 "jsonrpc": "2.0", 125 "id": -1, 126 "result": { 127 "value": "hello" 128 } 129 }`, string(body)) 130 131 // multiple arguments 132 w = httptest.NewRecorder() 133 err = WriteRPCResponseHTTP(w, 134 types.NewRPCSuccessResponse(id, &sampleResult{"hello"}), 135 types.NewRPCSuccessResponse(id, &sampleResult{"world"})) 136 require.NoError(t, err) 137 resp = w.Result() 138 body, err = ioutil.ReadAll(resp.Body) 139 _ = resp.Body.Close() 140 require.NoError(t, err) 141 142 assert.Equal(t, 200, resp.StatusCode) 143 assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) 144 assert.Equal(t, `[ 145 { 146 "jsonrpc": "2.0", 147 "id": -1, 148 "result": { 149 "value": "hello" 150 } 151 }, 152 { 153 "jsonrpc": "2.0", 154 "id": -1, 155 "result": { 156 "value": "world" 157 } 158 } 159 ]`, string(body)) 160 } 161 162 func TestWriteRPCResponseHTTPError(t *testing.T) { 163 w := httptest.NewRecorder() 164 err := WriteRPCResponseHTTPError( 165 w, 166 http.StatusInternalServerError, 167 types.RPCInternalError(types.JSONRPCIntID(-1), errors.New("foo"))) 168 require.NoError(t, err) 169 resp := w.Result() 170 body, err := ioutil.ReadAll(resp.Body) 171 _ = resp.Body.Close() 172 require.NoError(t, err) 173 assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) 174 assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) 175 assert.Equal(t, `{ 176 "jsonrpc": "2.0", 177 "id": -1, 178 "error": { 179 "code": -32603, 180 "message": "Internal error", 181 "data": "foo" 182 } 183 }`, string(body)) 184 }