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