github.com/ManabuSeki/goa-v1@v1.4.3/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 // "in_progress":true segment 60 xrayConn.Expect("Write", func(b []byte) (int, error) { 61 lines := strings.Split(string(b), "\n") 62 Expect(lines).To(HaveLen(2)) 63 Expect(lines[0]).To(Equal(`{"format": "json", "version": 1}`)) 64 65 var s Segment 66 Expect(json.Unmarshal([]byte(lines[1]), &s)).To(Succeed()) 67 Expect(s).To(MatchFields(IgnoreExtras, Fields{ 68 "Name": Equal("somehost:80"), 69 "Type": Equal("subsegment"), 70 "ID": SatisfyAll(Not(BeEmpty()), Not(Equal(segment.ID))), // randomly generated 71 "TraceID": Equal(traceID), 72 "ParentID": Equal(spanID), 73 "InProgress": BeTrue(), 74 })) 75 return len(b), nil 76 }) 77 78 // final "in_progress":false segment 79 xrayConn.Expect("Write", func(b []byte) (int, error) { 80 lines := strings.Split(string(b), "\n") 81 Expect(lines).To(HaveLen(2)) 82 Expect(lines[0]).To(Equal(`{"format": "json", "version": 1}`)) 83 84 var s Segment 85 err := json.Unmarshal([]byte(lines[1]), &s) 86 Expect(err).To(Succeed()) 87 Expect(s).To(MatchFields(IgnoreExtras, Fields{ 88 "Name": Equal("somehost:80"), 89 "Namespace": Equal("remote"), 90 "Type": Equal("subsegment"), 91 "ID": And(Not(BeEmpty()), Not(Equal(segment.ID))), // randomly generated 92 "TraceID": Equal(traceID), 93 "ParentID": Equal(spanID), 94 "Error": BeFalse(), 95 "HTTP": PointTo(MatchAllFields(Fields{ 96 "Request": Equal(&Request{Method: "GET", URL: "http://somehost:80/path"}), 97 "Response": Equal(&Response{Status: 123}), 98 })), 99 "InProgress": BeFalse(), 100 })) 101 return len(b), nil 102 }) 103 resp, err := WrapDoer(doer).Do(ctx, req) 104 Expect(err).To(Succeed()) 105 Expect(resp.StatusCode).To(Equal(123)) 106 Expect(doer.MetExpectations()).To(Succeed()) 107 Expect(xrayConn.MetExpectations()).To(Succeed()) 108 }) 109 110 t.Run(`with a segment in context - failed request`, func(t *testing.T) { 111 RegisterTestingT(t) 112 113 // add an xray segment to the context 114 xrayConn := NewTestNetConn() 115 segment := NewSegment(segmentName, traceID, spanID, xrayConn) 116 ctx = WithSegment(ctx, segment) 117 118 var ( 119 requestErr = errors.New("some request error") 120 ) 121 doer.Expect("Do", func(c context.Context, r *http.Request) (*http.Response, error) { 122 Expect(ContextSegment(c).ParentID).To(Equal(segment.ID)) 123 return nil, requestErr 124 }) 125 126 // "in_progress":true segment 127 xrayConn.Expect("Write", func(b []byte) (int, error) { 128 lines := strings.Split(string(b), "\n") 129 Expect(lines).To(HaveLen(2)) 130 Expect(lines[0]).To(Equal(`{"format": "json", "version": 1}`)) 131 132 var s Segment 133 Expect(json.Unmarshal([]byte(lines[1]), &s)).To(Succeed()) 134 Expect(s).To(MatchFields(IgnoreExtras, Fields{ 135 "Name": Equal("somehost:80"), 136 "Type": Equal("subsegment"), 137 "ID": SatisfyAll(Not(BeEmpty()), Not(Equal(segment.ID))), // randomly generated 138 "TraceID": Equal(traceID), 139 "ParentID": Equal(spanID), 140 "InProgress": BeTrue(), 141 })) 142 return len(b), nil 143 }) 144 145 // final "in_progress":false segment 146 xrayConn.Expect("Write", func(b []byte) (int, error) { 147 lines := strings.Split(string(b), "\n") 148 Expect(lines).To(HaveLen(2)) 149 Expect(lines[0]).To(Equal(`{"format": "json", "version": 1}`)) 150 151 var s Segment 152 err := json.Unmarshal([]byte(lines[1]), &s) 153 Expect(err).To(Succeed()) 154 Expect(s).To(MatchFields(IgnoreExtras, Fields{ 155 "Name": Equal("somehost:80"), 156 "Namespace": Equal("remote"), 157 "Type": Equal("subsegment"), 158 "ID": And(Not(BeEmpty()), Not(Equal(segment.ID))), // randomly generated 159 "TraceID": Equal(traceID), 160 "ParentID": Equal(spanID), 161 "Error": BeTrue(), 162 "HTTP": PointTo(MatchAllFields(Fields{ 163 "Request": Equal(&Request{Method: "GET", URL: "http://somehost:80/path"}), 164 "Response": BeNil(), 165 })), 166 "InProgress": BeFalse(), 167 })) 168 return len(b), nil 169 }) 170 _, err := WrapDoer(doer).Do(ctx, req) 171 Expect(err).To(MatchError(requestErr)) 172 173 Expect(doer.MetExpectations()).To(Succeed()) 174 Expect(xrayConn.MetExpectations()).To(Succeed()) 175 }) 176 } 177 178 type MockDoer struct { 179 *TestClientExpectation 180 } 181 182 func NewMockDoer() *MockDoer { 183 return &MockDoer{NewTestClientExpectation()} 184 } 185 186 func (m *MockDoer) Do(ctx context.Context, req *http.Request) (*http.Response, error) { 187 if e := m.Expectation("Do"); e != nil { 188 return e.(func(context.Context, *http.Request) (*http.Response, error))(ctx, req) 189 } 190 return nil, nil 191 }