Skip to content

Commit

Permalink
Add TracerProvider tests to oteltest harness (#1607)
Browse files Browse the repository at this point in the history
* Add TracerProvider tests to oteltest harness

* Update Tracer method docs

* Fix grammar
  • Loading branch information
MrAlias authored Mar 3, 2021
1 parent bb4c297 commit 992837f
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 7 deletions.
6 changes: 6 additions & 0 deletions internal/matchers/expectation.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ func (e *Expectation) ToBeFalse() {
}
}

func (e *Expectation) NotToPanic() {
if actual := recover(); actual != nil {
e.fail(fmt.Sprintf("Expected panic\n\t%v\nto have not been raised", actual))
}
}

func (e *Expectation) ToSucceed() {
switch actual := e.actual.(type) {
case error:
Expand Down
51 changes: 51 additions & 0 deletions oteltest/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package oteltest // import "go.opentelemetry.io/otel/oteltest"

import (
"context"
"fmt"
"sync"
"testing"
"time"
Expand All @@ -39,6 +40,56 @@ func NewHarness(t *testing.T) *Harness {
}
}

// TestTracer runs validation tests for an implementation of the OpenTelemetry
// TracerProvider API.
func (h *Harness) TestTracerProvider(subjectFactory func() trace.TracerProvider) {
h.t.Run("#Start", func(t *testing.T) {
t.Run("allow creating an arbitrary number of TracerProvider instances", func(t *testing.T) {
t.Parallel()

e := matchers.NewExpecter(t)

tp1 := subjectFactory()
tp2 := subjectFactory()

e.Expect(tp1).NotToEqual(tp2)
})
t.Run("all methods are safe to be called concurrently", func(t *testing.T) {
t.Parallel()

runner := func(tp trace.TracerProvider) <-chan struct{} {
done := make(chan struct{})
go func(tp trace.TracerProvider) {
var wg sync.WaitGroup
for i := 0; i < 20; i++ {
wg.Add(1)
go func(name, version string) {
_ = tp.Tracer(name, trace.WithInstrumentationVersion(version))
wg.Done()
}(fmt.Sprintf("tracer %d", i%5), fmt.Sprintf("%d", i))
}
wg.Wait()
done <- struct{}{}
}(tp)
return done
}

matchers.NewExpecter(t).Expect(func() {
// Run with multiple TracerProvider to ensure they encapsulate
// their own Tracers.
tp1 := subjectFactory()
tp2 := subjectFactory()

done1 := runner(tp1)
done2 := runner(tp2)

<-done1
<-done2
}).NotToPanic()
})
})
}

// TestTracer runs validation tests for an implementation of the OpenTelemetry
// Tracer API.
func (h *Harness) TestTracer(subjectFactory func() trace.Tracer) {
Expand Down
9 changes: 7 additions & 2 deletions sdk/trace/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,13 @@ func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
return tp
}

// Tracer with the given name. If a tracer for the given name does not exist,
// it is created first. If the name is empty, DefaultTracerName is used.
// Tracer returns a Tracer with the given name and options. If a Tracer for
// the given name and options does not exist it is created, otherwise the
// existing Tracer is returned.
//
// If name is empty, DefaultTracerName is used instead.
//
// This method is safe to be called concurrently.
func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
c := trace.NewTracerConfig(opts...)

Expand Down
13 changes: 8 additions & 5 deletions sdk/trace/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,16 @@ func init() {
}

func TestTracerFollowsExpectedAPIBehaviour(t *testing.T) {
tp := NewTracerProvider(WithConfig(Config{DefaultSampler: TraceIDRatioBased(0)}))
harness := oteltest.NewHarness(t)
subjectFactory := func() trace.Tracer {
return tp.Tracer("")
}

harness.TestTracer(subjectFactory)
harness.TestTracerProvider(func() trace.TracerProvider {
return NewTracerProvider(WithConfig(Config{DefaultSampler: TraceIDRatioBased(0)}))
})

tp := NewTracerProvider(WithConfig(Config{DefaultSampler: TraceIDRatioBased(0)}))
harness.TestTracer(func() trace.Tracer {
return tp.Tracer("")
})
}

type testExporter struct {
Expand Down
2 changes: 2 additions & 0 deletions trace/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,5 +558,7 @@ type TracerProvider interface {
// only if that code provides built-in instrumentation. If the
// instrumentationName is empty, then a implementation defined default
// name will be used instead.
//
// This method must be concurrency safe.
Tracer(instrumentationName string, opts ...TracerOption) Tracer
}

0 comments on commit 992837f

Please sign in to comment.