Skip to content

Commit

Permalink
ci: add test for instrumenter package (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
123liuziming authored and y1yang0 committed Jul 30, 2024
1 parent 5eed1e0 commit 2c080d6
Show file tree
Hide file tree
Showing 8 changed files with 330 additions and 14 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/go21.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:

- name: Build
run: make build

- name: InstUt
run: go test -v ./pkg/...
- name: Test
run: go test -short -timeout 50m -v github.com/alibaba/opentelemetry-go-auto-instrumentation/test
3 changes: 2 additions & 1 deletion .github/workflows/go22.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:

- name: Build
run: make build

- name: InstUt
run: go test -v ./pkg/...
- name: Test
run: go test -short -timeout 50m -v github.com/alibaba/opentelemetry-go-auto-instrumentation/test
68 changes: 68 additions & 0 deletions pkg/inst-api/instrumenter/extractor_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package instrumenter

import (
"errors"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
"testing"
)

type testSpan struct {
trace.Span
status *codes.Code
}

func (ts testSpan) SetStatus(status codes.Code, desc string) {
*ts.status = status
}

func TestDefaultSpanStatusExtractor(t *testing.T) {
unset := codes.Unset
ts := testSpan{Span: noop.Span{}, status: &unset}
d := defaultSpanStatusExtractor[interface{}, interface{}]{}
d.Extract(ts, nil, nil, errors.New(""))
if *ts.status != codes.Error {
t.Fatal("expected error code")
}
}

func TestAlwaysInternalExtractor(t *testing.T) {
a := AlwaysInternalExtractor()
kind := a.Extract(nil)
if kind != trace.SpanKindInternal {
t.Fatal("expected internal kind")
}
}

func TestAlwaysServerExtractor(t *testing.T) {
a := AlwaysServerExtractor()
kind := a.Extract(nil)
if kind != trace.SpanKindServer {
t.Fatal("expected server kind")
}
}

func TestAlwaysClientExtractor(t *testing.T) {
a := AlwaysClientExtractor()
kind := a.Extract(nil)
if kind != trace.SpanKindClient {
t.Fatal("expected client kind")
}
}

func TestAlwaysConsumerExtractor(t *testing.T) {
a := AlwaysConsumerExtractor()
kind := a.Extract(nil)
if kind != trace.SpanKindConsumer {
t.Fatal("expected consumer kind")
}
}

func TestAlwaysProducerExtractor(t *testing.T) {
a := AlwaysProducerExtractor()
kind := a.Extract(nil)
if kind != trace.SpanKindProducer {
t.Fatal("expected producer kind")
}
}
23 changes: 12 additions & 11 deletions pkg/inst-api/instrumenter/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,30 @@ type OperationListenerWrapper struct {
attrCustomizer AttrsShadower
}

func NewOperationListenerWrapper(listener OperationListener, attrCustomizer AttrsShadower) *OperationListenerWrapper {
return &OperationListenerWrapper{
listener: listener,
attrCustomizer: attrCustomizer,
}
}

func (w *OperationListenerWrapper) OnBeforeStart(parentContext context.Context, startTimestamp time.Time) context.Context {
return w.listener.OnBeforeStart(parentContext, startTimestamp)
}

func (w *OperationListenerWrapper) OnBeforeEnd(context context.Context, startAttributes []attribute.KeyValue, startTimestamp time.Time) context.Context {
validNum, startAttributes := w.attrCustomizer.Shadow(startAttributes)
return w.listener.OnBeforeEnd(context, startAttributes[:validNum], startTimestamp)
if w.attrCustomizer != nil {
validNum, startAttributes := w.attrCustomizer.Shadow(startAttributes)
return w.listener.OnBeforeEnd(context, startAttributes[:validNum], startTimestamp)
} else {
return w.listener.OnBeforeEnd(context, startAttributes, startTimestamp)
}
}

func (w *OperationListenerWrapper) OnAfterStart(context context.Context, endTimestamp time.Time) {
w.listener.OnAfterStart(context, endTimestamp)
}

func (w *OperationListenerWrapper) OnAfterEnd(context context.Context, endAttributes []attribute.KeyValue, endTimestamp time.Time) {
validNum, endAttributes := w.attrCustomizer.Shadow(endAttributes)
w.listener.OnAfterEnd(context, endAttributes[:validNum], endTimestamp)
if w.attrCustomizer != nil {
validNum, endAttributes := w.attrCustomizer.Shadow(endAttributes)
w.listener.OnAfterEnd(context, endAttributes[:validNum], endTimestamp)
} else {
w.listener.OnAfterEnd(context, endAttributes, endTimestamp)
}
}

type ContextCustomizer[REQUEST interface{}] interface {
Expand Down
105 changes: 105 additions & 0 deletions pkg/inst-api/instrumenter/hook_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package instrumenter

import (
"context"
"go.opentelemetry.io/otel/attribute"
"log"
"testing"
"time"
)

type testListener struct {
startTime time.Time
endTime time.Time
startAttributes []attribute.KeyValue
endAttributes []attribute.KeyValue
}

func (t *testListener) OnBeforeStart(parentContext context.Context, startTimestamp time.Time) context.Context {
t.startTime = startTimestamp
return context.WithValue(parentContext, "test1", "a")
}

func (t *testListener) OnBeforeEnd(ctx context.Context, startAttributes []attribute.KeyValue, startTimestamp time.Time) context.Context {
t.startAttributes = startAttributes
return context.WithValue(ctx, "test2", "a")
}

func (t *testListener) OnAfterStart(context context.Context, endTimestamp time.Time) {
t.endTime = endTimestamp
}

func (t *testListener) OnAfterEnd(context context.Context, endAttributes []attribute.KeyValue, endTimestamp time.Time) {
t.endAttributes = endAttributes
}

func TestShadower(t *testing.T) {
originAttrs := []attribute.KeyValue{
attribute.String("a", "b"),
attribute.String("a1", "a1"),
attribute.String("a2", "a2"),
attribute.String("a3", "a3"),
}

n := NoopAttrsShadower{}
num, newAttrs := n.Shadow(originAttrs)
if num != len(originAttrs) {
log.Fatal("origin attrs length is not equal to new attrs length")
}
for i := 0; i < num; i++ {
if newAttrs[i].Value != originAttrs[i].Value {
log.Fatal("origin attrs value is not equal to new attrs value")
}
}
}

func TestOnBeforeStart(t *testing.T) {
w := OperationListenerWrapper{listener: &testListener{}}
newCtx := w.OnBeforeStart(context.Background(), time.UnixMilli(123412341234))
wListener := w.listener.(*testListener)
if wListener.startTime.UnixMilli() != 123412341234 {
log.Fatal("start time is not equal to new start time")
}
if newCtx.Value("test1") != "a" {
log.Fatal("key test1 is not equal to new key value")
}
}

func TestOnBeforeEnd(t *testing.T) {
w := OperationListenerWrapper{listener: &testListener{}}
w.OnBeforeEnd(context.Background(), []attribute.KeyValue{{
Key: "123",
Value: attribute.StringValue("abcde"),
}}, time.UnixMilli(123412341234))
wListener := w.listener.(*testListener)
if wListener.startAttributes[0].Key != "123" {
log.Fatal("start attribute key is not equal to new start attribute key")
}
if wListener.startAttributes[0].Value.AsString() != "abcde" {
log.Fatal("start attribute value is not equal to new start attribute value")
}
}

func TestOnAfterStart(t *testing.T) {
w := OperationListenerWrapper{listener: &testListener{}}
w.OnAfterStart(context.Background(), time.UnixMilli(123412341234))
wListener := w.listener.(*testListener)
if wListener.endTime.UnixMilli() != 123412341234 {
log.Fatal("start time is not equal to new start time")
}
}

func TestOnAfterEnd(t *testing.T) {
w := OperationListenerWrapper{listener: &testListener{}}
w.OnAfterEnd(context.Background(), []attribute.KeyValue{{
Key: "123",
Value: attribute.StringValue("abcde"),
}}, time.UnixMilli(123412341234))
wListener := w.listener.(*testListener)
if wListener.endAttributes[0].Key != "123" {
log.Fatal("start attribute key is not equal to new start attribute key")
}
if wListener.endAttributes[0].Value.AsString() != "abcde" {
log.Fatal("start attribute value is not equal to new start attribute value")
}
}
106 changes: 106 additions & 0 deletions pkg/inst-api/instrumenter/instrumenter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package instrumenter

import (
"context"
"errors"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"testing"
"time"
)

type testRequest struct {
}

type testResponse struct {
status string
}

type testNameExtractor struct {
}

func (t testNameExtractor) Extract(request testRequest) string {
return "test"
}

type testOperationListener struct {
}

func (t *testOperationListener) OnBeforeStart(parentContext context.Context, startTimestamp time.Time) context.Context {
return context.WithValue(parentContext, "startTs", startTimestamp)
}

func (t *testOperationListener) OnBeforeEnd(ctx context.Context, startAttributes []attribute.KeyValue, startTimestamp time.Time) context.Context {
return context.WithValue(ctx, "startAttrs", startAttributes)
}

func (t *testOperationListener) OnAfterStart(context context.Context, endTimestamp time.Time) {
if time.Now().Sub(endTimestamp).Seconds() > 5 {
panic("duration too long")
}
}

func (t *testOperationListener) OnAfterEnd(context context.Context, endAttributes []attribute.KeyValue, endTimestamp time.Time) {
if endAttributes[0].Key != "testAttribute" {
panic("invalid attribute key")
}
if endAttributes[0].Value.AsString() != "testValue" {
panic("invalid attribute value")
}
}

type testAttributesExtractor struct {
}

func (t testAttributesExtractor) OnStart(attributes []attribute.KeyValue, parentContext context.Context, request testRequest) []attribute.KeyValue {
return []attribute.KeyValue{
attribute.String("testAttribute", "testValue"),
}
}

func (t testAttributesExtractor) OnEnd(attributes []attribute.KeyValue, context context.Context, request testRequest, response testResponse, err error) []attribute.KeyValue {
return []attribute.KeyValue{
attribute.String("testAttribute", "testValue"),
}
}

type testContextCustomizer struct {
}

func (t testContextCustomizer) OnStart(ctx context.Context, request testRequest, startAttributes []attribute.KeyValue) context.Context {
return context.WithValue(ctx, "test-customizer", "test-customizer")
}

type testStatusExtractor struct {
}

func (t testStatusExtractor) Extract(span trace.Span, request testRequest, response testResponse, err error) {
if err.Error() != "abc" {
panic(err)
}
}

func TestInstrumenter(t *testing.T) {
builder := Builder[testRequest, testResponse]{}
builder.Init().
SetSpanNameExtractor(testNameExtractor{}).
SetSpanKindExtractor(&alwaysClientExtractor[testRequest]{}).
AddAttributesExtractor(testAttributesExtractor{}).
AddOperationListeners(&OperationListenerWrapper{
listener: &testOperationListener{},
attrCustomizer: NoopAttrsShadower{},
}).AddContextCustomizers(testContextCustomizer{})
instrumenter := builder.BuildInstrumenter()
ctx := context.Background()
newCtx := instrumenter.Start(ctx, testRequest{})
if newCtx.Value("test-customizer") != "test-customizer" {
t.Fatal("key test-customizer is not expected")
}
if newCtx.Value("startTs") == nil {
t.Fatal("startTs is not expected")
}
if newCtx.Value("startAttrs") == nil {
t.Fatal("startAttrs is not expected")
}
instrumenter.End(ctx, testRequest{}, testResponse{}, errors.New("abc"))
}
35 changes: 35 additions & 0 deletions pkg/inst-api/instrumenter/span_supressor_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package instrumenter

import (
"context"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api/utils"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
"testing"
)

func TestNoopSpanSupressor(t *testing.T) {
n := NoopSpanSuppressor{}
ctx := context.Background()
n.StoreInContext(ctx, trace.SpanKindClient, noop.Span{})
if n.ShouldSuppress(ctx, trace.SpanKindClient) != false {
t.Errorf("should not suppress span")
}
}

func TestSpanKeySuppressor(t *testing.T) {
s := SpanKeySuppressor{
spanKeys: []attribute.Key{
utils.RPC_CLIENT_KEY,
},
}
ctx := context.Background()
newCtx := s.StoreInContext(ctx, trace.SpanKindClient, noop.Span{})
if !s.ShouldSuppress(newCtx, trace.SpanKindClient) {
t.Errorf("should suppress span")
}
if s.ShouldSuppress(context.Background(), trace.SpanKindClient) {
t.Errorf("should not suppress span")
}
}
1 change: 0 additions & 1 deletion pkg/verifier/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ func TestGetFreePort(t *testing.T) {
if port == 0 {
t.Fatal("port is 0")
}
t.Logf("port is %d", port)
}

0 comments on commit 2c080d6

Please sign in to comment.