1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,894 @@
package json_v1
import (
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/plugins/inputs/zipkin/codec"
)
func TestJSON_Decode(t *testing.T) {
addr := func(i int64) *int64 { return &i }
tests := []struct {
name string
octets []byte
want []codec.Span
wantErr bool
}{
{
name: "bad json is error",
octets: []byte(`
[
{
]`),
wantErr: true,
},
{
name: "Decodes simple trace",
octets: []byte(`
[
{
"traceId": "6b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c"
}
]`),
want: []codec.Span{
&span{
TraceID: "6b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
},
},
},
{
name: "Decodes two spans",
octets: []byte(`
[
{
"traceId": "6b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c"
},
{
"traceId": "6b221d5bc9e6496c",
"name": "get-traces",
"id": "c6946e9cb5d122b6",
"parentId": "6b221d5bc9e6496c",
"duration": 10000
}
]`),
want: []codec.Span{
&span{
TraceID: "6b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
},
&span{
TraceID: "6b221d5bc9e6496c",
SpanName: "get-traces",
ID: "c6946e9cb5d122b6",
ParentID: "6b221d5bc9e6496c",
Dur: addr(10000),
},
},
},
{
name: "Decodes trace with timestamp",
octets: []byte(`
[
{
"traceId": "6b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"timestamp": 1503031538791000
}
]`),
want: []codec.Span{
&span{
TraceID: "6b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
Time: addr(1503031538791000),
},
},
},
{
name: "Decodes simple trace with high and low trace id",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c"
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
},
},
},
{
name: "Error when trace id is null",
octets: []byte(`
[
{
"traceId": null,
"name": "get-traces",
"id": "6b221d5bc9e6496c"
}
]`),
wantErr: true,
},
{
name: "ignore null parentId",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"parentId": null
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
},
},
},
{
name: "ignore null timestamp",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"timestamp": null
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
},
},
},
{
name: "ignore null duration",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"duration": null
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
},
},
},
{
name: "ignore null annotation endpoint",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"annotations": [
{
"timestamp": 1461750491274000,
"value": "cs",
"endpoint": null
}
]
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
Anno: []annotation{
{
Time: 1461750491274000,
Val: "cs",
},
},
},
},
},
{
name: "ignore null binary annotation endpoint",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"binaryAnnotations": [
{
"key": "lc",
"value": "JDBCSpanStore",
"endpoint": null
}
]
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
BAnno: []binaryAnnotation{
{
K: "lc",
V: json.RawMessage(`"JDBCSpanStore"`),
},
},
},
},
},
{
name: "Error when binary annotation has no key",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"binaryAnnotations": [
{
"value": "JDBCSpanStore",
"endpoint": null
}
]
}
]`),
wantErr: true,
},
{
name: "Error when binary annotation has no value",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"binaryAnnotations": [
{
"key": "lc",
"endpoint": null
}
]
}
]`),
wantErr: true,
},
{
name: "binary annotation with endpoint",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"binaryAnnotations": [
{
"key": "lc",
"value": "JDBCSpanStore",
"endpoint": {
"serviceName": "service",
"port": 65535
}
}
]
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
BAnno: []binaryAnnotation{
{
K: "lc",
V: json.RawMessage(`"JDBCSpanStore"`),
Endpoint: &endpoint{
ServiceName: "service",
Port: 65535,
},
},
},
},
},
},
{
name: "binary annotation with double value",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"binaryAnnotations": [
{
"key": "num",
"value": 1.23456789,
"type": "DOUBLE"
}
]
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
BAnno: []binaryAnnotation{
{
K: "num",
V: json.RawMessage{0x31, 0x2e, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39},
Type: "DOUBLE",
},
},
},
},
},
{
name: "binary annotation with integer value",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"binaryAnnotations": [
{
"key": "num",
"value": 1,
"type": "I16"
}
]
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
BAnno: []binaryAnnotation{
{
K: "num",
V: json.RawMessage{0x31},
Type: "I16",
},
},
},
},
},
{
name: "binary annotation with bool value",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"binaryAnnotations": [
{
"key": "num",
"value": true,
"type": "BOOL"
}
]
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
BAnno: []binaryAnnotation{
{
K: "num",
V: json.RawMessage(`true`),
Type: "BOOL",
},
},
},
},
},
{
name: "binary annotation with bytes value",
octets: []byte(`
[
{
"traceId": "48485a3953bb61246b221d5bc9e6496c",
"name": "get-traces",
"id": "6b221d5bc9e6496c",
"binaryAnnotations": [
{
"key": "num",
"value": "1",
"type": "BYTES"
}
]
}
]`),
want: []codec.Span{
&span{
TraceID: "48485a3953bb61246b221d5bc9e6496c",
SpanName: "get-traces",
ID: "6b221d5bc9e6496c",
BAnno: []binaryAnnotation{
{
K: "num",
V: json.RawMessage(`"1"`),
Type: "BYTES",
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
j := &JSON{}
got, err := j.Decode(tt.octets)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, tt.want, got)
})
}
}
func Test_span_Trace(t *testing.T) {
tests := []struct {
name string
TraceID string
want string
wantErr bool
}{
{
name: "Trace IDs cannot be null",
TraceID: "",
wantErr: true,
},
{
name: "converts hex string correctly",
TraceID: "deadbeef",
want: "deadbeef",
},
{
name: "converts high and low trace id correctly",
TraceID: "48485a3953bb61246b221d5bc9e6496c",
want: "48485a3953bb61246b221d5bc9e6496c",
},
{
name: "errors when string isn't hex",
TraceID: "oxdeadbeef",
wantErr: true,
},
{
name: "errors when id is too long",
TraceID: "1234567890abcdef1234567890abcdef1",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &span{
TraceID: tt.TraceID,
}
got, err := s.Trace()
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, tt.want, got)
})
}
}
func Test_span_SpanID(t *testing.T) {
tests := []struct {
name string
ID string
want string
wantErr bool
}{
{
name: "Span IDs cannot be null",
ID: "",
wantErr: true,
},
{
name: "validates known id correctly",
ID: "b26412d1ac16767d",
want: "b26412d1ac16767d",
},
{
name: "validates hex string correctly",
ID: "deadbeef",
want: "deadbeef",
},
{
name: "errors when string isn't hex",
ID: "oxdeadbeef",
wantErr: true,
},
{
name: "errors when id is too long",
ID: "1234567890abcdef1",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &span{
ID: tt.ID,
}
got, err := s.SpanID()
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, tt.want, got)
})
}
}
func Test_span_Parent(t *testing.T) {
tests := []struct {
name string
ParentID string
want string
wantErr bool
}{
{
name: "when there is no parent return empty string",
ParentID: "",
want: "",
},
{
name: "validates hex string correctly",
ParentID: "deadbeef",
want: "deadbeef",
},
{
name: "errors when string isn't hex",
ParentID: "oxdeadbeef",
wantErr: true,
},
{
name: "errors when parent id is too long",
ParentID: "1234567890abcdef1",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &span{
ParentID: tt.ParentID,
}
got, err := s.Parent()
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, tt.want, got)
})
}
}
func Test_span_Timestamp(t *testing.T) {
tests := []struct {
name string
Time *int64
want time.Time
}{
{
name: "converts to microseconds",
Time: func(i int64) *int64 { return &i }(3000000),
want: time.Unix(3, 0).UTC(),
},
{
name: "nil time should be zero time",
Time: nil,
want: time.Time{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &span{
Time: tt.Time,
}
require.Equal(t, tt.want, s.Timestamp())
})
}
}
func Test_span_Duration(t *testing.T) {
tests := []struct {
name string
dur *int64
want time.Duration
}{
{
name: "converts from 3 microseconds",
dur: func(i int64) *int64 { return &i }(3000000),
want: 3 * time.Second,
},
{
name: "nil time should be zero duration",
dur: nil,
want: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &span{
Dur: tt.dur,
}
require.Equal(t, tt.want, s.Duration())
})
}
}
func Test_annotation(t *testing.T) {
type fields struct {
Endpoint *endpoint
Time int64
Val string
}
tests := []struct {
name string
fields fields
tm time.Time
val string
endpoint *endpoint
}{
{
name: "returns all fields",
fields: fields{
Time: 3000000,
Val: "myvalue",
Endpoint: &endpoint{
ServiceName: "myservice",
Ipv4: "127.0.0.1",
Port: 443,
},
},
tm: time.Unix(3, 0).UTC(),
val: "myvalue",
endpoint: &endpoint{
ServiceName: "myservice",
Ipv4: "127.0.0.1",
Port: 443,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
an := annotation(tt.fields)
a := &an
require.Equal(t, tt.tm, a.Timestamp())
require.Equal(t, tt.val, a.Value())
require.Equal(t, tt.endpoint, a.Host())
})
}
}
func Test_binaryAnnotation(t *testing.T) {
type fields struct {
K string
V json.RawMessage
Type string
Endpoint *endpoint
}
tests := []struct {
name string
fields fields
key string
value string
endpoint *endpoint
}{
{
name: "returns all fields",
fields: fields{
K: "key",
V: json.RawMessage(`"value"`),
Endpoint: &endpoint{
ServiceName: "myservice",
Ipv4: "127.0.0.1",
Port: 443,
},
},
key: "key",
value: "value",
endpoint: &endpoint{
ServiceName: "myservice",
Ipv4: "127.0.0.1",
Port: 443,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
bin := binaryAnnotation(tt.fields)
b := &bin
require.Equal(t, tt.key, b.Key())
require.Equal(t, tt.value, b.Value())
require.Equal(t, tt.endpoint, b.Host())
})
}
}
func Test_endpoint_Host(t *testing.T) {
type fields struct {
Ipv4 string
Port int
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "with port",
fields: fields{
Ipv4: "127.0.0.1",
Port: 443,
},
want: "127.0.0.1:443",
},
{
name: "no port",
fields: fields{
Ipv4: "127.0.0.1",
},
want: "127.0.0.1",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := &endpoint{
Ipv4: tt.fields.Ipv4,
Port: tt.fields.Port,
}
require.Equal(t, tt.want, e.Host())
})
}
}
func Test_endpoint_Name(t *testing.T) {
tests := []struct {
name string
ServiceName string
want string
}{
{
name: "has service name",
ServiceName: "myservicename",
want: "myservicename",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := &endpoint{
ServiceName: tt.ServiceName,
}
require.Equal(t, tt.want, e.Name())
})
}
}
func TestTraceIDFromString(t *testing.T) {
tests := []struct {
name string
s string
want string
wantErr bool
}{
{
name: "Convert hex string id",
s: "6b221d5bc9e6496c",
want: "6b221d5bc9e6496c",
},
{
name: "error : id too long",
s: "1234567890abcdef1234567890abcdef1",
wantErr: true,
},
{
name: "error : not parsable",
s: "howdyhowdyhowdy",
wantErr: true,
},
{
name: "Convert hex string with high/low",
s: "48485a3953bb61246b221d5bc9e6496c",
want: "48485a3953bb61246b221d5bc9e6496c",
},
{
name: "errors in high",
s: "ERR85a3953bb61246b221d5bc9e6496c",
wantErr: true,
},
{
name: "errors in low",
s: "48485a3953bb61246b221d5bc9e64ERR",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := traceIDFromString(tt.s)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, tt.want, got)
})
}
}
func TestIDFromString(t *testing.T) {
tests := []struct {
name string
s string
want string
wantErr bool
}{
{
name: "validates hex string id",
s: "6b221d5bc9e6496c",
want: "6b221d5bc9e6496c",
},
{
name: "error : id too long",
s: "1234567890abcdef1",
wantErr: true,
},
{
name: "error : not parsable",
s: "howdyhowdyhowdy",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := idFromString(tt.s)
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, tt.want, got)
})
}
}