github.com/klaytn/klaytn@v1.10.2/rlp/encode_test.go (about) 1 // Modifications Copyright 2022 The klaytn Authors 2 // Copyright 2014 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from rlp/encode_test.go(2022/05/19) 19 // Modified and improved for the klaytn development. 20 21 package rlp 22 23 import ( 24 "bytes" 25 "errors" 26 "fmt" 27 "io" 28 "io/ioutil" 29 "math/big" 30 "runtime" 31 "sync" 32 "testing" 33 34 "github.com/klaytn/klaytn/common/math" 35 ) 36 37 type testEncoder struct { 38 err error 39 } 40 41 func (e *testEncoder) EncodeRLP(w io.Writer) error { 42 if e == nil { 43 panic("EncodeRLP called on nil value") 44 } 45 if e.err != nil { 46 return e.err 47 } 48 w.Write([]byte{0, 1, 0, 1, 0, 1, 0, 1, 0, 1}) 49 return nil 50 } 51 52 type testEncoderValueMethod struct{} 53 54 func (e testEncoderValueMethod) EncodeRLP(w io.Writer) error { 55 w.Write([]byte{0xFA, 0xFE, 0xF0}) 56 return nil 57 } 58 59 type byteEncoder byte 60 61 func (e byteEncoder) EncodeRLP(w io.Writer) error { 62 w.Write(EmptyList) 63 return nil 64 } 65 66 type undecodableEncoder func() 67 68 func (f undecodableEncoder) EncodeRLP(w io.Writer) error { 69 w.Write([]byte{0xF5, 0xF5, 0xF5}) 70 return nil 71 } 72 73 type encodableReader struct { 74 A, B uint 75 } 76 77 func (e *encodableReader) Read(b []byte) (int, error) { 78 panic("called") 79 } 80 81 type namedByteType byte 82 83 var ( 84 _ = Encoder(&testEncoder{}) 85 _ = Encoder(byteEncoder(0)) 86 87 reader io.Reader = &encodableReader{1, 2} 88 ) 89 90 type encTest struct { 91 val interface{} 92 output, error string 93 } 94 95 var encTests = []encTest{ 96 // booleans 97 {val: true, output: "01"}, 98 {val: false, output: "80"}, 99 100 // integers 101 {val: uint32(0), output: "80"}, 102 {val: uint32(127), output: "7F"}, 103 {val: uint32(128), output: "8180"}, 104 {val: uint32(256), output: "820100"}, 105 {val: uint32(1024), output: "820400"}, 106 {val: uint32(0xFFFFFF), output: "83FFFFFF"}, 107 {val: uint32(0xFFFFFFFF), output: "84FFFFFFFF"}, 108 {val: uint64(0xFFFFFFFF), output: "84FFFFFFFF"}, 109 {val: uint64(0xFFFFFFFFFF), output: "85FFFFFFFFFF"}, 110 {val: uint64(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"}, 111 {val: uint64(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"}, 112 {val: uint64(0xFFFFFFFFFFFFFFFF), output: "88FFFFFFFFFFFFFFFF"}, 113 114 // big integers (should match uint for small values) 115 {val: big.NewInt(0), output: "80"}, 116 {val: big.NewInt(1), output: "01"}, 117 {val: big.NewInt(127), output: "7F"}, 118 {val: big.NewInt(128), output: "8180"}, 119 {val: big.NewInt(256), output: "820100"}, 120 {val: big.NewInt(1024), output: "820400"}, 121 {val: big.NewInt(0xFFFFFF), output: "83FFFFFF"}, 122 {val: big.NewInt(0xFFFFFFFF), output: "84FFFFFFFF"}, 123 {val: big.NewInt(0xFFFFFFFFFF), output: "85FFFFFFFFFF"}, 124 {val: big.NewInt(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"}, 125 {val: big.NewInt(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"}, 126 { 127 val: big.NewInt(0).SetBytes(unhex("102030405060708090A0B0C0D0E0F2")), 128 output: "8F102030405060708090A0B0C0D0E0F2", 129 }, 130 { 131 val: big.NewInt(0).SetBytes(unhex("0100020003000400050006000700080009000A000B000C000D000E01")), 132 output: "9C0100020003000400050006000700080009000A000B000C000D000E01", 133 }, 134 { 135 val: big.NewInt(0).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000")), 136 output: "A1010000000000000000000000000000000000000000000000000000000000000000", 137 }, 138 { 139 val: veryBigInt, 140 output: "89FFFFFFFFFFFFFFFFFF", 141 }, 142 { 143 val: veryVeryBigInt, 144 output: "B848FFFFFFFFFFFFFFFFF800000000000000001BFFFFFFFFFFFFFFFFC8000000000000000045FFFFFFFFFFFFFFFFC800000000000000001BFFFFFFFFFFFFFFFFF8000000000000000001", 145 }, 146 147 // non-pointer big.Int 148 {val: *big.NewInt(0), output: "80"}, 149 {val: *big.NewInt(0xFFFFFF), output: "83FFFFFF"}, 150 151 // negative ints are not supported 152 {val: big.NewInt(-1), error: "rlp: cannot encode negative big.Int"}, 153 {val: *big.NewInt(-1), error: "rlp: cannot encode negative big.Int"}, 154 155 // byte arrays 156 {val: [0]byte{}, output: "80"}, 157 {val: [1]byte{0}, output: "00"}, 158 {val: [1]byte{1}, output: "01"}, 159 {val: [1]byte{0x7F}, output: "7F"}, 160 {val: [1]byte{0x80}, output: "8180"}, 161 {val: [1]byte{0xFF}, output: "81FF"}, 162 {val: [3]byte{1, 2, 3}, output: "83010203"}, 163 {val: [57]byte{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, 164 165 // named byte type arrays 166 {val: [0]namedByteType{}, output: "80"}, 167 {val: [1]namedByteType{0}, output: "00"}, 168 {val: [1]namedByteType{1}, output: "01"}, 169 {val: [1]namedByteType{0x7F}, output: "7F"}, 170 {val: [1]namedByteType{0x80}, output: "8180"}, 171 {val: [1]namedByteType{0xFF}, output: "81FF"}, 172 {val: [3]namedByteType{1, 2, 3}, output: "83010203"}, 173 {val: [57]namedByteType{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, 174 175 // byte slices 176 {val: []byte{}, output: "80"}, 177 {val: []byte{0}, output: "00"}, 178 {val: []byte{0x7E}, output: "7E"}, 179 {val: []byte{0x7F}, output: "7F"}, 180 {val: []byte{0x80}, output: "8180"}, 181 {val: []byte{1, 2, 3}, output: "83010203"}, 182 183 // named byte type slices 184 {val: []namedByteType{}, output: "80"}, 185 {val: []namedByteType{0}, output: "00"}, 186 {val: []namedByteType{0x7E}, output: "7E"}, 187 {val: []namedByteType{0x7F}, output: "7F"}, 188 {val: []namedByteType{0x80}, output: "8180"}, 189 {val: []namedByteType{1, 2, 3}, output: "83010203"}, 190 191 // strings 192 {val: "", output: "80"}, 193 {val: "\x7E", output: "7E"}, 194 {val: "\x7F", output: "7F"}, 195 {val: "\x80", output: "8180"}, 196 {val: "dog", output: "83646F67"}, 197 { 198 val: "Lorem ipsum dolor sit amet, consectetur adipisicing eli", 199 output: "B74C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C69", 200 }, 201 { 202 val: "Lorem ipsum dolor sit amet, consectetur adipisicing elit", 203 output: "B8384C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C6974", 204 }, 205 { 206 val: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur mauris magna, suscipit sed vehicula non, iaculis faucibus tortor. Proin suscipit ultricies malesuada. Duis tortor elit, dictum quis tristique eu, ultrices at risus. Morbi a est imperdiet mi ullamcorper aliquet suscipit nec lorem. Aenean quis leo mollis, vulputate elit varius, consequat enim. Nulla ultrices turpis justo, et posuere urna consectetur nec. Proin non convallis metus. Donec tempor ipsum in mauris congue sollicitudin. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Suspendisse convallis sem vel massa faucibus, eget lacinia lacus tempor. Nulla quis ultricies purus. Proin auctor rhoncus nibh condimentum mollis. Aliquam consequat enim at metus luctus, a eleifend purus egestas. Curabitur at nibh metus. Nam bibendum, neque at auctor tristique, lorem libero aliquet arcu, non interdum tellus lectus sit amet eros. Cras rhoncus, metus ac ornare cursus, dolor justo ultrices metus, at ullamcorper volutpat", 207 output: "B904004C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742E20437572616269747572206D6175726973206D61676E612C20737573636970697420736564207665686963756C61206E6F6E2C20696163756C697320666175636962757320746F72746F722E2050726F696E20737573636970697420756C74726963696573206D616C6573756164612E204475697320746F72746F7220656C69742C2064696374756D2071756973207472697374697175652065752C20756C7472696365732061742072697375732E204D6F72626920612065737420696D70657264696574206D6920756C6C616D636F7270657220616C6971756574207375736369706974206E6563206C6F72656D2E2041656E65616E2071756973206C656F206D6F6C6C69732C2076756C70757461746520656C6974207661726975732C20636F6E73657175617420656E696D2E204E756C6C6120756C74726963657320747572706973206A7573746F2C20657420706F73756572652075726E6120636F6E7365637465747572206E65632E2050726F696E206E6F6E20636F6E76616C6C6973206D657475732E20446F6E65632074656D706F7220697073756D20696E206D617572697320636F6E67756520736F6C6C696369747564696E2E20566573746962756C756D20616E746520697073756D207072696D697320696E206661756369627573206F726369206C756374757320657420756C74726963657320706F737565726520637562696C69612043757261653B2053757370656E646973736520636F6E76616C6C69732073656D2076656C206D617373612066617563696275732C2065676574206C6163696E6961206C616375732074656D706F722E204E756C6C61207175697320756C747269636965732070757275732E2050726F696E20617563746F722072686F6E637573206E69626820636F6E64696D656E74756D206D6F6C6C69732E20416C697175616D20636F6E73657175617420656E696D206174206D65747573206C75637475732C206120656C656966656E6420707572757320656765737461732E20437572616269747572206174206E696268206D657475732E204E616D20626962656E64756D2C206E6571756520617420617563746F72207472697374697175652C206C6F72656D206C696265726F20616C697175657420617263752C206E6F6E20696E74657264756D2074656C6C7573206C65637475732073697420616D65742065726F732E20437261732072686F6E6375732C206D65747573206163206F726E617265206375727375732C20646F6C6F72206A7573746F20756C747269636573206D657475732C20617420756C6C616D636F7270657220766F6C7574706174", 208 }, 209 210 // slices 211 {val: []uint{}, output: "C0"}, 212 {val: []uint{1, 2, 3}, output: "C3010203"}, 213 { 214 // [ [], [[]], [ [], [[]] ] ] 215 val: []interface{}{[]interface{}{}, [][]interface{}{{}}, []interface{}{[]interface{}{}, [][]interface{}{{}}}}, 216 output: "C7C0C1C0C3C0C1C0", 217 }, 218 { 219 val: []string{"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo"}, 220 output: "F83C836161618362626283636363836464648365656583666666836767678368686883696969836A6A6A836B6B6B836C6C6C836D6D6D836E6E6E836F6F6F", 221 }, 222 { 223 val: []interface{}{uint(1), uint(0xFFFFFF), []interface{}{[]uint{4, 5, 5}}, "abc"}, 224 output: "CE0183FFFFFFC4C304050583616263", 225 }, 226 { 227 val: [][]string{ 228 {"asdf", "qwer", "zxcv"}, 229 {"asdf", "qwer", "zxcv"}, 230 {"asdf", "qwer", "zxcv"}, 231 {"asdf", "qwer", "zxcv"}, 232 {"asdf", "qwer", "zxcv"}, 233 {"asdf", "qwer", "zxcv"}, 234 {"asdf", "qwer", "zxcv"}, 235 {"asdf", "qwer", "zxcv"}, 236 {"asdf", "qwer", "zxcv"}, 237 {"asdf", "qwer", "zxcv"}, 238 {"asdf", "qwer", "zxcv"}, 239 {"asdf", "qwer", "zxcv"}, 240 {"asdf", "qwer", "zxcv"}, 241 {"asdf", "qwer", "zxcv"}, 242 {"asdf", "qwer", "zxcv"}, 243 {"asdf", "qwer", "zxcv"}, 244 {"asdf", "qwer", "zxcv"}, 245 {"asdf", "qwer", "zxcv"}, 246 {"asdf", "qwer", "zxcv"}, 247 {"asdf", "qwer", "zxcv"}, 248 {"asdf", "qwer", "zxcv"}, 249 {"asdf", "qwer", "zxcv"}, 250 {"asdf", "qwer", "zxcv"}, 251 {"asdf", "qwer", "zxcv"}, 252 {"asdf", "qwer", "zxcv"}, 253 {"asdf", "qwer", "zxcv"}, 254 {"asdf", "qwer", "zxcv"}, 255 {"asdf", "qwer", "zxcv"}, 256 {"asdf", "qwer", "zxcv"}, 257 {"asdf", "qwer", "zxcv"}, 258 {"asdf", "qwer", "zxcv"}, 259 {"asdf", "qwer", "zxcv"}, 260 }, 261 output: "F90200CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376", 262 }, 263 264 // RawValue 265 {val: RawValue(unhex("01")), output: "01"}, 266 {val: RawValue(unhex("82FFFF")), output: "82FFFF"}, 267 {val: []RawValue{unhex("01"), unhex("02")}, output: "C20102"}, 268 269 // structs 270 {val: simplestruct{}, output: "C28080"}, 271 {val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"}, 272 {val: &recstruct{5, nil}, output: "C205C0"}, 273 {val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"}, 274 {val: &intField{X: 3}, error: "rlp: type int is not RLP-serializable (struct field rlp.intField.X)"}, 275 276 // struct tag "-" 277 {val: &ignoredField{A: 1, B: 2, C: 3}, output: "C20103"}, 278 279 // struct tag "tail" 280 {val: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"}, 281 {val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"}, 282 {val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"}, 283 {val: &tailRaw{A: 1, Tail: nil}, output: "C101"}, 284 285 // struct tag "optional" 286 {val: &optionalFields{}, output: "C180"}, 287 {val: &optionalFields{A: 1}, output: "C101"}, 288 {val: &optionalFields{A: 1, B: 2}, output: "C20102"}, 289 {val: &optionalFields{A: 1, B: 2, C: 3}, output: "C3010203"}, 290 {val: &optionalFields{A: 1, B: 0, C: 3}, output: "C3018003"}, 291 {val: &optionalAndTailField{A: 1}, output: "C101"}, 292 {val: &optionalAndTailField{A: 1, B: 2}, output: "C20102"}, 293 {val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"}, 294 {val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"}, 295 {val: &optionalBigIntField{A: 1}, output: "C101"}, 296 {val: &optionalPtrField{A: 1}, output: "C101"}, 297 {val: &optionalPtrFieldNil{A: 1}, output: "C101"}, 298 299 // nil 300 {val: (*uint)(nil), output: "80"}, 301 {val: (*string)(nil), output: "80"}, 302 {val: (*[]byte)(nil), output: "80"}, 303 {val: (*[10]byte)(nil), output: "80"}, 304 {val: (*big.Int)(nil), output: "80"}, 305 {val: (*[]string)(nil), output: "C0"}, 306 {val: (*[10]string)(nil), output: "C0"}, 307 {val: (*[]interface{})(nil), output: "C0"}, 308 {val: (*[]struct{ uint })(nil), output: "C0"}, 309 {val: (*interface{})(nil), output: "C0"}, 310 311 // nil struct fields 312 { 313 val: struct { 314 X *[]byte 315 }{}, 316 output: "C180", 317 }, 318 { 319 val: struct { 320 X *[2]byte 321 }{}, 322 output: "C180", 323 }, 324 { 325 val: struct { 326 X *uint64 327 }{}, 328 output: "C180", 329 }, 330 { 331 val: struct { 332 X *uint64 `rlp:"nilList"` 333 }{}, 334 output: "C1C0", 335 }, 336 { 337 val: struct { 338 X *[]uint64 339 }{}, 340 output: "C1C0", 341 }, 342 { 343 val: struct { 344 X *[]uint64 `rlp:"nilString"` 345 }{}, 346 output: "C180", 347 }, 348 349 // interfaces 350 {val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct 351 352 // Encoder 353 {val: (*testEncoder)(nil), output: "C0"}, 354 {val: &testEncoder{}, output: "00010001000100010001"}, 355 {val: &testEncoder{errors.New("test error")}, error: "test error"}, 356 {val: struct{ E testEncoderValueMethod }{}, output: "C3FAFEF0"}, 357 {val: struct{ E *testEncoderValueMethod }{}, output: "C1C0"}, 358 359 // Verify that the Encoder interface works for unsupported types like func(). 360 {val: undecodableEncoder(func() {}), output: "F5F5F5"}, 361 362 // Verify that pointer method testEncoder.EncodeRLP is called for 363 // addressable non-pointer values. 364 {val: &struct{ TE testEncoder }{testEncoder{}}, output: "CA00010001000100010001"}, 365 {val: &struct{ TE testEncoder }{testEncoder{errors.New("test error")}}, error: "test error"}, 366 367 // Verify the error for non-addressable non-pointer Encoder. 368 {val: testEncoder{}, error: "rlp: unadressable value of type rlp.testEncoder, EncodeRLP is pointer method"}, 369 370 // Verify Encoder takes precedence over []byte. 371 {val: []byteEncoder{0, 1, 2, 3, 4}, output: "C5C0C0C0C0C0"}, 372 } 373 374 func runEncTests(t *testing.T, f func(val interface{}) ([]byte, error)) { 375 for i, test := range encTests { 376 output, err := f(test.val) 377 if err != nil && test.error == "" { 378 t.Errorf("test %d: unexpected error: %v\nvalue %#v\ntype %T", 379 i, err, test.val, test.val) 380 continue 381 } 382 if test.error != "" && fmt.Sprint(err) != test.error { 383 t.Errorf("test %d: error mismatch\ngot %v\nwant %v\nvalue %#v\ntype %T", 384 i, err, test.error, test.val, test.val) 385 continue 386 } 387 if err == nil && !bytes.Equal(output, unhex(test.output)) { 388 t.Errorf("test %d: output mismatch:\ngot %X\nwant %s\nvalue %#v\ntype %T", 389 i, output, test.output, test.val, test.val) 390 } 391 } 392 } 393 394 func TestEncode(t *testing.T) { 395 runEncTests(t, func(val interface{}) ([]byte, error) { 396 b := new(bytes.Buffer) 397 err := Encode(b, val) 398 return b.Bytes(), err 399 }) 400 } 401 402 func TestEncodeToBytes(t *testing.T) { 403 runEncTests(t, EncodeToBytes) 404 } 405 406 func TestEncodeAppendToBytes(t *testing.T) { 407 buffer := make([]byte, 20) 408 runEncTests(t, func(val interface{}) ([]byte, error) { 409 w := NewEncoderBuffer(nil) 410 defer w.Flush() 411 412 err := Encode(w, val) 413 if err != nil { 414 return nil, err 415 } 416 output := w.AppendToBytes(buffer[:0]) 417 return output, nil 418 }) 419 } 420 421 func TestEncodeToReader(t *testing.T) { 422 runEncTests(t, func(val interface{}) ([]byte, error) { 423 _, r, err := EncodeToReader(val) 424 if err != nil { 425 return nil, err 426 } 427 return ioutil.ReadAll(r) 428 }) 429 } 430 431 func TestEncodeToReaderPiecewise(t *testing.T) { 432 runEncTests(t, func(val interface{}) ([]byte, error) { 433 size, r, err := EncodeToReader(val) 434 if err != nil { 435 return nil, err 436 } 437 438 // read output piecewise 439 output := make([]byte, size) 440 for start, end := 0, 0; start < size; start = end { 441 if remaining := size - start; remaining < 3 { 442 end += remaining 443 } else { 444 end = start + 3 445 } 446 n, err := r.Read(output[start:end]) 447 end = start + n 448 if err == io.EOF { 449 break 450 } else if err != nil { 451 return nil, err 452 } 453 } 454 return output, nil 455 }) 456 } 457 458 // This is a regression test verifying that encReader 459 // returns its encbuf to the pool only once. 460 func TestEncodeToReaderReturnToPool(t *testing.T) { 461 buf := make([]byte, 50) 462 wg := new(sync.WaitGroup) 463 for i := 0; i < 5; i++ { 464 wg.Add(1) 465 go func() { 466 for i := 0; i < 1000; i++ { 467 _, r, _ := EncodeToReader("foo") 468 ioutil.ReadAll(r) 469 r.Read(buf) 470 r.Read(buf) 471 r.Read(buf) 472 r.Read(buf) 473 } 474 wg.Done() 475 }() 476 } 477 wg.Wait() 478 } 479 480 var sink interface{} 481 482 func BenchmarkIntsize(b *testing.B) { 483 for i := 0; i < b.N; i++ { 484 sink = intsize(0x12345678) 485 } 486 } 487 488 func BenchmarkPutint(b *testing.B) { 489 buf := make([]byte, 8) 490 for i := 0; i < b.N; i++ { 491 putint(buf, 0x12345678) 492 sink = buf 493 } 494 } 495 496 func BenchmarkEncodeBigInts(b *testing.B) { 497 ints := make([]*big.Int, 200) 498 for i := range ints { 499 ints[i] = math.BigPow(2, int64(i)) 500 } 501 out := bytes.NewBuffer(make([]byte, 0, 4096)) 502 b.ResetTimer() 503 b.ReportAllocs() 504 505 for i := 0; i < b.N; i++ { 506 out.Reset() 507 if err := Encode(out, ints); err != nil { 508 b.Fatal(err) 509 } 510 } 511 } 512 513 func BenchmarkEncodeConcurrentInterface(b *testing.B) { 514 type struct1 struct { 515 A string 516 B *big.Int 517 C [20]byte 518 } 519 value := []interface{}{ 520 uint(999), 521 &struct1{A: "hello", B: big.NewInt(0xFFFFFFFF)}, 522 [10]byte{1, 2, 3, 4, 5, 6}, 523 []string{"yeah", "yeah", "yeah"}, 524 } 525 526 var wg sync.WaitGroup 527 for cpu := 0; cpu < runtime.NumCPU(); cpu++ { 528 wg.Add(1) 529 go func() { 530 defer wg.Done() 531 532 var buffer bytes.Buffer 533 for i := 0; i < b.N; i++ { 534 buffer.Reset() 535 err := Encode(&buffer, value) 536 if err != nil { 537 panic(err) 538 } 539 } 540 }() 541 } 542 wg.Wait() 543 } 544 545 type byteArrayStruct struct { 546 A [20]byte 547 B [32]byte 548 C [32]byte 549 } 550 551 func BenchmarkEncodeByteArrayStruct(b *testing.B) { 552 var out bytes.Buffer 553 var value byteArrayStruct 554 555 b.ReportAllocs() 556 for i := 0; i < b.N; i++ { 557 out.Reset() 558 if err := Encode(&out, &value); err != nil { 559 b.Fatal(err) 560 } 561 } 562 } 563 564 type structSliceElem struct { 565 X uint64 566 Y uint64 567 Z uint64 568 } 569 570 type structPtrSlice []*structSliceElem 571 572 func BenchmarkEncodeStructPtrSlice(b *testing.B) { 573 var out bytes.Buffer 574 value := structPtrSlice{ 575 &structSliceElem{1, 1, 1}, 576 &structSliceElem{2, 2, 2}, 577 &structSliceElem{3, 3, 3}, 578 &structSliceElem{5, 5, 5}, 579 &structSliceElem{6, 6, 6}, 580 &structSliceElem{7, 7, 7}, 581 } 582 583 b.ReportAllocs() 584 for i := 0; i < b.N; i++ { 585 out.Reset() 586 if err := Encode(&out, &value); err != nil { 587 b.Fatal(err) 588 } 589 } 590 }