1 package yaml_test
2
3 import (
4 "strings"
5 "testing"
6
7 . "gopkg.in/check.v1"
8 "gopkg.in/yaml.v3"
9 )
10
11 var limitTests = []struct {
12 name string
13 data []byte
14 error string
15 }{
16 {
17 name: "1000kb of maps with 100 aliases",
18 data: []byte(`{a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-100) + `], b: &b [*a` + strings.Repeat(`,*a`, 99) + `]}`),
19 error: "yaml: document contains excessive aliasing",
20 }, {
21 name: "1000kb of deeply nested slices",
22 data: []byte(strings.Repeat(`[`, 1000*1024)),
23 error: "yaml: exceeded max depth of 10000",
24 }, {
25 name: "1000kb of deeply nested maps",
26 data: []byte("x: " + strings.Repeat(`{`, 1000*1024)),
27 error: "yaml: exceeded max depth of 10000",
28 }, {
29 name: "1000kb of deeply nested indents",
30 data: []byte(strings.Repeat(`- `, 1000*1024)),
31 error: "yaml: exceeded max depth of 10000",
32 }, {
33 name: "1000kb of 1000-indent lines",
34 data: []byte(strings.Repeat(strings.Repeat(`- `, 1000)+"\n", 1024/2)),
35 },
36 {name: "1kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1*1024/4-1) + `]`)},
37 {name: "10kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 10*1024/4-1) + `]`)},
38 {name: "100kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 100*1024/4-1) + `]`)},
39 {name: "1000kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-1) + `]`)},
40 {name: "1000kb slice nested at max-depth", data: []byte(strings.Repeat(`[`, 10000) + `1` + strings.Repeat(`,1`, 1000*1024/2-20000-1) + strings.Repeat(`]`, 10000))},
41 {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))},
42 {name: "1000kb of 10000-nested lines", data: []byte(strings.Repeat(`- `+strings.Repeat(`[`, 10000)+strings.Repeat(`]`, 10000)+"\n", 1000*1024/20000))},
43 }
44
45 func (s *S) TestLimits(c *C) {
46 if testing.Short() {
47 return
48 }
49 for _, tc := range limitTests {
50 var v interface{}
51 err := yaml.Unmarshal(tc.data, &v)
52 if len(tc.error) > 0 {
53 c.Assert(err, ErrorMatches, tc.error, Commentf("testcase: %s", tc.name))
54 } else {
55 c.Assert(err, IsNil, Commentf("testcase: %s", tc.name))
56 }
57 }
58 }
59
60 func Benchmark1000KB100Aliases(b *testing.B) {
61 benchmark(b, "1000kb of maps with 100 aliases")
62 }
63 func Benchmark1000KBDeeplyNestedSlices(b *testing.B) {
64 benchmark(b, "1000kb of deeply nested slices")
65 }
66 func Benchmark1000KBDeeplyNestedMaps(b *testing.B) {
67 benchmark(b, "1000kb of deeply nested maps")
68 }
69 func Benchmark1000KBDeeplyNestedIndents(b *testing.B) {
70 benchmark(b, "1000kb of deeply nested indents")
71 }
72 func Benchmark1000KB1000IndentLines(b *testing.B) {
73 benchmark(b, "1000kb of 1000-indent lines")
74 }
75 func Benchmark1KBMaps(b *testing.B) {
76 benchmark(b, "1kb of maps")
77 }
78 func Benchmark10KBMaps(b *testing.B) {
79 benchmark(b, "10kb of maps")
80 }
81 func Benchmark100KBMaps(b *testing.B) {
82 benchmark(b, "100kb of maps")
83 }
84 func Benchmark1000KBMaps(b *testing.B) {
85 benchmark(b, "1000kb of maps")
86 }
87
88 func BenchmarkDeepSlice(b *testing.B) {
89 benchmark(b, "1000kb slice nested at max-depth")
90 }
91
92 func BenchmarkDeepFlow(b *testing.B) {
93 benchmark(b, "1000kb slice nested in maps at max-depth")
94 }
95
96 func Benchmark1000KBMaxDepthNested(b *testing.B) {
97 benchmark(b, "1000kb of 10000-nested lines")
98 }
99
100 func benchmark(b *testing.B, name string) {
101 for _, t := range limitTests {
102 if t.name != name {
103 continue
104 }
105
106 b.ResetTimer()
107
108 for i := 0; i < b.N; i++ {
109 var v interface{}
110 err := yaml.Unmarshal(t.data, &v)
111 if len(t.error) > 0 {
112 if err == nil {
113 b.Errorf("expected error, got none")
114 } else if err.Error() != t.error {
115 b.Errorf("expected error '%s', got '%s'", t.error, err.Error())
116 }
117 } else {
118 if err != nil {
119 b.Errorf("unexpected error: %v", err)
120 }
121 }
122 }
123
124 return
125 }
126
127 b.Errorf("testcase %q not found", name)
128 }
129
View as plain text