| Index: appengine/ephelper/epfrontend/service_test.go
|
| diff --git a/appengine/ephelper/epfrontend/service_test.go b/appengine/ephelper/epfrontend/service_test.go
|
| deleted file mode 100644
|
| index 14168f27d84038ad9409ece7c9d487e4692d3021..0000000000000000000000000000000000000000
|
| --- a/appengine/ephelper/epfrontend/service_test.go
|
| +++ /dev/null
|
| @@ -1,300 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package epfrontend
|
| -
|
| -import (
|
| - "bytes"
|
| - "encoding/json"
|
| - "errors"
|
| - "fmt"
|
| - "net/http"
|
| - "net/http/httptest"
|
| - "net/url"
|
| - "testing"
|
| -
|
| - "github.com/GoogleCloudPlatform/go-endpoints/endpoints"
|
| - . "github.com/smartystreets/goconvey/convey"
|
| - "golang.org/x/net/context"
|
| -)
|
| -
|
| -type serviceBackendStub struct {
|
| - body bytes.Buffer
|
| - callback func(w http.ResponseWriter)
|
| -}
|
| -
|
| -func (s *serviceBackendStub) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
| - defer req.Body.Close()
|
| - _, err := s.body.ReadFrom(req.Body)
|
| - if err != nil {
|
| - panic(err)
|
| - }
|
| -
|
| - if s.callback != nil {
|
| - s.callback(w)
|
| - }
|
| -}
|
| -
|
| -type requestNormalizer struct {
|
| - http.Handler
|
| - scheme string
|
| - host string
|
| -}
|
| -
|
| -func (s *requestNormalizer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
| - u, err := url.ParseRequestURI(req.RequestURI)
|
| - if err != nil {
|
| - panic(err)
|
| - }
|
| -
|
| - u.Scheme = s.scheme
|
| - u.Host = s.host
|
| - req.URL = u
|
| - req.RequestURI = u.Path
|
| - req.Host = u.Host
|
| - s.Handler.ServeHTTP(w, req)
|
| -}
|
| -
|
| -type ServiceTestService struct {
|
| -}
|
| -
|
| -type ServiceTestPathReq struct {
|
| - Name string `endpoints:"required"`
|
| - Count int64 `endpoints:"required"`
|
| -}
|
| -
|
| -type ServiceTestResponse struct {
|
| - Count int64 `json:"count"`
|
| -}
|
| -
|
| -func (s *ServiceTestService) PathReq(c context.Context, req *ServiceTestPathReq) (*ServiceTestResponse, error) {
|
| - return nil, endpoints.UnauthorizedError
|
| -}
|
| -
|
| -type ServiceTestQueryReq struct {
|
| - Name string `endpoints:"required"`
|
| - Count int64 `json:"count,string"`
|
| -
|
| - S string
|
| - F float32
|
| - B bool
|
| - B2 bool
|
| - I int32
|
| -}
|
| -
|
| -func (s *ServiceTestService) QueryReq(c context.Context, req *ServiceTestQueryReq) error {
|
| - return endpoints.UnauthorizedError
|
| -}
|
| -
|
| -type ServiceTestPostReq struct {
|
| - S string
|
| - T string
|
| -}
|
| -
|
| -func (s *ServiceTestService) Post(c context.Context, req *ServiceTestPostReq) error {
|
| - return endpoints.UnauthorizedError
|
| -}
|
| -
|
| -func readErrorResponse(resp *http.Response) *outerError {
|
| - defer resp.Body.Close()
|
| -
|
| - e := outerError{}
|
| - if err := json.NewDecoder(resp.Body).Decode(&e); err != nil {
|
| - return nil
|
| - }
|
| - return &e
|
| -}
|
| -
|
| -func TestService(t *testing.T) {
|
| - Convey(`A testing service`, t, func() {
|
| - be := serviceBackendStub{}
|
| - fe := New("", &be)
|
| -
|
| - ts := httptest.NewServer(&requestNormalizer{
|
| - Handler: fe,
|
| - scheme: "http",
|
| - host: "example.com",
|
| - })
|
| - defer ts.Close()
|
| -
|
| - c := http.Client{}
|
| -
|
| - Convey(`Requests to non-root URLs are rejected.`, func() {
|
| - resp, err := c.Get(fmt.Sprintf("%s%s", ts.URL, "/ohai"))
|
| - So(err, ShouldBeNil)
|
| - So(resp.StatusCode, ShouldEqual, http.StatusNotFound)
|
| - })
|
| -
|
| - Convey(`With a registered test service (query parameters)`, func() {
|
| - // Create an endpoints backend because we need the API descriptors that it
|
| - // creates from our services.
|
| - epbe := endpoints.NewServer("")
|
| - svc, err := epbe.RegisterService(&ServiceTestService{}, "test", "v1", "Test Service", true)
|
| - So(err, ShouldBeNil)
|
| - So(svc, ShouldNotBeNil)
|
| -
|
| - m := svc.MethodByName("QueryReq")
|
| - m.Info().HTTPMethod = "GET"
|
| - m.Info().Path = "queryreq/{Name}"
|
| -
|
| - So(fe.RegisterService(svc), ShouldBeNil)
|
| -
|
| - Convey(`Will not register the service again.`, func() {
|
| - So(fe.RegisterService(svc), ShouldNotBeNil)
|
| - })
|
| -
|
| - Convey(`Exposes a redirecting "explorer" API.`, func() {
|
| - redirected := false
|
| - c.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
| - redirected = true
|
| - return errors.New("testing, no redirect")
|
| - }
|
| -
|
| - c.Get(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/explorer"))
|
| - So(redirected, ShouldBeTrue)
|
| - })
|
| -
|
| - Convey(`POST requests to directory endpoint return http.StatusMethodNotAllowed.`, func() {
|
| - resp, err := c.Post(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/discovery/v1/apis"), "", nil)
|
| - So(err, ShouldBeNil)
|
| - So(resp.StatusCode, ShouldEqual, http.StatusMethodNotAllowed)
|
| - })
|
| -
|
| - Convey(`Exposes a directory REST endpoint.`, func() {
|
| - exp := directoryList{}
|
| - loadJSONTestCase(&exp, "service", "test", "directory")
|
| -
|
| - act := directoryList{}
|
| - resp, err := c.Get(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/discovery/v1/apis"))
|
| - So(err, ShouldBeNil)
|
| - defer resp.Body.Close()
|
| - So(json.NewDecoder(resp.Body).Decode(&act), ShouldBeNil)
|
| -
|
| - So(act, ShouldResemble, exp)
|
| - })
|
| -
|
| - Convey(`Exposes a service REST endpoint.`, func() {
|
| - exp := restDescription{}
|
| - loadJSONTestCase(&exp, "service", "test", "service")
|
| -
|
| - act := restDescription{}
|
| - resp, err := c.Get(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/discovery/v1/apis/test/v1/rest"))
|
| - So(err, ShouldBeNil)
|
| - defer resp.Body.Close()
|
| - So(json.NewDecoder(resp.Body).Decode(&act), ShouldBeNil)
|
| -
|
| - So(act, ShouldResemble, exp)
|
| - })
|
| -
|
| - Convey(`Can access the "pathreq" endpoint with path elements.`, func() {
|
| - _, err := c.Get(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/test/v1/pathreq/testname/12345"))
|
| - So(err, ShouldBeNil)
|
| -
|
| - So(be.body.String(), ShouldEqual, `{"Count":"12345","Name":"testname"}`+"\n")
|
| - })
|
| -
|
| - Convey(`Will return an error if an invalid "pathreq" path parameter is supplied.`, func() {
|
| - resp, err := c.Get(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/test/v1/pathreq/testname/pi"))
|
| - So(err, ShouldBeNil)
|
| -
|
| - e := readErrorResponse(resp)
|
| - So(e, ShouldNotBeNil)
|
| - So(e.Error, ShouldNotBeNil)
|
| - So(e.Error.Code, ShouldEqual, http.StatusBadRequest)
|
| - So(e.Error.Message, ShouldEqual, "unspecified error")
|
| - })
|
| -
|
| - Convey(`Can access the "queryreq" endpoint with query parameters.`, func() {
|
| - _, err := c.Get(fmt.Sprintf("%s%s", ts.URL,
|
| - "/_ah/api/test/v1/queryreq/testname?count=12345&S=foo&F=3.14&B=true&B2=false&I=1337"))
|
| - So(err, ShouldBeNil)
|
| -
|
| - So(be.body.String(), ShouldEqual,
|
| - `{"B":true,"B2":false,"F":3.14,"I":1337,"Name":"testname","S":"foo","count":"12345"}`+"\n")
|
| - })
|
| -
|
| - Convey(`Will return an error if an invalid "queryreq" query parameter is supplied.`, func() {
|
| - resp, err := c.Get(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/test/v1/queryreq/testname?count=pi"))
|
| - So(err, ShouldBeNil)
|
| -
|
| - e := readErrorResponse(resp)
|
| - So(e, ShouldNotBeNil)
|
| - So(e.Error, ShouldNotBeNil)
|
| - So(e.Error.Code, ShouldEqual, http.StatusBadRequest)
|
| - So(e.Error.Message, ShouldEqual, "unspecified error")
|
| - })
|
| -
|
| - Convey(`Will augment POST data with query parameters.`, func() {
|
| - _, err := c.Post(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/test/v1/post?T=bar"),
|
| - "application/json", bytes.NewBufferString(`{"S":"foo"}`))
|
| - So(err, ShouldBeNil)
|
| -
|
| - So(be.body.String(), ShouldEqual, `{"S":"foo","T":"bar"}`+"\n")
|
| - })
|
| -
|
| - Convey(`Will return an error if an invalid endpoint is requested.`, func() {
|
| - resp, err := c.Post(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/test/v1/does.not.exist"), "", nil)
|
| - So(err, ShouldBeNil)
|
| -
|
| - e := readErrorResponse(resp)
|
| - So(e, ShouldNotBeNil)
|
| - So(e.Error, ShouldNotBeNil)
|
| - So(e.Error.Code, ShouldEqual, http.StatusNotFound)
|
| - So(e.Error.Message, ShouldEqual, "unspecified error")
|
| - })
|
| -
|
| - Convey(`Will catch backend panic() and wrap it with an error.`, func() {
|
| - didPanic := false
|
| - be.callback = func(http.ResponseWriter) {
|
| - didPanic = true
|
| - panic("test panic")
|
| - }
|
| -
|
| - resp, err := c.Post(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/test/v1/post"), "", nil)
|
| - So(err, ShouldBeNil)
|
| -
|
| - So(didPanic, ShouldBeTrue)
|
| -
|
| - e := readErrorResponse(resp)
|
| - So(e, ShouldNotBeNil)
|
| - So(e.Error, ShouldNotBeNil)
|
| - So(e.Error.Code, ShouldEqual, http.StatusServiceUnavailable)
|
| - })
|
| -
|
| - Convey(`Will catch and forward backend JSON errors.`, func() {
|
| - be.callback = func(w http.ResponseWriter) {
|
| - w.WriteHeader(http.StatusNotFound)
|
| - w.Write([]byte(`{"error_message": "test message"}`))
|
| - }
|
| -
|
| - resp, err := c.Post(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/test/v1/post"), "", nil)
|
| - So(err, ShouldBeNil)
|
| -
|
| - e := readErrorResponse(resp)
|
| - So(e, ShouldNotBeNil)
|
| - So(e.Error, ShouldNotBeNil)
|
| - So(e.Error.Code, ShouldEqual, http.StatusNotFound)
|
| - So(e.Error.Message, ShouldEqual, "test message")
|
| - })
|
| -
|
| - Convey(`Will catch non-JSON backend errors and wrap with generic error.`, func() {
|
| - be.callback = func(w http.ResponseWriter) {
|
| - w.WriteHeader(http.StatusNotFound)
|
| - w.Write([]byte("$$NOT JSON$$"))
|
| - }
|
| -
|
| - resp, err := c.Post(fmt.Sprintf("%s%s", ts.URL, "/_ah/api/test/v1/post"), "", nil)
|
| - So(err, ShouldBeNil)
|
| -
|
| - e := readErrorResponse(resp)
|
| - So(e, ShouldNotBeNil)
|
| - So(e.Error, ShouldNotBeNil)
|
| - So(e.Error.Code, ShouldEqual, http.StatusNotFound)
|
| - So(e.Error.Message, ShouldEqual, "unspecified error")
|
| - So(len(e.Error.Errors), ShouldEqual, 1)
|
| - So(e.Error.Errors[0].Message, ShouldContainSubstring, "Failed to decode error JSON")
|
| - })
|
| - })
|
| - })
|
| -}
|
|
|