summaryrefslogtreecommitdiff
path: root/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/gopkg.in/yaml.v2/limit_test.go
blob: 8d8ec2d224539641cab57fa7e462a72e56bb6a9f (plain)
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
package yaml_test

import (
	"strings"
	"testing"

	. "gopkg.in/check.v1"
	"gopkg.in/yaml.v2"
)

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: document contains excessive aliasing",
	}, {
		name:  "1000kb of deeply nested slices",
		data:  []byte(strings.Repeat(`[`, 1000*1024)),
		error: "yaml: exceeded max depth of 10000",
	}, {
		name:  "1000kb of deeply nested maps",
		data:  []byte("x: " + strings.Repeat(`{`, 1000*1024)),
		error: "yaml: exceeded max depth of 10000",
	}, {
		name:  "1000kb of deeply nested indents",
		data:  []byte(strings.Repeat(`- `, 1000*1024)),
		error: "yaml: 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 (s *S) TestLimits(c *C) {
	if testing.Short() {
		return
	}
	for _, tc := range limitTests {
		var v interface{}
		err := yaml.Unmarshal(tc.data, &v)
		if len(tc.error) > 0 {
			c.Assert(err, ErrorMatches, tc.error, Commentf("testcase: %s", tc.name))
		} else {
			c.Assert(err, IsNil, Commentf("testcase: %s", tc.name))
		}
	}
}

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 interface{}
			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)
}