github.com/zak-blake/goa@v1.4.1/middleware/xray/wrap_doer_test.go (about)

     1  package xray
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"net/http"
     8  	"strings"
     9  	"testing"
    10  
    11  	. "github.com/onsi/gomega"
    12  	. "github.com/onsi/gomega/gstruct"
    13  )
    14  
    15  func TestWrapDoer(t *testing.T) {
    16  	RegisterTestingT(t)
    17  
    18  	var (
    19  		doer = NewMockDoer()
    20  		ctx  = context.Background()
    21  	)
    22  	req, err := http.NewRequest("GET", "http://somehost:80/path", nil)
    23  	Expect(err).To(Succeed())
    24  
    25  	t.Run(`no segment in context; success`, func(t *testing.T) {
    26  		RegisterTestingT(t)
    27  
    28  		doer.Expect("Do", func(c context.Context, r *http.Request) (*http.Response, error) {
    29  			Expect(r).To(Equal(req))
    30  			Expect(c).To(Equal(ctx))
    31  			return &http.Response{StatusCode: 123}, nil
    32  		})
    33  		resp, err := WrapDoer(doer).Do(ctx, req)
    34  		Expect(err).To(Succeed())
    35  		Expect(resp.StatusCode).To(Equal(123))
    36  		Expect(doer.MetExpectations()).To(Succeed())
    37  	})
    38  
    39  	const (
    40  		segmentName = "segmentName1"
    41  		traceID     = "traceID1"
    42  		spanID      = "spanID1"
    43  	)
    44  
    45  	t.Run(`with a segment in context - successful request`, func(t *testing.T) {
    46  		RegisterTestingT(t)
    47  
    48  		// add an xray segment to the context
    49  		xrayConn := NewTestNetConn()
    50  		segment := NewSegment(segmentName, traceID, spanID, xrayConn)
    51  		ctx = WithSegment(ctx, segment)
    52  
    53  		doer.Expect("Do", func(c context.Context, r *http.Request) (*http.Response, error) {
    54  			Expect(r).To(Equal(req))
    55  			Expect(ContextSegment(c).ParentID).To(Equal(segment.ID))
    56  			return &http.Response{StatusCode: 123}, nil
    57  		})
    58  
    59  		xrayConn.Expect("Write", func(b []byte) (int, error) {
    60  			lines := strings.Split(string(b), "\n")
    61  			Expect(lines).To(HaveLen(2))
    62  			Expect(lines[0]).To(Equal(`{"format": "json", "version": 1}`))
    63  
    64  			var s Segment
    65  			err := json.Unmarshal([]byte(lines[1]), &s)
    66  			Expect(err).To(Succeed())
    67  			Expect(s).To(MatchFields(IgnoreMissing|IgnoreExtras, Fields{
    68  				"Name":      Equal("somehost:80"),
    69  				"Namespace": Equal("remote"),
    70  				"Type":      Equal("subsegment"),
    71  				"ID":        And(Not(BeEmpty()), Not(Equal(segment.ID))), // randomly generated
    72  				"TraceID":   Equal(traceID),
    73  				"ParentID":  Equal(spanID),
    74  				"Error":     BeFalse(),
    75  				"HTTP": PointTo(MatchAllFields(Fields{
    76  					"Request":  Equal(&Request{Method: "GET", URL: "http://somehost:80/path"}),
    77  					"Response": Equal(&Response{Status: 123}),
    78  				})),
    79  			}))
    80  			return len(b), nil
    81  		})
    82  		resp, err := WrapDoer(doer).Do(ctx, req)
    83  		Expect(err).To(Succeed())
    84  		Expect(resp.StatusCode).To(Equal(123))
    85  		Expect(doer.MetExpectations()).To(Succeed())
    86  		Expect(xrayConn.MetExpectations()).To(Succeed())
    87  	})
    88  
    89  	t.Run(`with a segment in context - failed request`, func(t *testing.T) {
    90  		RegisterTestingT(t)
    91  
    92  		// add an xray segment to the context
    93  		xrayConn := NewTestNetConn()
    94  		segment := NewSegment(segmentName, traceID, spanID, xrayConn)
    95  		ctx = WithSegment(ctx, segment)
    96  
    97  		var (
    98  			requestErr = errors.New("some request error")
    99  		)
   100  		doer.Expect("Do", func(c context.Context, r *http.Request) (*http.Response, error) {
   101  			Expect(ContextSegment(c).ParentID).To(Equal(segment.ID))
   102  			return nil, requestErr
   103  		})
   104  
   105  		xrayConn.Expect("Write", func(b []byte) (int, error) {
   106  			lines := strings.Split(string(b), "\n")
   107  			Expect(lines).To(HaveLen(2))
   108  			Expect(lines[0]).To(Equal(`{"format": "json", "version": 1}`))
   109  
   110  			var s Segment
   111  			err := json.Unmarshal([]byte(lines[1]), &s)
   112  			Expect(err).To(Succeed())
   113  			Expect(s).To(MatchFields(IgnoreMissing|IgnoreExtras, Fields{
   114  				"Name":      Equal("somehost:80"),
   115  				"Namespace": Equal("remote"),
   116  				"Type":      Equal("subsegment"),
   117  				"ID":        And(Not(BeEmpty()), Not(Equal(segment.ID))), // randomly generated
   118  				"TraceID":   Equal(traceID),
   119  				"ParentID":  Equal(spanID),
   120  				"Error":     BeTrue(),
   121  				"HTTP": PointTo(MatchAllFields(Fields{
   122  					"Request":  Equal(&Request{Method: "GET", URL: "http://somehost:80/path"}),
   123  					"Response": BeNil(),
   124  				})),
   125  			}))
   126  			return len(b), nil
   127  		})
   128  		_, err := WrapDoer(doer).Do(ctx, req)
   129  		Expect(err).To(MatchError(requestErr))
   130  
   131  		Expect(doer.MetExpectations()).To(Succeed())
   132  		Expect(xrayConn.MetExpectations()).To(Succeed())
   133  	})
   134  }
   135  
   136  type MockDoer struct {
   137  	*TestClientExpectation
   138  }
   139  
   140  func NewMockDoer() *MockDoer {
   141  	return &MockDoer{NewTestClientExpectation()}
   142  }
   143  
   144  func (m *MockDoer) Do(ctx context.Context, req *http.Request) (*http.Response, error) {
   145  	if e := m.Expectation("Do"); e != nil {
   146  		return e.(func(context.Context, *http.Request) (*http.Response, error))(ctx, req)
   147  	}
   148  	return nil, nil
   149  }