Files
Alexander 9150f466e5 test: add comprehensive test harness across all packages (156 tests)
Characterization tests capturing current behavior before refactoring.
Covers auth, config, logging, proxy, ratelimit, server, and telemetry
packages with race-safe concurrent access tests.
2026-04-15 10:40:43 +02:00

179 lines
3.9 KiB
Go

package telemetry
import (
"encoding/json"
"testing"
otellog "go.opentelemetry.io/otel/log"
sdklog "go.opentelemetry.io/otel/sdk/log"
)
func TestMapSeverity(t *testing.T) {
tests := []struct {
input string
want otellog.Severity
}{
{"trace", otellog.SeverityTrace},
{"debug", otellog.SeverityDebug},
{"info", otellog.SeverityInfo},
{"warn", otellog.SeverityWarn},
{"warning", otellog.SeverityWarn},
{"error", otellog.SeverityError},
{"fatal", otellog.SeverityFatal},
{"panic", otellog.SeverityFatal2},
{"unknown", otellog.SeverityInfo},
{"", otellog.SeverityInfo},
{"INFO", otellog.SeverityInfo}, // uppercase falls to default
{"PANIC", otellog.SeverityInfo}, // uppercase falls to default
{"gibberish", otellog.SeverityInfo},
}
for _, tc := range tests {
t.Run("level_"+tc.input, func(t *testing.T) {
got := mapSeverity(tc.input)
if got != tc.want {
t.Errorf("mapSeverity(%q) = %v, want %v", tc.input, got, tc.want)
}
})
}
}
func newTestBridge(t *testing.T) *LogBridge {
t.Helper()
provider := sdklog.NewLoggerProvider()
t.Cleanup(func() {
_ = provider.Shutdown(t.Context())
})
return &LogBridge{provider: provider}
}
func TestLogBridgeWrite(t *testing.T) {
tests := []struct {
name string
input interface{} // will be marshaled to JSON; use string for raw input
raw string // if non-empty, use this directly instead of marshaling input
}{
{
name: "valid_json_with_message_level_and_extras",
input: map[string]interface{}{
"message": "request handled",
"level": "info",
"method": "GET",
"status": float64(200),
},
},
{
name: "message_only_no_level",
input: map[string]interface{}{
"message": "hello world",
},
},
{
name: "level_only_no_message",
input: map[string]interface{}{
"level": "error",
},
},
{
name: "empty_json_object",
input: map[string]interface{}{},
},
{
name: "string_float64_bool_attributes",
input: map[string]interface{}{
"message": "test",
"level": "debug",
"str_val": "hello",
"num_val": float64(3.14),
"bool_val": true,
},
},
{
name: "complex_nested_object_attribute",
input: map[string]interface{}{
"message": "nested",
"level": "warn",
"nested": map[string]interface{}{"foo": "bar", "n": float64(1)},
},
},
{
name: "time_field_skipped_in_attributes",
input: map[string]interface{}{
"message": "with time",
"level": "info",
"time": "2025-01-01T00:00:00Z",
"extra": "kept",
},
},
{
name: "malformed_json",
raw: "this is not json at all",
},
{
name: "malformed_json_partial",
raw: `{"broken":`,
},
{
name: "array_attribute_marshaled_as_string",
input: map[string]interface{}{
"message": "arrays",
"tags": []interface{}{"a", "b"},
},
},
{
name: "null_value_attribute",
input: map[string]interface{}{
"message": "nulls",
"val": nil,
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
bridge := newTestBridge(t)
var p []byte
if tc.raw != "" {
p = []byte(tc.raw)
} else {
var err error
p, err = json.Marshal(tc.input)
if err != nil {
t.Fatalf("failed to marshal test input: %v", err)
}
}
n, err := bridge.Write(p)
if n != len(p) {
t.Errorf("Write() returned n=%d, want %d", n, len(p))
}
if err != nil {
t.Errorf("Write() returned err=%v, want nil", err)
}
})
}
}
func TestLogBridgeWriteAlwaysReturnsLenAndNil(t *testing.T) {
bridge := newTestBridge(t)
inputs := [][]byte{
[]byte(`{"message":"ok","level":"info"}`),
[]byte(`not json`),
[]byte(`{}`),
[]byte(``),
[]byte(`[]`),
}
for _, p := range inputs {
n, err := bridge.Write(p)
if n != len(p) {
t.Errorf("Write(%q) n=%d, want %d", string(p), n, len(p))
}
if err != nil {
t.Errorf("Write(%q) err=%v, want nil", string(p), err)
}
}
}