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