github.com/amazechain/amc@v0.1.3/internal/avm/rlp/encode_test.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package rlp
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  	"github.com/amazechain/amc/common/math"
    24  	"io"
    25  	"math/big"
    26  	"sync"
    27  	"testing"
    28  
    29  	"github.com/holiman/uint256"
    30  )
    31  
    32  type testEncoder struct {
    33  	err error
    34  }
    35  
    36  func (e *testEncoder) EncodeRLP(w io.Writer) error {
    37  	if e == nil {
    38  		panic("EncodeRLP called on nil value")
    39  	}
    40  	if e.err != nil {
    41  		return e.err
    42  	}
    43  	if _, err := w.Write([]byte{0, 1, 0, 1, 0, 1, 0, 1, 0, 1}); err != nil {
    44  		return err
    45  	}
    46  	return nil
    47  }
    48  
    49  type testEncoderValueMethod struct{}
    50  
    51  func (e testEncoderValueMethod) EncodeRLP(w io.Writer) error {
    52  	_, err := w.Write([]byte{0xFA, 0xFE, 0xF0})
    53  	return err
    54  }
    55  
    56  type byteEncoder byte
    57  
    58  func (e byteEncoder) EncodeRLP(w io.Writer) error {
    59  	_, err := w.Write(EmptyList)
    60  	return err
    61  }
    62  
    63  type undecodableEncoder func()
    64  
    65  func (f undecodableEncoder) EncodeRLP(w io.Writer) error {
    66  	_, err := w.Write([]byte{0xF5, 0xF5, 0xF5})
    67  	return err
    68  }
    69  
    70  type encodableReader struct {
    71  	A, B uint
    72  }
    73  
    74  func (e *encodableReader) Read(b []byte) (int, error) {
    75  	panic("called")
    76  }
    77  
    78  type namedByteType byte
    79  
    80  var (
    81  	_ = Encoder(&testEncoder{})
    82  	_ = Encoder(byteEncoder(0))
    83  
    84  	reader io.Reader = &encodableReader{1, 2}
    85  )
    86  
    87  type encTest struct {
    88  	val           interface{}
    89  	output, error string
    90  }
    91  
    92  var encTests = []encTest{
    93  	// booleans
    94  	{val: true, output: "01"},
    95  	{val: false, output: "80"},
    96  
    97  	// integers
    98  	{val: uint32(0), output: "80"},
    99  	{val: uint32(127), output: "7F"},
   100  	{val: uint32(128), output: "8180"},
   101  	{val: uint32(256), output: "820100"},
   102  	{val: uint32(1024), output: "820400"},
   103  	{val: uint32(0xFFFFFF), output: "83FFFFFF"},
   104  	{val: uint32(0xFFFFFFFF), output: "84FFFFFFFF"},
   105  	{val: uint64(0xFFFFFFFF), output: "84FFFFFFFF"},
   106  	{val: uint64(0xFFFFFFFFFF), output: "85FFFFFFFFFF"},
   107  	{val: uint64(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"},
   108  	{val: uint64(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"},
   109  	{val: uint64(0xFFFFFFFFFFFFFFFF), output: "88FFFFFFFFFFFFFFFF"},
   110  
   111  	// big integers (should match uint for small values)
   112  	{val: big.NewInt(0), output: "80"},
   113  	{val: big.NewInt(1), output: "01"},
   114  	{val: big.NewInt(127), output: "7F"},
   115  	{val: big.NewInt(128), output: "8180"},
   116  	{val: big.NewInt(256), output: "820100"},
   117  	{val: big.NewInt(1024), output: "820400"},
   118  	{val: big.NewInt(0xFFFFFF), output: "83FFFFFF"},
   119  	{val: big.NewInt(0xFFFFFFFF), output: "84FFFFFFFF"},
   120  	{val: big.NewInt(0xFFFFFFFFFF), output: "85FFFFFFFFFF"},
   121  	{val: big.NewInt(0xFFFFFFFFFFFF), output: "86FFFFFFFFFFFF"},
   122  	{val: big.NewInt(0xFFFFFFFFFFFFFF), output: "87FFFFFFFFFFFFFF"},
   123  	{
   124  		val:    big.NewInt(0).SetBytes(unhex("102030405060708090A0B0C0D0E0F2")),
   125  		output: "8F102030405060708090A0B0C0D0E0F2",
   126  	},
   127  	{
   128  		val:    big.NewInt(0).SetBytes(unhex("0100020003000400050006000700080009000A000B000C000D000E01")),
   129  		output: "9C0100020003000400050006000700080009000A000B000C000D000E01",
   130  	},
   131  	{
   132  		val:    big.NewInt(0).SetBytes(unhex("010000000000000000000000000000000000000000000000000000000000000000")),
   133  		output: "A1010000000000000000000000000000000000000000000000000000000000000000",
   134  	},
   135  	{
   136  		val:    veryBigInt,
   137  		output: "89FFFFFFFFFFFFFFFFFF",
   138  	},
   139  	{
   140  		val:    veryVeryBigInt,
   141  		output: "B848FFFFFFFFFFFFFFFFF800000000000000001BFFFFFFFFFFFFFFFFC8000000000000000045FFFFFFFFFFFFFFFFC800000000000000001BFFFFFFFFFFFFFFFFF8000000000000000001",
   142  	},
   143  
   144  	// non-pointer big.Int
   145  	{val: *big.NewInt(0), output: "80"},
   146  	{val: *big.NewInt(0xFFFFFF), output: "83FFFFFF"},
   147  
   148  	// negative ints are not supported
   149  	{val: big.NewInt(-1), error: "rlp: cannot encode negative *big.Int"},
   150  
   151  	// uint256 integers (should match uint for small values)
   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:    uint256.NewInt(0).SetBytes(unhex("102030405060708090A0B0C0D0E0F2")),
   165  		output: "8F102030405060708090A0B0C0D0E0F2",
   166  	},
   167  	{
   168  		val:    uint256.NewInt(0).SetBytes(unhex("0100020003000400050006000700080009000A000B000C000D000E01")),
   169  		output: "9C0100020003000400050006000700080009000A000B000C000D000E01",
   170  	},
   171  
   172  	// named byte type arrays
   173  	{val: [0]namedByteType{}, output: "80"},
   174  	{val: [1]namedByteType{0}, output: "00"},
   175  	{val: [1]namedByteType{1}, output: "01"},
   176  	{val: [1]namedByteType{0x7F}, output: "7F"},
   177  	{val: [1]namedByteType{0x80}, output: "8180"},
   178  	{val: [1]namedByteType{0xFF}, output: "81FF"},
   179  	{val: [3]namedByteType{1, 2, 3}, output: "83010203"},
   180  	{val: [57]namedByteType{1, 2, 3}, output: "B839010203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},
   181  
   182  	// byte slices
   183  	{val: []byte{}, output: "80"},
   184  	{val: []byte{0}, output: "00"},
   185  	{val: []byte{0x7E}, output: "7E"},
   186  	{val: []byte{0x7F}, output: "7F"},
   187  	{val: []byte{0x80}, output: "8180"},
   188  	{val: []byte{1, 2, 3}, output: "83010203"},
   189  
   190  	// named byte type slices
   191  	{val: []namedByteType{}, output: "80"},
   192  	{val: []namedByteType{0}, output: "00"},
   193  	{val: []namedByteType{0x7E}, output: "7E"},
   194  	{val: []namedByteType{0x7F}, output: "7F"},
   195  	{val: []namedByteType{0x80}, output: "8180"},
   196  	{val: []namedByteType{1, 2, 3}, output: "83010203"},
   197  
   198  	// strings
   199  	{val: "", output: "80"},
   200  	{val: "\x7E", output: "7E"},
   201  	{val: "\x7F", output: "7F"},
   202  	{val: "\x80", output: "8180"},
   203  	{val: "dog", output: "83646F67"},
   204  	{
   205  		val:    "Lorem ipsum dolor sit amet, consectetur adipisicing eli",
   206  		output: "B74C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C69",
   207  	},
   208  	{
   209  		val:    "Lorem ipsum dolor sit amet, consectetur adipisicing elit",
   210  		output: "B8384C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E7365637465747572206164697069736963696E6720656C6974",
   211  	},
   212  	{
   213  		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",
   214  		output: "B904004C6F72656D20697073756D20646F6C6F722073697420616D65742C20636F6E73656374657475722061646970697363696E6720656C69742E20437572616269747572206D6175726973206D61676E612C20737573636970697420736564207665686963756C61206E6F6E2C20696163756C697320666175636962757320746F72746F722E2050726F696E20737573636970697420756C74726963696573206D616C6573756164612E204475697320746F72746F7220656C69742C2064696374756D2071756973207472697374697175652065752C20756C7472696365732061742072697375732E204D6F72626920612065737420696D70657264696574206D6920756C6C616D636F7270657220616C6971756574207375736369706974206E6563206C6F72656D2E2041656E65616E2071756973206C656F206D6F6C6C69732C2076756C70757461746520656C6974207661726975732C20636F6E73657175617420656E696D2E204E756C6C6120756C74726963657320747572706973206A7573746F2C20657420706F73756572652075726E6120636F6E7365637465747572206E65632E2050726F696E206E6F6E20636F6E76616C6C6973206D657475732E20446F6E65632074656D706F7220697073756D20696E206D617572697320636F6E67756520736F6C6C696369747564696E2E20566573746962756C756D20616E746520697073756D207072696D697320696E206661756369627573206F726369206C756374757320657420756C74726963657320706F737565726520637562696C69612043757261653B2053757370656E646973736520636F6E76616C6C69732073656D2076656C206D617373612066617563696275732C2065676574206C6163696E6961206C616375732074656D706F722E204E756C6C61207175697320756C747269636965732070757275732E2050726F696E20617563746F722072686F6E637573206E69626820636F6E64696D656E74756D206D6F6C6C69732E20416C697175616D20636F6E73657175617420656E696D206174206D65747573206C75637475732C206120656C656966656E6420707572757320656765737461732E20437572616269747572206174206E696268206D657475732E204E616D20626962656E64756D2C206E6571756520617420617563746F72207472697374697175652C206C6F72656D206C696265726F20616C697175657420617263752C206E6F6E20696E74657264756D2074656C6C7573206C65637475732073697420616D65742065726F732E20437261732072686F6E6375732C206D65747573206163206F726E617265206375727375732C20646F6C6F72206A7573746F20756C747269636573206D657475732C20617420756C6C616D636F7270657220766F6C7574706174",
   215  	},
   216  
   217  	// slices
   218  	{val: []uint{}, output: "C0"},
   219  	{val: []uint{1, 2, 3}, output: "C3010203"},
   220  	{
   221  		// [ [], [[]], [ [], [[]] ] ]
   222  		val:    []interface{}{[]interface{}{}, [][]interface{}{{}}, []interface{}{[]interface{}{}, [][]interface{}{{}}}},
   223  		output: "C7C0C1C0C3C0C1C0",
   224  	},
   225  	{
   226  		val:    []string{"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo"},
   227  		output: "F83C836161618362626283636363836464648365656583666666836767678368686883696969836A6A6A836B6B6B836C6C6C836D6D6D836E6E6E836F6F6F",
   228  	},
   229  	{
   230  		val:    []interface{}{uint(1), uint(0xFFFFFF), []interface{}{[]uint{4, 5, 5}}, "abc"},
   231  		output: "CE0183FFFFFFC4C304050583616263",
   232  	},
   233  	{
   234  		val: [][]string{
   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  			{"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  		},
   268  		output: "F90200CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376CF84617364668471776572847A786376",
   269  	},
   270  
   271  	// RawValue
   272  	{val: RawValue(unhex("01")), output: "01"},
   273  	{val: RawValue(unhex("82FFFF")), output: "82FFFF"},
   274  	{val: []RawValue{unhex("01"), unhex("02")}, output: "C20102"},
   275  
   276  	// structs
   277  	{val: simplestruct{}, output: "C28080"},
   278  	{val: simplestruct{A: 3, B: "foo"}, output: "C50383666F6F"},
   279  	{val: &recstruct{5, nil}, output: "C205C0"},
   280  	{val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"},
   281  	{val: &intField{X: 3}, error: "rlp: type int is not RLP-serializable (struct field rlp.intField.X)"},
   282  
   283  	// struct tag "-"
   284  	{val: &ignoredField{A: 1, B: 2, C: 3}, output: "C20103"},
   285  
   286  	// struct tag "tail"
   287  	{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02"), unhex("03")}}, output: "C3010203"},
   288  	{val: &tailRaw{A: 1, Tail: []RawValue{unhex("02")}}, output: "C20102"},
   289  	{val: &tailRaw{A: 1, Tail: []RawValue{}}, output: "C101"},
   290  	{val: &tailRaw{A: 1, Tail: nil}, output: "C101"},
   291  
   292  	// struct tag "optional"
   293  	{val: &optionalFields{}, output: "C180"},
   294  	{val: &optionalFields{A: 1}, output: "C101"},
   295  	{val: &optionalFields{A: 1, B: 2}, output: "C20102"},
   296  	{val: &optionalFields{A: 1, B: 2, C: 3}, output: "C3010203"},
   297  	{val: &optionalFields{A: 1, B: 0, C: 3}, output: "C3018003"},
   298  	{val: &optionalAndTailField{A: 1}, output: "C101"},
   299  	{val: &optionalAndTailField{A: 1, B: 2}, output: "C20102"},
   300  	{val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"},
   301  	{val: &optionalAndTailField{A: 1, Tail: []uint{5, 6}}, output: "C401800506"},
   302  	{val: &optionalBigIntField{A: 1}, output: "C101"},
   303  	{val: &optionalPtrField{A: 1}, output: "C101"},
   304  	{val: &optionalPtrFieldNil{A: 1}, output: "C101"},
   305  
   306  	// nil
   307  	{val: (*uint)(nil), output: "80"},
   308  	{val: (*string)(nil), output: "80"},
   309  	{val: (*[]byte)(nil), output: "80"},
   310  	{val: (*[10]byte)(nil), output: "80"},
   311  	{val: (*big.Int)(nil), output: "80"},
   312  	{val: (*uint256.Int)(nil), output: "80"},
   313  	{val: (*[]string)(nil), output: "C0"},
   314  	{val: (*[10]string)(nil), output: "C0"},
   315  	{val: (*[]interface{})(nil), output: "C0"},
   316  	{val: (*[]struct{ uint })(nil), output: "C0"},
   317  	{val: (*interface{})(nil), output: "C0"},
   318  
   319  	// nil struct fields
   320  	{
   321  		val: struct {
   322  			X *[]byte
   323  		}{},
   324  		output: "C180",
   325  	},
   326  	{
   327  		val: struct {
   328  			X *[2]byte
   329  		}{},
   330  		output: "C180",
   331  	},
   332  	{
   333  		val: struct {
   334  			X *uint64
   335  		}{},
   336  		output: "C180",
   337  	},
   338  	{
   339  		val: struct {
   340  			X *uint64 `rlp:"nilList"`
   341  		}{},
   342  		output: "C1C0",
   343  	},
   344  	{
   345  		val: struct {
   346  			X *[]uint64
   347  		}{},
   348  		output: "C1C0",
   349  	},
   350  	{
   351  		val: struct {
   352  			X *[]uint64 `rlp:"nilString"`
   353  		}{},
   354  		output: "C180",
   355  	},
   356  
   357  	// interfaces
   358  	{val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct
   359  
   360  	// Encoder
   361  	{val: (*testEncoder)(nil), output: "C0"},
   362  	{val: &testEncoder{}, output: "00010001000100010001"},
   363  	{val: &testEncoder{errors.New("test error")}, error: "test error"},
   364  	{val: struct{ E testEncoderValueMethod }{}, output: "C3FAFEF0"},
   365  	{val: struct{ E *testEncoderValueMethod }{}, output: "C1C0"},
   366  
   367  	// Verify that the Encoder interface works for unsupported types like func().
   368  	{val: undecodableEncoder(func() {}), output: "F5F5F5"},
   369  
   370  	// Verify that pointer method testEncoder.EncodeRLP is called for
   371  	// addressable non-pointer values.
   372  	{val: &struct{ TE testEncoder }{testEncoder{}}, output: "CA00010001000100010001"},
   373  	{val: &struct{ TE testEncoder }{testEncoder{errors.New("test error")}}, error: "test error"},
   374  
   375  	// Verify the error for non-addressable non-pointer Encoder.
   376  	{val: testEncoder{}, error: "rlp: unadressable value of type rlp.testEncoder, EncodeRLP is pointer method"},
   377  
   378  	// Verify Encoder takes precedence over []byte.
   379  	{val: []byteEncoder{0, 1, 2, 3, 4}, output: "C5C0C0C0C0C0"},
   380  }
   381  
   382  func runEncTests(t *testing.T, f func(val interface{}) ([]byte, error)) {
   383  	for i, test := range encTests {
   384  		output, err := f(test.val)
   385  		if err != nil && test.error == "" {
   386  			t.Errorf("test %d: unexpected error: %v\nvalue %#v\ntype %T",
   387  				i, err, test.val, test.val)
   388  			continue
   389  		}
   390  		if test.error != "" && fmt.Sprint(err) != test.error {
   391  			t.Errorf("test %d: error mismatch\ngot   %v\nwant  %v\nvalue %#v\ntype  %T",
   392  				i, err, test.error, test.val, test.val)
   393  			continue
   394  		}
   395  		if err == nil && !bytes.Equal(output, unhex(test.output)) {
   396  			t.Errorf("test %d: output mismatch:\ngot   %X\nwant  %s\nvalue %#v\ntype  %T",
   397  				i, output, test.output, test.val, test.val)
   398  		}
   399  	}
   400  }
   401  
   402  func TestEncode(t *testing.T) {
   403  	runEncTests(t, func(val interface{}) ([]byte, error) {
   404  		b := new(bytes.Buffer)
   405  		err := Encode(b, val)
   406  		return b.Bytes(), err
   407  	})
   408  }
   409  
   410  func TestEncodeToBytes(t *testing.T) {
   411  	runEncTests(t, EncodeToBytes)
   412  }
   413  
   414  func TestEncodeToReader(t *testing.T) {
   415  	runEncTests(t, func(val interface{}) ([]byte, error) {
   416  		_, r, err := EncodeToReader(val)
   417  		if err != nil {
   418  			return nil, err
   419  		}
   420  		return io.ReadAll(r)
   421  	})
   422  }
   423  
   424  func TestEncodeToReaderPiecewise(t *testing.T) {
   425  	runEncTests(t, func(val interface{}) ([]byte, error) {
   426  		size, r, err := EncodeToReader(val)
   427  		if err != nil {
   428  			return nil, err
   429  		}
   430  
   431  		// read output piecewise
   432  		output := make([]byte, size)
   433  		for start, end := 0, 0; start < size; start = end {
   434  			if remaining := size - start; remaining < 3 {
   435  				end += remaining
   436  			} else {
   437  				end = start + 3
   438  			}
   439  			n, err := r.Read(output[start:end])
   440  			end = start + n
   441  			if errors.Is(err, io.EOF) {
   442  				break
   443  			} else if err != nil {
   444  				return nil, err
   445  			}
   446  		}
   447  		return output, nil
   448  	})
   449  }
   450  
   451  // This is a regression test verifying that encReader
   452  // returns its encbuf to the pool only once.
   453  func TestEncodeToReaderReturnToPool(t *testing.T) {
   454  	buf := make([]byte, 50)
   455  	wg := new(sync.WaitGroup)
   456  	for i := 0; i < 5; i++ {
   457  		wg.Add(1)
   458  		go func() {
   459  			for i := 0; i < 1000; i++ {
   460  				_, r, _ := EncodeToReader("foo")
   461  				io.ReadAll(r)
   462  				r.Read(buf)
   463  				r.Read(buf)
   464  				r.Read(buf)
   465  				r.Read(buf)
   466  			}
   467  			wg.Done()
   468  		}()
   469  	}
   470  	wg.Wait()
   471  }
   472  
   473  var sink interface{}
   474  
   475  func BenchmarkIntsize(b *testing.B) {
   476  	for i := 0; i < b.N; i++ {
   477  		sink = intsize(0x12345678)
   478  	}
   479  }
   480  
   481  func BenchmarkPutint(b *testing.B) {
   482  	buf := make([]byte, 8)
   483  	for i := 0; i < b.N; i++ {
   484  		putint(buf, 0x12345678)
   485  		sink = buf
   486  	}
   487  }
   488  
   489  func BenchmarkEncodeBigInts(b *testing.B) {
   490  	ints := make([]*big.Int, 200)
   491  	for i := range ints {
   492  		ints[i] = math.BigPow(2, int64(i))
   493  	}
   494  	out := bytes.NewBuffer(make([]byte, 0, 4096))
   495  	b.ResetTimer()
   496  	b.ReportAllocs()
   497  
   498  	for i := 0; i < b.N; i++ {
   499  		out.Reset()
   500  		if err := Encode(out, ints); err != nil {
   501  			b.Fatal(err)
   502  		}
   503  	}
   504  }