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