Skip to content

Commit

Permalink
test: server read and write timeouts
Browse files Browse the repository at this point in the history
  • Loading branch information
sietseringers committed Aug 2, 2020
1 parent ddc64f7 commit 1e22953
Showing 1 changed file with 89 additions and 0 deletions.
89 changes: 89 additions & 0 deletions server/api_test.go
@@ -1,9 +1,14 @@
package server

import (
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"testing"
"time"

"github.com/privacybydesign/irmago"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -73,3 +78,87 @@ func TestParseSessionRequest(t *testing.T) {
require.Error(t, err)
})
}

type readerFunc func(p []byte) (int, error)

func (r readerFunc) Read(p []byte) (int, error) { return r(p) }

func TestServerTimeouts(t *testing.T) {
timeout := 250 * time.Millisecond
var called bool

tests := []struct {
name string
handler http.Handler
body io.Reader
readTimeout time.Duration
}{
{
name: "write",
handler: TimeoutMiddleware(nil, timeout)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
called = true
time.Sleep(2 * timeout)
})),
body: nil,
readTimeout: ReadTimeout,
},
{
name: "read",
handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
called = true
start := time.Now()
_, err := ioutil.ReadAll(r.Body)
// check that reading has halted with an error just after the deadline
require.Error(t, err)
require.Greater(t, int64(timeout+50*time.Millisecond), int64(time.Now().Sub(start)))
w.WriteHeader(400)
}),
body: readerFunc(func(p []byte) (int, error) {
time.Sleep(2 * timeout)
return 0, io.EOF
}),
readTimeout: timeout,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
// start server
s := startServer(t, test.handler, test.readTimeout)
defer stopServer(t, s)

// do request
called = false
req, err := http.NewRequest(http.MethodPost, "http://localhost:34534", test.body)
require.NoError(t, err)
start := time.Now()
res, err := http.DefaultClient.Do(req)
require.NoError(t, err)

// check that request was aborted after the timeout and before the handler finished
require.Greater(t, int64(timeout+50*time.Millisecond), int64(time.Now().Sub(start)))
require.GreaterOrEqual(t, res.StatusCode, 400)
require.True(t, called)
})
}
}

func startServer(t *testing.T, handler http.Handler, timeout time.Duration) *http.Server {
s := &http.Server{
Addr: "localhost:34534",
Handler: handler,
ReadTimeout: timeout,
}
go func() {
err := s.ListenAndServe()
require.Equal(t, http.ErrServerClosed, err)
}()
time.Sleep(50 * time.Millisecond) // give server time to start
return s
}

func stopServer(t *testing.T, server *http.Server) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
require.NoError(t, server.Shutdown(ctx))
cancel()
}

0 comments on commit 1e22953

Please sign in to comment.