Adds HTTP serving tests (#98)

* options

* service, topic test

* binding, invoke, topic tests
This commit is contained in:
Mark Chmarny 2020-10-28 17:11:17 -07:00 committed by GitHub
parent 5cfb55bdda
commit e606bbc035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 151 additions and 29 deletions

View File

@ -55,3 +55,32 @@ func TestBindingHandlerWithData(t *testing.T) {
assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, "test", resp.Body.String())
}
func bindingHandlerFn(ctx context.Context, in *common.BindingEvent) (out []byte, err error) {
if in == nil {
return nil, errors.New("nil input")
}
return []byte("test"), nil
}
func bindingHandlerFnWithError(ctx context.Context, in *common.BindingEvent) (out []byte, err error) {
return nil, errors.New("intentional error")
}
func TestBindingHandlerErrors(t *testing.T) {
data := `{"name": "test"}`
s := newServer("", nil)
err := s.AddBindingInvocationHandler("", bindingHandlerFn)
assert.Errorf(t, err, "expected error adding binding event handler sans route")
err = s.AddBindingInvocationHandler("errors", bindingHandlerFnWithError)
assert.NoErrorf(t, err, "error adding binding event handler sans slash")
req, err := http.NewRequest(http.MethodPost, "/errors", strings.NewReader(data))
assert.NoErrorf(t, err, "error creating request")
req.Header.Set("Content-Type", "application/json")
resp := httptest.NewRecorder()
s.mux.ServeHTTP(resp, req)
assert.Equal(t, http.StatusInternalServerError, resp.Code)
}

View File

@ -6,6 +6,7 @@ import (
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
@ -68,17 +69,43 @@ func TestInvocationHandlerWithoutInputData(t *testing.T) {
assert.Equal(t, "", string(b))
}
func emptyInvocationFn(ctx context.Context, in *common.InvocationEvent) (out *common.Content, err error) {
return nil, nil
}
func TestInvocationHandlerWithInvalidRoute(t *testing.T) {
s := newServer("", nil)
err := s.AddServiceInvocationHandler("/a", func(ctx context.Context, in *common.InvocationEvent) (out *common.Content, err error) {
return nil, nil
})
err := s.AddServiceInvocationHandler("no-slash", emptyInvocationFn)
assert.NoErrorf(t, err, "error adding no slash route event handler")
err = s.AddServiceInvocationHandler("", emptyInvocationFn)
assert.Errorf(t, err, "expected error from adding no route event handler")
err = s.AddServiceInvocationHandler("/a", emptyInvocationFn)
assert.NoErrorf(t, err, "error adding event handler")
req, err := http.NewRequest(http.MethodPost, "/b", nil)
assert.NoErrorf(t, err, "error creating request")
resp := httptest.NewRecorder()
s.mux.ServeHTTP(resp, req)
assert.Equal(t, http.StatusNotFound, resp.Code)
makeEventRequest(t, s, "/b", "", http.StatusNotFound)
}
func errorInvocationFn(ctx context.Context, in *common.InvocationEvent) (out *common.Content, err error) {
return nil, errors.New("intentional test error")
}
func TestInvocationHandlerWithError(t *testing.T) {
s := newServer("", nil)
err := s.AddServiceInvocationHandler("/error", errorInvocationFn)
assert.NoErrorf(t, err, "error adding error event handler")
makeEventRequest(t, s, "/error", "", http.StatusInternalServerError)
}
func TestValuesToMap(t *testing.T) {
m := valuesToMap(url.Values{
"k1": []string{"v11", "v12", "v13"},
"k2": []string{"v21", "v22", "v23"},
"k3": []string{"v31", "v32", "v33"},
})
assert.Equal(t, 3, len(m["k2"]))
}

View File

@ -50,13 +50,17 @@ func (s *Server) Stop() error {
return nil
}
func setOptions(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST,OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "authorization, origin, content-type, accept")
w.Header().Set("Allow", "POST,OPTIONS")
}
func optionsHandler(h http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodOptions {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST,OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "authorization, origin, content-type, accept")
w.Header().Set("Allow", "POST,OPTIONS")
setOptions(w, r)
} else {
h.ServeHTTP(w, r)
}

View File

@ -1,6 +1,8 @@
package http
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
@ -9,4 +11,27 @@ import (
func TestStoppingUnstartedService(t *testing.T) {
s := newServer("", nil)
assert.NotNil(t, s)
err := s.Stop()
assert.NoError(t, err)
}
func TestSettingOptions(t *testing.T) {
req, err := http.NewRequest(http.MethodOptions, "/", nil)
assert.NoErrorf(t, err, "error creating request")
w := httptest.NewRecorder()
setOptions(w, req)
resp := w.Result()
assert.NotNil(t, resp)
assert.Equal(t, "*", resp.Header.Get("Access-Control-Allow-Origin"))
assert.Equal(t, "POST,OPTIONS", resp.Header.Get("Access-Control-Allow-Methods"))
assert.Equal(t, "authorization, origin, content-type, accept", resp.Header.Get("Access-Control-Allow-Headers"))
assert.Equal(t, "POST,OPTIONS", resp.Header.Get("Allow"))
}
func testRequest(t *testing.T, s *Server, r *http.Request, expectedStatusCode int) {
rr := httptest.NewRecorder()
s.mux.ServeHTTP(rr, r)
rez := rr.Result()
assert.NotNil(t, rez)
assert.Equal(t, expectedStatusCode, rez.StatusCode)
}

View File

@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
@ -13,6 +12,20 @@ import (
"github.com/stretchr/testify/assert"
)
func testTopicFunc(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
if e == nil {
return false, errors.New("nil content")
}
if e.DataContentType != "application/json" {
return false, fmt.Errorf("invalid content type: %s", e.DataContentType)
}
return false, nil
}
func testErrorTopicFunc(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
return true, errors.New("error to cause a retry")
}
func TestEventHandler(t *testing.T) {
data := `{
"specversion" : "1.0",
@ -35,23 +48,47 @@ func TestEventHandler(t *testing.T) {
Route: "/",
Metadata: map[string]string{},
}
err := s.AddTopicEventHandler(sub, func(ctx context.Context, e *common.TopicEvent) (retry bool, err error) {
if e == nil {
return false, errors.New("nil content")
}
if e.DataContentType != "application/json" {
return false, fmt.Errorf("invalid content type: %s", e.DataContentType)
}
return false, nil
})
err := s.AddTopicEventHandler(sub, testTopicFunc)
assert.NoErrorf(t, err, "error adding event handler")
req, err := http.NewRequest(http.MethodPost, "/", strings.NewReader(data))
assert.NoErrorf(t, err, "error creating request")
req.Header.Set("Content-Type", "application/json")
sub2 := &common.Subscription{
PubsubName: "messages",
Topic: "errors",
Route: "/errors",
Metadata: map[string]string{},
}
err = s.AddTopicEventHandler(sub2, testErrorTopicFunc)
assert.NoErrorf(t, err, "error adding error event handler")
rr := httptest.NewRecorder()
s.registerSubscribeHandler()
s.mux.ServeHTTP(rr, req)
assert.Equal(t, http.StatusOK, rr.Code)
makeEventRequest(t, s, "/", data, http.StatusOK)
makeEventRequest(t, s, "/", "", http.StatusSeeOther)
makeEventRequest(t, s, "/", "not JSON", http.StatusSeeOther)
makeEventRequest(t, s, "/errors", data, http.StatusOK)
}
func makeEventRequest(t *testing.T, s *Server, route, data string, expectedStatusCode int) {
req, err := http.NewRequest(http.MethodPost, route, strings.NewReader(data))
assert.NoErrorf(t, err, "error creating request: %s", data)
req.Header.Set("Content-Type", "application/json")
testRequest(t, s, req, expectedStatusCode)
}
func TestAddingInvalidEventHandlers(t *testing.T) {
s := newServer("", nil)
err := s.AddTopicEventHandler(nil, testTopicFunc)
assert.Errorf(t, err, "expected error adding no sub event handler")
sub := &common.Subscription{Metadata: map[string]string{}}
err = s.AddTopicEventHandler(sub, testTopicFunc)
assert.Errorf(t, err, "expected error adding empty sub event handler")
sub.Topic = "test"
err = s.AddTopicEventHandler(sub, testTopicFunc)
assert.Errorf(t, err, "expected error adding sub without component event handler")
sub.PubsubName = "messages"
err = s.AddTopicEventHandler(sub, testTopicFunc)
assert.Errorf(t, err, "expected error adding sub without route event handler")
}