github.com/klaytn/klaytn@v1.10.2/rlp/encode_test.go (about)

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