From 67c9a71686abd0e933675f942f64a8a07d633128 Mon Sep 17 00:00:00 2001 From: "Alex Ellis (VMware)" Date: Sat, 5 Jan 2019 16:22:01 +0000 Subject: [PATCH] Add unit tests for MakeNotifierWrapper - fixes issue where result was assigned to value rather than to pointer reference. Signed-off-by: Alex Ellis (VMware) --- gateway/handlers/notifier_handler.go | 27 +++++-- gateway/handlers/notifier_wrapper_test.go | 89 +++++++++++++++++++++++ 2 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 gateway/handlers/notifier_wrapper_test.go diff --git a/gateway/handlers/notifier_handler.go b/gateway/handlers/notifier_handler.go index 8a407ce3..c7ca6c26 100644 --- a/gateway/handlers/notifier_handler.go +++ b/gateway/handlers/notifier_handler.go @@ -13,32 +13,43 @@ func MakeNotifierWrapper(next http.HandlerFunc, notifiers []HTTPNotifier) http.H return func(w http.ResponseWriter, r *http.Request) { then := time.Now() - writer := newCustomWriter(w) - next(w, r) + writer := newWriteInterceptor(w) + next(&writer, r) url := r.URL.String() for _, notifier := range notifiers { - notifier.Notify(r.Method, url, url, writer.CapturedStatusCode, time.Since(then)) + notifier.Notify(r.Method, url, url, writer.Status(), time.Since(then)) } } } -func newCustomWriter(w http.ResponseWriter) customWriter { - return customWriter{ +func newWriteInterceptor(w http.ResponseWriter) writeInterceptor { + return writeInterceptor{ w: w, } } -type customWriter struct { +type writeInterceptor struct { CapturedStatusCode int w http.ResponseWriter } -func (c *customWriter) Write(data []byte) (int, error) { +func (c *writeInterceptor) Status() int { + if c.CapturedStatusCode == 0 { + return http.StatusOK + } + return c.CapturedStatusCode +} + +func (c *writeInterceptor) Header() http.Header { + return c.w.Header() +} + +func (c *writeInterceptor) Write(data []byte) (int, error) { return c.w.Write(data) } -func (c *customWriter) WriteHeader(code int) { +func (c *writeInterceptor) WriteHeader(code int) { c.CapturedStatusCode = code c.w.WriteHeader(code) } diff --git a/gateway/handlers/notifier_wrapper_test.go b/gateway/handlers/notifier_wrapper_test.go new file mode 100644 index 00000000..39f29424 --- /dev/null +++ b/gateway/handlers/notifier_wrapper_test.go @@ -0,0 +1,89 @@ +// Copyright (c) OpenFaaS Author(s) 2018. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +package handlers + +import ( + "net/http" + "net/http/httptest" + "testing" + "time" +) + +func Test_MakeNotifierWrapper_ReceivesHttpStatusInNotifier(t *testing.T) { + notifier := &testNotifier{} + handlerVisited := false + handlerWant := http.StatusAccepted + + handler := MakeNotifierWrapper(func(w http.ResponseWriter, r *http.Request) { + handlerVisited = true + w.WriteHeader(handlerWant) + }, []HTTPNotifier{notifier}) + + req := httptest.NewRequest(http.MethodGet, "/", nil) + rec := httptest.NewRecorder() + + handler.ServeHTTP(rec, req) + + if handlerVisited != true { + t.Errorf("expected handler to have been visited") + } + + if notifier.StatusReceived == 0 { + t.Errorf("notifier wanted a status, but got none") + t.Fail() + return + } + + if rec.Result().StatusCode != handlerWant { + t.Errorf("recorder status want: %d, got %d", handlerWant, rec.Result().StatusCode) + } + + if notifier.StatusReceived != handlerWant { + t.Errorf("notifier status want: %d, got %d", handlerWant, notifier.StatusReceived) + } + +} + +func Test_MakeNotifierWrapper_ReceivesDefaultHttpStatusWhenNotSet(t *testing.T) { + notifier := &testNotifier{} + handlerVisited := false + handlerWant := http.StatusOK + + handler := MakeNotifierWrapper(func(w http.ResponseWriter, r *http.Request) { + handlerVisited = true + }, []HTTPNotifier{notifier}) + + req := httptest.NewRequest(http.MethodGet, "/", nil) + rec := httptest.NewRecorder() + + handler.ServeHTTP(rec, req) + + if handlerVisited != true { + t.Errorf("expected handler to have been visited") + } + + if notifier.StatusReceived == 0 { + t.Errorf("notifier wanted a status, but got none") + t.Fail() + return + } + + if rec.Result().StatusCode != handlerWant { + t.Errorf("recorder status want: %d, got %d", handlerWant, rec.Result().StatusCode) + } + + if notifier.StatusReceived != handlerWant { + t.Errorf("notifier status want: %d, got %d", handlerWant, notifier.StatusReceived) + } + +} + +type testNotifier struct { + StatusReceived int +} + +// Notify about service metrics +func (tf *testNotifier) Notify(method string, URL string, originalURL string, statusCode int, duration time.Duration) { + tf.StatusReceived = statusCode +}