308 lines
10 KiB
Go
308 lines
10 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package pprofile
|
|
|
|
import (
|
|
"testing"
|
|
|
|
jsoniter "github.com/json-iterator/go"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.opentelemetry.io/collector/pdata/pcommon"
|
|
)
|
|
|
|
var (
|
|
_ Marshaler = (*JSONMarshaler)(nil)
|
|
_ Unmarshaler = (*JSONUnmarshaler)(nil)
|
|
)
|
|
|
|
var profilesOTLP = func() Profiles {
|
|
startTimestamp := pcommon.Timestamp(1684617382541971000)
|
|
durationTimestamp := pcommon.Timestamp(1684623646539558000)
|
|
profileID := ProfileID([16]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10})
|
|
traceID := pcommon.TraceID([16]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10})
|
|
spanID := pcommon.SpanID([8]byte{0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18})
|
|
|
|
pd := NewProfiles()
|
|
// Add ResourceProfiles.
|
|
rp := pd.ResourceProfiles().AppendEmpty()
|
|
rp.SetSchemaUrl("schemaURL")
|
|
// Add resource.
|
|
rp.Resource().Attributes().PutStr("host.name", "testHost")
|
|
rp.Resource().Attributes().PutStr("service.name", "testService")
|
|
rp.Resource().SetDroppedAttributesCount(1)
|
|
// Add ScopeProfiles.
|
|
sp := rp.ScopeProfiles().AppendEmpty()
|
|
sp.SetSchemaUrl("schemaURL")
|
|
sp.Scope().SetName("scope name")
|
|
sp.Scope().SetVersion("scope version")
|
|
// Add profiles
|
|
pro := sp.Profiles().AppendEmpty()
|
|
pro.SetProfileID(profileID)
|
|
pro.SetTime(startTimestamp)
|
|
pro.SetDuration(durationTimestamp)
|
|
pro.Attributes().PutStr("hello", "world")
|
|
pro.Attributes().PutStr("foo", "bar")
|
|
pro.SetDroppedAttributesCount(1)
|
|
|
|
// Add sample type
|
|
st := pro.SampleType().AppendEmpty()
|
|
st.SetTypeStrindex(1)
|
|
st.SetUnitStrindex(2)
|
|
// Add samples
|
|
s := pro.Sample().AppendEmpty()
|
|
s.SetLocationsStartIndex(1)
|
|
s.SetLocationsLength(10)
|
|
s.Value().Append(3)
|
|
s.AttributeIndices().Append(1)
|
|
s.TimestampsUnixNano().Append(12345)
|
|
|
|
// Add mappings
|
|
m := pro.MappingTable().AppendEmpty()
|
|
m.SetMemoryStart(2)
|
|
m.SetMemoryLimit(3)
|
|
m.SetFileOffset(4)
|
|
m.SetFilenameStrindex(5)
|
|
m.AttributeIndices().Append(7)
|
|
m.AttributeIndices().Append(8)
|
|
m.SetHasFunctions(true)
|
|
m.SetHasFilenames(true)
|
|
m.SetHasLineNumbers(true)
|
|
m.SetHasInlineFrames(true)
|
|
|
|
// Add location
|
|
l := pro.LocationTable().AppendEmpty()
|
|
l.SetMappingIndex(3)
|
|
l.SetAddress(4)
|
|
l.SetIsFolded(true)
|
|
l.AttributeIndices().Append(6)
|
|
l.AttributeIndices().Append(7)
|
|
li := l.Line().AppendEmpty()
|
|
li.SetFunctionIndex(1)
|
|
li.SetLine(2)
|
|
li.SetColumn(3)
|
|
pro.LocationIndices().Append(1)
|
|
|
|
// Add function
|
|
f := pro.FunctionTable().AppendEmpty()
|
|
f.SetNameStrindex(2)
|
|
f.SetSystemNameStrindex(3)
|
|
f.SetFilenameStrindex(4)
|
|
f.SetStartLine(5)
|
|
|
|
// Add attribute table
|
|
at := pro.AttributeTable()
|
|
a := at.AppendEmpty()
|
|
a.SetKey("answer")
|
|
a.Value().SetInt(42)
|
|
|
|
// Add attribute units
|
|
au := pro.AttributeUnits().AppendEmpty()
|
|
au.SetAttributeKeyStrindex(1)
|
|
au.SetUnitStrindex(5)
|
|
|
|
// Add link table
|
|
lt := pro.LinkTable().AppendEmpty()
|
|
lt.SetTraceID(traceID)
|
|
lt.SetSpanID(spanID)
|
|
|
|
// Add string table
|
|
pro.StringTable().Append("foobar")
|
|
pro.SetTime(1234)
|
|
pro.SetDuration(5678)
|
|
pro.PeriodType().SetTypeStrindex(1)
|
|
pro.PeriodType().SetUnitStrindex(2)
|
|
pro.SetPeriod(3)
|
|
pro.CommentStrindices().Append(1)
|
|
pro.CommentStrindices().Append(2)
|
|
pro.SetDefaultSampleTypeStrindex(4)
|
|
|
|
return pd
|
|
}()
|
|
|
|
var profilesJSON = `{"resourceProfiles":[{"resource":{"attributes":[{"key":"host.name","value":{"stringValue":"testHost"}},{"key":"service.name","value":{"stringValue":"testService"}}],"droppedAttributesCount":1},"scopeProfiles":[{"scope":{"name":"scope name","version":"scope version"},"profiles":[{"sampleType":[{"typeStrindex":1,"unitStrindex":2}],"sample":[{"locationsStartIndex":1,"locationsLength":10,"value":["3"],"attributeIndices":[1],"timestampsUnixNano":["12345"]}],"mappingTable":[{"memoryStart":"2","memoryLimit":"3","fileOffset":"4","filenameStrindex":5,"attributeIndices":[7,8],"hasFunctions":true,"hasFilenames":true,"hasLineNumbers":true,"hasInlineFrames":true}],"locationTable":[{"mappingIndex":3,"address":"4","line":[{"functionIndex":1,"line":"2","column":"3"}],"isFolded":true,"attributeIndices":[6,7]}],"locationIndices":[1],"functionTable":[{"nameStrindex":2,"systemNameStrindex":3,"filenameStrindex":4,"startLine":"5"}],"attributeTable":[{"key":"answer","value":{"intValue":"42"}}],"attributeUnits":[{"attributeKeyStrindex":1,"unitStrindex":5}],"linkTable":[{"traceId":"0102030405060708090a0b0c0d0e0f10","spanId":"1112131415161718"}],"stringTable":["foobar"],"timeNanos":"1234","durationNanos":"5678","periodType":{"typeStrindex":1,"unitStrindex":2},"period":"3","commentStrindices":[1,2],"defaultSampleTypeStrindex":4,"profileId":"0102030405060708090a0b0c0d0e0f10","attributes":[{"key":"hello","value":{"stringValue":"world"}},{"key":"foo","value":{"stringValue":"bar"}}],"droppedAttributesCount":1}],"schemaUrl":"schemaURL"}],"schemaUrl":"schemaURL"}]}`
|
|
|
|
func TestJSONUnmarshal(t *testing.T) {
|
|
decoder := &JSONUnmarshaler{}
|
|
got, err := decoder.UnmarshalProfiles([]byte(profilesJSON))
|
|
require.NoError(t, err)
|
|
assert.EqualValues(t, profilesOTLP, got)
|
|
}
|
|
|
|
func TestJSONMarshal(t *testing.T) {
|
|
encoder := &JSONMarshaler{}
|
|
jsonBuf, err := encoder.MarshalProfiles(profilesOTLP)
|
|
require.NoError(t, err)
|
|
assert.JSONEq(t, profilesJSON, string(jsonBuf))
|
|
}
|
|
|
|
func TestJSONUnmarshalInvalid(t *testing.T) {
|
|
jsonStr := `{"extra":"", "resourceProfiles": "extra"}`
|
|
decoder := &JSONUnmarshaler{}
|
|
_, err := decoder.UnmarshalProfiles([]byte(jsonStr))
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterProfileData(t *testing.T) {
|
|
jsonStr := `{"extra":"", "resourceProfiles": [{"extra":""}]}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewProfiles()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, 1, val.ResourceProfiles().Len())
|
|
}
|
|
|
|
func TestUnmarshalJsoniterProfileInvalidProfileIDField(t *testing.T) {
|
|
jsonStr := `{"profile_id":"--"}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
NewProfile().unmarshalJsoniter(iter)
|
|
assert.ErrorContains(t, iter.Error, "parse profile_id")
|
|
}
|
|
|
|
func TestUnmarshalJsoniterResourceProfiles(t *testing.T) {
|
|
jsonStr := `{"extra":"", "resource": {}, "scopeProfiles": []}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewResourceProfiles()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewResourceProfiles(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterScopeProfiles(t *testing.T) {
|
|
jsonStr := `{"extra":"", "scope": {}, "profiles": []}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewScopeProfiles()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewScopeProfiles(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterProfile(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewProfile()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewProfile(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterValueType(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewValueType()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewValueType(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterSample(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewSample()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewSample(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterMapping(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewMapping()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewMapping(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterLocation(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewLocation()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewLocation(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterLine(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewLine()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewLine(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterFunction(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewFunction()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewFunction(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterAttributeUnit(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewAttributeUnit()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewAttributeUnit(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterLink(t *testing.T) {
|
|
jsonStr := `{"extra":""}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
val := NewLink()
|
|
val.unmarshalJsoniter(iter)
|
|
require.NoError(t, iter.Error)
|
|
assert.Equal(t, NewLink(), val)
|
|
}
|
|
|
|
func TestUnmarshalJsoniterLinkInvalidTraceIDField(t *testing.T) {
|
|
jsonStr := `{"trace_id":"--"}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
NewLink().unmarshalJsoniter(iter)
|
|
assert.ErrorContains(t, iter.Error, "parse trace_id")
|
|
}
|
|
|
|
func TestUnmarshalJsoniterSpanLinkInvalidSpanIDField(t *testing.T) {
|
|
jsonStr := `{"span_id":"--"}`
|
|
iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr))
|
|
defer jsoniter.ConfigFastest.ReturnIterator(iter)
|
|
NewLink().unmarshalJsoniter(iter)
|
|
assert.ErrorContains(t, iter.Error, "parse span_id")
|
|
}
|
|
|
|
func BenchmarkJSONUnmarshal(b *testing.B) {
|
|
b.ReportAllocs()
|
|
|
|
encoder := &JSONMarshaler{}
|
|
jsonBuf, err := encoder.MarshalProfiles(profilesOTLP)
|
|
require.NoError(b, err)
|
|
decoder := &JSONUnmarshaler{}
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
_, err := decoder.UnmarshalProfiles(jsonBuf)
|
|
assert.NoError(b, err)
|
|
}
|
|
})
|
|
}
|