Files
potency/potency_test.go
2023-04-24 22:30:39 +00:00

232 lines
4.7 KiB
Go

package potency_test
import (
"context"
"fmt"
"io"
"net"
"net/http"
"os"
"testing"
"time"
"github.com/dchest/uniuri"
"github.com/go-resty/resty/v2"
"github.com/gopatchy/potency"
"github.com/stretchr/testify/require"
)
func TestGET(t *testing.T) {
t.Parallel()
ts := newTestServer(t)
defer ts.shutdown(t)
key1 := uniuri.New()
resp, err := ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
Get("")
require.NoError(t, err)
require.False(t, resp.IsError())
require.Equal(t, "bar", resp.Header().Get("X-Response"))
resp1 := resp.String()
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
Get("")
require.NoError(t, err)
require.False(t, resp.IsError())
require.Equal(t, "bar", resp.Header().Get("X-Response"))
require.Equal(t, resp1, resp.String())
key2 := uniuri.New()
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key2)).
Get("")
require.NoError(t, err)
require.False(t, resp.IsError())
require.Equal(t, "bar", resp.Header().Get("X-Response"))
resp2 := resp.String()
require.NotEqual(t, resp2, resp1)
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
Get("x")
require.NoError(t, err)
require.True(t, resp.IsError())
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
Delete("")
require.NoError(t, err)
require.True(t, resp.IsError())
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
SetHeader("Authorization", "Bearer xyz").
Get("")
require.NoError(t, err)
require.True(t, resp.IsError())
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
SetHeader("Accept", "text/xml").
Get("")
require.NoError(t, err)
require.True(t, resp.IsError())
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
SetHeader("X-Test", "foo").
Get("")
require.NoError(t, err)
require.False(t, resp.IsError())
require.Equal(t, "bar", resp.Header().Get("X-Response"))
require.Equal(t, resp1, resp.String())
}
func TestPOST(t *testing.T) {
t.Parallel()
ts := newTestServer(t)
defer ts.shutdown(t)
key1 := uniuri.New()
resp, err := ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
SetBody("test1").
Post("")
require.NoError(t, err)
require.False(t, resp.IsError())
resp1 := resp.String()
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
SetBody("test1").
Post("")
require.NoError(t, err)
require.False(t, resp.IsError())
require.Equal(t, resp1, resp.String())
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
SetBody("test2").
Post("")
require.NoError(t, err)
require.True(t, resp.IsError())
}
func TestExpire(t *testing.T) {
t.Parallel()
ts := newTestServer(t)
defer ts.shutdown(t)
ts.pot.SetLifetime(1 * time.Second)
require.Equal(t, 0, ts.pot.NumCached())
key1 := uniuri.New()
resp, err := ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key1)).
SetBody("test1").
Post("")
require.NoError(t, err)
require.False(t, resp.IsError())
require.Equal(t, 1, ts.pot.NumCached())
key2 := uniuri.New()
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key2)).
SetBody("test2").
Post("")
require.NoError(t, err)
require.False(t, resp.IsError())
require.Equal(t, 2, ts.pot.NumCached())
time.Sleep(1100 * time.Millisecond)
key3 := uniuri.New()
resp, err = ts.r().
SetHeader("Idempotency-Key", fmt.Sprintf(`"%s"`, key3)).
SetBody("test3").
Post("")
require.NoError(t, err)
require.False(t, resp.IsError())
require.Equal(t, 1, ts.pot.NumCached())
}
type testServer struct {
dir string
pot *potency.Potency
srv *http.Server
rst *resty.Client
}
func newTestServer(t *testing.T) *testServer {
dir, err := os.MkdirTemp("", "")
require.NoError(t, err)
mux := http.NewServeMux()
p := potency.NewPotency(mux)
listener, err := net.Listen("tcp", "[::]:0")
require.NoError(t, err)
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, err := io.ReadAll(r.Body)
require.NoError(t, err)
w.Header().Add("X-Response", "bar")
_, err = w.Write([]byte(uniuri.New()))
require.NoError(t, err)
})
srv := &http.Server{
Handler: p,
ReadHeaderTimeout: 1 * time.Second,
}
go func() {
_ = srv.Serve(listener)
}()
baseURL := fmt.Sprintf("http://[::1]:%d/", listener.Addr().(*net.TCPAddr).Port)
rst := resty.New().
SetHeader("Content-Type", "application/json").
SetBaseURL(baseURL)
return &testServer{
dir: dir,
pot: p,
srv: srv,
rst: rst,
}
}
func (ts *testServer) r() *resty.Request {
return ts.rst.R()
}
func (ts *testServer) shutdown(t *testing.T) {
err := ts.srv.Shutdown(context.Background())
require.NoError(t, err)
os.RemoveAll(ts.dir)
}