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.
51 math
.Float32frombits(0x1f202122),
52 math
.Float64frombits(0x232425262728292a),
54 math
.Float32frombits(0x2b2c2d2e),
55 math
.Float32frombits(0x2f303132),
58 math
.Float64frombits(0x333435363738393a),
59 math
.Float64frombits(0x3b3c3d3e3f404142),
62 [4]uint8{0x43, 0x44, 0x45, 0x46},
65 [4]bool{true, false, true, false},
72 8, 9, 10, 11, 12, 13, 14, 15,
76 23, 24, 25, 26, 27, 28, 29, 30,
79 35, 36, 37, 38, 39, 40, 41, 42,
80 43, 44, 45, 46, 47, 48, 49, 50,
81 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
93 15, 14, 13, 12, 11, 10, 9, 8,
97 30, 29, 28, 27, 26, 25, 24, 23,
100 42, 41, 40, 39, 38, 37, 36, 35,
101 46, 45, 44, 43, 50, 49, 48, 47,
102 58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59,
110 var src
= []byte{1, 2, 3, 4, 5, 6, 7, 8}
111 var res
= []int32{0x01020304, 0x05060708}
113 func checkResult(t
*testing
.T
, dir
string, order ByteOrder
, err error
, have
, want
interface{}) {
115 t
.Errorf("%v %v: %v", dir
, order
, err
)
118 if !reflect
.DeepEqual(have
, want
) {
119 t
.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir
, order
, have
, want
)
123 func testRead(t
*testing
.T
, order ByteOrder
, b
[]byte, s1
interface{}) {
125 err
:= Read(bytes
.NewReader(b
), order
, &s2
)
126 checkResult(t
, "Read", order
, err
, s2
, s1
)
129 func testWrite(t
*testing
.T
, order ByteOrder
, b
[]byte, s1
interface{}) {
130 buf
:= new(bytes
.Buffer
)
131 err
:= Write(buf
, order
, s1
)
132 checkResult(t
, "Write", order
, err
, buf
.Bytes(), b
)
135 func TestLittleEndianRead(t
*testing
.T
) { testRead(t
, LittleEndian
, little
, s
) }
136 func TestLittleEndianWrite(t
*testing
.T
) { testWrite(t
, LittleEndian
, little
, s
) }
137 func TestLittleEndianPtrWrite(t
*testing
.T
) { testWrite(t
, LittleEndian
, little
, &s
) }
139 func TestBigEndianRead(t
*testing
.T
) { testRead(t
, BigEndian
, big
, s
) }
140 func TestBigEndianWrite(t
*testing
.T
) { testWrite(t
, BigEndian
, big
, s
) }
141 func TestBigEndianPtrWrite(t
*testing
.T
) { testWrite(t
, BigEndian
, big
, &s
) }
143 func TestReadSlice(t
*testing
.T
) {
144 slice
:= make([]int32, 2)
145 err
:= Read(bytes
.NewReader(src
), BigEndian
, slice
)
146 checkResult(t
, "ReadSlice", BigEndian
, err
, slice
, res
)
149 func TestWriteSlice(t
*testing
.T
) {
150 buf
:= new(bytes
.Buffer
)
151 err
:= Write(buf
, BigEndian
, res
)
152 checkResult(t
, "WriteSlice", BigEndian
, err
, buf
.Bytes(), src
)
155 func TestReadBool(t
*testing
.T
) {
158 err
= Read(bytes
.NewReader([]byte{0}), BigEndian
, &res
)
159 checkResult(t
, "ReadBool", BigEndian
, err
, res
, false)
161 err
= Read(bytes
.NewReader([]byte{1}), BigEndian
, &res
)
162 checkResult(t
, "ReadBool", BigEndian
, err
, res
, true)
164 err
= Read(bytes
.NewReader([]byte{2}), BigEndian
, &res
)
165 checkResult(t
, "ReadBool", BigEndian
, err
, res
, true)
168 func TestReadBoolSlice(t
*testing
.T
) {
169 slice
:= make([]bool, 4)
170 err
:= Read(bytes
.NewReader([]byte{0, 1, 2, 255}), BigEndian
, slice
)
171 checkResult(t
, "ReadBoolSlice", BigEndian
, err
, slice
, []bool{false, true, true, true})
174 // Addresses of arrays are easier to manipulate with reflection than are slices.
175 var intArrays
= []interface{}{
186 func TestSliceRoundTrip(t
*testing
.T
) {
187 buf
:= new(bytes
.Buffer
)
188 for _
, array
:= range intArrays
{
189 src
:= reflect
.ValueOf(array
).Elem()
191 switch src
.Index(0).Kind() {
192 case reflect
.Uint8
, reflect
.Uint16
, reflect
.Uint32
, reflect
.Uint64
:
195 for i
:= 0; i
< src
.Len(); i
++ {
197 src
.Index(i
).SetUint(uint64(i
* 0x07654321))
199 src
.Index(i
).SetInt(int64(i
* 0x07654321))
203 srcSlice
:= src
.Slice(0, src
.Len())
204 err
:= Write(buf
, BigEndian
, srcSlice
.Interface())
208 dst
:= reflect
.New(src
.Type()).Elem()
209 dstSlice
:= dst
.Slice(0, dst
.Len())
210 err
= Read(buf
, BigEndian
, dstSlice
.Interface())
214 if !reflect
.DeepEqual(src
.Interface(), dst
.Interface()) {
220 func TestWriteT(t
*testing
.T
) {
221 buf
:= new(bytes
.Buffer
)
223 if err
:= Write(buf
, BigEndian
, ts
); err
== nil {
224 t
.Errorf("WriteT: have err == nil, want non-nil")
227 tv
:= reflect
.Indirect(reflect
.ValueOf(ts
))
228 for i
, n
:= 0, tv
.NumField(); i
< n
; i
++ {
229 typ
:= tv
.Field(i
).Type().String()
231 typ
= "int" // the problem is int, not the [4]
233 if err
:= Write(buf
, BigEndian
, tv
.Field(i
).Interface()); err
== nil {
234 t
.Errorf("WriteT.%v: have err == nil, want non-nil", tv
.Field(i
).Type())
235 } else if !strings
.Contains(err
.Error(), typ
) {
236 t
.Errorf("WriteT: have err == %q, want it to mention %s", err
, typ
)
241 type BlankFields
struct {
253 type BlankFieldsProbe
struct {
265 func TestBlankFields(t
*testing
.T
) {
266 buf
:= new(bytes
.Buffer
)
267 b1
:= BlankFields
{A
: 1234567890, B
: 2.718281828, C
: 42}
268 if err
:= Write(buf
, LittleEndian
, &b1
); err
!= nil {
272 // zero values must have been written for blank fields
273 var p BlankFieldsProbe
274 if err
:= Read(buf
, LittleEndian
, &p
); err
!= nil {
278 // quick test: only check first value of slices
279 if p
.P0
!= 0 || p
.P1
[0] != 0 || p
.P2
[0] != 0 || p
.P3
.F
[0] != 0 {
280 t
.Errorf("non-zero values for originally blank fields: %#v", p
)
283 // write p and see if we can probe only some fields
284 if err
:= Write(buf
, LittleEndian
, &p
); err
!= nil {
288 // read should ignore blank fields in b2
290 if err
:= Read(buf
, LittleEndian
, &b2
); err
!= nil {
293 if b1
.A
!= b2
.A || b1
.B
!= b2
.B || b1
.C
!= b2
.C
{
294 t
.Errorf("%#v != %#v", b1
, b2
)
298 // An attempt to read into a struct with an unexported field will
299 // panic. This is probably not the best choice, but at this point
300 // anything else would be an API change.
302 type Unexported
struct {
306 func TestUnexportedRead(t
*testing
.T
) {
308 u1
:= Unexported
{a
: 1}
309 if err
:= Write(&buf
, LittleEndian
, &u1
); err
!= nil {
314 if recover() == nil {
315 t
.Fatal("did not panic")
319 Read(&buf
, LittleEndian
, &u2
)
322 func TestReadErrorMsg(t
*testing
.T
) {
324 read
:= func(data
interface{}) {
325 err
:= Read(&buf
, LittleEndian
, data
)
326 want
:= "binary.Read: invalid type " + reflect
.TypeOf(data
).String()
328 t
.Errorf("%T: got no error; want %q", data
, want
)
331 if got
:= err
.Error(); got
!= want
{
332 t
.Errorf("%T: got %q; want %q", data
, got
, want
)
342 func TestReadTruncated(t
*testing
.T
) {
343 const data
= "0123456789abcdef"
345 var b1
= make([]int32, 4)
352 for i
:= 0; i
<= len(data
); i
++ {
360 errWant
= io
.ErrUnexpectedEOF
363 if err
:= Read(strings
.NewReader(data
[:i
]), LittleEndian
, &b1
); err
!= errWant
{
364 t
.Errorf("Read(%d) with slice: got %v, want %v", i
, err
, errWant
)
366 if err
:= Read(strings
.NewReader(data
[:i
]), LittleEndian
, &b2
); err
!= errWant
{
367 t
.Errorf("Read(%d) with struct: got %v, want %v", i
, err
, errWant
)
372 func testUint64SmallSliceLengthPanics() (panicked
bool) {
374 panicked
= recover() != nil
376 b
:= [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
377 LittleEndian
.Uint64(b
[:4])
381 func testPutUint64SmallSliceLengthPanics() (panicked
bool) {
383 panicked
= recover() != nil
386 LittleEndian
.PutUint64(b
[:4], 0x0102030405060708)
390 func TestEarlyBoundsChecks(t
*testing
.T
) {
391 if testUint64SmallSliceLengthPanics() != true {
392 t
.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't")
394 if testPutUint64SmallSliceLengthPanics() != true {
395 t
.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't")
399 type byteSliceReader
struct {
403 func (br
*byteSliceReader
) Read(p
[]byte) (int, error
) {
404 n
:= copy(p
, br
.remain
)
405 br
.remain
= br
.remain
[n
:]
409 func BenchmarkReadSlice1000Int32s(b
*testing
.B
) {
410 bsr
:= &byteSliceReader
{}
411 slice
:= make([]int32, 1000)
412 buf
:= make([]byte, len(slice
)*4)
413 b
.SetBytes(int64(len(buf
)))
415 for i
:= 0; i
< b
.N
; i
++ {
417 Read(bsr
, BigEndian
, slice
)
421 func BenchmarkReadStruct(b
*testing
.B
) {
422 bsr
:= &byteSliceReader
{}
424 Write(&buf
, BigEndian
, &s
)
425 b
.SetBytes(int64(dataSize(reflect
.ValueOf(s
))))
428 for i
:= 0; i
< b
.N
; i
++ {
429 bsr
.remain
= buf
.Bytes()
430 Read(bsr
, BigEndian
, &t
)
433 if b
.N
> 0 && !reflect
.DeepEqual(s
, t
) {
434 b
.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t
, s
)
438 func BenchmarkReadInts(b
*testing
.B
) {
440 bsr
:= &byteSliceReader
{}
441 var r io
.Reader
= bsr
442 b
.SetBytes(2 * (1 + 2 + 4 + 8))
444 for i
:= 0; i
< b
.N
; i
++ {
446 Read(r
, BigEndian
, &ls
.Int8
)
447 Read(r
, BigEndian
, &ls
.Int16
)
448 Read(r
, BigEndian
, &ls
.Int32
)
449 Read(r
, BigEndian
, &ls
.Int64
)
450 Read(r
, BigEndian
, &ls
.Uint8
)
451 Read(r
, BigEndian
, &ls
.Uint16
)
452 Read(r
, BigEndian
, &ls
.Uint32
)
453 Read(r
, BigEndian
, &ls
.Uint64
)
461 want
.Array
= [4]uint8{0, 0, 0, 0}
463 want
.BoolArray
= [4]bool{false, false, false, false}
464 if b
.N
> 0 && !reflect
.DeepEqual(ls
, want
) {
465 b
.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls
, want
)
469 func BenchmarkWriteInts(b
*testing
.B
) {
470 buf
:= new(bytes
.Buffer
)
471 var w io
.Writer
= buf
472 b
.SetBytes(2 * (1 + 2 + 4 + 8))
474 for i
:= 0; i
< b
.N
; i
++ {
476 Write(w
, BigEndian
, s
.Int8
)
477 Write(w
, BigEndian
, s
.Int16
)
478 Write(w
, BigEndian
, s
.Int32
)
479 Write(w
, BigEndian
, s
.Int64
)
480 Write(w
, BigEndian
, s
.Uint8
)
481 Write(w
, BigEndian
, s
.Uint16
)
482 Write(w
, BigEndian
, s
.Uint32
)
483 Write(w
, BigEndian
, s
.Uint64
)
486 if b
.N
> 0 && !bytes
.Equal(buf
.Bytes(), big
[:30]) {
487 b
.Fatalf("first half doesn't match: %x %x", buf
.Bytes(), big
[:30])
491 func BenchmarkWriteSlice1000Int32s(b
*testing
.B
) {
492 slice
:= make([]int32, 1000)
493 buf
:= new(bytes
.Buffer
)
494 var w io
.Writer
= buf
497 for i
:= 0; i
< b
.N
; i
++ {
499 Write(w
, BigEndian
, slice
)
504 func BenchmarkPutUint16(b
*testing
.B
) {
507 for i
:= 0; i
< b
.N
; i
++ {
508 BigEndian
.PutUint16(buf
[:], uint16(i
))
512 func BenchmarkPutUint32(b
*testing
.B
) {
515 for i
:= 0; i
< b
.N
; i
++ {
516 BigEndian
.PutUint32(buf
[:], uint32(i
))
520 func BenchmarkPutUint64(b
*testing
.B
) {
523 for i
:= 0; i
< b
.N
; i
++ {
524 BigEndian
.PutUint64(buf
[:], uint64(i
))