service/log_sanitize_test.go
AI Engineer 556d60661c feat(service): Session Save/Load/Remove 增强,日志脱敏引擎,响应体捕获修复(by AI)
Co-Authored-By: deepseek-v4-pro[1m] <deepseek-ai@claude-code-best.win>
2026-06-21 22:53:37 +08:00

251 lines
5.9 KiB
Go

package service
import (
"reflect"
"testing"
)
func TestSanitizeScalars(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 3, objectNum: 10}
tests := []struct {
name string
input any
expected any
}{
{"nil", nil, nil},
{"int", 42, 42},
{"float", 3.14, 3.14},
{"bool_true", true, true},
{"bool_false", false, false},
{"string_short", "hello", "hello"},
{"string_exact", "12345678901234567890", "12345678901234567890"},
{"string_over", "123456789012345678901234567890", "12345678901234567890"},
{"string_unicode", "你好世界你好世界你好世界你好世界你好世界你好世界你好世界", "你好世界你好世界你好世界你好世界你好世界"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := sanitizeLogData(tt.input, opts)
if !reflect.DeepEqual(got, tt.expected) {
t.Errorf("got %v, want %v", got, tt.expected)
}
})
}
}
func TestSanitizeMapBasic(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 3, objectNum: 10}
input := map[string]any{
"name": "John",
"bio": "A very long biography that should be truncated at twenty",
"status": "active",
}
expected := map[string]any{
"name": "John",
"bio": "A very long biograph",
"status": "active",
}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}
func TestSanitizeMapObjectNum(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 3, objectNum: 3}
input := map[string]any{
"k1": "v1",
"k2": "v2",
"k3": "v3",
"k4": "v4",
"k5": "v5",
}
expected := map[string]any{
"k1": "v1",
"k2": "v2",
"k3": "v3",
}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}
func TestSanitizeSlice(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 3, objectNum: 10}
input := []any{1, 2, 3, 4, 5, 6, 7}
expected := []any{1, 2, 3}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}
func TestSanitizeSliceWithStrings(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 3, objectNum: 10}
input := []any{
"short",
"this string is definitely way too long for twenty characters",
"ok",
"this would be fourth but arrayNum is 3",
}
expected := []any{
"short",
"this string is defin",
"ok",
}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}
func TestSanitizeNested(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 3, objectNum: 10}
input := map[string]any{
"user": map[string]any{
"name": "John Doe",
"bio": "A very long description that should be truncated at twenty chars",
"tags": []any{"go", "javascript-long-name", "rust", "python", "java", "c++"},
},
"score": 100,
}
expected := map[string]any{
"user": map[string]any{
"name": "John Doe",
"bio": "A very long descript",
"tags": []any{"go", "javascript-long-name", "rust"},
},
"score": 100,
}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}
func TestSanitizeTopLevelArray(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 3, objectNum: 10}
input := []any{
map[string]any{"id": 1, "name": "Alice"},
map[string]any{"id": 2, "name": "Bob"},
map[string]any{"id": 3, "name": "Charlie"},
map[string]any{"id": 4, "name": "Diana"},
map[string]any{"id": 5, "name": "Eve"},
}
expected := []any{
map[string]any{"id": 1, "name": "Alice"},
map[string]any{"id": 2, "name": "Bob"},
map[string]any{"id": 3, "name": "Charlie"},
}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}
func TestSanitizeBudgetExhausted(t *testing.T) {
opts := sanitizeOpts{maxSize: 22, fieldSize: 20, arrayNum: 10, objectNum: 10}
input := map[string]any{
"a": "1234567890",
"b": "abcdefghij",
"c": "should-be-dropped",
}
expected := map[string]any{
"a": "1234567890",
"b": "abcdefghij",
}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}
func TestSanitizeNestedBudgetExhausted(t *testing.T) {
opts := sanitizeOpts{maxSize: 30, fieldSize: 20, arrayNum: 10, objectNum: 10}
input := map[string]any{
"small": "hi",
"nested": map[string]any{
"field1": "1234567890",
"field2": "abcdefghij",
},
"after": "no",
}
// 按字母序: after(7) → nested(22) → small(被跳过)
expected := map[string]any{
"after": "no",
"nested": map[string]any{
"field1": "1234567890",
},
}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}
func TestSanitizeEmptyContainers(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 3, objectNum: 10}
tests := []struct {
name string
input any
expected any
}{
{"empty_map", map[string]any{}, map[string]any{}},
{"empty_slice", []any{}, []any{}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := sanitizeLogData(tt.input, opts)
if !reflect.DeepEqual(got, tt.expected) {
t.Errorf("got %v, want %v", got, tt.expected)
}
})
}
}
func TestSanitizeMixedSlice(t *testing.T) {
opts := sanitizeOpts{maxSize: 200, fieldSize: 20, arrayNum: 10, objectNum: 10}
input := []any{
"ok",
42,
true,
nil,
map[string]any{"nested": "value"},
"this one is too long and will be trimmed to twenty chars",
nil,
}
expected := []any{
"ok",
42,
true,
nil,
map[string]any{"nested": "value"},
"this one is too long",
nil,
}
got := sanitizeLogData(input, opts)
if !reflect.DeepEqual(got, expected) {
t.Errorf("got %v, want %v", got, expected)
}
}