Skip to content

Commit

Permalink
Merge pull request #4 from Comcast/standUpMachine
Browse files Browse the repository at this point in the history
http handler unit tests
  • Loading branch information
schmidtw authored Sep 22, 2017
2 parents 0f06048 + 5d13269 commit ef9b767
Show file tree
Hide file tree
Showing 13 changed files with 908 additions and 421 deletions.
26 changes: 14 additions & 12 deletions src/glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion src/glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package: .
homepage: https://github.com/Comcast/tr1d1um
import:
- package: github.com/Comcast/webpa-common
version: cb246362b61aaf042a936fa615a48554d111f9b4
version: 5ec9cf570e11eb4bef1162c269f3d301040e7be9
- package: github.com/go-ozzo/ozzo-validation
version: v3.3
- package: gopkg.in/h2non/gock.v1
version: v1.0.6
79 changes: 79 additions & 0 deletions src/tr1d1um/communication.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package main

import (
"bytes"
"io"
"net/http"

"github.com/Comcast/webpa-common/logging"
"github.com/Comcast/webpa-common/wrp"
"github.com/go-kit/kit/log"
"github.com/gorilla/mux"
)

//SendAndHandle wraps the methods to communicate both back to a requester and to a target server
type SendAndHandle interface {
Send(*ConversionHandler, http.ResponseWriter, []byte, *http.Request) (*http.Response, error)
HandleResponse(*ConversionHandler, error, *http.Response, http.ResponseWriter)
}

//Tr1SendAndHandle implements the behaviors of SendAndHandle
type Tr1SendAndHandle struct {
log log.Logger
timedClient *http.Client
NewHTTPRequest func(string, string, io.Reader) (*http.Request, error)
}

//Send prepares and subsequently sends a WRP encoded message to a predefined server
//Its response is then handled in HandleResponse
func (tr1 *Tr1SendAndHandle) Send(ch *ConversionHandler, resp http.ResponseWriter, data []byte, req *http.Request) (respFromServer *http.Response, err error) {
var errorLogger = logging.Error(tr1.log)
wrpMsg := ch.wdmpConvert.GetConfiguredWRP(data, mux.Vars(req), req.Header)

wrpPayload, err := ch.encodingHelper.GenericEncode(wrpMsg, wrp.JSON)

if err != nil {
resp.WriteHeader(http.StatusInternalServerError)
errorLogger.Log(logging.ErrorKey(), err)
return
}

requestToServer, err := tr1.NewHTTPRequest(http.MethodGet, ch.targetURL, bytes.NewBuffer(wrpPayload))

if err != nil {
resp.WriteHeader(http.StatusInternalServerError)
errorLogger.Log(logging.ErrorKey(), err)
return
}

//todo: any more headers to be added here
requestToServer.Header.Set("Content-Type", wrp.JSON.ContentType())
respFromServer, err = tr1.timedClient.Do(requestToServer)
return
}

//HandleResponse contains the instructions of what to write back to the original requester (origin)
//based on the responses of a server we have contacted through Send
func (tr1 *Tr1SendAndHandle) HandleResponse(ch *ConversionHandler, err error, respFromServer *http.Response, origin http.ResponseWriter) {
var errorLogger = logging.Error(tr1.log)

if err != nil {
origin.WriteHeader(http.StatusInternalServerError)
errorLogger.Log(logging.ErrorKey(), err)
return
}

if respFromServer.StatusCode != http.StatusOK {
origin.WriteHeader(respFromServer.StatusCode)
errorLogger.Log(logging.MessageKey(), "non-200 response from server", logging.ErrorKey(), respFromServer.Status)
return
}

if responsePayload, err := ch.encodingHelper.ExtractPayload(respFromServer.Body, wrp.JSON); err == nil {
origin.WriteHeader(http.StatusOK)
origin.Write(responsePayload)
} else {
origin.WriteHeader(http.StatusInternalServerError)
errorLogger.Log(logging.ErrorKey(), err)
}
}
139 changes: 139 additions & 0 deletions src/tr1d1um/communication_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package main

import (
"errors"
"io"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/Comcast/webpa-common/wrp"
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
"gopkg.in/h2non/gock.v1"
)

func TestSend(t *testing.T) {
assert := assert.New(t)

data := []byte("data")
WRPMsg := &wrp.Message{}
WRPPayload := []byte("payload")
validURL := "http://someValidURL"

tr1 := &Tr1SendAndHandle{log: &logTracker{}, timedClient: &http.Client{Timeout: time.Second}}
tr1.NewHTTPRequest = http.NewRequest
ch := &ConversionHandler{encodingHelper: mockEncoding, wdmpConvert: mockConversion, targetURL: validURL}

t.Run("SendEncodeErr", func(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, validURL, nil)

var URLVars Vars = mux.Vars(req)
mockConversion.On("GetConfiguredWRP", data, URLVars, req.Header).Return(WRPMsg).Once()
mockEncoding.On("GenericEncode", WRPMsg, wrp.JSON).Return(WRPPayload, errors.New(errMsg)).Once()

recorder := httptest.NewRecorder()

_, err := tr1.Send(ch, recorder, data, req)

assert.NotNil(err)
assert.EqualValues(http.StatusInternalServerError, recorder.Code)
mockConversion.AssertExpectations(t)
mockEncoding.AssertExpectations(t)
})

t.Run("SendNewRequestErr", func(t *testing.T) {
defer func() {
tr1.NewHTTPRequest = http.NewRequest
}()

tr1.NewHTTPRequest = NewHTTPRequestFail

req := httptest.NewRequest(http.MethodGet, validURL, nil)

var URLVars Vars = mux.Vars(req)
mockConversion.On("GetConfiguredWRP", data, URLVars, req.Header).Return(WRPMsg).Once()
mockEncoding.On("GenericEncode", WRPMsg, wrp.JSON).Return(WRPPayload, nil).Once()

recorder := httptest.NewRecorder()
_, err := tr1.Send(ch, recorder, data, req)

assert.NotNil(err)
assert.EqualValues(http.StatusInternalServerError, recorder.Code)
mockConversion.AssertExpectations(t)
mockEncoding.AssertExpectations(t)

})

t.Run("SendIdeal", func(t *testing.T) {
defer gock.OffAll()

req := httptest.NewRequest(http.MethodGet, validURL, nil)

var URLVars Vars = mux.Vars(req)
mockConversion.On("GetConfiguredWRP", data, URLVars, req.Header).Return(WRPMsg).Once()
mockEncoding.On("GenericEncode", WRPMsg, wrp.JSON).Return(WRPPayload, nil).Once()

gock.New(validURL).Reply(http.StatusOK)
recorder := httptest.NewRecorder()

_, err := tr1.Send(ch, recorder, data, req)

assert.Nil(err)
assert.EqualValues(http.StatusOK, recorder.Code)
mockConversion.AssertExpectations(t)
mockEncoding.AssertExpectations(t)
})
}

func TestHandleResponse(t *testing.T) {
assert := assert.New(t)
tr1 := &Tr1SendAndHandle{log: &logTracker{}, timedClient: &http.Client{Timeout: time.Second}}
tr1.NewHTTPRequest = http.NewRequest

ch := &ConversionHandler{encodingHelper: mockEncoding, wdmpConvert: mockConversion}

//Cases
//incoming err
t.Run("IncomingErr", func(t *testing.T) {
recorder := httptest.NewRecorder()
tr1.HandleResponse(nil, errors.New(errMsg), nil, recorder)
assert.EqualValues(http.StatusInternalServerError, recorder.Code)
})

t.Run("StatusNotOK", func(t *testing.T) {
recorder := httptest.NewRecorder()
fakeResponse := &http.Response{StatusCode: http.StatusBadRequest}
tr1.HandleResponse(nil, nil, fakeResponse, recorder)
assert.EqualValues(http.StatusBadRequest, recorder.Code)
})

t.Run("ExtractPayloadFail", func(t *testing.T) {
fakeResponse := &http.Response{StatusCode: http.StatusOK}
mockEncoding.On("ExtractPayload", fakeResponse.Body, wrp.JSON).Return([]byte(""),
errors.New(errMsg)).Once()
recorder := httptest.NewRecorder()
tr1.HandleResponse(ch, nil, fakeResponse, recorder)

assert.EqualValues(http.StatusInternalServerError, recorder.Code)
mockEncoding.AssertExpectations(t)
})

t.Run("IdealCase", func(t *testing.T) {
fakeResponse := &http.Response{StatusCode: http.StatusOK}
extractedData := []byte("extract")

mockEncoding.On("ExtractPayload", fakeResponse.Body, wrp.JSON).Return(extractedData, nil).Once()
recorder := httptest.NewRecorder()
tr1.HandleResponse(ch, nil, fakeResponse, recorder)

assert.EqualValues(http.StatusOK, recorder.Code)
assert.EqualValues(extractedData, recorder.Body.Bytes())
mockEncoding.AssertExpectations(t)
})
}

func NewHTTPRequestFail(_, _ string, _ io.Reader) (*http.Request, error) {
return nil, errors.New(errMsg)
}
Loading

0 comments on commit ef9b767

Please sign in to comment.