-
Notifications
You must be signed in to change notification settings - Fork 2
/
limit_test.go
149 lines (126 loc) · 3.93 KB
/
limit_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package yaml_test
import (
"fmt"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/go-faster/yaml"
)
var limitTests = []struct {
name string
data []byte
error string
}{
{
name: "1000kb of maps with 100 aliases",
data: []byte(`{a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-100) + `], b: &b [*a` + strings.Repeat(`,*a`, 99) + `]}`),
error: "yaml: line 1: document contains excessive aliasing",
},
{
name: "1000kb of deeply nested slices",
data: []byte(strings.Repeat(`[`, 1000*1024)),
error: "yaml: offset 10000: exceeded max depth of 10000",
},
{
name: "1000kb of deeply nested maps",
data: []byte("x: " + strings.Repeat(`{`, 1000*1024)),
error: "yaml: offset 10003: exceeded max depth of 10000",
},
{
name: "1000kb of deeply nested indents",
data: []byte(strings.Repeat(`- `, 1000*1024)),
error: "yaml: offset 20000: exceeded max depth of 10000",
},
{
name: "1000kb of 1000-indent lines",
data: []byte(strings.Repeat(strings.Repeat(`- `, 1000)+"\n", 1024/2)),
},
{name: "1kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1*1024/4-1) + `]`)},
{name: "10kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 10*1024/4-1) + `]`)},
{name: "100kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 100*1024/4-1) + `]`)},
{name: "1000kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-1) + `]`)},
{name: "1000kb slice nested at max-depth", data: []byte(strings.Repeat(`[`, 10000) + `1` + strings.Repeat(`,1`, 1000*1024/2-20000-1) + strings.Repeat(`]`, 10000))},
{name: "1000kb slice nested in maps at max-depth", data: []byte("{a,b:\n" + strings.Repeat(" {a,b:", 10000-2) + ` [1` + strings.Repeat(",1", 1000*1024/2-6*10000-1) + `]` + strings.Repeat(`}`, 10000-1))},
{name: "1000kb of 10000-nested lines", data: []byte(strings.Repeat(`- `+strings.Repeat(`[`, 10000)+strings.Repeat(`]`, 10000)+"\n", 1000*1024/20000))},
}
func TestLimits(t *testing.T) {
if testing.Short() {
return
}
for i, tc := range limitTests {
tc := tc
t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) {
t.Logf("Test %s", tc.name)
a := require.New(t)
var v any
err := yaml.Unmarshal(tc.data, &v)
if len(tc.error) > 0 {
a.Error(err)
a.Regexp(tc.error, err.Error())
return
}
a.NoError(err)
})
}
}
func Benchmark1000KB100Aliases(b *testing.B) {
benchmark(b, "1000kb of maps with 100 aliases")
}
func Benchmark1000KBDeeplyNestedSlices(b *testing.B) {
benchmark(b, "1000kb of deeply nested slices")
}
func Benchmark1000KBDeeplyNestedMaps(b *testing.B) {
benchmark(b, "1000kb of deeply nested maps")
}
func Benchmark1000KBDeeplyNestedIndents(b *testing.B) {
benchmark(b, "1000kb of deeply nested indents")
}
func Benchmark1000KB1000IndentLines(b *testing.B) {
benchmark(b, "1000kb of 1000-indent lines")
}
func Benchmark1KBMaps(b *testing.B) {
benchmark(b, "1kb of maps")
}
func Benchmark10KBMaps(b *testing.B) {
benchmark(b, "10kb of maps")
}
func Benchmark100KBMaps(b *testing.B) {
benchmark(b, "100kb of maps")
}
func Benchmark1000KBMaps(b *testing.B) {
benchmark(b, "1000kb of maps")
}
func BenchmarkDeepSlice(b *testing.B) {
benchmark(b, "1000kb slice nested at max-depth")
}
func BenchmarkDeepFlow(b *testing.B) {
benchmark(b, "1000kb slice nested in maps at max-depth")
}
func Benchmark1000KBMaxDepthNested(b *testing.B) {
benchmark(b, "1000kb of 10000-nested lines")
}
func benchmark(b *testing.B, name string) {
for _, t := range limitTests {
if t.name != name {
continue
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v any
err := yaml.Unmarshal(t.data, &v)
if len(t.error) > 0 {
if err == nil {
b.Errorf("expected error, got none")
} else if err.Error() != t.error {
b.Errorf("expected error '%s', got '%s'", t.error, err.Error())
}
} else {
if err != nil {
b.Errorf("unexpected error: %v", err)
}
}
}
return
}
b.Errorf("testcase %q not found", name)
}