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