|
|
@@ -2,18 +2,27 @@ package web
|
|
|
|
|
|
import (
|
|
|
"bytes"
|
|
|
+ "encoding/base64"
|
|
|
"encoding/json"
|
|
|
+ "errors"
|
|
|
"fmt"
|
|
|
"io"
|
|
|
"io/ioutil"
|
|
|
"net/http"
|
|
|
+ "net/url"
|
|
|
"os"
|
|
|
"path/filepath"
|
|
|
"testing"
|
|
|
+ "time"
|
|
|
|
|
|
"github.com/kellegous/go/context"
|
|
|
+ "github.com/syndtr/goleveldb/leveldb"
|
|
|
)
|
|
|
|
|
|
+type urlReq struct {
|
|
|
+ URL string `json:"url"`
|
|
|
+}
|
|
|
+
|
|
|
type env struct {
|
|
|
mux *http.ServeMux
|
|
|
dir string
|
|
|
@@ -24,42 +33,41 @@ func (e *env) destroy() {
|
|
|
os.RemoveAll(e.dir)
|
|
|
}
|
|
|
|
|
|
-func (e *env) getAPI(m *msg, name string) error {
|
|
|
- return e.callAPI(m, "GET", name, nil)
|
|
|
+func (e *env) get(path string) (*mockResponse, error) {
|
|
|
+ return e.call("GET", path, nil)
|
|
|
}
|
|
|
|
|
|
-func (e *env) postAPI(m *msg, name, url string) error {
|
|
|
- r := struct {
|
|
|
- URL string `json:"url"`
|
|
|
- }{
|
|
|
- url,
|
|
|
- }
|
|
|
+func (e *env) post(path string, body interface{}) (*mockResponse, error) {
|
|
|
+ return e.callWithJSON("POST", path, body)
|
|
|
+}
|
|
|
+
|
|
|
+func (e *env) callWithJSON(method, path string, body interface{}) (*mockResponse, error) {
|
|
|
+ var r io.Reader
|
|
|
|
|
|
- var buf bytes.Buffer
|
|
|
- if err := json.NewEncoder(&buf).Encode(&r); err != nil {
|
|
|
- return err
|
|
|
+ if body != nil {
|
|
|
+ var buf bytes.Buffer
|
|
|
+ if err := json.NewEncoder(&buf).Encode(body); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ r = &buf
|
|
|
}
|
|
|
|
|
|
- return e.callAPI(m, "POST", name, &buf)
|
|
|
+ return e.call(method, path, r)
|
|
|
}
|
|
|
|
|
|
-func (e *env) callAPI(m *msg, method, name string, body io.Reader) error {
|
|
|
- req, err := http.NewRequest(method, fmt.Sprintf("/api/url/%s", name), body)
|
|
|
+func (e *env) call(method, path string, body io.Reader) (*mockResponse, error) {
|
|
|
+ req, err := http.NewRequest(method, path, body)
|
|
|
if err != nil {
|
|
|
- return err
|
|
|
+ return nil, err
|
|
|
}
|
|
|
|
|
|
- res := mockResponse{
|
|
|
+ res := &mockResponse{
|
|
|
header: map[string][]string{},
|
|
|
}
|
|
|
|
|
|
- e.mux.ServeHTTP(&res, req)
|
|
|
-
|
|
|
- if err := json.NewDecoder(&res).Decode(&m); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
+ e.mux.ServeHTTP(res, req)
|
|
|
|
|
|
- return nil
|
|
|
+ return res, nil
|
|
|
}
|
|
|
|
|
|
func newEnv() (*env, error) {
|
|
|
@@ -107,42 +115,52 @@ func (r *mockResponse) WriteHeader(status int) {
|
|
|
r.status = status
|
|
|
}
|
|
|
|
|
|
-func assertJustOk(t *testing.T, m *msg) {
|
|
|
- if !m.Ok {
|
|
|
- t.Fatal("expected OK message, but it's not OK")
|
|
|
+func mustBeSameNamedRoute(t *testing.T, a, b *routeWithName) {
|
|
|
+ if a.Name != b.Name || a.URL != b.URL || a.Time.UnixNano() != b.Time.UnixNano() {
|
|
|
+ t.Fatalf("routes are not same: %v vs %v", a, b)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func mustBeRouteOf(t *testing.T, rt *context.Route, url string) {
|
|
|
+ if rt == nil {
|
|
|
+ t.Fatal("route is nil")
|
|
|
}
|
|
|
|
|
|
- if m.Error != "" {
|
|
|
- t.Fatalf("expected no error, but got %s", m.Error)
|
|
|
+ if rt.URL != url {
|
|
|
+ t.Fatalf("expected url of %s, got %s", url, rt.URL)
|
|
|
}
|
|
|
|
|
|
- if m.Route != nil {
|
|
|
- t.Fatalf("expected no route, got %v", m.Route)
|
|
|
+ if rt.Time.IsZero() {
|
|
|
+ t.Fatal("route time is empty")
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func assertOkWithRoute(t *testing.T, m *msg, url string) {
|
|
|
- if !m.Ok {
|
|
|
- t.Fatal("expected OK message, but it's not OK")
|
|
|
+func mustBeNamedRouteOf(t *testing.T, rt *routeWithName, name, url string) {
|
|
|
+ mustBeRouteOf(t, rt.Route, url)
|
|
|
+ if rt.Name != name {
|
|
|
+ t.Fatalf("expected name of %s, got %s", name, rt.Name)
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- if m.Error != "" {
|
|
|
- t.Fatalf("expected no error, but got %s", m.Error)
|
|
|
+func mustBeOk(t *testing.T, ok bool) {
|
|
|
+ if !ok {
|
|
|
+ t.Fatal("response is not ok")
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- if m.Route == nil {
|
|
|
- t.Fatalf("Route is nil, expected one with url of %s", url)
|
|
|
+func mustBeErr(t *testing.T, m *msgErr) {
|
|
|
+ if m.Ok {
|
|
|
+ t.Fatal("response is ok, should be err")
|
|
|
}
|
|
|
|
|
|
- if m.Route.URL != url {
|
|
|
- t.Fatalf("Expected url of %s, got %s", url, m.Route.URL)
|
|
|
+ if m.Error == "" {
|
|
|
+ t.Fatal("expected an Error, but it is empty")
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func assertOkWithNamedRoute(t *testing.T, m *msg, name, url string) {
|
|
|
- assertOkWithRoute(t, m, url)
|
|
|
- if m.Route.Name != name {
|
|
|
- t.Fatalf("expected name %s, got %s", name, m.Route.Name)
|
|
|
+func mustHaveStatus(t *testing.T, res *mockResponse, status int) {
|
|
|
+ if res.status != status {
|
|
|
+ t.Fatalf("expected response status %d, got %d", status, res.status)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -150,13 +168,26 @@ func TestAPIGetNotFound(t *testing.T) {
|
|
|
e := needEnv(t)
|
|
|
defer e.destroy()
|
|
|
|
|
|
- var m msg
|
|
|
- names := []string{"", "nothing", "nothing/there"}
|
|
|
- for _, name := range names {
|
|
|
- if err := e.getAPI(&m, name); err != nil {
|
|
|
+ names := map[string]int{
|
|
|
+ "": http.StatusBadRequest,
|
|
|
+ "nothing": http.StatusNotFound,
|
|
|
+ "nothing/there": http.StatusNotFound,
|
|
|
+ }
|
|
|
+
|
|
|
+ for name, status := range names {
|
|
|
+ res, err := e.get(fmt.Sprintf("/api/url/%s", name))
|
|
|
+ if err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
- assertJustOk(t, &m)
|
|
|
+
|
|
|
+ mustHaveStatus(t, res, status)
|
|
|
+
|
|
|
+ var m msgErr
|
|
|
+ if err := json.NewDecoder(res).Decode(&m); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ mustBeErr(t, &m)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -164,61 +195,383 @@ func TestAPIPutThenGet(t *testing.T) {
|
|
|
e := needEnv(t)
|
|
|
defer e.destroy()
|
|
|
|
|
|
- var pm msg
|
|
|
- if err := e.postAPI(&pm, "xxx", "http://ex.com/"); err != nil {
|
|
|
+ res, err := e.post("/api/url/xxx", &urlReq{
|
|
|
+ URL: "http://ex.com/",
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ mustHaveStatus(t, res, http.StatusOK)
|
|
|
+
|
|
|
+ var pm msgRoute
|
|
|
+ if err := json.NewDecoder(res).Decode(&pm); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ mustBeOk(t, pm.Ok)
|
|
|
+ mustBeNamedRouteOf(t, pm.Route, "xxx", "http://ex.com/")
|
|
|
+
|
|
|
+ res, err = e.get("/api/url/xxx")
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ mustHaveStatus(t, res, http.StatusOK)
|
|
|
+
|
|
|
+ var gm msgRoute
|
|
|
+ if err := json.NewDecoder(res).Decode(&gm); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ mustBeOk(t, gm.Ok)
|
|
|
+ mustBeNamedRouteOf(t, pm.Route, "xxx", "http://ex.com/")
|
|
|
+}
|
|
|
+
|
|
|
+func TestBadPuts(t *testing.T) {
|
|
|
+ e := needEnv(t)
|
|
|
+ defer e.destroy()
|
|
|
+
|
|
|
+ var m msgErr
|
|
|
+
|
|
|
+ res, err := e.call("POST", "/api/url/yyy", bytes.NewBufferString("not json"))
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ mustHaveStatus(t, res, http.StatusBadRequest)
|
|
|
+
|
|
|
+ if err := json.NewDecoder(res).Decode(&m); err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
- assertOkWithRoute(t, &pm, "http://ex.com/")
|
|
|
+ mustBeErr(t, &m)
|
|
|
|
|
|
- var gm msg
|
|
|
- if err := e.getAPI(&gm, "xxx"); err != nil {
|
|
|
+ res, err = e.post("/api/url/yyy", &urlReq{})
|
|
|
+ if err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
- assertOkWithNamedRoute(t, &gm, "xxx", "http://ex.com/")
|
|
|
+ mustHaveStatus(t, res, http.StatusBadRequest)
|
|
|
+
|
|
|
+ if err := json.NewDecoder(res).Decode(&m); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ mustBeErr(t, &m)
|
|
|
+
|
|
|
+ res, err = e.post("/api/url/yyy", &urlReq{"not a URL"})
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ mustHaveStatus(t, res, http.StatusBadRequest)
|
|
|
+
|
|
|
+ if err := json.NewDecoder(res).Decode(&m); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ mustBeErr(t, &m)
|
|
|
}
|
|
|
|
|
|
func TestAPIDel(t *testing.T) {
|
|
|
e := needEnv(t)
|
|
|
defer e.destroy()
|
|
|
|
|
|
- var am msg
|
|
|
- if err := e.postAPI(&am, "yyy", ""); err != nil {
|
|
|
+ if err := e.ctx.Put("xxx", &context.Route{
|
|
|
+ URL: "http://ex.com/",
|
|
|
+ Time: time.Now(),
|
|
|
+ }); err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
- assertJustOk(t, &am)
|
|
|
|
|
|
- var bm msg
|
|
|
- if err := e.postAPI(&bm, "yyy", "https://a.com/"); err != nil {
|
|
|
+ res, err := e.call("DELETE", "/api/url/xxx", nil)
|
|
|
+ if err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
- assertOkWithNamedRoute(t, &bm, "yyy", "https://a.com/")
|
|
|
|
|
|
- var cm msg
|
|
|
- if err := e.postAPI(&cm, "yyy", ""); err != nil {
|
|
|
+ mustHaveStatus(t, res, http.StatusOK)
|
|
|
+
|
|
|
+ var m msg
|
|
|
+ if err := json.NewDecoder(res).Decode(&m); err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
- assertJustOk(t, &cm)
|
|
|
+ mustBeOk(t, m.Ok)
|
|
|
|
|
|
- var dm msg
|
|
|
- if err := e.getAPI(&dm, "yyy"); err != nil {
|
|
|
- t.Fatal(err)
|
|
|
+ if _, err := e.ctx.Get("xxx"); err != leveldb.ErrNotFound {
|
|
|
+ t.Fatal("expected xxx to be deleted")
|
|
|
}
|
|
|
- assertJustOk(t, &dm)
|
|
|
}
|
|
|
|
|
|
func TestAPIPutThenGetAuto(t *testing.T) {
|
|
|
e := needEnv(t)
|
|
|
defer e.destroy()
|
|
|
|
|
|
- var am msg
|
|
|
- if err := e.postAPI(&am, "", "http://b.com/"); err != nil {
|
|
|
+ res, err := e.post("/api/url/", &urlReq{URL: "http://b.com/"})
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ mustHaveStatus(t, res, http.StatusOK)
|
|
|
+
|
|
|
+ var am msgRoute
|
|
|
+ if err := json.NewDecoder(res).Decode(&am); err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
- assertOkWithRoute(t, &am, "http://b.com/")
|
|
|
+ mustBeOk(t, am.Ok)
|
|
|
+ mustBeRouteOf(t, am.Route.Route, "http://b.com/")
|
|
|
|
|
|
- var bm msg
|
|
|
- if err := e.getAPI(&bm, am.Route.Name); err != nil {
|
|
|
+ res, err = e.get(fmt.Sprintf("/api/url/%s", am.Route.Name))
|
|
|
+ if err != nil {
|
|
|
t.Fatal(err)
|
|
|
}
|
|
|
- assertOkWithNamedRoute(t, &bm, am.Route.Name, "http://b.com/")
|
|
|
+
|
|
|
+ mustHaveStatus(t, res, http.StatusOK)
|
|
|
+
|
|
|
+ var bm msgRoute
|
|
|
+ if err := json.NewDecoder(res).Decode(&bm); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ mustBeOk(t, bm.Ok)
|
|
|
+ mustBeNamedRouteOf(t, bm.Route, am.Route.Name, "http://b.com/")
|
|
|
+}
|
|
|
+
|
|
|
+func getInPages(e *env, params url.Values) ([][]*routeWithName, error) {
|
|
|
+ var pages [][]*routeWithName
|
|
|
+
|
|
|
+ for {
|
|
|
+ res, err := e.get("/api/urls/?" + params.Encode())
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if res.status != http.StatusOK {
|
|
|
+ return nil, fmt.Errorf("HTTP status: %d", res.status)
|
|
|
+ }
|
|
|
+
|
|
|
+ var m msgRoutes
|
|
|
+ if err := json.NewDecoder(res).Decode(&m); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if !m.Ok {
|
|
|
+ return nil, errors.New("response is not ok")
|
|
|
+ }
|
|
|
+
|
|
|
+ pages = append(pages, m.Routes)
|
|
|
+
|
|
|
+ if m.Next == "" {
|
|
|
+ return pages, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ params.Set("cursor", m.Next)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+type listTest struct {
|
|
|
+ Params url.Values
|
|
|
+ Pages [][]*routeWithName
|
|
|
+}
|
|
|
+
|
|
|
+func TestAPIList(t *testing.T) {
|
|
|
+ e := needEnv(t)
|
|
|
+ defer e.destroy()
|
|
|
+
|
|
|
+ rts := []*routeWithName{
|
|
|
+ &routeWithName{
|
|
|
+ Name: "0",
|
|
|
+ Route: &context.Route{
|
|
|
+ URL: "http://0.com/",
|
|
|
+ Time: time.Now(),
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ &routeWithName{
|
|
|
+ Name: "1",
|
|
|
+ Route: &context.Route{
|
|
|
+ URL: "http://1.com/",
|
|
|
+ Time: time.Now(),
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ &routeWithName{
|
|
|
+ Name: ":a",
|
|
|
+ Route: &context.Route{
|
|
|
+ URL: "http://ga.com/",
|
|
|
+ Time: time.Now(),
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ &routeWithName{
|
|
|
+ Name: ":b",
|
|
|
+ Route: &context.Route{
|
|
|
+ URL: "http://gb.com/",
|
|
|
+ Time: time.Now(),
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ &routeWithName{
|
|
|
+ Name: "a",
|
|
|
+ Route: &context.Route{
|
|
|
+ URL: "http://a.com/",
|
|
|
+ Time: time.Now(),
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ &routeWithName{
|
|
|
+ Name: "b",
|
|
|
+ Route: &context.Route{
|
|
|
+ URL: "http://b.com/",
|
|
|
+ Time: time.Now(),
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, rt := range rts {
|
|
|
+ if err := e.ctx.Put(rt.Name, rt.Route); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ tests := []*listTest{
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{}),
|
|
|
+ Pages: [][]*routeWithName{
|
|
|
+ []*routeWithName{rts[0], rts[1], rts[4], rts[5]},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{
|
|
|
+ "include-generated-names": {"true"},
|
|
|
+ }),
|
|
|
+ Pages: [][]*routeWithName{rts},
|
|
|
+ },
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{
|
|
|
+ "include-generated-names": {"false"},
|
|
|
+ }),
|
|
|
+ Pages: [][]*routeWithName{
|
|
|
+ []*routeWithName{rts[0], rts[1], rts[4], rts[5]},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{
|
|
|
+ "limit": {"2"},
|
|
|
+ }),
|
|
|
+ Pages: [][]*routeWithName{
|
|
|
+ []*routeWithName{rts[0], rts[1]},
|
|
|
+ []*routeWithName{rts[4], rts[5]},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{
|
|
|
+ "limit": {"2"},
|
|
|
+ "include-generated-names": {"true"},
|
|
|
+ }),
|
|
|
+ Pages: [][]*routeWithName{
|
|
|
+ []*routeWithName{rts[0], rts[1]},
|
|
|
+ []*routeWithName{rts[2], rts[3]},
|
|
|
+ []*routeWithName{rts[4], rts[5]},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{
|
|
|
+ "limit": {"2"},
|
|
|
+ "cursor": {base64.URLEncoding.EncodeToString([]byte{':'})},
|
|
|
+ }),
|
|
|
+ Pages: [][]*routeWithName{
|
|
|
+ []*routeWithName{rts[4], rts[5]},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{
|
|
|
+ "limit": {"3"},
|
|
|
+ "include-generated-names": {"true"},
|
|
|
+ "cursor": {base64.URLEncoding.EncodeToString([]byte{':'})},
|
|
|
+ }),
|
|
|
+ Pages: [][]*routeWithName{
|
|
|
+ []*routeWithName{rts[2], rts[3], rts[4]},
|
|
|
+ []*routeWithName{rts[5]},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{
|
|
|
+ "limit": {"1"},
|
|
|
+ }),
|
|
|
+ Pages: [][]*routeWithName{
|
|
|
+ []*routeWithName{rts[0]},
|
|
|
+ []*routeWithName{rts[1]},
|
|
|
+ []*routeWithName{rts[4]},
|
|
|
+ []*routeWithName{rts[5]},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ &listTest{
|
|
|
+ Params: url.Values(map[string][]string{
|
|
|
+ "cursor": {base64.URLEncoding.EncodeToString([]byte{'z'})},
|
|
|
+ }),
|
|
|
+ Pages: [][]*routeWithName{nil},
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, test := range tests {
|
|
|
+ t.Logf("running tests for ?%s", test.Params.Encode())
|
|
|
+ pages, err := getInPages(e, test.Params)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(pages) != len(test.Pages) {
|
|
|
+ t.Fatalf("number of pages mismatch %d vs %d", len(pages), len(test.Pages))
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, n := 0, len(pages); i < n; i++ {
|
|
|
+ page := pages[i]
|
|
|
+ expected := test.Pages[i]
|
|
|
+
|
|
|
+ if len(page) != len(expected) {
|
|
|
+ t.Fatalf("page %d, length mismatch expected %d got %d", i, len(expected), len(page))
|
|
|
+ }
|
|
|
+
|
|
|
+ for j, m := 0, len(page); j < m; j++ {
|
|
|
+ mustBeSameNamedRoute(t, page[j], expected[j])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestBadList(t *testing.T) {
|
|
|
+ e := needEnv(t)
|
|
|
+ defer e.destroy()
|
|
|
+
|
|
|
+ tests := map[string]int{
|
|
|
+ url.Values{
|
|
|
+ "cursor": {"not a cursor"},
|
|
|
+ }.Encode(): http.StatusBadRequest,
|
|
|
+
|
|
|
+ url.Values{
|
|
|
+ "limit": {"0"},
|
|
|
+ }.Encode(): http.StatusBadRequest,
|
|
|
+
|
|
|
+ url.Values{
|
|
|
+ "limit": {"not a limit"},
|
|
|
+ }.Encode(): http.StatusBadRequest,
|
|
|
+
|
|
|
+ url.Values{
|
|
|
+ "limit": {"100000"},
|
|
|
+ }.Encode(): http.StatusBadRequest,
|
|
|
+
|
|
|
+ url.Values{
|
|
|
+ "include-generated-names": {"butter"},
|
|
|
+ }.Encode(): http.StatusBadRequest,
|
|
|
+ }
|
|
|
+
|
|
|
+ for params, status := range tests {
|
|
|
+ res, err := e.get("/api/urls/?" + params)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ mustHaveStatus(t, res, status)
|
|
|
+
|
|
|
+ var m msgErr
|
|
|
+ if err := json.NewDecoder(res).Decode(&m); err != nil {
|
|
|
+ t.Fatal(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ mustBeErr(t, &m)
|
|
|
+ }
|
|
|
}
|