github.com/jimmyx0x/go-ethereum@v1.10.28/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 {val: &multipleOptionalFields{A: nil, B: nil}, output: "C0"}, 294 {val: &multipleOptionalFields{A: &[3]byte{1, 2, 3}, B: &[3]byte{1, 2, 3}}, output: "C88301020383010203"}, 295 {val: &multipleOptionalFields{A: nil, B: &[3]byte{1, 2, 3}}, output: "C58083010203"}, // encodes without error but decode will fail 296 {val: &nonOptionalPtrField{A: 1}, output: "C20180"}, // encodes without error but decode will fail 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 var 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 }