github.com/core-coin/go-core/v2@v2.1.9/rlp/encode_test.go (about)

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