Skip to content

Commit

Permalink
Add encoding tests to the telemetry package (#1196)
Browse files Browse the repository at this point in the history
* Add encoding tests to telemetry pkg

* Test link flags
  • Loading branch information
MrAlias authored Oct 19, 2024
1 parent 8b55ec1 commit 756cc23
Show file tree
Hide file tree
Showing 9 changed files with 706 additions and 32 deletions.
160 changes: 139 additions & 21 deletions sdk/telemetry/attr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,10 @@

package telemetry

import (
"encoding/json"
"testing"
import "testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

var (
decoded = []Attr{
func TestAttrEncoding(t *testing.T) {
attrs := []Attr{
String("user", "Alice"),
Bool("admin", true),
Int64("floor", -2),
Expand All @@ -22,17 +16,141 @@ var (
Bytes("secret", []byte("NUI4RUZGRjc5ODAzODEwM0QyNjlCNjMzODEzRkM2MEM=")),
}

encoded = []byte(`[{"key":"user","value":{"stringValue":"Alice"}},{"key":"admin","value":{"boolValue":true}},{"key":"floor","value":{"intValue":"-2"}},{"key":"impact","value":{"doubleValue":0.21362}},{"key":"reports","value":{"arrayValue":{"values":[{"stringValue":"Bob"},{"stringValue":"Dave"}]}}},{"key":"favorites","value":{"kvlistValue":{"values":[{"key":"food","value":{"stringValue":"hot dog"}},{"key":"number","value":{"intValue":"13"}}]}}},{"key":"secret","value":{"bytesValue":"TlVJNFJVWkdSamM1T0RBek9ERXdNMFF5TmpsQ05qTXpPREV6UmtNMk1FTT0="}}]`)
)

func TestAttrUnmarshal(t *testing.T) {
var got []Attr
require.NoError(t, json.Unmarshal(encoded, &got))
assert.Equal(t, decoded, got)
}
t.Run("CamelCase", runJSONEncodingTests(attrs, []byte(`[
{
"key": "user",
"value": {
"stringValue": "Alice"
}
},
{
"key": "admin",
"value": {
"boolValue": true
}
},
{
"key": "floor",
"value": {
"intValue": "-2"
}
},
{
"key": "impact",
"value": {
"doubleValue": 0.21362
}
},
{
"key": "reports",
"value": {
"arrayValue": {
"values": [
{
"stringValue": "Bob"
},
{
"stringValue": "Dave"
}
]
}
}
},
{
"key": "favorites",
"value": {
"kvlistValue": {
"values": [
{
"key": "food",
"value": {
"stringValue": "hot dog"
}
},
{
"key": "number",
"value": {
"intValue": "13"
}
}
]
}
}
},
{
"key": "secret",
"value": {
"bytesValue": "TlVJNFJVWkdSamM1T0RBek9ERXdNMFF5TmpsQ05qTXpPREV6UmtNMk1FTT0="
}
}
]`)))

func TestAttrMarshal(t *testing.T) {
got, err := json.Marshal(decoded)
require.NoError(t, err)
assert.Equal(t, string(encoded), string(got))
t.Run("SnakeCase/Unmarshal", runJSONUnmarshalTest(attrs, []byte(`[
{
"key": "user",
"value": {
"string_value": "Alice"
}
},
{
"key": "admin",
"value": {
"bool_value": true
}
},
{
"key": "floor",
"value": {
"int_value": "-2"
}
},
{
"key": "impact",
"value": {
"double_value": 0.21362
}
},
{
"key": "reports",
"value": {
"array_value": {
"values": [
{
"string_value": "Bob"
},
{
"string_value": "Dave"
}
]
}
}
},
{
"key": "favorites",
"value": {
"kvlist_value": {
"values": [
{
"key": "food",
"value": {
"string_value": "hot dog"
}
},
{
"key": "number",
"value": {
"int_value": "13"
}
}
]
}
}
},
{
"key": "secret",
"value": {
"bytes_value": "TlVJNFJVWkdSamM1T0RBek9ERXdNMFF5TmpsQ05qTXpPREV6UmtNMk1FTT0="
}
}
]`)))
}
50 changes: 50 additions & 0 deletions sdk/telemetry/conv_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package telemetry

import (
"bytes"
"encoding/json"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const schema100 = "http://go.opentelemetry.io/schema/v1.0.0"

var y2k = time.Unix(0, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).UnixNano()) // No location.

func runJSONEncodingTests[T any](decoded T, encoded []byte) func(*testing.T) {
return func(t *testing.T) {
t.Helper()

t.Run("Unmarshal", runJSONUnmarshalTest(decoded, encoded))
t.Run("Marshal", runJSONMarshalTest(decoded, encoded))
}
}

func runJSONMarshalTest[T any](decoded T, encoded []byte) func(*testing.T) {
return func(t *testing.T) {
t.Helper()

got, err := json.Marshal(decoded)
require.NoError(t, err)

var want bytes.Buffer
require.NoError(t, json.Compact(&want, encoded))
assert.Equal(t, want.String(), string(got))
}
}

func runJSONUnmarshalTest[T any](decoded T, encoded []byte) func(*testing.T) {
return func(t *testing.T) {
t.Helper()

var got T
require.NoError(t, json.Unmarshal(encoded, &got))
assert.Equal(t, decoded, got)
}
}
37 changes: 37 additions & 0 deletions sdk/telemetry/resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package telemetry

import "testing"

func TestResourceEncoding(t *testing.T) {
res := &Resource{
Attrs: []Attr{String("key", "val")},
DroppedAttrs: 10,
}

t.Run("CamelCase", runJSONEncodingTests(res, []byte(`{
"attributes": [
{
"key": "key",
"value": {
"stringValue": "val"
}
}
],
"droppedAttributesCount": 10
}`)))

t.Run("SnakeCase/Unmarshal", runJSONUnmarshalTest(res, []byte(`{
"attributes": [
{
"key": "key",
"value": {
"string_value": "val"
}
}
],
"dropped_attributes_count": 10
}`)))
}
55 changes: 55 additions & 0 deletions sdk/telemetry/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,65 @@

package telemetry

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
)

// Scope is the identifying values of the instrumentation scope.
type Scope struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
Attrs []Attr `json:"attributes,omitempty"`
DroppedAttrs uint32 `json:"droppedAttributesCount,omitempty"`
}

// UnmarshalJSON decodes the OTLP formatted JSON contained in data into r.
func (s *Scope) UnmarshalJSON(data []byte) error {
decoder := json.NewDecoder(bytes.NewReader(data))

t, err := decoder.Token()
if err != nil {
return err
}
if t != json.Delim('{') {
return errors.New("invalid Scope type")
}

for decoder.More() {
keyIface, err := decoder.Token()
if err != nil {
if errors.Is(err, io.EOF) {
// Empty.
return nil
}
return err
}

key, ok := keyIface.(string)
if !ok {
return fmt.Errorf("invalid Scope field: %#v", keyIface)
}

switch key {
case "name":
err = decoder.Decode(&s.Name)
case "version":
err = decoder.Decode(&s.Version)
case "attributes":
err = decoder.Decode(&s.Attrs)
case "droppedAttributesCount", "dropped_attributes_count":
err = decoder.Decode(&s.DroppedAttrs)
default:
// Skip unknown.
}

if err != nil {
return err
}
}
return nil
}
43 changes: 43 additions & 0 deletions sdk/telemetry/scope_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package telemetry

import "testing"

func TestScopeEncoding(t *testing.T) {
scope := &Scope{
Name: "go.opentelemetry.io/auto/sdk/telemetry/test",
Version: "v0.0.1",
Attrs: []Attr{String("department", "ops")},
DroppedAttrs: 1,
}

t.Run("CamelCase", runJSONEncodingTests(scope, []byte(`{
"name": "go.opentelemetry.io/auto/sdk/telemetry/test",
"version": "v0.0.1",
"attributes": [
{
"key": "department",
"value": {
"stringValue": "ops"
}
}
],
"droppedAttributesCount": 1
}`)))

t.Run("SnakeCase/Unmarshal", runJSONUnmarshalTest(scope, []byte(`{
"name": "go.opentelemetry.io/auto/sdk/telemetry/test",
"version": "v0.0.1",
"attributes": [
{
"key": "department",
"value": {
"string_value": "ops"
}
}
],
"dropped_attributes_count": 1
}`)))
}
Loading

0 comments on commit 756cc23

Please sign in to comment.