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