github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/runtime/serializer/json/json_limit_test.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package json 18 19 import ( 20 gojson "encoding/json" 21 "strings" 22 "testing" 23 24 utiljson "github.com/spotmaxtech/k8s-apimachinery-v0260/pkg/util/json" 25 ) 26 27 type testcase struct { 28 name string 29 data []byte 30 checkErr func(t testing.TB, err error) 31 32 benchmark bool 33 } 34 35 func testcases() []testcase { 36 // verify we got an error of some kind 37 nonNilError := func(t testing.TB, err error) { 38 if err == nil { 39 t.Errorf("expected error, got none") 40 } 41 } 42 // verify the parse completed, either with success or a max depth error 43 successOrMaxDepthError := func(t testing.TB, err error) { 44 if err != nil && !strings.Contains(err.Error(), "max depth") { 45 t.Errorf("expected success or error containing 'max depth', got: %v", err) 46 } 47 } 48 49 return []testcase{ 50 { 51 name: "3MB of deeply nested slices", 52 checkErr: successOrMaxDepthError, 53 data: []byte(`{"a":` + strings.Repeat(`[`, 3*1024*1024/2) + strings.Repeat(`]`, 3*1024*1024/2) + "}"), 54 }, 55 { 56 name: "3MB of unbalanced nested slices", 57 checkErr: nonNilError, 58 data: []byte(`{"a":` + strings.Repeat(`[`, 3*1024*1024)), 59 }, 60 { 61 name: "3MB of deeply nested maps", 62 checkErr: successOrMaxDepthError, 63 data: []byte(strings.Repeat(`{"":`, 3*1024*1024/5/2) + "{}" + strings.Repeat(`}`, 3*1024*1024/5/2)), 64 }, 65 { 66 name: "3MB of unbalanced nested maps", 67 checkErr: nonNilError, 68 data: []byte(strings.Repeat(`{"":`, 3*1024*1024/5)), 69 }, 70 { 71 name: "3MB of empty slices", 72 data: []byte(`{"a":[` + strings.Repeat(`[],`, 3*1024*1024/3-2) + `[]]}`), 73 benchmark: true, 74 }, 75 { 76 name: "3MB of slices", 77 data: []byte(`{"a":[` + strings.Repeat(`[0],`, 3*1024*1024/4-2) + `[0]]}`), 78 benchmark: true, 79 }, 80 { 81 name: "3MB of empty maps", 82 data: []byte(`{"a":[` + strings.Repeat(`{},`, 3*1024*1024/3-2) + `{}]}`), 83 benchmark: true, 84 }, 85 { 86 name: "3MB of maps", 87 data: []byte(`{"a":[` + strings.Repeat(`{"a":0},`, 3*1024*1024/8-2) + `{"a":0}]}`), 88 benchmark: true, 89 }, 90 { 91 name: "3MB of ints", 92 data: []byte(`{"a":[` + strings.Repeat(`0,`, 3*1024*1024/2-2) + `0]}`), 93 benchmark: true, 94 }, 95 { 96 name: "3MB of floats", 97 data: []byte(`{"a":[` + strings.Repeat(`0.0,`, 3*1024*1024/4-2) + `0.0]}`), 98 benchmark: true, 99 }, 100 { 101 name: "3MB of bools", 102 data: []byte(`{"a":[` + strings.Repeat(`true,`, 3*1024*1024/5-2) + `true]}`), 103 benchmark: true, 104 }, 105 { 106 name: "3MB of empty strings", 107 data: []byte(`{"a":[` + strings.Repeat(`"",`, 3*1024*1024/3-2) + `""]}`), 108 benchmark: true, 109 }, 110 { 111 name: "3MB of strings", 112 data: []byte(`{"a":[` + strings.Repeat(`"abcdefghijklmnopqrstuvwxyz012",`, 3*1024*1024/30-2) + `"abcdefghijklmnopqrstuvwxyz012"]}`), 113 benchmark: true, 114 }, 115 { 116 name: "3MB of nulls", 117 data: []byte(`{"a":[` + strings.Repeat(`null,`, 3*1024*1024/5-2) + `null]}`), 118 benchmark: true, 119 }, 120 } 121 } 122 123 var decoders = map[string]func([]byte, interface{}) error{ 124 "gojson": gojson.Unmarshal, 125 "utiljson": utiljson.Unmarshal, 126 } 127 128 func TestJSONLimits(t *testing.T) { 129 for _, tc := range testcases() { 130 if tc.benchmark { 131 continue 132 } 133 t.Run(tc.name, func(t *testing.T) { 134 for decoderName, decoder := range decoders { 135 t.Run(decoderName, func(t *testing.T) { 136 v := map[string]interface{}{} 137 err := decoder(tc.data, &v) 138 139 if tc.checkErr != nil { 140 tc.checkErr(t, err) 141 } else if err != nil { 142 t.Errorf("unexpected error: %v", err) 143 } 144 }) 145 } 146 }) 147 } 148 } 149 150 func BenchmarkJSONLimits(b *testing.B) { 151 for _, tc := range testcases() { 152 b.Run(tc.name, func(b *testing.B) { 153 for decoderName, decoder := range decoders { 154 b.Run(decoderName, func(b *testing.B) { 155 for i := 0; i < b.N; i++ { 156 v := map[string]interface{}{} 157 err := decoder(tc.data, &v) 158 159 if tc.checkErr != nil { 160 tc.checkErr(b, err) 161 } else if err != nil { 162 b.Errorf("unexpected error: %v", err) 163 } 164 } 165 }) 166 } 167 }) 168 } 169 }