github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/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  	"io"
    10  	"math"
    11  	"reflect"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  type Struct struct {
    17  	Int8       int8
    18  	Int16      int16
    19  	Int32      int32
    20  	Int64      int64
    21  	Uint8      uint8
    22  	Uint16     uint16
    23  	Uint32     uint32
    24  	Uint64     uint64
    25  	Float32    float32
    26  	Float64    float64
    27  	Complex64  complex64
    28  	Complex128 complex128
    29  	Array      [4]uint8
    30  }
    31  
    32  type T struct {
    33  	Int     int
    34  	Uint    uint
    35  	Uintptr uintptr
    36  	Array   [4]int
    37  }
    38  
    39  var s = Struct{
    40  	0x01,
    41  	0x0203,
    42  	0x04050607,
    43  	0x08090a0b0c0d0e0f,
    44  	0x10,
    45  	0x1112,
    46  	0x13141516,
    47  	0x1718191a1b1c1d1e,
    48  
    49  	math.Float32frombits(0x1f202122),
    50  	math.Float64frombits(0x232425262728292a),
    51  	complex(
    52  		math.Float32frombits(0x2b2c2d2e),
    53  		math.Float32frombits(0x2f303132),
    54  	),
    55  	complex(
    56  		math.Float64frombits(0x333435363738393a),
    57  		math.Float64frombits(0x3b3c3d3e3f404142),
    58  	),
    59  
    60  	[4]uint8{0x43, 0x44, 0x45, 0x46},
    61  }
    62  
    63  var big = []byte{
    64  	1,
    65  	2, 3,
    66  	4, 5, 6, 7,
    67  	8, 9, 10, 11, 12, 13, 14, 15,
    68  	16,
    69  	17, 18,
    70  	19, 20, 21, 22,
    71  	23, 24, 25, 26, 27, 28, 29, 30,
    72  
    73  	31, 32, 33, 34,
    74  	35, 36, 37, 38, 39, 40, 41, 42,
    75  	43, 44, 45, 46, 47, 48, 49, 50,
    76  	51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
    77  
    78  	67, 68, 69, 70,
    79  }
    80  
    81  var little = []byte{
    82  	1,
    83  	3, 2,
    84  	7, 6, 5, 4,
    85  	15, 14, 13, 12, 11, 10, 9, 8,
    86  	16,
    87  	18, 17,
    88  	22, 21, 20, 19,
    89  	30, 29, 28, 27, 26, 25, 24, 23,
    90  
    91  	34, 33, 32, 31,
    92  	42, 41, 40, 39, 38, 37, 36, 35,
    93  	46, 45, 44, 43, 50, 49, 48, 47,
    94  	58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59,
    95  
    96  	67, 68, 69, 70,
    97  }
    98  
    99  var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
   100  var res = []int32{0x01020304, 0x05060708}
   101  
   102  func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want interface{}) {
   103  	if err != nil {
   104  		t.Errorf("%v %v: %v", dir, order, err)
   105  		return
   106  	}
   107  	if !reflect.DeepEqual(have, want) {
   108  		t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want)
   109  	}
   110  }
   111  
   112  func testRead(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
   113  	var s2 Struct
   114  	err := Read(bytes.NewBuffer(b), order, &s2)
   115  	checkResult(t, "Read", order, err, s2, s1)
   116  }
   117  
   118  func testWrite(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
   119  	buf := new(bytes.Buffer)
   120  	err := Write(buf, order, s1)
   121  	checkResult(t, "Write", order, err, buf.Bytes(), b)
   122  }
   123  
   124  func TestLittleEndianRead(t *testing.T)     { testRead(t, LittleEndian, little, s) }
   125  func TestLittleEndianWrite(t *testing.T)    { testWrite(t, LittleEndian, little, s) }
   126  func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
   127  
   128  func TestBigEndianRead(t *testing.T)     { testRead(t, BigEndian, big, s) }
   129  func TestBigEndianWrite(t *testing.T)    { testWrite(t, BigEndian, big, s) }
   130  func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
   131  
   132  func TestReadSlice(t *testing.T) {
   133  	slice := make([]int32, 2)
   134  	err := Read(bytes.NewBuffer(src), BigEndian, slice)
   135  	checkResult(t, "ReadSlice", BigEndian, err, slice, res)
   136  }
   137  
   138  func TestWriteSlice(t *testing.T) {
   139  	buf := new(bytes.Buffer)
   140  	err := Write(buf, BigEndian, res)
   141  	checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
   142  }
   143  
   144  func TestWriteT(t *testing.T) {
   145  	buf := new(bytes.Buffer)
   146  	ts := T{}
   147  	if err := Write(buf, BigEndian, ts); err == nil {
   148  		t.Errorf("WriteT: have err == nil, want non-nil")
   149  	}
   150  
   151  	tv := reflect.Indirect(reflect.ValueOf(ts))
   152  	for i, n := 0, tv.NumField(); i < n; i++ {
   153  		typ := tv.Field(i).Type().String()
   154  		if typ == "[4]int" {
   155  			typ = "int" // the problem is int, not the [4]
   156  		}
   157  		if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil {
   158  			t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type())
   159  		} else if !strings.Contains(err.Error(), typ) {
   160  			t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ)
   161  		}
   162  	}
   163  }
   164  
   165  type BlankFields struct {
   166  	A uint32
   167  	_ int32
   168  	B float64
   169  	_ [4]int16
   170  	C byte
   171  	_ [7]byte
   172  	_ struct {
   173  		f [8]float32
   174  	}
   175  }
   176  
   177  type BlankFieldsProbe struct {
   178  	A  uint32
   179  	P0 int32
   180  	B  float64
   181  	P1 [4]int16
   182  	C  byte
   183  	P2 [7]byte
   184  	P3 struct {
   185  		F [8]float32
   186  	}
   187  }
   188  
   189  func TestBlankFields(t *testing.T) {
   190  	buf := new(bytes.Buffer)
   191  	b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42}
   192  	if err := Write(buf, LittleEndian, &b1); err != nil {
   193  		t.Error(err)
   194  	}
   195  
   196  	// zero values must have been written for blank fields
   197  	var p BlankFieldsProbe
   198  	if err := Read(buf, LittleEndian, &p); err != nil {
   199  		t.Error(err)
   200  	}
   201  
   202  	// quick test: only check first value of slices
   203  	if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 {
   204  		t.Errorf("non-zero values for originally blank fields: %#v", p)
   205  	}
   206  
   207  	// write p and see if we can probe only some fields
   208  	if err := Write(buf, LittleEndian, &p); err != nil {
   209  		t.Error(err)
   210  	}
   211  
   212  	// read should ignore blank fields in b2
   213  	var b2 BlankFields
   214  	if err := Read(buf, LittleEndian, &b2); err != nil {
   215  		t.Error(err)
   216  	}
   217  	if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C {
   218  		t.Errorf("%#v != %#v", b1, b2)
   219  	}
   220  }
   221  
   222  type byteSliceReader struct {
   223  	remain []byte
   224  }
   225  
   226  func (br *byteSliceReader) Read(p []byte) (int, error) {
   227  	n := copy(p, br.remain)
   228  	br.remain = br.remain[n:]
   229  	return n, nil
   230  }
   231  
   232  func BenchmarkReadSlice1000Int32s(b *testing.B) {
   233  	bsr := &byteSliceReader{}
   234  	slice := make([]int32, 1000)
   235  	buf := make([]byte, len(slice)*4)
   236  	b.SetBytes(int64(len(buf)))
   237  	b.ResetTimer()
   238  	for i := 0; i < b.N; i++ {
   239  		bsr.remain = buf
   240  		Read(bsr, BigEndian, slice)
   241  	}
   242  }
   243  
   244  func BenchmarkReadStruct(b *testing.B) {
   245  	bsr := &byteSliceReader{}
   246  	var buf bytes.Buffer
   247  	Write(&buf, BigEndian, &s)
   248  	n, _ := dataSize(reflect.ValueOf(s))
   249  	b.SetBytes(int64(n))
   250  	t := s
   251  	b.ResetTimer()
   252  	for i := 0; i < b.N; i++ {
   253  		bsr.remain = buf.Bytes()
   254  		Read(bsr, BigEndian, &t)
   255  	}
   256  	b.StopTimer()
   257  	if !reflect.DeepEqual(s, t) {
   258  		b.Fatal("no match")
   259  	}
   260  }
   261  
   262  func BenchmarkReadInts(b *testing.B) {
   263  	var ls Struct
   264  	bsr := &byteSliceReader{}
   265  	var r io.Reader = bsr
   266  	b.SetBytes(2 * (1 + 2 + 4 + 8))
   267  	b.ResetTimer()
   268  	for i := 0; i < b.N; i++ {
   269  		bsr.remain = big
   270  		Read(r, BigEndian, &ls.Int8)
   271  		Read(r, BigEndian, &ls.Int16)
   272  		Read(r, BigEndian, &ls.Int32)
   273  		Read(r, BigEndian, &ls.Int64)
   274  		Read(r, BigEndian, &ls.Uint8)
   275  		Read(r, BigEndian, &ls.Uint16)
   276  		Read(r, BigEndian, &ls.Uint32)
   277  		Read(r, BigEndian, &ls.Uint64)
   278  	}
   279  
   280  	want := s
   281  	want.Float32 = 0
   282  	want.Float64 = 0
   283  	want.Complex64 = 0
   284  	want.Complex128 = 0
   285  	for i := range want.Array {
   286  		want.Array[i] = 0
   287  	}
   288  	b.StopTimer()
   289  	if !reflect.DeepEqual(ls, want) {
   290  		panic("no match")
   291  	}
   292  }
   293  
   294  func BenchmarkWriteInts(b *testing.B) {
   295  	buf := new(bytes.Buffer)
   296  	var w io.Writer = buf
   297  	b.SetBytes(2 * (1 + 2 + 4 + 8))
   298  	b.ResetTimer()
   299  	for i := 0; i < b.N; i++ {
   300  		buf.Reset()
   301  		Write(w, BigEndian, s.Int8)
   302  		Write(w, BigEndian, s.Int16)
   303  		Write(w, BigEndian, s.Int32)
   304  		Write(w, BigEndian, s.Int64)
   305  		Write(w, BigEndian, s.Uint8)
   306  		Write(w, BigEndian, s.Uint16)
   307  		Write(w, BigEndian, s.Uint32)
   308  		Write(w, BigEndian, s.Uint64)
   309  	}
   310  	b.StopTimer()
   311  	if !bytes.Equal(buf.Bytes(), big[:30]) {
   312  		b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
   313  	}
   314  }