util/common/traces/base/base.go (115 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT
package base
import (
"context"
"encoding/json"
"reflect"
"testing"
"time"
"github.com/aws/aws-sdk-go-v2/service/xray/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/attribute"
"github.com/aws/amazon-cloudwatch-agent-test/util/awsservice"
"github.com/aws/amazon-cloudwatch-agent-test/util/common"
)
const (
AGENT_SHUTDOWN_DELAY = 20 * time.Second // this const is the delay between stopping trace generation and stopping agent
)
type TraceTestConfig struct {
Generator TraceGeneratorInterface
Name string
AgentConfigPath string
AgentRuntime time.Duration
}
type TraceGeneratorConfig struct {
Interval time.Duration
Annotations map[string]interface{}
Metadata map[string]map[string]interface{}
Attributes []attribute.KeyValue
}
type TraceGenerator struct {
Cfg *TraceGeneratorConfig
SegmentsGenerationCount int
SegmentsEndedCount int
AgentConfigPath string
AgentRuntime time.Duration
Name string
Done chan struct{}
}
type TraceGeneratorInterface interface {
StartSendingTraces(ctx context.Context) error
StopSendingTraces()
Generate(ctx context.Context) error
GetSegmentCount() (int, int)
GetAgentConfigPath() string
GetGeneratorConfig() *TraceGeneratorConfig
GetContext() context.Context
GetAgentRuntime() time.Duration
GetName() string
}
func TraceTest(t *testing.T, traceTest TraceTestConfig) error {
t.Helper()
startTime := time.Now()
common.CopyFile(traceTest.AgentConfigPath, common.ConfigOutputPath)
require.NoError(t, common.StartAgent(common.ConfigOutputPath, true, false), "Couldn't Start the agent")
go func() {
require.NoError(t, traceTest.Generator.StartSendingTraces(context.Background()), "load generator exited with error")
}()
time.Sleep(traceTest.AgentRuntime)
traceTest.Generator.StopSendingTraces()
time.Sleep(AGENT_SHUTDOWN_DELAY)
common.StopAgent()
testsGenerated, testsEnded := traceTest.Generator.GetSegmentCount()
t.Logf("For %s , Test Cases Generated %d | Test Cases Ended: %d", traceTest.Name, testsGenerated, testsEnded)
endTime := time.Now()
t.Logf("Agent has been running for %s", endTime.Sub(startTime))
time.Sleep(10 * time.Second)
traceIDs, err := awsservice.GetTraceIDs(startTime, endTime, awsservice.FilterExpression(
traceTest.Generator.GetGeneratorConfig().Annotations))
require.NoError(t, err, "unable to get trace IDs")
segments, err := awsservice.GetSegments(traceIDs)
require.NoError(t, err, "unable to get segments")
assert.True(t, len(segments) >= testsGenerated,
"FAILED: Not enough segments, expected %d but got %d , traceIDCount: %d",
testsGenerated, len(segments), len(traceIDs))
require.NoError(t, SegmentValidationTest(t, traceTest, segments), "Segment Validation Failed")
return nil
}
func SegmentValidationTest(t *testing.T, traceTest TraceTestConfig, segments []types.Segment) error {
t.Helper()
cfg := traceTest.Generator.GetGeneratorConfig()
for _, segment := range segments {
var result map[string]interface{}
require.NoError(t, json.Unmarshal([]byte(*segment.Document), &result))
if _, ok := result["parent_id"]; ok {
// skip subsegments
continue
}
annotations, ok := result["annotations"]
assert.True(t, ok, "missing annotations")
assert.True(t, reflect.DeepEqual(annotations, cfg.Annotations), "mismatching annotations")
metadataByNamespace, ok := result["metadata"].(map[string]interface{})
assert.True(t, ok, "missing metadata")
for namespace, wantMetadata := range cfg.Metadata {
var gotMetadata map[string]interface{}
gotMetadata, ok = metadataByNamespace[namespace].(map[string]interface{})
assert.Truef(t, ok, "missing metadata in namespace: %s", namespace)
for key, wantValue := range wantMetadata {
var gotValue interface{}
gotValue, ok = gotMetadata[key]
assert.Truef(t, ok, "missing expected metadata key: %s", key)
assert.Truef(t, reflect.DeepEqual(gotValue, wantValue), "mismatching values for key (%s):\ngot\n\t%v\nwant\n\t%v", key, gotValue, wantValue)
}
}
}
return nil
}
func GenerateTraces(traceTest TraceTestConfig) error {
common.CopyFile(traceTest.AgentConfigPath, common.ConfigOutputPath)
go func() {
traceTest.Generator.StartSendingTraces(context.Background())
}()
time.Sleep(traceTest.AgentRuntime)
traceTest.Generator.StopSendingTraces()
time.Sleep(AGENT_SHUTDOWN_DELAY)
return nil
}