github.com/gregpr07/bsc@v1.1.2/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  	"io/ioutil"
    25  	"math/big"
    26  	"runtime"
    27  	"sync"
    28  	"testing"
    29  
    30  	"github.com/gregpr07/bsc/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:    big.NewInt(0).SetBytes(unhex("102030405060708090A0B0C0D0E0F2")),
   124  		output: "8F102030405060708090A0B0C0D0E0F2",
   125  	},
   126  	{
   127  		val:    big.NewInt(0).SetBytes(unhex("0100020003000400050006000700080009000A000B000C000D000E01")),
   128  		output: "9C0100020003000400050006000700080009000A000B000C000D000E01",
   129  	},
   130  	{
   131  		val:    big.NewInt(0).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  
   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: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"},
   270  	{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
   271  	{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
   272  	{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
   273  	{val: &hasIgnoredField{A: 1, B: 2, C: 3}, output: "C20103"},
   274  	{val: &intField{X: 3}, error: "rlp: type int is not RLP-serializable (struct field rlp.intField.X)"},
   275  
   276  	// nil
   277  	{val: (*uint)(nil), output: "80"},
   278  	{val: (*string)(nil), output: "80"},
   279  	{val: (*[]byte)(nil), output: "80"},
   280  	{val: (*[10]byte)(nil), output: "80"},
   281  	{val: (*big.Int)(nil), output: "80"},
   282  	{val: (*[]string)(nil), output: "C0"},
   283  	{val: (*[10]string)(nil), output: "C0"},
   284  	{val: (*[]interface{})(nil), output: "C0"},
   285  	{val: (*[]struct{ uint })(nil), output: "C0"},
   286  	{val: (*interface{})(nil), output: "C0"},
   287  
   288  	// nil struct fields
   289  	{
   290  		val: struct {
   291  			X *[]byte
   292  		}{},
   293  		output: "C180",
   294  	},
   295  	{
   296  		val: struct {
   297  			X *[2]byte
   298  		}{},
   299  		output: "C180",
   300  	},
   301  	{
   302  		val: struct {
   303  			X *uint64
   304  		}{},
   305  		output: "C180",
   306  	},
   307  	{
   308  		val: struct {
   309  			X *uint64 `rlp:"nilList"`
   310  		}{},
   311  		output: "C1C0",
   312  	},
   313  	{
   314  		val: struct {
   315  			X *[]uint64
   316  		}{},
   317  		output: "C1C0",
   318  	},
   319  	{
   320  		val: struct {
   321  			X *[]uint64 `rlp:"nilString"`
   322  		}{},
   323  		output: "C180",
   324  	},
   325  
   326  	// interfaces
   327  	{val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct
   328  
   329  	// Encoder
   330  	{val: (*testEncoder)(nil), output: "C0"},
   331  	{val: &testEncoder{}, output: "00010001000100010001"},
   332  	{val: &testEncoder{errors.New("test error")}, error: "test error"},
   333  	{val: struct{ E testEncoderValueMethod }{}, output: "C3FAFEF0"},
   334  	{val: struct{ E *testEncoderValueMethod }{}, output: "C1C0"},
   335  
   336  	// Verify that the Encoder interface works for unsupported types like func().
   337  	{val: undecodableEncoder(func() {}), output: "F5F5F5"},
   338  
   339  	// Verify that pointer method testEncoder.EncodeRLP is called for
   340  	// addressable non-pointer values.
   341  	{val: &struct{ TE testEncoder }{testEncoder{}}, output: "CA00010001000100010001"},
   342  	{val: &struct{ TE testEncoder }{testEncoder{errors.New("test error")}}, error: "test error"},
   343  
   344  	// Verify the error for non-addressable non-pointer Encoder.
   345  	{val: testEncoder{}, error: "rlp: unadressable value of type rlp.testEncoder, EncodeRLP is pointer method"},
   346  
   347  	// Verify Encoder takes precedence over []byte.
   348  	{val: []byteEncoder{0, 1, 2, 3, 4}, output: "C5C0C0C0C0C0"},
   349  }
   350  
   351  func runEncTests(t *testing.T, f func(val interface{}) ([]byte, error)) {
   352  	for i, test := range encTests {
   353  		output, err := f(test.val)
   354  		if err != nil && test.error == "" {
   355  			t.Errorf("test %d: unexpected error: %v\nvalue %#v\ntype %T",
   356  				i, err, test.val, test.val)
   357  			continue
   358  		}
   359  		if test.error != "" && fmt.Sprint(err) != test.error {
   360  			t.Errorf("test %d: error mismatch\ngot   %v\nwant  %v\nvalue %#v\ntype  %T",
   361  				i, err, test.error, test.val, test.val)
   362  			continue
   363  		}
   364  		if err == nil && !bytes.Equal(output, unhex(test.output)) {
   365  			t.Errorf("test %d: output mismatch:\ngot   %X\nwant  %s\nvalue %#v\ntype  %T",
   366  				i, output, test.output, test.val, test.val)
   367  		}
   368  	}
   369  }
   370  
   371  func TestEncode(t *testing.T) {
   372  	runEncTests(t, func(val interface{}) ([]byte, error) {
   373  		b := new(bytes.Buffer)
   374  		err := Encode(b, val)
   375  		return b.Bytes(), err
   376  	})
   377  }
   378  
   379  func TestEncodeToBytes(t *testing.T) {
   380  	runEncTests(t, EncodeToBytes)
   381  }
   382  
   383  func TestEncodeToReader(t *testing.T) {
   384  	runEncTests(t, func(val interface{}) ([]byte, error) {
   385  		_, r, err := EncodeToReader(val)
   386  		if err != nil {
   387  			return nil, err
   388  		}
   389  		return ioutil.ReadAll(r)
   390  	})
   391  }
   392  
   393  func TestEncodeToReaderPiecewise(t *testing.T) {
   394  	runEncTests(t, func(val interface{}) ([]byte, error) {
   395  		size, r, err := EncodeToReader(val)
   396  		if err != nil {
   397  			return nil, err
   398  		}
   399  
   400  		// read output piecewise
   401  		output := make([]byte, size)
   402  		for start, end := 0, 0; start < size; start = end {
   403  			if remaining := size - start; remaining < 3 {
   404  				end += remaining
   405  			} else {
   406  				end = start + 3
   407  			}
   408  			n, err := r.Read(output[start:end])
   409  			end = start + n
   410  			if err == io.EOF {
   411  				break
   412  			} else if err != nil {
   413  				return nil, err
   414  			}
   415  		}
   416  		return output, nil
   417  	})
   418  }
   419  
   420  // This is a regression test verifying that encReader
   421  // returns its encbuf to the pool only once.
   422  func TestEncodeToReaderReturnToPool(t *testing.T) {
   423  	buf := make([]byte, 50)
   424  	wg := new(sync.WaitGroup)
   425  	for i := 0; i < 5; i++ {
   426  		wg.Add(1)
   427  		go func() {
   428  			for i := 0; i < 1000; i++ {
   429  				_, r, _ := EncodeToReader("foo")
   430  				ioutil.ReadAll(r)
   431  				r.Read(buf)
   432  				r.Read(buf)
   433  				r.Read(buf)
   434  				r.Read(buf)
   435  			}
   436  			wg.Done()
   437  		}()
   438  	}
   439  	wg.Wait()
   440  }
   441  
   442  var sink interface{}
   443  
   444  func BenchmarkIntsize(b *testing.B) {
   445  	for i := 0; i < b.N; i++ {
   446  		sink = intsize(0x12345678)
   447  	}
   448  }
   449  
   450  func BenchmarkPutint(b *testing.B) {
   451  	buf := make([]byte, 8)
   452  	for i := 0; i < b.N; i++ {
   453  		putint(buf, 0x12345678)
   454  		sink = buf
   455  	}
   456  }
   457  
   458  func BenchmarkEncodeBigInts(b *testing.B) {
   459  	ints := make([]*big.Int, 200)
   460  	for i := range ints {
   461  		ints[i] = math.BigPow(2, int64(i))
   462  	}
   463  	out := bytes.NewBuffer(make([]byte, 0, 4096))
   464  	b.ResetTimer()
   465  	b.ReportAllocs()
   466  
   467  	for i := 0; i < b.N; i++ {
   468  		out.Reset()
   469  		if err := Encode(out, ints); err != nil {
   470  			b.Fatal(err)
   471  		}
   472  	}
   473  }
   474  
   475  func BenchmarkEncodeConcurrentInterface(b *testing.B) {
   476  	type struct1 struct {
   477  		A string
   478  		B *big.Int
   479  		C [20]byte
   480  	}
   481  	value := []interface{}{
   482  		uint(999),
   483  		&struct1{A: "hello", B: big.NewInt(0xFFFFFFFF)},
   484  		[10]byte{1, 2, 3, 4, 5, 6},
   485  		[]string{"yeah", "yeah", "yeah"},
   486  	}
   487  
   488  	var wg sync.WaitGroup
   489  	for cpu := 0; cpu < runtime.NumCPU(); cpu++ {
   490  		wg.Add(1)
   491  		go func() {
   492  			defer wg.Done()
   493  
   494  			var buffer bytes.Buffer
   495  			for i := 0; i < b.N; i++ {
   496  				buffer.Reset()
   497  				err := Encode(&buffer, value)
   498  				if err != nil {
   499  					panic(err)
   500  				}
   501  			}
   502  		}()
   503  	}
   504  	wg.Wait()
   505  }
   506  
   507  type byteArrayStruct struct {
   508  	A [20]byte
   509  	B [32]byte
   510  	C [32]byte
   511  }
   512  
   513  func BenchmarkEncodeByteArrayStruct(b *testing.B) {
   514  	var out bytes.Buffer
   515  	var value byteArrayStruct
   516  
   517  	b.ReportAllocs()
   518  	for i := 0; i < b.N; i++ {
   519  		out.Reset()
   520  		if err := Encode(&out, &value); err != nil {
   521  			b.Fatal(err)
   522  		}
   523  	}
   524  }