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  }