limit_test.go 3.0 KB

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