...

Source file src/gopkg.in/yaml.v3/limit_test.go

Documentation: gopkg.in/yaml.v3

     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