Assisted-by: GLM 5.3 Flash
This commit is contained in:
+102
@@ -2024,3 +2024,105 @@ func TestMarshalAppend(t *testing.T) {
|
||||
t.Errorf("MarshalAppend with an unencodable value = %q, want an error", out3)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalCyclicData(t *testing.T) {
|
||||
t.Run("a cyclic struct is an error, not a crash", func(t *testing.T) {
|
||||
type Node struct {
|
||||
Name string `toml:"name"`
|
||||
Next *Node `toml:"next"`
|
||||
}
|
||||
a := &Node{Name: "a"}
|
||||
b := &Node{Name: "b"}
|
||||
a.Next = b
|
||||
b.Next = a
|
||||
_, err := Marshal(a)
|
||||
if err == nil {
|
||||
t.Fatal("Marshal(cyclic) succeeded, want an error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "may be cyclic") {
|
||||
t.Errorf("err = %v, want it to name the cycle", err)
|
||||
}
|
||||
})
|
||||
t.Run("a cyclic map is an error", func(t *testing.T) {
|
||||
m := map[string]any{}
|
||||
m["self"] = m
|
||||
if _, err := Marshal(m); err == nil {
|
||||
t.Fatal("Marshal(cyclic map) succeeded, want an error")
|
||||
}
|
||||
})
|
||||
t.Run("a cyclic value array is an error", func(t *testing.T) {
|
||||
m := map[string]any{}
|
||||
m["items"] = []any{int64(1), m}
|
||||
if _, err := Marshal(map[string]any{"outer": m}); err == nil {
|
||||
t.Fatal("Marshal(cyclic array) succeeded, want an error")
|
||||
}
|
||||
})
|
||||
t.Run("a deeply nested but finite value encodes", func(t *testing.T) {
|
||||
type Node struct {
|
||||
Next *Node `toml:"next"`
|
||||
}
|
||||
root := &Node{}
|
||||
cur := root
|
||||
for range 5000 {
|
||||
cur.Next = &Node{}
|
||||
cur = cur.Next
|
||||
}
|
||||
if _, err := Marshal(root); err != nil {
|
||||
t.Errorf("Marshal(deep) = %v, want nil", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestUnmarshalWithOptions(t *testing.T) {
|
||||
data := []byte("host = \"db\"\nextra = 1\n")
|
||||
type Config struct {
|
||||
Host string `toml:"host,required"`
|
||||
}
|
||||
t.Run("the zero value takes the defaults", func(t *testing.T) {
|
||||
var cfg struct {
|
||||
Host string `toml:"host"`
|
||||
Extra int `toml:"extra"`
|
||||
}
|
||||
if err := UnmarshalWithOptions(data, &cfg, DecodeOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cfg.Host != "db" || cfg.Extra != 1 {
|
||||
t.Errorf("decoded %+v", cfg)
|
||||
}
|
||||
})
|
||||
t.Run("strict and required work in one call", func(t *testing.T) {
|
||||
err := UnmarshalWithOptions(data, &Config{}, DecodeOptions{DisallowUnknownFields: true})
|
||||
want := `interpres: unknown field "extra" for interpres.Config`
|
||||
if err == nil || err.Error() != want {
|
||||
t.Errorf("err = %v, want %q", err, want)
|
||||
}
|
||||
})
|
||||
t.Run("UseNumber keeps the literal", func(t *testing.T) {
|
||||
var tree map[string]any
|
||||
in := []byte("n = 1_000\n")
|
||||
if err := UnmarshalWithOptions(in, &tree, DecodeOptions{UseNumber: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, ok := tree["n"].(Number); !ok || got != "1_000" {
|
||||
t.Errorf("n = %#v, want Number(\"1_000\")", tree["n"])
|
||||
}
|
||||
})
|
||||
t.Run("the limits apply", func(t *testing.T) {
|
||||
var nested strings.Builder
|
||||
nested.WriteString("x = ")
|
||||
for range 20 {
|
||||
nested.WriteString("[")
|
||||
}
|
||||
nested.WriteString("1")
|
||||
for range 20 {
|
||||
nested.WriteString("]")
|
||||
}
|
||||
var tree map[string]any
|
||||
if err := UnmarshalWithOptions([]byte(nested.String()), &tree, DecodeOptions{MaxDepth: 10}); err == nil {
|
||||
t.Error("a document over MaxDepth decoded, want an error")
|
||||
}
|
||||
if err := UnmarshalWithOptions([]byte("a = 1\n"), &tree, DecodeOptions{MaxInputSize: 2}); err == nil {
|
||||
t.Error("a document over MaxInputSize decoded, want an error")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user