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

Commit 9fa7389

Browse files
author
Bogdan Drutu
authored
Add tests for observabilitytest, change api to return error. (#482)
* Add tests for observabilitytest, change api to return error. * Fix comment example. * Remove debugging printfs and update test names for nop.
1 parent 79342d9 commit 9fa7389

File tree

8 files changed

+256
-85
lines changed

8 files changed

+256
-85
lines changed

exporter/exportertest/nop_exporter.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,20 @@ import (
2121
"github.com/census-instrumentation/opencensus-service/exporter"
2222
)
2323

24-
type nopExporter int
24+
// NopExporterOption represents options that can be applied to a NopExporter.
25+
type NopExporterOption func(*nopExporter)
26+
27+
type nopExporter struct{ retError error }
2528

2629
var _ exporter.TraceExporter = (*nopExporter)(nil)
2730
var _ exporter.MetricsExporter = (*nopExporter)(nil)
2831

2932
func (ne *nopExporter) ConsumeTraceData(ctx context.Context, td data.TraceData) error {
30-
return nil
33+
return ne.retError
3134
}
3235

3336
func (ne *nopExporter) ConsumeMetricsData(ctx context.Context, md data.MetricsData) error {
34-
return nil
37+
return ne.retError
3538
}
3639

3740
const (
@@ -48,11 +51,26 @@ func (ne *nopExporter) MetricsExportFormat() string {
4851
}
4952

5053
// NewNopTraceExporter creates an TraceExporter that just drops the received data.
51-
func NewNopTraceExporter() exporter.TraceExporter {
52-
return new(nopExporter)
54+
func NewNopTraceExporter(options ...NopExporterOption) exporter.TraceExporter {
55+
return newNopExporter(options...)
5356
}
5457

5558
// NewNopMetricsExporter creates an MetricsExporter that just drops the received data.
56-
func NewNopMetricsExporter() exporter.MetricsExporter {
57-
return new(nopExporter)
59+
func NewNopMetricsExporter(options ...NopExporterOption) exporter.MetricsExporter {
60+
return newNopExporter(options...)
61+
}
62+
63+
// WithReturnError returns a NopExporterOption that enforces the nop Exporters to return the given error.
64+
func WithReturnError(retError error) NopExporterOption {
65+
return func(ne *nopExporter) {
66+
ne.retError = retError
67+
}
68+
}
69+
70+
func newNopExporter(options ...NopExporterOption) *nopExporter {
71+
ne := new(nopExporter)
72+
for _, opt := range options {
73+
opt(ne)
74+
}
75+
return ne
5876
}

exporter/exportertest/nop_exporter_test.go

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,64 @@ package exportertest
1515

1616
import (
1717
"context"
18+
"errors"
1819
"testing"
1920

2021
metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
2122
tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1"
2223
"github.com/census-instrumentation/opencensus-service/data"
2324
)
2425

25-
func TestNopTraceExporterNoErrors(t *testing.T) {
26+
func TestNopTraceExporter_NoErrors(t *testing.T) {
2627
nte := NewNopTraceExporter()
2728
td := data.TraceData{
2829
Spans: make([]*tracepb.Span, 7),
2930
}
3031
if err := nte.ConsumeTraceData(context.Background(), td); err != nil {
31-
t.Errorf("Wanted nil got error")
32-
return
32+
t.Fatalf("Wanted nil got error")
3333
}
3434
if "nop_trace" != nte.TraceExportFormat() {
35-
t.Errorf("Wanted nop_trace got %s", nte.TraceExportFormat())
36-
return
35+
t.Fatalf("Wanted nop_trace got %s", nte.TraceExportFormat())
3736
}
3837
}
3938

40-
func TestNoopMetricsExporterNoErrors(t *testing.T) {
39+
func TestNopTraceExporter_WithErrors(t *testing.T) {
40+
want := errors.New("MyError")
41+
nte := NewNopTraceExporter(WithReturnError(want))
42+
td := data.TraceData{
43+
Spans: make([]*tracepb.Span, 7),
44+
}
45+
if got := nte.ConsumeTraceData(context.Background(), td); got != want {
46+
t.Fatalf("Want %v Got %v", want, got)
47+
}
48+
if "nop_trace" != nte.TraceExportFormat() {
49+
t.Fatalf("Wanted nop_trace got %s", nte.TraceExportFormat())
50+
}
51+
}
52+
53+
func TestNopMetricsExporter_NoErrors(t *testing.T) {
4154
nme := NewNopMetricsExporter()
4255
md := data.MetricsData{
4356
Metrics: make([]*metricspb.Metric, 7),
4457
}
4558
if err := nme.ConsumeMetricsData(context.Background(), md); err != nil {
46-
t.Errorf("Wanted nil got error")
47-
return
59+
t.Fatalf("Wanted nil got error")
60+
}
61+
if "nop_metrics" != nme.MetricsExportFormat() {
62+
t.Fatalf("Wanted nop_metrics got %s", nme.MetricsExportFormat())
63+
}
64+
}
65+
66+
func TestNopMetricsExporter_WithErrors(t *testing.T) {
67+
want := errors.New("MyError")
68+
nme := NewNopMetricsExporter(WithReturnError(want))
69+
md := data.MetricsData{
70+
Metrics: make([]*metricspb.Metric, 7),
71+
}
72+
if got := nme.ConsumeMetricsData(context.Background(), md); got != want {
73+
t.Fatalf("Want %v Got %v", want, got)
4874
}
4975
if "nop_metrics" != nme.MetricsExportFormat() {
50-
t.Errorf("Wanted nop_metrics got %s", nme.MetricsExportFormat())
51-
return
76+
t.Fatalf("Wanted nop_metrics got %s", nme.MetricsExportFormat())
5277
}
5378
}

exporter/exportertest/sink_exporter_test.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ func TestSinkTraceExporter(t *testing.T) {
3131
want := make([]data.TraceData, 0, 7)
3232
for i := 0; i < 7; i++ {
3333
if err := sink.ConsumeTraceData(context.Background(), td); err != nil {
34-
t.Errorf("Wanted nil got error")
35-
return
34+
t.Fatalf("Wanted nil got error")
3635
}
3736
want = append(want, td)
3837
}
@@ -42,7 +41,6 @@ func TestSinkTraceExporter(t *testing.T) {
4241
}
4342
if "sink_trace" != sink.TraceExportFormat() {
4443
t.Errorf("Wanted sink_trace got %s", sink.TraceExportFormat())
45-
return
4644
}
4745
}
4846

@@ -54,8 +52,7 @@ func TestSinkMetricsExporter(t *testing.T) {
5452
want := make([]data.MetricsData, 0, 7)
5553
for i := 0; i < 7; i++ {
5654
if err := sink.ConsumeMetricsData(context.Background(), md); err != nil {
57-
t.Errorf("Wanted nil got error")
58-
return
55+
t.Fatalf("Wanted nil got error")
5956
}
6057
want = append(want, md)
6158
}
@@ -65,6 +62,5 @@ func TestSinkMetricsExporter(t *testing.T) {
6562
}
6663
if "sink_metrics" != sink.MetricsExportFormat() {
6764
t.Errorf("Wanted sink_metrics got %s", sink.MetricsExportFormat())
68-
return
6965
}
7066
}

exporter/loggingexporter/logging_exporter_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ func TestLoggingTraceExporterNoErrors(t *testing.T) {
3030
Spans: make([]*tracepb.Span, 7),
3131
}
3232
if err := lte.ConsumeTraceData(context.Background(), td); err != nil {
33-
t.Errorf("Wanted nil got error")
34-
return
33+
t.Fatalf("Wanted nil got error")
3534
}
3635
if "logging_trace" != lte.TraceExportFormat() {
3736
t.Errorf("Wanted logging_trace got %v", lte.TraceExportFormat())
@@ -40,7 +39,9 @@ func TestLoggingTraceExporterNoErrors(t *testing.T) {
4039

4140
func TestLoggingTraceExporterRecordMetrics(t *testing.T) {
4241
lte := NewTraceExporter(zap.NewNop())
43-
observabilitytest.CheckRecordedMetricsForTraceExporter(t, lte)
42+
if err := observabilitytest.CheckRecordedMetricsForTraceExporter(lte); err != nil {
43+
t.Fatalf("When test LoggingTraceExporter recording metrics: want nil got %v", err)
44+
}
4445
}
4546

4647
func TestLoggingMetricsExporterNoErrors(t *testing.T) {
@@ -49,8 +50,7 @@ func TestLoggingMetricsExporterNoErrors(t *testing.T) {
4950
Metrics: make([]*metricspb.Metric, 7),
5051
}
5152
if err := lme.ConsumeMetricsData(context.Background(), md); err != nil {
52-
t.Errorf("Wanted nil got error")
53-
return
53+
t.Fatalf("Wanted nil got error")
5454
}
5555
if "logging_metrics" != lme.MetricsExportFormat() {
5656
t.Errorf("Wanted logging_metrics got %v", lme.MetricsExportFormat())

observability/observability_test.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
// observability and observabilitytest
1717
package observability_test
1818

19-
// This file contains helpers that are useful to add observability
20-
// with metrics and tracing using OpenCensus to the various pieces
21-
// of the service.
22-
2319
import (
2420
"context"
2521
"testing"
@@ -34,14 +30,22 @@ const (
3430
)
3531

3632
func TestTracePieplineRecordedMetrics(t *testing.T) {
37-
defer observabilitytest.SetupRecordedMetricsTest(t)()
33+
defer observabilitytest.SetupRecordedMetricsTest()()
3834

3935
receiverCtx := observability.ContextWithReceiverName(context.Background(), receiverName)
4036
observability.RecordTraceReceiverMetrics(receiverCtx, 17, 13)
4137
exporterCtx := observability.ContextWithExporterName(receiverCtx, exporterName)
4238
observability.RecordTraceExporterMetrics(exporterCtx, 27, 23)
43-
observabilitytest.CheckValueViewReceiverReceivedSpans(t, receiverName, 17)
44-
observabilitytest.CheckValueViewReceiverDroppedSpans(t, receiverName, 13)
45-
observabilitytest.CheckValueViewExporterReceivedSpans(t, receiverName, exporterName, 27)
46-
observabilitytest.CheckValueViewExporterDroppedSpans(t, receiverName, exporterName, 23)
39+
if err := observabilitytest.CheckValueViewReceiverReceivedSpans(receiverName, 17); err != nil {
40+
t.Fatalf("When check recorded values: want nil got %v", err)
41+
}
42+
if err := observabilitytest.CheckValueViewReceiverDroppedSpans(receiverName, 13); err != nil {
43+
t.Fatalf("When check recorded values: want nil got %v", err)
44+
}
45+
if err := observabilitytest.CheckValueViewExporterReceivedSpans(receiverName, exporterName, 27); err != nil {
46+
t.Fatalf("When check recorded values: want nil got %v", err)
47+
}
48+
if err := observabilitytest.CheckValueViewExporterDroppedSpans(receiverName, exporterName, 23); err != nil {
49+
t.Fatalf("When check recorded values: want nil got %v", err)
50+
}
4751
}

observability/observabilitytest/observabilitytest.go

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ package observabilitytest
1616

1717
import (
1818
"context"
19+
"fmt"
1920
"reflect"
2021
"sort"
21-
"testing"
2222
"time"
2323

2424
tracepb "github.com/census-instrumentation/opencensus-proto/gen-go/trace/v1"
@@ -42,16 +42,14 @@ var _ view.Exporter = (*nopMetricsExporter)(nil)
4242
func (cme *nopMetricsExporter) ExportView(vd *view.Data) {}
4343

4444
// SetupRecordedMetricsTest does setup the testing environment to check the metrics recorded by receivers, producers or exporters.
45-
// The returned function should be deferred "defer SetupRecordedMetricsTest(t)()".
46-
func SetupRecordedMetricsTest(t *testing.T) func() {
45+
// The returned function should be deferred "defer SetupRecordedMetricsTest()()".
46+
func SetupRecordedMetricsTest() func() {
4747
// Register a nop metrics exporter for the OC library.
4848
nmp := new(nopMetricsExporter)
4949
view.RegisterExporter(nmp)
5050

5151
// Now for the stats exporter
52-
if err := view.Register(observability.AllViews...); err != nil {
53-
t.Fatalf("Failed to register all views: %v", err)
54-
}
52+
view.Register(observability.AllViews...)
5553

5654
return func() {
5755
view.UnregisterExporter(nmp)
@@ -62,8 +60,8 @@ func SetupRecordedMetricsTest(t *testing.T) func() {
6260
// CheckRecordedMetricsForTraceExporter checks that the given TraceExporter records the correct set of metrics with the correct
6361
// set of tags by sending few TraceData to the exporter. The exporter should be able to handle the requests correctly without
6462
// dropping.
65-
func CheckRecordedMetricsForTraceExporter(t *testing.T, te exporter.TraceExporter) {
66-
defer SetupRecordedMetricsTest(t)()
63+
func CheckRecordedMetricsForTraceExporter(te exporter.TraceExporter) error {
64+
defer SetupRecordedMetricsTest()()
6765

6866
now := time.Now().UTC()
6967
spans := []*tracepb.Span{
@@ -87,70 +85,64 @@ func CheckRecordedMetricsForTraceExporter(t *testing.T, te exporter.TraceExporte
8785
},
8886
},
8987
},
90-
{
91-
TraceId: []byte{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E},
92-
SpanId: []byte{0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F},
93-
ParentSpanId: []byte{0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7},
94-
Name: &tracepb.TruncatableString{Value: "LocalSpan"},
95-
Kind: tracepb.Span_SPAN_KIND_UNSPECIFIED,
96-
StartTime: internal.TimeToTimestamp(now.Add(-15 * time.Millisecond)),
97-
EndTime: internal.TimeToTimestamp(now),
98-
Status: &tracepb.Status{Code: int32(0), Message: "OK"},
99-
Tracestate: &tracepb.Span_Tracestate{},
100-
},
10188
}
10289
td := data.TraceData{Spans: spans}
10390
ctx := observability.ContextWithReceiverName(context.Background(), fakeReceiverName)
10491
const numBatches = 7
10592
for i := 0; i < numBatches; i++ {
10693
if err := te.ConsumeTraceData(ctx, td); err != nil {
107-
t.Fatalf("Want nil got %v", err)
94+
return fmt.Errorf("Want nil got %v", err)
10895
}
10996
}
11097

111-
CheckValueViewExporterReceivedSpans(t, fakeReceiverName, te.TraceExportFormat(), int64(numBatches*len(spans)))
112-
CheckValueViewExporterDroppedSpans(t, fakeReceiverName, te.TraceExportFormat(), 0)
98+
if err := CheckValueViewExporterReceivedSpans(fakeReceiverName, te.TraceExportFormat(), numBatches*len(spans)); err != nil {
99+
return err
100+
}
101+
if err := CheckValueViewExporterDroppedSpans(fakeReceiverName, te.TraceExportFormat(), 0); err != nil {
102+
return err
103+
}
104+
return nil
113105
}
114106

115107
// CheckValueViewExporterReceivedSpans checks that for the current exported value in the ViewExporterReceivedSpans
116108
// for {TagKeyReceiver: receiverName, TagKeyExporter: exporterTagName} is equal to "value".
117-
// In tests that this function is called it is required to also call SetupRecordedMetricsTest as first thing.
118-
func CheckValueViewExporterReceivedSpans(t *testing.T, receiverName string, exporterTagName string, value int64) {
119-
checkValueForView(t, observability.ViewExporterReceivedSpans.Name,
120-
wantsTagsForExporterView(receiverName, exporterTagName), value)
109+
// When this function is called it is required to also call SetupRecordedMetricsTest as first thing.
110+
func CheckValueViewExporterReceivedSpans(receiverName string, exporterTagName string, value int) error {
111+
return checkValueForView(observability.ViewExporterReceivedSpans.Name,
112+
wantsTagsForExporterView(receiverName, exporterTagName), int64(value))
121113
}
122114

123115
// CheckValueViewExporterDroppedSpans checks that for the current exported value in the ViewExporterDroppedSpans
124116
// for {TagKeyReceiver: receiverName} is equal to "value".
125117
// In tests that this function is called it is required to also call SetupRecordedMetricsTest as first thing.
126-
func CheckValueViewExporterDroppedSpans(t *testing.T, receiverName string, exporterTagName string, value int64) {
127-
checkValueForView(t, observability.ViewExporterDroppedSpans.Name,
128-
wantsTagsForExporterView(receiverName, exporterTagName), value)
118+
func CheckValueViewExporterDroppedSpans(receiverName string, exporterTagName string, value int) error {
119+
return checkValueForView(observability.ViewExporterDroppedSpans.Name,
120+
wantsTagsForExporterView(receiverName, exporterTagName), int64(value))
129121
}
130122

131123
// CheckValueViewReceiverReceivedSpans checks that for the current exported value in the ViewReceiverReceivedSpans
132124
// for {TagKeyReceiver: receiverName, TagKeyExporter: exporterTagName} is equal to "value".
133125
// In tests that this function is called it is required to also call SetupRecordedMetricsTest as first thing.
134-
func CheckValueViewReceiverReceivedSpans(t *testing.T, receiverName string, value int64) {
135-
checkValueForView(t, observability.ViewReceiverReceivedSpans.Name,
136-
wantsTagsForReceiverView(receiverName), value)
126+
func CheckValueViewReceiverReceivedSpans(receiverName string, value int) error {
127+
return checkValueForView(observability.ViewReceiverReceivedSpans.Name,
128+
wantsTagsForReceiverView(receiverName), int64(value))
137129
}
138130

139131
// CheckValueViewReceiverDroppedSpans checks that for the current exported value in the ViewReceiverDroppedSpans
140132
// for {TagKeyReceiver: receiverName} is equal to "value".
141133
// In tests that this function is called it is required to also call SetupRecordedMetricsTest as first thing.
142-
func CheckValueViewReceiverDroppedSpans(t *testing.T, receiverName string, value int64) {
143-
checkValueForView(t, observability.ViewReceiverDroppedSpans.Name,
144-
wantsTagsForReceiverView(receiverName), value)
134+
func CheckValueViewReceiverDroppedSpans(receiverName string, value int) error {
135+
return checkValueForView(observability.ViewReceiverDroppedSpans.Name,
136+
wantsTagsForReceiverView(receiverName), int64(value))
145137
}
146138

147-
func checkValueForView(t *testing.T, vName string, wantTags []tag.Tag, value int64) {
139+
func checkValueForView(vName string, wantTags []tag.Tag, value int64) error {
148140
// Make sure the tags slice is sorted by tag keys.
149141
sortTags(wantTags)
150142

151143
rows, err := view.RetrieveData(vName)
152144
if err != nil {
153-
t.Fatalf("Error retrieving view data for view Name %s", vName)
145+
return fmt.Errorf("Error retrieving view data for view Name %s", vName)
154146
}
155147

156148
for _, row := range rows {
@@ -159,13 +151,13 @@ func checkValueForView(t *testing.T, vName string, wantTags []tag.Tag, value int
159151
if reflect.DeepEqual(wantTags, row.Tags) {
160152
sum := row.Data.(*view.SumData)
161153
if float64(value) != sum.Value {
162-
t.Fatalf("Want %v got %v", float64(value), sum.Value)
154+
return fmt.Errorf("Different recorded value: want %v got %v", float64(value), sum.Value)
163155
}
164156
// We found the result
165-
return
157+
return nil
166158
}
167159
}
168-
t.Fatalf("Could not find wantTags: %s in rows %v", wantTags, rows)
160+
return fmt.Errorf("Could not find wantTags: %s in rows %v", wantTags, rows)
169161
}
170162

171163
func wantsTagsForExporterView(receiverName string, exporterTagName string) []tag.Tag {

0 commit comments

Comments
 (0)