v0.1.8 tests converted to standard library from testify
This commit is contained in:
+254
-213
@@ -4,220 +4,306 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func eq[T comparable](tb testing.TB, got, want T, ctx string) {
|
||||
tb.Helper()
|
||||
if got != want {
|
||||
tb.Errorf("%s: got %#v, want %#v", ctx, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewSanitizer(t *testing.T) {
|
||||
// Default passthrough behavior
|
||||
// No rules configured means full passthrough
|
||||
s := New()
|
||||
input := "abc\x00xyz"
|
||||
assert.Equal(t, input, s.Sanitize(input), "default sanitizer should pass through all characters")
|
||||
in := "abc\x00xyz"
|
||||
eq(t, s.Sanitize(in), in, "default passthrough")
|
||||
}
|
||||
|
||||
func TestSingleRule(t *testing.T) {
|
||||
t.Run("strip non-printable", func(t *testing.T) {
|
||||
s := New().Rule(FilterNonPrintable, TransformStrip)
|
||||
assert.Equal(t, "ab", s.Sanitize("a\x00b"))
|
||||
assert.Equal(t, "test", s.Sanitize("test\x01\x02\x03"))
|
||||
})
|
||||
tests := []struct {
|
||||
name string
|
||||
sanitizer *Sanitizer
|
||||
in, want string
|
||||
}{
|
||||
{"strip non-printable", New().Rule(FilterNonPrintable, TransformStrip), "a\x00b", "ab"},
|
||||
{"strip non-printable run", New().Rule(FilterNonPrintable, TransformStrip), "test\x01\x02\x03", "test"},
|
||||
{"hex encode non-printable", New().Rule(FilterNonPrintable, TransformHexEncode), "a\x00b", "a<00>b"},
|
||||
{"hex encode bell and tab", New().Rule(FilterNonPrintable, TransformHexEncode), "bell\x07tab\x09", "bell<07>tab<09>"},
|
||||
{"json escape newline", New().Rule(FilterControl, TransformJSONEscape), "line1\nline2", `line1\nline2`},
|
||||
{"json escape tab", New().Rule(FilterControl, TransformJSONEscape), "tab\there", `tab\there`},
|
||||
{"json escape nul", New().Rule(FilterControl, TransformJSONEscape), "null\x00byte", `null\u0000byte`},
|
||||
{"strip whitespace", New().Rule(FilterWhitespace, TransformStrip), "no spaces here", "nospaceshere"},
|
||||
{"strip tabs", New().Rule(FilterWhitespace, TransformStrip), "tabs\t\tgone", "tabsgone"},
|
||||
{"strip shell semicolon", New().Rule(FilterShellSpecial, TransformStrip), "cmd; echo test", "cmd echo test"},
|
||||
{"strip shell pipe", New().Rule(FilterShellSpecial, TransformStrip), "no | pipes", "no pipes"},
|
||||
{"strip shell dollar", New().Rule(FilterShellSpecial, TransformStrip), "$var", "var"},
|
||||
}
|
||||
|
||||
t.Run("hex encode non-printable", func(t *testing.T) {
|
||||
s := New().Rule(FilterNonPrintable, TransformHexEncode)
|
||||
assert.Equal(t, "a<00>b", s.Sanitize("a\x00b"))
|
||||
assert.Equal(t, "bell<07>tab<09>", s.Sanitize("bell\x07tab\x09"))
|
||||
})
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
eq(t, tt.sanitizer.Sanitize(tt.in), tt.want, tt.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("JSON escape control", func(t *testing.T) {
|
||||
s := New().Rule(FilterControl, TransformJSONEscape)
|
||||
assert.Equal(t, "line1\\nline2", s.Sanitize("line1\nline2"))
|
||||
assert.Equal(t, "tab\\there", s.Sanitize("tab\there"))
|
||||
assert.Equal(t, "null\\u0000byte", s.Sanitize("null\x00byte"))
|
||||
})
|
||||
func TestRuleFunc(t *testing.T) {
|
||||
// Predicate rules take priority over filter evaluation within the same rule
|
||||
s := New().RuleFunc(func(r rune) bool { return r == 'x' }, TransformStrip)
|
||||
eq(t, s.Sanitize("axbxc"), "abc", "predicate strip")
|
||||
eq(t, s.Sanitize("clean"), "clean", "predicate miss")
|
||||
|
||||
t.Run("strip whitespace", func(t *testing.T) {
|
||||
s := New().Rule(FilterWhitespace, TransformStrip)
|
||||
assert.Equal(t, "nospaceshere", s.Sanitize("no spaces here"))
|
||||
assert.Equal(t, "tabsgone", s.Sanitize("tabs\t\tgone"))
|
||||
})
|
||||
|
||||
t.Run("strip shell special", func(t *testing.T) {
|
||||
s := New().Rule(FilterShellSpecial, TransformStrip)
|
||||
assert.Equal(t, "cmd echo test", s.Sanitize("cmd; echo test"))
|
||||
assert.Equal(t, "no pipes", s.Sanitize("no | pipes"))
|
||||
assert.Equal(t, "var", s.Sanitize("$var"))
|
||||
})
|
||||
s = New().RuleFunc(func(r rune) bool { return r > 0x7f }, TransformHexEncode)
|
||||
eq(t, s.Sanitize("a√b"), "a<e2889a>b", "predicate hex encode")
|
||||
}
|
||||
|
||||
func TestPolicy(t *testing.T) {
|
||||
t.Run("PolicyTxt", func(t *testing.T) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
assert.Equal(t, "hello<07>world", s.Sanitize("hello\x07world"))
|
||||
assert.Equal(t, "clean text", s.Sanitize("clean text"))
|
||||
})
|
||||
tests := []struct {
|
||||
name string
|
||||
policy PolicyPreset
|
||||
in, want string
|
||||
}{
|
||||
{"txt control", PolicyTxt, "hello\x07world", "hello<07>world"},
|
||||
{"txt clean", PolicyTxt, "clean text", "clean text"},
|
||||
// Tab is non-printable per strconv.IsPrint and is encoded like any control byte
|
||||
{"txt tab", PolicyTxt, "col1\tcol2", "col1<09>col2"},
|
||||
{"json newline", PolicyJSON, "line1\nline2", `line1\nline2`},
|
||||
{"json tab", PolicyJSON, "\ttab", `\ttab`},
|
||||
{"shell semicolon", PolicyShell, "cmd; echo", "cmdecho"},
|
||||
{"shell whitespace", PolicyShell, "no spaces", "nospaces"},
|
||||
{"raw passthrough", PolicyRaw, "a\x00b", "a\x00b"},
|
||||
}
|
||||
|
||||
t.Run("PolicyJSON", func(t *testing.T) {
|
||||
s := New().Policy(PolicyJSON)
|
||||
assert.Equal(t, "line1\\nline2", s.Sanitize("line1\nline2"))
|
||||
assert.Equal(t, "\\ttab", s.Sanitize("\ttab"))
|
||||
})
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
eq(t, New().Policy(tt.policy).Sanitize(tt.in), tt.want, tt.name)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("PolicyShellArg", func(t *testing.T) {
|
||||
s := New().Policy(PolicyShell)
|
||||
assert.Equal(t, "cmdecho", s.Sanitize("cmd; echo"))
|
||||
assert.Equal(t, "nospaces", s.Sanitize("no spaces"))
|
||||
t.Run("unknown policy is a no-op", func(t *testing.T) {
|
||||
s := New().Policy(PolicyPreset("bogus"))
|
||||
eq(t, s.Sanitize("a\x00b"), "a\x00b", "unknown preset")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRulePrecedence(t *testing.T) {
|
||||
// With append + forward iteration: Policy is checked before Rule
|
||||
s := New().Policy(PolicyTxt).Rule(FilterControl, TransformStrip)
|
||||
func TestPolicyShellExtended(t *testing.T) {
|
||||
s := New().Policy(PolicyShell)
|
||||
eq(t, s.Sanitize(`a'b"c`), "abc", "quotes")
|
||||
eq(t, s.Sanitize(`a\b`), "ab", "backslash")
|
||||
eq(t, s.Sanitize("file*?"), "file", "glob")
|
||||
eq(t, s.Sanitize("rm -rf *"), "rm-rf", "whitespace and glob")
|
||||
eq(t, s.Sanitize("a\x00\x1bb"), "ab", "control")
|
||||
eq(t, s.Sanitize("a{b}c[d]e~f!g"), "abcdefg", "braces, brackets, tilde, bang")
|
||||
}
|
||||
|
||||
// \x07 is both control AND non-printable - matches PolicyTxt first
|
||||
// \x00 is both control AND non-printable - matches PolicyTxt first
|
||||
input := "a\x07b\x00c"
|
||||
expected := "a<07>b<00>c" // FIXED: Policy wins now
|
||||
result := s.Sanitize(input)
|
||||
func TestRuleOrdering(t *testing.T) {
|
||||
t.Run("policy precedes later rules", func(t *testing.T) {
|
||||
// Rules append in call order and the first match wins, so a Policy
|
||||
// registered first shadows overlapping custom rules
|
||||
s := New().Policy(PolicyTxt).Rule(FilterControl, TransformStrip)
|
||||
eq(t, s.Sanitize("a\x07b\x00c"), "a<07>b<00>c", "policy wins")
|
||||
})
|
||||
|
||||
assert.Equal(t, expected, result,
|
||||
"Policy() is now checked before Rule() - non-printable chars get hex encoded")
|
||||
t.Run("first rule wins", func(t *testing.T) {
|
||||
s := New().
|
||||
Rule(FilterControl, TransformStrip).
|
||||
Rule(FilterControl, TransformHexEncode) // unreachable
|
||||
eq(t, s.Sanitize("a\x00b"), "ab", "first rule")
|
||||
})
|
||||
|
||||
t.Run("chained distinct filters", func(t *testing.T) {
|
||||
s := New().
|
||||
Rule(FilterWhitespace, TransformStrip).
|
||||
Rule(FilterShellSpecial, TransformHexEncode)
|
||||
eq(t, s.Sanitize("cmd; echo hello"), "cmd<3b>echohello", "chained")
|
||||
})
|
||||
|
||||
t.Run("policy plus custom rules", func(t *testing.T) {
|
||||
s := New().
|
||||
Policy(PolicyTxt).
|
||||
Rule(FilterControl, TransformStrip).
|
||||
Rule(FilterWhitespace, TransformJSONEscape)
|
||||
// \x07 and \x7F are non-printable and match PolicyTxt first;
|
||||
// the space matches the whitespace rule but JSON-escapes to itself
|
||||
eq(t, s.Sanitize("a\x07b c\x7Fd"), "a<07>b c<7f>d", "combined")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCompositeFilter(t *testing.T) {
|
||||
s := New().Rule(FilterShellSpecial|FilterWhitespace, TransformStrip)
|
||||
assert.Equal(t, "cmdechohello", s.Sanitize("cmd; echo hello"))
|
||||
assert.Equal(t, "nopipesnospaces", s.Sanitize("no |pipes| no spaces"))
|
||||
eq(t, s.Sanitize("cmd; echo hello"), "cmdechohello", "composite mask")
|
||||
eq(t, s.Sanitize("no |pipes| no spaces"), "nopipesnospaces", "composite mask")
|
||||
}
|
||||
|
||||
func TestChaining(t *testing.T) {
|
||||
s := New().
|
||||
Rule(FilterWhitespace, TransformStrip).
|
||||
Rule(FilterShellSpecial, TransformHexEncode)
|
||||
|
||||
// Rules append in call order; first match wins.
|
||||
// Whitespace rule strips spaces; shell rule hex-encodes ';'.
|
||||
assert.Equal(t, "cmd<3b>echohello", s.Sanitize("cmd; echo hello"))
|
||||
}
|
||||
|
||||
func TestMultipleRulesOrder(t *testing.T) {
|
||||
// Test that first matching rule wins
|
||||
s := New().
|
||||
Rule(FilterControl, TransformStrip).
|
||||
Rule(FilterControl, TransformHexEncode) // This should never match
|
||||
|
||||
assert.Equal(t, "ab", s.Sanitize("a\x00b"), "first rule should win")
|
||||
func TestTransformPriority(t *testing.T) {
|
||||
// applyTransform evaluates Strip first; only one transform applies per rule
|
||||
s := New().Rule(FilterControl, TransformStrip|TransformHexEncode)
|
||||
eq(t, s.Sanitize("a\x00b"), "ab", "strip precedence")
|
||||
}
|
||||
|
||||
func TestEdgeCases(t *testing.T) {
|
||||
t.Run("empty string", func(t *testing.T) {
|
||||
s := New().Rule(FilterNonPrintable, TransformStrip)
|
||||
assert.Equal(t, "", s.Sanitize(""))
|
||||
strip := New().Rule(FilterNonPrintable, TransformStrip)
|
||||
hex := New().Rule(FilterNonPrintable, TransformHexEncode)
|
||||
|
||||
eq(t, strip.Sanitize(""), "", "empty string")
|
||||
eq(t, strip.Sanitize("\x00\x01\x02\x03"), "", "fully stripped")
|
||||
eq(t, hex.Sanitize("Hello 世界 ✓"), "Hello 世界 ✓", "printable UTF-8 passthrough")
|
||||
// U+0085 (NEL) is one non-printable rune encoded as two UTF-8 bytes
|
||||
eq(t, hex.Sanitize("line1\u0085line2"), "line1<c285>line2", "multi-byte control")
|
||||
}
|
||||
|
||||
func TestHexMarkerEscaping(t *testing.T) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
eq(t, s.Sanitize("a\x00b"), "a<00>b", "actual NUL")
|
||||
// Literal '<' is encoded so input cannot forge a marker
|
||||
eq(t, s.Sanitize("a<00>b"), "a<3c>00>b", "literal marker text")
|
||||
}
|
||||
|
||||
func TestSanitizeCleanFastPath(t *testing.T) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
in := "clean ascii text"
|
||||
eq(t, s.Sanitize(in), in, "unchanged")
|
||||
if n := testing.AllocsPerRun(100, func() { _ = s.Sanitize(in) }); n != 0 {
|
||||
t.Errorf("clean input allocated %v times, want 0", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendSanitize(t *testing.T) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
buf := append([]byte(nil), "prefix:"...)
|
||||
buf = s.AppendSanitize(buf, "a\x00b")
|
||||
eq(t, string(buf), "prefix:a<00>b", "append with rules")
|
||||
|
||||
// No rules configured appends verbatim
|
||||
buf = append([]byte(nil), "prefix:"...)
|
||||
buf = New().AppendSanitize(buf, "a\x00b")
|
||||
eq(t, string(buf), "prefix:a\x00b", "append passthrough")
|
||||
}
|
||||
|
||||
func TestSanitizerConcurrent(t *testing.T) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
var wg sync.WaitGroup
|
||||
for range 16 {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for range 500 {
|
||||
// Errorf is goroutine-safe; Fatal variants are not
|
||||
if got := s.Sanitize("a\x00b\x07c"); got != "a<00>b<07>c" {
|
||||
t.Errorf("concurrent Sanitize: got %q", got)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestSerializerWriteString(t *testing.T) {
|
||||
t.Run("raw applies sanitizer", func(t *testing.T) {
|
||||
se := NewSerializer("raw", New().Rule(FilterNonPrintable, TransformHexEncode))
|
||||
var buf []byte
|
||||
se.WriteString(&buf, "test\x00data")
|
||||
eq(t, string(buf), "test<00>data", "raw")
|
||||
})
|
||||
|
||||
t.Run("only sanitizable characters", func(t *testing.T) {
|
||||
s := New().Rule(FilterNonPrintable, TransformStrip)
|
||||
assert.Equal(t, "", s.Sanitize("\x00\x01\x02\x03"))
|
||||
t.Run("txt quotes conditionally", func(t *testing.T) {
|
||||
se := NewSerializer("txt", New())
|
||||
var buf []byte
|
||||
se.WriteString(&buf, "hello world")
|
||||
eq(t, string(buf), `"hello world"`, "quoted")
|
||||
|
||||
buf = nil
|
||||
se.WriteString(&buf, "nospace")
|
||||
eq(t, string(buf), "nospace", "unquoted")
|
||||
|
||||
buf = nil
|
||||
se.WriteString(&buf, `has"quote`)
|
||||
eq(t, string(buf), `"has\"quote"`, "escaped quote")
|
||||
})
|
||||
|
||||
t.Run("multi-byte UTF-8", func(t *testing.T) {
|
||||
s := New().Rule(FilterNonPrintable, TransformHexEncode)
|
||||
input := "Hello 世界 ✓"
|
||||
assert.Equal(t, input, s.Sanitize(input), "UTF-8 should pass through")
|
||||
t.Run("json escapes transport characters", func(t *testing.T) {
|
||||
se := NewSerializer("json", New())
|
||||
var buf []byte
|
||||
se.WriteString(&buf, "line1\nline2\t\"quoted\"")
|
||||
eq(t, string(buf), `"line1\nline2\t\"quoted\""`, "escapes")
|
||||
|
||||
buf = nil
|
||||
se.WriteString(&buf, "null\x00byte")
|
||||
eq(t, string(buf), `"null\u0000byte"`, "control escape")
|
||||
|
||||
buf = nil
|
||||
se.WriteString(&buf, "héllo 世界")
|
||||
eq(t, string(buf), `"héllo 世界"`, "UTF-8 passthrough")
|
||||
})
|
||||
|
||||
t.Run("multi-byte control character", func(t *testing.T) {
|
||||
s := New().Rule(FilterNonPrintable, TransformHexEncode)
|
||||
// NEL (Next Line) is U+0085, encoded as C2 85 in UTF-8
|
||||
assert.Equal(t, "line1<c285>line2", s.Sanitize("line1\u0085line2"))
|
||||
t.Run("json applies sanitizer before escaping", func(t *testing.T) {
|
||||
se := NewSerializer("json", New().Policy(PolicyTxt))
|
||||
var buf []byte
|
||||
se.WriteString(&buf, "a\x00b")
|
||||
eq(t, string(buf), `"a<00>b"`, "layered")
|
||||
})
|
||||
}
|
||||
|
||||
func TestSerializer(t *testing.T) {
|
||||
t.Run("raw format with sanitizer", func(t *testing.T) {
|
||||
san := New().Rule(FilterNonPrintable, TransformHexEncode)
|
||||
handler := NewSerializer("raw", san)
|
||||
func TestSerializerScalars(t *testing.T) {
|
||||
san := New()
|
||||
|
||||
t.Run("numbers and booleans", func(t *testing.T) {
|
||||
se := NewSerializer("json", san)
|
||||
var buf []byte
|
||||
handler.WriteString(&buf, "test\x00data")
|
||||
assert.Equal(t, "test<00>data", string(buf))
|
||||
se.WriteNumber(&buf, "42")
|
||||
se.WriteBool(&buf, true)
|
||||
se.WriteBool(&buf, false)
|
||||
eq(t, string(buf), "42truefalse", "scalars are unquoted")
|
||||
})
|
||||
|
||||
t.Run("txt format with quotes", func(t *testing.T) {
|
||||
san := New() // No sanitization
|
||||
handler := NewSerializer("txt", san)
|
||||
|
||||
t.Run("nil per format", func(t *testing.T) {
|
||||
var buf []byte
|
||||
handler.WriteString(&buf, "hello world")
|
||||
assert.Equal(t, `"hello world"`, string(buf))
|
||||
NewSerializer("raw", san).WriteNil(&buf)
|
||||
eq(t, string(buf), "nil", "raw nil")
|
||||
|
||||
buf = nil
|
||||
handler.WriteString(&buf, "nospace")
|
||||
assert.Equal(t, "nospace", string(buf))
|
||||
})
|
||||
|
||||
t.Run("json format escaping", func(t *testing.T) {
|
||||
san := New() // JSON handler does its own escaping
|
||||
handler := NewSerializer("json", san)
|
||||
|
||||
var buf []byte
|
||||
handler.WriteString(&buf, "line1\nline2\t\"quoted\"")
|
||||
assert.Equal(t, `"line1\nline2\t\"quoted\""`, string(buf))
|
||||
NewSerializer("json", san).WriteNil(&buf)
|
||||
eq(t, string(buf), "null", "json nil")
|
||||
|
||||
buf = nil
|
||||
handler.WriteString(&buf, "null\x00byte")
|
||||
assert.Equal(t, `"null\u0000byte"`, string(buf))
|
||||
NewSerializer("txt", san).WriteNil(&buf)
|
||||
eq(t, string(buf), "null", "txt nil")
|
||||
})
|
||||
|
||||
t.Run("complex value handling", func(t *testing.T) {
|
||||
san := New()
|
||||
handler := NewSerializer("raw", san)
|
||||
|
||||
t.Run("complex values", func(t *testing.T) {
|
||||
var buf []byte
|
||||
handler.WriteComplex(&buf, map[string]int{"a": 1})
|
||||
assert.Contains(t, string(buf), "map[")
|
||||
})
|
||||
|
||||
t.Run("json utf8 passthrough", func(t *testing.T) {
|
||||
handler := NewSerializer("json", New())
|
||||
var buf []byte
|
||||
handler.WriteString(&buf, "héllo 世界")
|
||||
assert.Equal(t, `"héllo 世界"`, string(buf))
|
||||
})
|
||||
|
||||
t.Run("json sanitizer applied", func(t *testing.T) {
|
||||
handler := NewSerializer("json", New().Policy(PolicyTxt))
|
||||
var buf []byte
|
||||
handler.WriteString(&buf, "a\x00b")
|
||||
assert.Equal(t, `"a<00>b"`, string(buf))
|
||||
})
|
||||
|
||||
t.Run("nil handling", func(t *testing.T) {
|
||||
san := New()
|
||||
|
||||
rawHandler := NewSerializer("raw", san)
|
||||
var buf []byte
|
||||
rawHandler.WriteNil(&buf)
|
||||
assert.Equal(t, "nil", string(buf))
|
||||
|
||||
jsonHandler := NewSerializer("json", san)
|
||||
buf = nil
|
||||
jsonHandler.WriteNil(&buf)
|
||||
assert.Equal(t, "null", string(buf))
|
||||
NewSerializer("raw", san).WriteComplex(&buf, map[string]int{"a": 1})
|
||||
eq(t, string(buf), "map[a:1]", "map formatting")
|
||||
})
|
||||
}
|
||||
|
||||
func TestPolicyWithCustomRules(t *testing.T) {
|
||||
s := New().
|
||||
Policy(PolicyTxt).
|
||||
Rule(FilterControl, TransformStrip).
|
||||
Rule(FilterWhitespace, TransformJSONEscape)
|
||||
func TestNeedsQuotes(t *testing.T) {
|
||||
tests := []struct {
|
||||
format string
|
||||
in string
|
||||
want bool
|
||||
}{
|
||||
{"json", "anything", true},
|
||||
{"raw", "anything", false},
|
||||
{"txt", "", true},
|
||||
{"txt", "plain", false},
|
||||
{"txt", "has space", true},
|
||||
{"txt", "semi;colon", true},
|
||||
{"txt", "pipe|char", true},
|
||||
{"txt", "brace{x}", true},
|
||||
{"txt", "percent%", true},
|
||||
{"txt", "equals=", true},
|
||||
{"txt", "ctrl\x01", true},
|
||||
{"txt", "dash-underscore_", false},
|
||||
}
|
||||
|
||||
// \x07 is non-printable AND control - matches PolicyTxt first (hex encode)
|
||||
// \x7F is non-printable but NOT control - matches PolicyTxt (hex encode)
|
||||
input := "a\x07b c\x7Fd"
|
||||
result := s.Sanitize(input)
|
||||
|
||||
assert.Equal(t, "a<07>b c<7f>d", result) // FIXED: \x07 now hex encoded
|
||||
for _, tt := range tests {
|
||||
se := NewSerializer(tt.format, New())
|
||||
if got := se.NeedsQuotes(tt.in); got != tt.want {
|
||||
t.Errorf("NeedsQuotes(%s, %q) = %v, want %v", tt.format, tt.in, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSanitizer(b *testing.B) {
|
||||
@@ -238,65 +324,20 @@ func BenchmarkSanitizer(b *testing.B) {
|
||||
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
_ = bm.sanitizer.Sanitize(input)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransformPriority(t *testing.T) {
|
||||
// Test that only one transform is applied per rule
|
||||
s := New().Rule(FilterControl, TransformStrip|TransformHexEncode)
|
||||
|
||||
// Should strip (first flag checked), not hex encode
|
||||
assert.Equal(t, "ab", s.Sanitize("a\x00b"))
|
||||
}
|
||||
|
||||
func TestSanitizerConcurrent(t *testing.T) {
|
||||
func BenchmarkSanitizerClean(b *testing.B) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 16; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for j := 0; j < 500; j++ {
|
||||
if got := s.Sanitize("a\x00b\x07c"); got != "a<00>b<07>c" {
|
||||
t.Errorf("got %q", got)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
input := strings.Repeat("clean ascii text ", 100)
|
||||
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
_ = s.Sanitize(input)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestSanitizeCleanFastPath(t *testing.T) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
in := "clean ascii text"
|
||||
assert.Equal(t, in, s.Sanitize(in))
|
||||
assert.Zero(t, testing.AllocsPerRun(100, func() { _ = s.Sanitize(in) }))
|
||||
}
|
||||
|
||||
func TestAppendSanitize(t *testing.T) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
buf := append([]byte(nil), "prefix:"...)
|
||||
buf = s.AppendSanitize(buf, "a\x00b")
|
||||
assert.Equal(t, "prefix:a<00>b", string(buf))
|
||||
}
|
||||
|
||||
func TestHexMarkerEscaping(t *testing.T) {
|
||||
s := New().Policy(PolicyTxt)
|
||||
assert.Equal(t, "a<00>b", s.Sanitize("a\x00b")) // actual NUL
|
||||
assert.Equal(t, "a<3c>00>b", s.Sanitize("a<00>b")) // literal text "<00>" — unambiguous
|
||||
}
|
||||
|
||||
func TestPolicyShellExtended(t *testing.T) {
|
||||
s := New().Policy(PolicyShell)
|
||||
assert.Equal(t, "abc", s.Sanitize(`a'b"c`))
|
||||
assert.Equal(t, "ab", s.Sanitize(`a\b`))
|
||||
assert.Equal(t, "file", s.Sanitize("file*?"))
|
||||
assert.Equal(t, "rm-rf", s.Sanitize("rm -rf *"))
|
||||
assert.Equal(t, "ab", s.Sanitize("a\x00\x1bb")) // control stripped
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user