github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/encoding/binary/binary_test.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package binary
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"math"
    12  	"reflect"
    13  	"strings"
    14  	"sync"
    15  	"testing"
    16  )
    17  
    18  type Struct struct {
    19  	Int8       int8
    20  	Int16      int16
    21  	Int32      int32
    22  	Int64      int64
    23  	Uint8      uint8
    24  	Uint16     uint16
    25  	Uint32     uint32
    26  	Uint64     uint64
    27  	Float32    float32
    28  	Float64    float64
    29  	Complex64  complex64
    30  	Complex128 complex128
    31  	Array      [4]uint8
    32  	Bool       bool
    33  	BoolArray  [4]bool
    34  }
    35  
    36  type T struct {
    37  	Int     int
    38  	Uint    uint
    39  	Uintptr uintptr
    40  	Array   [4]int
    41  }
    42  
    43  var s = Struct{
    44  	0x01,
    45  	0x0203,
    46  	0x04050607,
    47  	0x08090a0b0c0d0e0f,
    48  	0x10,
    49  	0x1112,
    50  	0x13141516,
    51  	0x1718191a1b1c1d1e,
    52  
    53  	math.Float32frombits(0x1f202122),
    54  	math.Float64frombits(0x232425262728292a),
    55  	complex(
    56  		math.Float32frombits(0x2b2c2d2e),
    57  		math.Float32frombits(0x2f303132),
    58  	),
    59  	complex(
    60  		math.Float64frombits(0x333435363738393a),
    61  		math.Float64frombits(0x3b3c3d3e3f404142),
    62  	),
    63  
    64  	[4]uint8{0x43, 0x44, 0x45, 0x46},
    65  
    66  	true,
    67  	[4]bool{true, false, true, false},
    68  }
    69  
    70  var big = []byte{
    71  	1,
    72  	2, 3,
    73  	4, 5, 6, 7,
    74  	8, 9, 10, 11, 12, 13, 14, 15,
    75  	16,
    76  	17, 18,
    77  	19, 20, 21, 22,
    78  	23, 24, 25, 26, 27, 28, 29, 30,
    79  
    80  	31, 32, 33, 34,
    81  	35, 36, 37, 38, 39, 40, 41, 42,
    82  	43, 44, 45, 46, 47, 48, 49, 50,
    83  	51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
    84  
    85  	67, 68, 69, 70,
    86  
    87  	1,
    88  	1, 0, 1, 0,
    89  }
    90  
    91  var little = []byte{
    92  	1,
    93  	3, 2,
    94  	7, 6, 5, 4,
    95  	15, 14, 13, 12, 11, 10, 9, 8,
    96  	16,
    97  	18, 17,
    98  	22, 21, 20, 19,
    99  	30, 29, 28, 27, 26, 25, 24, 23,
   100  
   101  	34, 33, 32, 31,
   102  	42, 41, 40, 39, 38, 37, 36, 35,
   103  	46, 45, 44, 43, 50, 49, 48, 47,
   104  	58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59,
   105  
   106  	67, 68, 69, 70,
   107  
   108  	1,
   109  	1, 0, 1, 0,
   110  }
   111  
   112  var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
   113  var res = []int32{0x01020304, 0x05060708}
   114  var putbuf = []byte{0, 0, 0, 0, 0, 0, 0, 0}
   115  
   116  func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want any) {
   117  	if err != nil {
   118  		t.Errorf("%v %v: %v", dir, order, err)
   119  		return
   120  	}
   121  	if !reflect.DeepEqual(have, want) {
   122  		t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want)
   123  	}
   124  }
   125  
   126  func testRead(t *testing.T, order ByteOrder, b []byte, s1 any) {
   127  	var s2 Struct
   128  	err := Read(bytes.NewReader(b), order, &s2)
   129  	checkResult(t, "Read", order, err, s2, s1)
   130  }
   131  
   132  func testWrite(t *testing.T, order ByteOrder, b []byte, s1 any) {
   133  	buf := new(bytes.Buffer)
   134  	err := Write(buf, order, s1)
   135  	checkResult(t, "Write", order, err, buf.Bytes(), b)
   136  }
   137  
   138  func TestLittleEndianRead(t *testing.T)     { testRead(t, LittleEndian, little, s) }
   139  func TestLittleEndianWrite(t *testing.T)    { testWrite(t, LittleEndian, little, s) }
   140  func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
   141  
   142  func TestBigEndianRead(t *testing.T)     { testRead(t, BigEndian, big, s) }
   143  func TestBigEndianWrite(t *testing.T)    { testWrite(t, BigEndian, big, s) }
   144  func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
   145  
   146  func TestReadSlice(t *testing.T) {
   147  	slice := make([]int32, 2)
   148  	err := Read(bytes.NewReader(src), BigEndian, slice)
   149  	checkResult(t, "ReadSlice", BigEndian, err, slice, res)
   150  }
   151  
   152  func TestWriteSlice(t *testing.T) {
   153  	buf := new(bytes.Buffer)
   154  	err := Write(buf, BigEndian, res)
   155  	checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
   156  }
   157  
   158  func TestReadBool(t *testing.T) {
   159  	var res bool
   160  	var err error
   161  	err = Read(bytes.NewReader([]byte{0}), BigEndian, &res)
   162  	checkResult(t, "ReadBool", BigEndian, err, res, false)
   163  	res = false
   164  	err = Read(bytes.NewReader([]byte{1}), BigEndian, &res)
   165  	checkResult(t, "ReadBool", BigEndian, err, res, true)
   166  	res = false
   167  	err = Read(bytes.NewReader([]byte{2}), BigEndian, &res)
   168  	checkResult(t, "ReadBool", BigEndian, err, res, true)
   169  }
   170  
   171  func TestReadBoolSlice(t *testing.T) {
   172  	slice := make([]bool, 4)
   173  	err := Read(bytes.NewReader([]byte{0, 1, 2, 255}), BigEndian, slice)
   174  	checkResult(t, "ReadBoolSlice", BigEndian, err, slice, []bool{false, true, true, true})
   175  }
   176  
   177  // Addresses of arrays are easier to manipulate with reflection than are slices.
   178  var intArrays = []any{
   179  	&[100]int8{},
   180  	&[100]int16{},
   181  	&[100]int32{},
   182  	&[100]int64{},
   183  	&[100]uint8{},
   184  	&[100]uint16{},
   185  	&[100]uint32{},
   186  	&[100]uint64{},
   187  }
   188  
   189  func TestSliceRoundTrip(t *testing.T) {
   190  	buf := new(bytes.Buffer)
   191  	for _, array := range intArrays {
   192  		src := reflect.ValueOf(array).Elem()
   193  		unsigned := false
   194  		switch src.Index(0).Kind() {
   195  		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   196  			unsigned = true
   197  		}
   198  		for i := 0; i < src.Len(); i++ {
   199  			if unsigned {
   200  				src.Index(i).SetUint(uint64(i * 0x07654321))
   201  			} else {
   202  				src.Index(i).SetInt(int64(i * 0x07654321))
   203  			}
   204  		}
   205  		buf.Reset()
   206  		srcSlice := src.Slice(0, src.Len())
   207  		err := Write(buf, BigEndian, srcSlice.Interface())
   208  		if err != nil {
   209  			t.Fatal(err)
   210  		}
   211  		dst := reflect.New(src.Type()).Elem()
   212  		dstSlice := dst.Slice(0, dst.Len())
   213  		err = Read(buf, BigEndian, dstSlice.Interface())
   214  		if err != nil {
   215  			t.Fatal(err)
   216  		}
   217  		if !reflect.DeepEqual(src.Interface(), dst.Interface()) {
   218  			t.Fatal(src)
   219  		}
   220  	}
   221  }
   222  
   223  func TestWriteT(t *testing.T) {
   224  	buf := new(bytes.Buffer)
   225  	ts := T{}
   226  	if err := Write(buf, BigEndian, ts); err == nil {
   227  		t.Errorf("WriteT: have err == nil, want non-nil")
   228  	}
   229  
   230  	tv := reflect.Indirect(reflect.ValueOf(ts))
   231  	for i, n := 0, tv.NumField(); i < n; i++ {
   232  		typ := tv.Field(i).Type().String()
   233  		if typ == "[4]int" {
   234  			typ = "int" // the problem is int, not the [4]
   235  		}
   236  		if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil {
   237  			t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type())
   238  		} else if !strings.Contains(err.Error(), typ) {
   239  			t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ)
   240  		}
   241  	}
   242  }
   243  
   244  type BlankFields struct {
   245  	A uint32
   246  	_ int32
   247  	B float64
   248  	_ [4]int16
   249  	C byte
   250  	_ [7]byte
   251  	_ struct {
   252  		f [8]float32
   253  	}
   254  }
   255  
   256  type BlankFieldsProbe struct {
   257  	A  uint32
   258  	P0 int32
   259  	B  float64
   260  	P1 [4]int16
   261  	C  byte
   262  	P2 [7]byte
   263  	P3 struct {
   264  		F [8]float32
   265  	}
   266  }
   267  
   268  func TestBlankFields(t *testing.T) {
   269  	buf := new(bytes.Buffer)
   270  	b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42}
   271  	if err := Write(buf, LittleEndian, &b1); err != nil {
   272  		t.Error(err)
   273  	}
   274  
   275  	// zero values must have been written for blank fields
   276  	var p BlankFieldsProbe
   277  	if err := Read(buf, LittleEndian, &p); err != nil {
   278  		t.Error(err)
   279  	}
   280  
   281  	// quick test: only check first value of slices
   282  	if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 {
   283  		t.Errorf("non-zero values for originally blank fields: %#v", p)
   284  	}
   285  
   286  	// write p and see if we can probe only some fields
   287  	if err := Write(buf, LittleEndian, &p); err != nil {
   288  		t.Error(err)
   289  	}
   290  
   291  	// read should ignore blank fields in b2
   292  	var b2 BlankFields
   293  	if err := Read(buf, LittleEndian, &b2); err != nil {
   294  		t.Error(err)
   295  	}
   296  	if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C {
   297  		t.Errorf("%#v != %#v", b1, b2)
   298  	}
   299  }
   300  
   301  func TestSizeStructCache(t *testing.T) {
   302  	// Reset the cache, otherwise multiple test runs fail.
   303  	structSize = sync.Map{}
   304  
   305  	count := func() int {
   306  		var i int
   307  		structSize.Range(func(_, _ any) bool {
   308  			i++
   309  			return true
   310  		})
   311  		return i
   312  	}
   313  
   314  	var total int
   315  	added := func() int {
   316  		delta := count() - total
   317  		total += delta
   318  		return delta
   319  	}
   320  
   321  	type foo struct {
   322  		A uint32
   323  	}
   324  
   325  	type bar struct {
   326  		A Struct
   327  		B foo
   328  		C Struct
   329  	}
   330  
   331  	testcases := []struct {
   332  		val  any
   333  		want int
   334  	}{
   335  		{new(foo), 1},
   336  		{new(bar), 1},
   337  		{new(bar), 0},
   338  		{new(struct{ A Struct }), 1},
   339  		{new(struct{ A Struct }), 0},
   340  	}
   341  
   342  	for _, tc := range testcases {
   343  		if Size(tc.val) == -1 {
   344  			t.Fatalf("Can't get the size of %T", tc.val)
   345  		}
   346  
   347  		if n := added(); n != tc.want {
   348  			t.Errorf("Sizing %T added %d entries to the cache, want %d", tc.val, n, tc.want)
   349  		}
   350  	}
   351  }
   352  
   353  // An attempt to read into a struct with an unexported field will
   354  // panic. This is probably not the best choice, but at this point
   355  // anything else would be an API change.
   356  
   357  type Unexported struct {
   358  	a int32
   359  }
   360  
   361  func TestUnexportedRead(t *testing.T) {
   362  	var buf bytes.Buffer
   363  	u1 := Unexported{a: 1}
   364  	if err := Write(&buf, LittleEndian, &u1); err != nil {
   365  		t.Fatal(err)
   366  	}
   367  
   368  	defer func() {
   369  		if recover() == nil {
   370  			t.Fatal("did not panic")
   371  		}
   372  	}()
   373  	var u2 Unexported
   374  	Read(&buf, LittleEndian, &u2)
   375  }
   376  
   377  func TestReadErrorMsg(t *testing.T) {
   378  	var buf bytes.Buffer
   379  	read := func(data any) {
   380  		err := Read(&buf, LittleEndian, data)
   381  		want := "binary.Read: invalid type " + reflect.TypeOf(data).String()
   382  		if err == nil {
   383  			t.Errorf("%T: got no error; want %q", data, want)
   384  			return
   385  		}
   386  		if got := err.Error(); got != want {
   387  			t.Errorf("%T: got %q; want %q", data, got, want)
   388  		}
   389  	}
   390  	read(0)
   391  	s := new(struct{})
   392  	read(&s)
   393  	p := &s
   394  	read(&p)
   395  }
   396  
   397  func TestReadTruncated(t *testing.T) {
   398  	const data = "0123456789abcdef"
   399  
   400  	var b1 = make([]int32, 4)
   401  	var b2 struct {
   402  		A, B, C, D byte
   403  		E          int32
   404  		F          float64
   405  	}
   406  
   407  	for i := 0; i <= len(data); i++ {
   408  		var errWant error
   409  		switch i {
   410  		case 0:
   411  			errWant = io.EOF
   412  		case len(data):
   413  			errWant = nil
   414  		default:
   415  			errWant = io.ErrUnexpectedEOF
   416  		}
   417  
   418  		if err := Read(strings.NewReader(data[:i]), LittleEndian, &b1); err != errWant {
   419  			t.Errorf("Read(%d) with slice: got %v, want %v", i, err, errWant)
   420  		}
   421  		if err := Read(strings.NewReader(data[:i]), LittleEndian, &b2); err != errWant {
   422  			t.Errorf("Read(%d) with struct: got %v, want %v", i, err, errWant)
   423  		}
   424  	}
   425  }
   426  
   427  func testUint64SmallSliceLengthPanics() (panicked bool) {
   428  	defer func() {
   429  		panicked = recover() != nil
   430  	}()
   431  	b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
   432  	LittleEndian.Uint64(b[:4])
   433  	return false
   434  }
   435  
   436  func testPutUint64SmallSliceLengthPanics() (panicked bool) {
   437  	defer func() {
   438  		panicked = recover() != nil
   439  	}()
   440  	b := [8]byte{}
   441  	LittleEndian.PutUint64(b[:4], 0x0102030405060708)
   442  	return false
   443  }
   444  
   445  func TestByteOrder(t *testing.T) {
   446  	type byteOrder interface {
   447  		ByteOrder
   448  		AppendByteOrder
   449  	}
   450  	buf := make([]byte, 8)
   451  	for _, order := range []byteOrder{LittleEndian, BigEndian} {
   452  		const offset = 3
   453  		for _, value := range []uint64{
   454  			0x0000000000000000,
   455  			0x0123456789abcdef,
   456  			0xfedcba9876543210,
   457  			0xffffffffffffffff,
   458  			0xaaaaaaaaaaaaaaaa,
   459  			math.Float64bits(math.Pi),
   460  			math.Float64bits(math.E),
   461  		} {
   462  			want16 := uint16(value)
   463  			order.PutUint16(buf[:2], want16)
   464  			if got := order.Uint16(buf[:2]); got != want16 {
   465  				t.Errorf("PutUint16: Uint16 = %v, want %v", got, want16)
   466  			}
   467  			buf = order.AppendUint16(buf[:offset], want16)
   468  			if got := order.Uint16(buf[offset:]); got != want16 {
   469  				t.Errorf("AppendUint16: Uint16 = %v, want %v", got, want16)
   470  			}
   471  			if len(buf) != offset+2 {
   472  				t.Errorf("AppendUint16: len(buf) = %d, want %d", len(buf), offset+2)
   473  			}
   474  
   475  			want32 := uint32(value)
   476  			order.PutUint32(buf[:4], want32)
   477  			if got := order.Uint32(buf[:4]); got != want32 {
   478  				t.Errorf("PutUint32: Uint32 = %v, want %v", got, want32)
   479  			}
   480  			buf = order.AppendUint32(buf[:offset], want32)
   481  			if got := order.Uint32(buf[offset:]); got != want32 {
   482  				t.Errorf("AppendUint32: Uint32 = %v, want %v", got, want32)
   483  			}
   484  			if len(buf) != offset+4 {
   485  				t.Errorf("AppendUint32: len(buf) = %d, want %d", len(buf), offset+4)
   486  			}
   487  
   488  			want64 := uint64(value)
   489  			order.PutUint64(buf[:8], want64)
   490  			if got := order.Uint64(buf[:8]); got != want64 {
   491  				t.Errorf("PutUint64: Uint64 = %v, want %v", got, want64)
   492  			}
   493  			buf = order.AppendUint64(buf[:offset], want64)
   494  			if got := order.Uint64(buf[offset:]); got != want64 {
   495  				t.Errorf("AppendUint64: Uint64 = %v, want %v", got, want64)
   496  			}
   497  			if len(buf) != offset+8 {
   498  				t.Errorf("AppendUint64: len(buf) = %d, want %d", len(buf), offset+8)
   499  			}
   500  		}
   501  	}
   502  }
   503  
   504  func TestEarlyBoundsChecks(t *testing.T) {
   505  	if testUint64SmallSliceLengthPanics() != true {
   506  		t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't")
   507  	}
   508  	if testPutUint64SmallSliceLengthPanics() != true {
   509  		t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't")
   510  	}
   511  }
   512  
   513  func TestReadInvalidDestination(t *testing.T) {
   514  	testReadInvalidDestination(t, BigEndian)
   515  	testReadInvalidDestination(t, LittleEndian)
   516  }
   517  
   518  func testReadInvalidDestination(t *testing.T, order ByteOrder) {
   519  	destinations := []any{
   520  		int8(0),
   521  		int16(0),
   522  		int32(0),
   523  		int64(0),
   524  
   525  		uint8(0),
   526  		uint16(0),
   527  		uint32(0),
   528  		uint64(0),
   529  
   530  		bool(false),
   531  	}
   532  
   533  	for _, dst := range destinations {
   534  		err := Read(bytes.NewReader([]byte{1, 2, 3, 4, 5, 6, 7, 8}), order, dst)
   535  		want := fmt.Sprintf("binary.Read: invalid type %T", dst)
   536  		if err == nil || err.Error() != want {
   537  			t.Fatalf("for type %T: got %q; want %q", dst, err, want)
   538  		}
   539  	}
   540  }
   541  
   542  type byteSliceReader struct {
   543  	remain []byte
   544  }
   545  
   546  func (br *byteSliceReader) Read(p []byte) (int, error) {
   547  	n := copy(p, br.remain)
   548  	br.remain = br.remain[n:]
   549  	return n, nil
   550  }
   551  
   552  func BenchmarkReadSlice1000Int32s(b *testing.B) {
   553  	bsr := &byteSliceReader{}
   554  	slice := make([]int32, 1000)
   555  	buf := make([]byte, len(slice)*4)
   556  	b.SetBytes(int64(len(buf)))
   557  	b.ResetTimer()
   558  	for i := 0; i < b.N; i++ {
   559  		bsr.remain = buf
   560  		Read(bsr, BigEndian, slice)
   561  	}
   562  }
   563  
   564  func BenchmarkReadStruct(b *testing.B) {
   565  	bsr := &byteSliceReader{}
   566  	var buf bytes.Buffer
   567  	Write(&buf, BigEndian, &s)
   568  	b.SetBytes(int64(dataSize(reflect.ValueOf(s))))
   569  	t := s
   570  	b.ResetTimer()
   571  	for i := 0; i < b.N; i++ {
   572  		bsr.remain = buf.Bytes()
   573  		Read(bsr, BigEndian, &t)
   574  	}
   575  	b.StopTimer()
   576  	if b.N > 0 && !reflect.DeepEqual(s, t) {
   577  		b.Fatalf("struct doesn't match:\ngot  %v;\nwant %v", t, s)
   578  	}
   579  }
   580  
   581  func BenchmarkWriteStruct(b *testing.B) {
   582  	b.SetBytes(int64(Size(&s)))
   583  	b.ResetTimer()
   584  	for i := 0; i < b.N; i++ {
   585  		Write(io.Discard, BigEndian, &s)
   586  	}
   587  }
   588  
   589  func BenchmarkReadInts(b *testing.B) {
   590  	var ls Struct
   591  	bsr := &byteSliceReader{}
   592  	var r io.Reader = bsr
   593  	b.SetBytes(2 * (1 + 2 + 4 + 8))
   594  	b.ResetTimer()
   595  	for i := 0; i < b.N; i++ {
   596  		bsr.remain = big
   597  		Read(r, BigEndian, &ls.Int8)
   598  		Read(r, BigEndian, &ls.Int16)
   599  		Read(r, BigEndian, &ls.Int32)
   600  		Read(r, BigEndian, &ls.Int64)
   601  		Read(r, BigEndian, &ls.Uint8)
   602  		Read(r, BigEndian, &ls.Uint16)
   603  		Read(r, BigEndian, &ls.Uint32)
   604  		Read(r, BigEndian, &ls.Uint64)
   605  	}
   606  	b.StopTimer()
   607  	want := s
   608  	want.Float32 = 0
   609  	want.Float64 = 0
   610  	want.Complex64 = 0
   611  	want.Complex128 = 0
   612  	want.Array = [4]uint8{0, 0, 0, 0}
   613  	want.Bool = false
   614  	want.BoolArray = [4]bool{false, false, false, false}
   615  	if b.N > 0 && !reflect.DeepEqual(ls, want) {
   616  		b.Fatalf("struct doesn't match:\ngot  %v;\nwant %v", ls, want)
   617  	}
   618  }
   619  
   620  func BenchmarkWriteInts(b *testing.B) {
   621  	buf := new(bytes.Buffer)
   622  	var w io.Writer = buf
   623  	b.SetBytes(2 * (1 + 2 + 4 + 8))
   624  	b.ResetTimer()
   625  	for i := 0; i < b.N; i++ {
   626  		buf.Reset()
   627  		Write(w, BigEndian, s.Int8)
   628  		Write(w, BigEndian, s.Int16)
   629  		Write(w, BigEndian, s.Int32)
   630  		Write(w, BigEndian, s.Int64)
   631  		Write(w, BigEndian, s.Uint8)
   632  		Write(w, BigEndian, s.Uint16)
   633  		Write(w, BigEndian, s.Uint32)
   634  		Write(w, BigEndian, s.Uint64)
   635  	}
   636  	b.StopTimer()
   637  	if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) {
   638  		b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
   639  	}
   640  }
   641  
   642  func BenchmarkWriteSlice1000Int32s(b *testing.B) {
   643  	slice := make([]int32, 1000)
   644  	buf := new(bytes.Buffer)
   645  	var w io.Writer = buf
   646  	b.SetBytes(4 * 1000)
   647  	b.ResetTimer()
   648  	for i := 0; i < b.N; i++ {
   649  		buf.Reset()
   650  		Write(w, BigEndian, slice)
   651  	}
   652  	b.StopTimer()
   653  }
   654  
   655  func BenchmarkPutUint16(b *testing.B) {
   656  	b.SetBytes(2)
   657  	for i := 0; i < b.N; i++ {
   658  		BigEndian.PutUint16(putbuf[:2], uint16(i))
   659  	}
   660  }
   661  
   662  func BenchmarkAppendUint16(b *testing.B) {
   663  	b.SetBytes(2)
   664  	for i := 0; i < b.N; i++ {
   665  		putbuf = BigEndian.AppendUint16(putbuf[:0], uint16(i))
   666  	}
   667  }
   668  
   669  func BenchmarkPutUint32(b *testing.B) {
   670  	b.SetBytes(4)
   671  	for i := 0; i < b.N; i++ {
   672  		BigEndian.PutUint32(putbuf[:4], uint32(i))
   673  	}
   674  }
   675  
   676  func BenchmarkAppendUint32(b *testing.B) {
   677  	b.SetBytes(4)
   678  	for i := 0; i < b.N; i++ {
   679  		putbuf = BigEndian.AppendUint32(putbuf[:0], uint32(i))
   680  	}
   681  }
   682  
   683  func BenchmarkPutUint64(b *testing.B) {
   684  	b.SetBytes(8)
   685  	for i := 0; i < b.N; i++ {
   686  		BigEndian.PutUint64(putbuf[:8], uint64(i))
   687  	}
   688  }
   689  
   690  func BenchmarkAppendUint64(b *testing.B) {
   691  	b.SetBytes(8)
   692  	for i := 0; i < b.N; i++ {
   693  		putbuf = BigEndian.AppendUint64(putbuf[:0], uint64(i))
   694  	}
   695  }
   696  
   697  func BenchmarkLittleEndianPutUint16(b *testing.B) {
   698  	b.SetBytes(2)
   699  	for i := 0; i < b.N; i++ {
   700  		LittleEndian.PutUint16(putbuf[:2], uint16(i))
   701  	}
   702  }
   703  
   704  func BenchmarkLittleEndianAppendUint16(b *testing.B) {
   705  	b.SetBytes(2)
   706  	for i := 0; i < b.N; i++ {
   707  		putbuf = LittleEndian.AppendUint16(putbuf[:0], uint16(i))
   708  	}
   709  }
   710  
   711  func BenchmarkLittleEndianPutUint32(b *testing.B) {
   712  	b.SetBytes(4)
   713  	for i := 0; i < b.N; i++ {
   714  		LittleEndian.PutUint32(putbuf[:4], uint32(i))
   715  	}
   716  }
   717  
   718  func BenchmarkLittleEndianAppendUint32(b *testing.B) {
   719  	b.SetBytes(4)
   720  	for i := 0; i < b.N; i++ {
   721  		putbuf = LittleEndian.AppendUint32(putbuf[:0], uint32(i))
   722  	}
   723  }
   724  
   725  func BenchmarkLittleEndianPutUint64(b *testing.B) {
   726  	b.SetBytes(8)
   727  	for i := 0; i < b.N; i++ {
   728  		LittleEndian.PutUint64(putbuf[:8], uint64(i))
   729  	}
   730  }
   731  
   732  func BenchmarkLittleEndianAppendUint64(b *testing.B) {
   733  	b.SetBytes(8)
   734  	for i := 0; i < b.N; i++ {
   735  		putbuf = LittleEndian.AppendUint64(putbuf[:0], uint64(i))
   736  	}
   737  }
   738  
   739  func BenchmarkReadFloats(b *testing.B) {
   740  	var ls Struct
   741  	bsr := &byteSliceReader{}
   742  	var r io.Reader = bsr
   743  	b.SetBytes(4 + 8)
   744  	b.ResetTimer()
   745  	for i := 0; i < b.N; i++ {
   746  		bsr.remain = big[30:]
   747  		Read(r, BigEndian, &ls.Float32)
   748  		Read(r, BigEndian, &ls.Float64)
   749  	}
   750  	b.StopTimer()
   751  	want := s
   752  	want.Int8 = 0
   753  	want.Int16 = 0
   754  	want.Int32 = 0
   755  	want.Int64 = 0
   756  	want.Uint8 = 0
   757  	want.Uint16 = 0
   758  	want.Uint32 = 0
   759  	want.Uint64 = 0
   760  	want.Complex64 = 0
   761  	want.Complex128 = 0
   762  	want.Array = [4]uint8{0, 0, 0, 0}
   763  	want.Bool = false
   764  	want.BoolArray = [4]bool{false, false, false, false}
   765  	if b.N > 0 && !reflect.DeepEqual(ls, want) {
   766  		b.Fatalf("struct doesn't match:\ngot  %v;\nwant %v", ls, want)
   767  	}
   768  }
   769  
   770  func BenchmarkWriteFloats(b *testing.B) {
   771  	buf := new(bytes.Buffer)
   772  	var w io.Writer = buf
   773  	b.SetBytes(4 + 8)
   774  	b.ResetTimer()
   775  	for i := 0; i < b.N; i++ {
   776  		buf.Reset()
   777  		Write(w, BigEndian, s.Float32)
   778  		Write(w, BigEndian, s.Float64)
   779  	}
   780  	b.StopTimer()
   781  	if b.N > 0 && !bytes.Equal(buf.Bytes(), big[30:30+4+8]) {
   782  		b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[30:30+4+8])
   783  	}
   784  }
   785  
   786  func BenchmarkReadSlice1000Float32s(b *testing.B) {
   787  	bsr := &byteSliceReader{}
   788  	slice := make([]float32, 1000)
   789  	buf := make([]byte, len(slice)*4)
   790  	b.SetBytes(int64(len(buf)))
   791  	b.ResetTimer()
   792  	for i := 0; i < b.N; i++ {
   793  		bsr.remain = buf
   794  		Read(bsr, BigEndian, slice)
   795  	}
   796  }
   797  
   798  func BenchmarkWriteSlice1000Float32s(b *testing.B) {
   799  	slice := make([]float32, 1000)
   800  	buf := new(bytes.Buffer)
   801  	var w io.Writer = buf
   802  	b.SetBytes(4 * 1000)
   803  	b.ResetTimer()
   804  	for i := 0; i < b.N; i++ {
   805  		buf.Reset()
   806  		Write(w, BigEndian, slice)
   807  	}
   808  	b.StopTimer()
   809  }
   810  
   811  func BenchmarkReadSlice1000Uint8s(b *testing.B) {
   812  	bsr := &byteSliceReader{}
   813  	slice := make([]uint8, 1000)
   814  	buf := make([]byte, len(slice))
   815  	b.SetBytes(int64(len(buf)))
   816  	b.ResetTimer()
   817  	for i := 0; i < b.N; i++ {
   818  		bsr.remain = buf
   819  		Read(bsr, BigEndian, slice)
   820  	}
   821  }
   822  
   823  func BenchmarkWriteSlice1000Uint8s(b *testing.B) {
   824  	slice := make([]uint8, 1000)
   825  	buf := new(bytes.Buffer)
   826  	var w io.Writer = buf
   827  	b.SetBytes(1000)
   828  	b.ResetTimer()
   829  	for i := 0; i < b.N; i++ {
   830  		buf.Reset()
   831  		Write(w, BigEndian, slice)
   832  	}
   833  }