Skip to content
This repository was archived by the owner on Nov 7, 2022. It is now read-only.

Commit ee33463

Browse files
author
Paulo Janotti
authored
Make TestZipkinExportersFromYAML_roundtripJSON reliable (#391)
The test depends on the 3 spans from the test data to arrive as a single batch. However, the zipkin exporter does not exposes this fine control of the zipkin reporter used to send the spans. In principle we could expose an option to adjust zipkin reporter batch size but that still requires the test to coordinate the send/receive of the batch. A simpler solution is to implement a mock of the zipkin reporter that behaves synchronously, avoiding any synchronization issue. This also avoids more API surface on the product code.
1 parent 77741c8 commit ee33463

1 file changed

Lines changed: 67 additions & 4 deletions

File tree

exporter/exporterparser/zipkin_test.go

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ package exporterparser
1717
import (
1818
"bytes"
1919
"context"
20+
"encoding/json"
21+
"fmt"
2022
"io"
2123
"io/ioutil"
2224
"net"
@@ -28,6 +30,7 @@ import (
2830

2931
commonpb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/common/v1"
3032
zipkinmodel "github.com/openzipkin/zipkin-go/model"
33+
zipkinreporter "github.com/openzipkin/zipkin-go/reporter"
3134

3235
"github.com/census-instrumentation/opencensus-service/exporter"
3336
"github.com/census-instrumentation/opencensus-service/internal/config/viperutils"
@@ -133,12 +136,10 @@ func TestZipkinEndpointFromNode(t *testing.T) {
133136
//
134137
// The rest of the fields should match up exactly
135138
func TestZipkinExportersFromViper_roundtripJSON(t *testing.T) {
136-
responseReady := make(chan bool)
137139
buf := new(bytes.Buffer)
138140
cst := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
139141
io.Copy(buf, r.Body)
140142
r.Body.Close()
141-
responseReady <- true
142143
}))
143144
defer cst.Close()
144145

@@ -161,6 +162,11 @@ zipkin:
161162
t.Errorf("Number of trace exporters: Got %d Want %d", g, w)
162163
}
163164

165+
// The test requires the spans from zipkinSpansJSONJavaLibrary to be sent in a single batch, use
166+
// a mock to ensure that this happens as intended.
167+
mzr := newMockZipkinReporter(cst.URL)
168+
tes[0].(*zipkinExporter).reporter = mzr
169+
164170
// Run the Zipkin receiver to "receive spans upload from a client application"
165171
zi, err := zipkinreceiver.New(":0")
166172
if err != nil {
@@ -177,8 +183,12 @@ zipkin:
177183
req, _ := http.NewRequest("POST", "https://tld.org/", strings.NewReader(zipkinSpansJSONJavaLibrary))
178184
responseWriter := httptest.NewRecorder()
179185
zi.ServeHTTP(responseWriter, req)
180-
// Wait for the server to write the response.
181-
<-responseReady
186+
187+
// Use the mock zipkin reporter to ensure all expected spans in a single batch. Since Flush waits for
188+
// server response there is no need for further synchronization.
189+
if err := mzr.Flush(); err != nil {
190+
t.Fatalf("Failed to flush zipkin reporter: %v", err)
191+
}
182192

183193
// We expect back the exact JSON that was received
184194
want := testutils.GenerateNormalizedJSON(`
@@ -224,6 +234,59 @@ zipkin:
224234
}
225235
}
226236

237+
type mockZipkinReporter struct {
238+
url string
239+
client *http.Client
240+
batch []*zipkinmodel.SpanModel
241+
}
242+
243+
var _ (zipkinreporter.Reporter) = (*mockZipkinReporter)(nil)
244+
245+
func (r *mockZipkinReporter) Send(span zipkinmodel.SpanModel) {
246+
r.batch = append(r.batch, &span)
247+
}
248+
func (r *mockZipkinReporter) Close() error {
249+
return nil
250+
}
251+
252+
func newMockZipkinReporter(url string) *mockZipkinReporter {
253+
return &mockZipkinReporter{
254+
url: url,
255+
client: &http.Client{},
256+
}
257+
}
258+
259+
func (r *mockZipkinReporter) Flush() error {
260+
sendBatch := r.batch
261+
r.batch = nil
262+
263+
if len(sendBatch) == 0 {
264+
return nil
265+
}
266+
267+
body, err := json.Marshal(sendBatch)
268+
if err != nil {
269+
return err
270+
}
271+
272+
req, err := http.NewRequest("POST", r.url, bytes.NewReader(body))
273+
if err != nil {
274+
return err
275+
}
276+
req.Header.Set("Content-Type", "application/json")
277+
278+
resp, err := r.client.Do(req)
279+
if err != nil {
280+
return err
281+
}
282+
_ = resp.Body.Close()
283+
if resp.StatusCode < 200 || resp.StatusCode > 299 {
284+
return fmt.Errorf("http request failed with status code %d", resp.StatusCode)
285+
}
286+
287+
return nil
288+
}
289+
227290
const zipkinSpansJSONJavaLibrary = `
228291
[{
229292
"traceId": "4d1e00c0db9010db86154a4ba6e91385",

0 commit comments

Comments
 (0)