feat: import jsteenb2/testttp directly into pkg

pull/15880/head
Johnny Steenbergen 2019-11-12 13:48:58 -08:00 committed by Johnny Steenbergen
parent b1749ce257
commit f6dbfec346
5 changed files with 251 additions and 6 deletions

1
go.mod
View File

@ -44,7 +44,6 @@ require (
github.com/influxdata/influxql v0.0.0-20180925231337-1cbfca8e56b6
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368
github.com/jessevdk/go-flags v1.4.0
github.com/jsteenb2/testttp v0.0.0-20191106182320-3a9029951f41
github.com/jsternberg/zap-logfmt v1.2.0
github.com/julienschmidt/httprouter v1.2.0
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef

6
go.sum
View File

@ -239,10 +239,10 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/changelog v1.1.0 h1:HXhmLZDrbuC+Ca5YX7g8B8cH5DmJpaOjd844d9Y7aTQ=
github.com/influxdata/changelog v1.1.0/go.mod h1:uzpGWE/qehT8L426YuXwpMQub+a63vIINhIeEI9mnSM=
github.com/influxdata/flux v0.54.0 h1:DjAkGoPkgHLDPEn1jSuOpsH4QgcjmSBkRuxSAaQCj1Q=
github.com/influxdata/flux v0.54.0/go.mod h1:ZFf4F0c8ACFP/5BkfCwk9I/vUwcByr0vMdLxwgOk57E=
github.com/influxdata/cron v0.0.0-20191112133922-ad5847cfab62 h1:YipnPuvJKPAzyBhr7eXIMA49L2Eooga/NSytWdLLI8U=
github.com/influxdata/cron v0.0.0-20191112133922-ad5847cfab62/go.mod h1:XabtPPW2qsCg0tl+kjaPU+cFS+CjQXEXbT1VJvHT4og=
github.com/influxdata/flux v0.54.0 h1:DjAkGoPkgHLDPEn1jSuOpsH4QgcjmSBkRuxSAaQCj1Q=
github.com/influxdata/flux v0.54.0/go.mod h1:ZFf4F0c8ACFP/5BkfCwk9I/vUwcByr0vMdLxwgOk57E=
github.com/influxdata/goreleaser v0.97.0-influx h1:jT5OrcW7WfS0e2QxfwmTBjhLvpIC9CDLRhNgZJyhj8s=
github.com/influxdata/goreleaser v0.97.0-influx/go.mod h1:MnjA0e0Uq6ISqjG1WxxMAl+3VS1QYjILSWVnMYDxasE=
github.com/influxdata/influxql v0.0.0-20180925231337-1cbfca8e56b6 h1:CFx+pP90q/qg3spoiZjf8donE4WpAdjeJfPOcoNqkWo=
@ -262,8 +262,6 @@ github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jsteenb2/testttp v0.0.0-20191106182320-3a9029951f41 h1:x4CmjEFDJd2LVNwfd35xxBsNHOySHAeTzdZuwV/CuXs=
github.com/jsteenb2/testttp v0.0.0-20191106182320-3a9029951f41/go.mod h1:Bpl/IMLYUekm9vMu/EA8SwzUtmH+rGBPKeY4xLswom8=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jsternberg/zap-logfmt v1.2.0 h1:1v+PK4/B48cy8cfQbxL4FmmNZrjnIMr2BsnyEmXqv2o=
github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0=

View File

@ -12,8 +12,8 @@ import (
"github.com/influxdata/influxdb"
fluxTTP "github.com/influxdata/influxdb/http"
"github.com/influxdata/influxdb/mock"
"github.com/influxdata/influxdb/pkg/testttp"
"github.com/influxdata/influxdb/pkger"
"github.com/jsteenb2/testttp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"

127
pkg/testttp/http.go Normal file
View File

@ -0,0 +1,127 @@
package testttp
import (
"bytes"
"io"
"net/http"
"net/http/httptest"
"testing"
)
// Req is a request builder.
type Req struct {
addr string
method string
body io.Reader
headers []string
}
// HTTP runs creates a request for an http call.
func HTTP(method, addr string, body io.Reader) *Req {
return &Req{
addr: addr,
method: method,
body: body,
}
}
// Delete creates a DELETE request.
func Delete(addr string) *Req {
return HTTP(http.MethodDelete, addr, nil)
}
// Get creates a GET request.
func Get(addr string) *Req {
return HTTP(http.MethodGet, addr, nil)
}
// Patch creates a PATCH request.
func Patch(addr string, body io.Reader) *Req {
return HTTP(http.MethodPatch, addr, body)
}
// Post creates a POST request.
func Post(addr string, body io.Reader) *Req {
return HTTP(http.MethodPost, addr, body)
}
// Put creates a PUT request.
func Put(addr string, body io.Reader) *Req {
return HTTP(http.MethodPut, addr, body)
}
// Headers allows the user to set headers on the http request.
func (r *Req) Headers(k, v string, rest ...string) *Req {
r.headers = append(r.headers, k, v)
r.headers = append(r.headers, rest...)
return r
}
// Do runs the request against the provided handler.
func (r *Req) Do(handler http.Handler) *Resp {
req := httptest.NewRequest(r.method, r.addr, r.body)
rec := httptest.NewRecorder()
for i := 0; i < len(r.headers); i += 2 {
if i+1 >= len(r.headers) {
break
}
k, v := r.headers[i], r.headers[i+1]
req.Header.Add(k, v)
}
handler.ServeHTTP(rec, req)
return &Resp{
Req: req,
Rec: rec,
}
}
// Resp is a http recorder wrapper.
type Resp struct {
Req *http.Request
Rec *httptest.ResponseRecorder
}
// Expect allows the assertions against the raw Resp.
func (r *Resp) Expect(fn func(*Resp)) *Resp {
fn(r)
return r
}
// ExpectStatus compares the expected status code against the recorded status code.
func (r *Resp) ExpectStatus(t *testing.T, code int) *Resp {
t.Helper()
if r.Rec.Code != code {
t.Errorf("unexpected status code: expected=%d got=%d", code, r.Rec.Code)
}
return r
}
// ExpectBody provides an assertion against the recorder body.
func (r *Resp) ExpectBody(fn func(*bytes.Buffer)) *Resp {
fn(r.Rec.Body)
return r
}
// ExpectHeader asserts that the header is in the recorder.
func (r *Resp) ExpectHeader(t *testing.T, k, v string) *Resp {
t.Helper()
vals, ok := r.Rec.Header()[k]
if !ok {
t.Errorf("did not find expected header: %q", k)
return r
}
for _, vv := range vals {
if vv == v {
return r
}
}
t.Errorf("did not find expected value for header %q; got: %v", k, vals)
return r
}

121
pkg/testttp/http_test.go Normal file
View File

@ -0,0 +1,121 @@
package testttp_test
import (
"bytes"
"encoding/json"
"io"
"net/http"
"strings"
"testing"
"github.com/influxdata/influxdb/pkg/testttp"
)
func TestHTTP(t *testing.T) {
svr := newMux()
t.Run("Get", func(t *testing.T) {
testttp.Get("/").
Do(svr).
ExpectStatus(t, http.StatusOK).
ExpectBody(assertBody(t, http.MethodGet))
})
t.Run("Post", func(t *testing.T) {
testttp.Post("/", nil).Do(svr).
ExpectStatus(t, http.StatusCreated).
ExpectBody(assertBody(t, http.MethodPost))
})
t.Run("Put", func(t *testing.T) {
testttp.Put("/", nil).
Do(svr).
ExpectStatus(t, http.StatusAccepted).
ExpectBody(assertBody(t, http.MethodPut))
})
t.Run("Patch", func(t *testing.T) {
testttp.Patch("/", nil).
Do(svr).
ExpectStatus(t, http.StatusPartialContent).
ExpectBody(assertBody(t, http.MethodPatch))
})
t.Run("Delete", func(t *testing.T) {
testttp.Delete("/").
Do(svr).
ExpectStatus(t, http.StatusNoContent)
})
t.Run("Headers", func(t *testing.T) {
testttp.Post("/", strings.NewReader(`a: foo`)).
Headers("Content-Type", "text/yml").
Do(svr).
Expect(func(resp *testttp.Resp) {
equals(t, "text/yml", resp.Req.Header.Get("Content-Type"))
})
})
}
type foo struct {
Name, Thing, Method string
}
func newMux() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
writeFn(w, req.Method, http.StatusOK)
case http.MethodPost:
writeFn(w, req.Method, http.StatusCreated)
case http.MethodPut:
writeFn(w, req.Method, http.StatusAccepted)
case http.MethodPatch:
writeFn(w, req.Method, http.StatusPartialContent)
case http.MethodDelete:
w.WriteHeader(http.StatusNoContent)
}
})
return mux
}
func assertBody(t *testing.T, method string) func(*bytes.Buffer) {
return func(buf *bytes.Buffer) {
var f foo
if err := json.NewDecoder(buf).Decode(&f); err != nil {
t.Fatal(err)
}
expected := foo{Name: "name", Thing: "thing", Method: method}
equals(t, expected, f)
}
}
func writeFn(w http.ResponseWriter, method string, statusCode int) {
f := foo{Name: "name", Thing: "thing", Method: method}
r, err := encodeBuf(f)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(statusCode)
if _, err := io.Copy(w, r); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
}
func equals(t *testing.T, expected, actual interface{}) {
t.Helper()
if expected == actual {
return
}
t.Errorf("expected: %v\tactual: %v", expected, actual)
}
func encodeBuf(v interface{}) (io.Reader, error) {
var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(v); err != nil {
return nil, err
}
return &buf, nil
}