Skip to content

Commit

Permalink
ref(test): Move assert* helpers to internal package (#562)
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyo authored Feb 1, 2023
1 parent c9145b9 commit beca7e6
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 130 deletions.
70 changes: 4 additions & 66 deletions helpers_test.go
Original file line number Diff line number Diff line change
@@ -1,71 +1,9 @@
package sentry

import (
"fmt"
"reflect"
"testing"

"github.com/getsentry/sentry-go/internal/otel/baggage"
"github.com/getsentry/sentry-go/internal/testutils"
)

func assertEqual(t *testing.T, got, want interface{}, userMessage ...interface{}) {
t.Helper()

if !reflect.DeepEqual(got, want) {
logFailedAssertion(t, formatUnequalValues(got, want), userMessage...)
}
}

func assertNotEqual(t *testing.T, got, want interface{}, userMessage ...interface{}) {
t.Helper()

if reflect.DeepEqual(got, want) {
logFailedAssertion(t, formatUnequalValues(got, want), userMessage...)
}
}

func logFailedAssertion(t *testing.T, summary string, userMessage ...interface{}) {
t.Helper()
text := summary

if len(userMessage) > 0 {
if message, ok := userMessage[0].(string); ok {
if message != "" && len(userMessage) > 1 {
text = fmt.Sprintf(message, userMessage[1:]...) + text
} else if message != "" {
text = fmt.Sprint(message) + text
}
}
}

t.Error(text)
}

func formatUnequalValues(got, want interface{}) string {
var a, b string

if reflect.TypeOf(got) != reflect.TypeOf(want) {
a, b = fmt.Sprintf("%T(%#v)", got, got), fmt.Sprintf("%T(%#v)", want, want)
} else {
a, b = fmt.Sprintf("%#v", got), fmt.Sprintf("%#v", want)
}

return fmt.Sprintf("\ngot: %s\nwant: %s", a, b)
}

func assertBaggageStringsEqual(t *testing.T, got, want string, userMessage ...interface{}) {
t.Helper()

baggageGot, err := baggage.Parse(got)
if err != nil {
t.Error(err)
}
baggageWant, err := baggage.Parse(want)
if err != nil {
t.Error(err)
}

if !reflect.DeepEqual(baggageGot, baggageWant) {
logFailedAssertion(t, formatUnequalValues(got, want), userMessage...)
}
}
var assertEqual = testutils.AssertEqual
var assertNotEqual = testutils.AssertNotEqual
var assertBaggageStringsEqual = testutils.AssertBaggageStringsEqual
96 changes: 96 additions & 0 deletions internal/testutils/asserts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package testutils

import (
"fmt"
"reflect"
"testing"

"github.com/getsentry/sentry-go/internal/otel/baggage"
"github.com/google/go-cmp/cmp"
)

func AssertEqual(t *testing.T, got, want interface{}, userMessage ...interface{}) {
t.Helper()

// Ideally, we would switch to cmp.Diff. However, in a general case, cmp.Diff
// is not able to compare structs with unexported (private) fields by default. There
// are ways to override modify that behaviour (e.g. by passing AllowUnexported), but
// it significantly complicates its usage.
if !reflect.DeepEqual(got, want) {
logFailedAssertion(t, formatUnequalValues(got, want), userMessage...)
}
}

func AssertNotEqual(t *testing.T, got, want interface{}, userMessage ...interface{}) {
t.Helper()

if reflect.DeepEqual(got, want) {
logFailedAssertion(t, formatUnequalValues(got, want), userMessage...)
}
}

func AssertTrue(t *testing.T, condition bool, userMessage ...interface{}) {
t.Helper()

if !condition {
logFailedAssertion(t, "\nExpected: true", userMessage...)
}
}

func AssertFalse(t *testing.T, condition bool, userMessage ...interface{}) {
t.Helper()

if condition {
logFailedAssertion(t, "\nExpected: false", userMessage...)
}
}

func logFailedAssertion(t *testing.T, summary string, userMessage ...interface{}) {
t.Helper()
text := summary

if len(userMessage) > 0 {
if message, ok := userMessage[0].(string); ok {
if message != "" && len(userMessage) > 1 {
text = fmt.Sprintf(message, userMessage[1:]...) + text
} else if message != "" {
text = fmt.Sprint(message) + text
}
}
}

t.Error(text)
}

func formatUnequalValues(got, want interface{}) string {
var a, b string

if reflect.TypeOf(got) != reflect.TypeOf(want) {
a, b = fmt.Sprintf("%T(%#v)", got, got), fmt.Sprintf("%T(%#v)", want, want)
} else {
a, b = fmt.Sprintf("%#v", got), fmt.Sprintf("%#v", want)
}

return fmt.Sprintf("\ngot: %s\nwant: %s", a, b)
}

func AssertBaggageStringsEqual(t *testing.T, got, want string, userMessage ...interface{}) {
t.Helper()

baggageGot, err := baggage.Parse(got)
if err != nil {
t.Error(err)
}
baggageWant, err := baggage.Parse(want)
if err != nil {
t.Error(err)
}

if diff := cmp.Diff(
baggageWant,
baggageGot,
cmp.AllowUnexported(baggage.Member{}, baggage.Baggage{}),
); diff != "" {
t.Errorf("Comparing Baggage (-want +got):\n%s", diff)
}
}
64 changes: 12 additions & 52 deletions otel/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,25 @@

package sentryotel

// TODO(anton): This is a copy of helpers_test.go in the repo root.
// We should figure out how to share testing helpers.

import (
"encoding/hex"
"fmt"
"reflect"
"sort"
"sync"
"testing"
"time"

"github.com/getsentry/sentry-go"
"github.com/getsentry/sentry-go/internal/testutils"
"github.com/google/go-cmp/cmp"
"go.opentelemetry.io/otel/baggage"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)

func assertEqual(t *testing.T, got, want interface{}, userMessage ...interface{}) {
t.Helper()

if !reflect.DeepEqual(got, want) {
logFailedAssertion(t, formatUnequalValues(got, want), userMessage...)
}
}

func assertNotEqual(t *testing.T, got, want interface{}, userMessage ...interface{}) {
t.Helper()

if reflect.DeepEqual(got, want) {
logFailedAssertion(t, formatUnequalValues(got, want), userMessage...)
}
}

func logFailedAssertion(t *testing.T, summary string, userMessage ...interface{}) {
t.Helper()
text := summary

if len(userMessage) > 0 {
if message, ok := userMessage[0].(string); ok {
if message != "" && len(userMessage) > 1 {
text = fmt.Sprintf(message, userMessage[1:]...) + text
} else if message != "" {
text = fmt.Sprint(message) + text
}
}
}

t.Error(text)
}

func formatUnequalValues(got, want interface{}) string {
var a, b string

if reflect.TypeOf(got) != reflect.TypeOf(want) {
a, b = fmt.Sprintf("%T(%#v)", got, got), fmt.Sprintf("%T(%#v)", want, want)
} else {
a, b = fmt.Sprintf("%#v", got), fmt.Sprintf("%#v", want)
}

return fmt.Sprintf("\ngot: %s\nwant: %s", a, b)
}
var assertEqual = testutils.AssertEqual
var assertNotEqual = testutils.AssertNotEqual
var assertTrue = testutils.AssertTrue
var assertFalse = testutils.AssertFalse

// assertMapCarrierEqual compares two values of type propagation.MapCarrier and raises an
// assertion error if the values differ.
Expand Down Expand Up @@ -95,8 +51,6 @@ func assertMapCarrierEqual(t *testing.T, got, want propagation.MapCarrier, userM
t.Errorf("Comparing Baggage parsing errors (-want +got):\n%s", diff)
}

// sortedBaggage = gotBaggage.Members()

if diff := cmp.Diff(
wantBaggage,
gotBaggage,
Expand Down Expand Up @@ -159,7 +113,13 @@ func otelSpanIDFromHex(s string) trace.SpanID {
return spanID
}

// FIXME(anton): copie from mocks_test.go
// FIXME(anton): TransportMock is copied from mocks_test.go
// I don't see an easy way right now to reuse this struct in "sentry" and
// "sentryotel" packages: it naturally depends on "sentry", but tests in "sentry"
// package also depend on it, so if we move it to a new package, we'll get an
// import cycle.
// Alternatively, it could be made public on "sentry" package, but it doesn't
// feel right.

type TransportMock struct {
mu sync.Mutex
Expand Down
24 changes: 12 additions & 12 deletions otel/span_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ func TestOnStartRootSpan(t *testing.T) {
otelTraceId := otelSpan.SpanContext().TraceID()
otelSpanId := otelSpan.SpanContext().SpanID()
// TODO(anton): use a simple "assert", not "assertEqual"
assertEqual(t, otelSpan.SpanContext().IsValid(), true)
assertTrue(t, otelSpan.SpanContext().IsValid())
assertEqual(t, sentrySpan.SpanID.String(), otelSpanId.String())
assertEqual(t, sentrySpan.TraceID.String(), otelTraceId.String())
assertEqual(t, sentrySpan.ParentSpanID, sentry.SpanID{})
assertEqual(t, sentrySpan.IsTransaction(), true)
assertTrue(t, sentrySpan.IsTransaction())
assertEqual(t, sentrySpan.ToBaggage(), "")
assertEqual(t, sentrySpan.Sampled, sentry.SampledTrue)
assertEqual(t, transactionName(sentrySpan), "spanName")
Expand Down Expand Up @@ -171,13 +171,13 @@ func TestOnStartWithTraceParentContext(t *testing.T) {
t.Errorf("Sentry span not found in the map")
}

assertEqual(t, otelSpan.SpanContext().IsValid(), true)
assertTrue(t, otelSpan.SpanContext().IsValid())
assertEqual(t, sentrySpan.SpanID.String(), otelSpan.SpanContext().SpanID().String())
// We're currently taking trace id and parent span id from the otel span context,
// (not sentry-trace header), mostly to be aligned with other SDKs.
assertEqual(t, sentrySpan.TraceID.String(), "bc6d53f15eb88f4320054569b8c553d4")
assertEqual(t, sentrySpan.ParentSpanID, SpanIDFromHex("b72fa28504b07285"))
assertEqual(t, sentrySpan.IsTransaction(), true)
assertTrue(t, sentrySpan.IsTransaction())
assertEqual(t, sentrySpan.ToBaggage(), "sentry-environment=dev")
assertEqual(t, sentrySpan.Sampled, sentry.SampledFalse)
assertEqual(t, transactionName(sentrySpan), "spanName")
Expand Down Expand Up @@ -213,12 +213,12 @@ func TestOnStartWithExistingParentSpan(t *testing.T) {
t.Errorf("Sentry span not found in the map")
}

assertEqual(t, otelChildSpan.SpanContext().IsValid(), true)
assertEqual(t, otelRootSpan.SpanContext().IsValid(), true)
assertTrue(t, otelChildSpan.SpanContext().IsValid())
assertTrue(t, otelRootSpan.SpanContext().IsValid())
assertEqual(t, sentryChildSpan.ParentSpanID, sentryTransaction.SpanID)
assertEqual(t, sentryChildSpan.SpanID.String(), otelChildSpan.SpanContext().SpanID().String())
assertEqual(t, sentryChildSpan.TraceID.String(), "bc6d53f15eb88f4320054569b8c553d4")
assertEqual(t, sentryChildSpan.IsTransaction(), false)
assertFalse(t, sentryChildSpan.IsTransaction())
assertEqual(t, transactionName(sentryChildSpan), "rootSpan")
assertEqual(t, sentryChildSpan.Op, "childSpan")
}
Expand All @@ -233,13 +233,13 @@ func TestOnEndWithTransaction(t *testing.T) {
),
)
sentryTransaction, _ := sentrySpanMap.Get(otelSpan.SpanContext().SpanID())
assertEqual(t, sentryTransaction.EndTime.IsZero(), true)
assertTrue(t, sentryTransaction.EndTime.IsZero())
otelSpan.End()

// The span map should be empty
assertEqual(t, sentrySpanMap.Len(), 0)
// EndTime should be populated
assertEqual(t, sentryTransaction.EndTime.IsZero(), false)
assertFalse(t, sentryTransaction.EndTime.IsZero())

assertEqual(t, sentryTransaction.Status, sentry.SpanStatusOK)
assertEqual(t, sentryTransaction.Source, sentry.TransactionSource("custom"))
Expand Down Expand Up @@ -286,8 +286,8 @@ func TestOnEndWithChildSpan(t *testing.T) {
// The span map should be empty
assertEqual(t, sentrySpanMap.Len(), 0)
// EndTime should be populated
assertEqual(t, sentryTransaction.EndTime.IsZero(), false)
assertEqual(t, sentryChildSpan.EndTime.IsZero(), false)
assertFalse(t, sentryTransaction.EndTime.IsZero())
assertFalse(t, sentryChildSpan.EndTime.IsZero())

assertEqual(t, sentryChildSpan.Status, sentry.SpanStatusOK)
assertEqual(t, sentryChildSpan.Source, sentry.TransactionSource(""))
Expand Down Expand Up @@ -322,7 +322,7 @@ func TestOnEndDoesNotFinishSentryRequests(t *testing.T) {
// The span map should be empty
assertEqual(t, sentrySpanMap.Len(), 0)
// EndTime should NOT be populated
assertEqual(t, sentrySpan.EndTime.IsZero(), true)
assertTrue(t, sentrySpan.EndTime.IsZero())
// No events should be captured by transport
sentryTransport := getSentryTransportFromContext(ctx)
events := sentryTransport.Events()
Expand Down

0 comments on commit beca7e6

Please sign in to comment.