88 lines
2.0 KiB
Go
88 lines
2.0 KiB
Go
package toml
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
func FuzzParse(f *testing.F) {
|
|
for _, s := range []string{
|
|
"",
|
|
`key = "value"`,
|
|
"[table]\nk = 1",
|
|
"[[arr]]\nx = 1.5\n[[arr]]\nx = 2e3",
|
|
"t = { a = 1, b = { c = [1, 2] } }",
|
|
`s = "esc \u00E9 \t"`,
|
|
"n = -0x10\nb = 0b101\no = 0o17",
|
|
} {
|
|
f.Add([]byte(s))
|
|
}
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
p := NewParser(data)
|
|
_, _ = p.Parse() // property: no panic, no hang
|
|
})
|
|
}
|
|
|
|
// normalize collapses the parser's dual slice representations
|
|
// ([]map[string]any for [[headers]], []any for inline arrays) so the
|
|
// fixpoint compares values, not construction syntax.
|
|
func normalize(v any) any {
|
|
switch t := v.(type) {
|
|
case map[string]any:
|
|
for k, vv := range t {
|
|
t[k] = normalize(vv)
|
|
}
|
|
return t
|
|
case []map[string]any:
|
|
out := make([]any, len(t))
|
|
for i, m := range t {
|
|
out[i] = normalize(m)
|
|
}
|
|
return out
|
|
case []any:
|
|
for i, vv := range t {
|
|
t[i] = normalize(vv)
|
|
}
|
|
return t
|
|
}
|
|
return v
|
|
}
|
|
|
|
func FuzzRoundTrip(f *testing.F) {
|
|
for _, s := range []string{
|
|
"a = 1\nb = 2.5\nc = true\nd = \"x\"",
|
|
"[t]\nk = [1, 2, 3]",
|
|
"[[s]]\nn = \"a\"\n[[s]]\nn = \"b\"",
|
|
`m = { x = 1, y = { z = "q" } }`,
|
|
`u = "日本語 \u00E9"`,
|
|
"big = 1e100\nsmall = 1e-100",
|
|
} {
|
|
f.Add([]byte(s))
|
|
}
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
// Encoder normalizes invalid UTF-8 to U+FFFD (WriteRune); byte-exact
|
|
// round trip is only a property of valid input.
|
|
if !utf8.Valid(data) {
|
|
t.Skip()
|
|
}
|
|
m1, err := NewParser(data).Parse()
|
|
if err != nil {
|
|
t.Skip()
|
|
}
|
|
out, err := Marshal(m1)
|
|
if err != nil {
|
|
// Parser accepts values the encoder cannot represent
|
|
// (mixed table/scalar arrays). Documented asymmetry.
|
|
t.Skip()
|
|
}
|
|
m2, err := NewParser(out).Parse()
|
|
if err != nil {
|
|
t.Fatalf("emitted TOML failed to re-parse: %v\nemitted:\n%s", err, out)
|
|
}
|
|
if !reflect.DeepEqual(normalize(m1), normalize(m2)) {
|
|
t.Fatalf("fixpoint violation:\nm1: %#v\nm2: %#v\nemitted:\n%s", m1, m2, out)
|
|
}
|
|
})
|
|
}
|