|
@@ -0,0 +1,123 @@
|
|
|
|
|
+package yaml_test
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "strings"
|
|
|
|
|
+ "testing"
|
|
|
|
|
+
|
|
|
|
|
+ . "gopkg.in/check.v1"
|
|
|
|
|
+ "gopkg.in/yaml.v2"
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+type testcase struct {
|
|
|
|
|
+ name string
|
|
|
|
|
+ data []byte
|
|
|
|
|
+ error string
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func testcases() []testcase {
|
|
|
|
|
+ return []testcase{
|
|
|
|
|
+ {
|
|
|
|
|
+ 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) + `]`)},
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (s *S) TestLimits(c *C) {
|
|
|
|
|
+ if testing.Short() {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ for _, tc := range testcases() {
|
|
|
|
|
+ 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 benchmark(b *testing.B, name string) {
|
|
|
|
|
+ var tc testcase
|
|
|
|
|
+ for _, t := range testcases() {
|
|
|
|
|
+ if t.name == name {
|
|
|
|
|
+ tc = t
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if tc.name != name {
|
|
|
|
|
+ b.Errorf("testcase %q not found", name)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ b.ResetTimer()
|
|
|
|
|
+
|
|
|
|
|
+ for i := 0; i < b.N; i++ {
|
|
|
|
|
+ var v interface{}
|
|
|
|
|
+ err := yaml.Unmarshal(tc.data, &v)
|
|
|
|
|
+ if len(tc.error) > 0 {
|
|
|
|
|
+ if err == nil {
|
|
|
|
|
+ b.Errorf("expected error, got none")
|
|
|
|
|
+ } else if err.Error() != tc.error {
|
|
|
|
|
+ b.Errorf("expected error '%s', got '%s'", tc.error, err.Error())
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ b.Errorf("unexpected error: %v", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|