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}
112 var putbuf
= []byte{0, 0, 0, 0, 0, 0, 0, 0}
114 func checkResult(t
*testing
.T
, dir
string, order ByteOrder
, err error
, have
, want
interface{}) {
116 t
.Errorf("%v %v: %v", dir
, order
, err
)
119 if !reflect
.DeepEqual(have
, want
) {
120 t
.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir
, order
, have
, want
)
124 func testRead(t
*testing
.T
, order ByteOrder
, b
[]byte, s1
interface{}) {
126 err
:= Read(bytes
.NewReader(b
), order
, &s2
)
127 checkResult(t
, "Read", order
, err
, s2
, s1
)
130 func testWrite(t
*testing
.T
, order ByteOrder
, b
[]byte, s1
interface{}) {
131 buf
:= new(bytes
.Buffer
)
132 err
:= Write(buf
, order
, s1
)
133 checkResult(t
, "Write", order
, err
, buf
.Bytes(), b
)
136 func TestLittleEndianRead(t
*testing
.T
) { testRead(t
, LittleEndian
, little
, s
) }
137 func TestLittleEndianWrite(t
*testing
.T
) { testWrite(t
, LittleEndian
, little
, s
) }
138 func TestLittleEndianPtrWrite(t
*testing
.T
) { testWrite(t
, LittleEndian
, little
, &s
) }
140 func TestBigEndianRead(t
*testing
.T
) { testRead(t
, BigEndian
, big
, s
) }
141 func TestBigEndianWrite(t
*testing
.T
) { testWrite(t
, BigEndian
, big
, s
) }
142 func TestBigEndianPtrWrite(t
*testing
.T
) { testWrite(t
, BigEndian
, big
, &s
) }
144 func TestReadSlice(t
*testing
.T
) {
145 slice
:= make([]int32, 2)
146 err
:= Read(bytes
.NewReader(src
), BigEndian
, slice
)
147 checkResult(t
, "ReadSlice", BigEndian
, err
, slice
, res
)
150 func TestWriteSlice(t
*testing
.T
) {
151 buf
:= new(bytes
.Buffer
)
152 err
:= Write(buf
, BigEndian
, res
)
153 checkResult(t
, "WriteSlice", BigEndian
, err
, buf
.Bytes(), src
)
156 func TestReadBool(t
*testing
.T
) {
159 err
= Read(bytes
.NewReader([]byte{0}), BigEndian
, &res
)
160 checkResult(t
, "ReadBool", BigEndian
, err
, res
, false)
162 err
= Read(bytes
.NewReader([]byte{1}), BigEndian
, &res
)
163 checkResult(t
, "ReadBool", BigEndian
, err
, res
, true)
165 err
= Read(bytes
.NewReader([]byte{2}), BigEndian
, &res
)
166 checkResult(t
, "ReadBool", BigEndian
, err
, res
, true)
169 func TestReadBoolSlice(t
*testing
.T
) {
170 slice
:= make([]bool, 4)
171 err
:= Read(bytes
.NewReader([]byte{0, 1, 2, 255}), BigEndian
, slice
)
172 checkResult(t
, "ReadBoolSlice", BigEndian
, err
, slice
, []bool{false, true, true, true})
175 // Addresses of arrays are easier to manipulate with reflection than are slices.
176 var intArrays
= []interface{}{
187 func TestSliceRoundTrip(t
*testing
.T
) {
188 buf
:= new(bytes
.Buffer
)
189 for _
, array
:= range intArrays
{
190 src
:= reflect
.ValueOf(array
).Elem()
192 switch src
.Index(0).Kind() {
193 case reflect
.Uint8
, reflect
.Uint16
, reflect
.Uint32
, reflect
.Uint64
:
196 for i
:= 0; i
< src
.Len(); i
++ {
198 src
.Index(i
).SetUint(uint64(i
* 0x07654321))
200 src
.Index(i
).SetInt(int64(i
* 0x07654321))
204 srcSlice
:= src
.Slice(0, src
.Len())
205 err
:= Write(buf
, BigEndian
, srcSlice
.Interface())
209 dst
:= reflect
.New(src
.Type()).Elem()
210 dstSlice
:= dst
.Slice(0, dst
.Len())
211 err
= Read(buf
, BigEndian
, dstSlice
.Interface())
215 if !reflect
.DeepEqual(src
.Interface(), dst
.Interface()) {
221 func TestWriteT(t
*testing
.T
) {
222 buf
:= new(bytes
.Buffer
)
224 if err
:= Write(buf
, BigEndian
, ts
); err
== nil {
225 t
.Errorf("WriteT: have err == nil, want non-nil")
228 tv
:= reflect
.Indirect(reflect
.ValueOf(ts
))
229 for i
, n
:= 0, tv
.NumField(); i
< n
; i
++ {
230 typ
:= tv
.Field(i
).Type().String()
232 typ
= "int" // the problem is int, not the [4]
234 if err
:= Write(buf
, BigEndian
, tv
.Field(i
).Interface()); err
== nil {
235 t
.Errorf("WriteT.%v: have err == nil, want non-nil", tv
.Field(i
).Type())
236 } else if !strings
.Contains(err
.Error(), typ
) {
237 t
.Errorf("WriteT: have err == %q, want it to mention %s", err
, typ
)
242 type BlankFields
struct {
254 type BlankFieldsProbe
struct {
266 func TestBlankFields(t
*testing
.T
) {
267 buf
:= new(bytes
.Buffer
)
268 b1
:= BlankFields
{A
: 1234567890, B
: 2.718281828, C
: 42}
269 if err
:= Write(buf
, LittleEndian
, &b1
); err
!= nil {
273 // zero values must have been written for blank fields
274 var p BlankFieldsProbe
275 if err
:= Read(buf
, LittleEndian
, &p
); err
!= nil {
279 // quick test: only check first value of slices
280 if p
.P0
!= 0 || p
.P1
[0] != 0 || p
.P2
[0] != 0 || p
.P3
.F
[0] != 0 {
281 t
.Errorf("non-zero values for originally blank fields: %#v", p
)
284 // write p and see if we can probe only some fields
285 if err
:= Write(buf
, LittleEndian
, &p
); err
!= nil {
289 // read should ignore blank fields in b2
291 if err
:= Read(buf
, LittleEndian
, &b2
); err
!= nil {
294 if b1
.A
!= b2
.A || b1
.B
!= b2
.B || b1
.C
!= b2
.C
{
295 t
.Errorf("%#v != %#v", b1
, b2
)
299 // An attempt to read into a struct with an unexported field will
300 // panic. This is probably not the best choice, but at this point
301 // anything else would be an API change.
303 type Unexported
struct {
307 func TestUnexportedRead(t
*testing
.T
) {
309 u1
:= Unexported
{a
: 1}
310 if err
:= Write(&buf
, LittleEndian
, &u1
); err
!= nil {
315 if recover() == nil {
316 t
.Fatal("did not panic")
320 Read(&buf
, LittleEndian
, &u2
)
323 func TestReadErrorMsg(t
*testing
.T
) {
325 read
:= func(data
interface{}) {
326 err
:= Read(&buf
, LittleEndian
, data
)
327 want
:= "binary.Read: invalid type " + reflect
.TypeOf(data
).String()
329 t
.Errorf("%T: got no error; want %q", data
, want
)
332 if got
:= err
.Error(); got
!= want
{
333 t
.Errorf("%T: got %q; want %q", data
, got
, want
)
343 func TestReadTruncated(t
*testing
.T
) {
344 const data
= "0123456789abcdef"
346 var b1
= make([]int32, 4)
353 for i
:= 0; i
<= len(data
); i
++ {
361 errWant
= io
.ErrUnexpectedEOF
364 if err
:= Read(strings
.NewReader(data
[:i
]), LittleEndian
, &b1
); err
!= errWant
{
365 t
.Errorf("Read(%d) with slice: got %v, want %v", i
, err
, errWant
)
367 if err
:= Read(strings
.NewReader(data
[:i
]), LittleEndian
, &b2
); err
!= errWant
{
368 t
.Errorf("Read(%d) with struct: got %v, want %v", i
, err
, errWant
)
373 func testUint64SmallSliceLengthPanics() (panicked
bool) {
375 panicked
= recover() != nil
377 b
:= [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
378 LittleEndian
.Uint64(b
[:4])
382 func testPutUint64SmallSliceLengthPanics() (panicked
bool) {
384 panicked
= recover() != nil
387 LittleEndian
.PutUint64(b
[:4], 0x0102030405060708)
391 func TestEarlyBoundsChecks(t
*testing
.T
) {
392 if testUint64SmallSliceLengthPanics() != true {
393 t
.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't")
395 if testPutUint64SmallSliceLengthPanics() != true {
396 t
.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't")
400 type byteSliceReader
struct {
404 func (br
*byteSliceReader
) Read(p
[]byte) (int, error
) {
405 n
:= copy(p
, br
.remain
)
406 br
.remain
= br
.remain
[n
:]
410 func BenchmarkReadSlice1000Int32s(b
*testing
.B
) {
411 bsr
:= &byteSliceReader
{}
412 slice
:= make([]int32, 1000)
413 buf
:= make([]byte, len(slice
)*4)
414 b
.SetBytes(int64(len(buf
)))
416 for i
:= 0; i
< b
.N
; i
++ {
418 Read(bsr
, BigEndian
, slice
)
422 func BenchmarkReadStruct(b
*testing
.B
) {
423 bsr
:= &byteSliceReader
{}
425 Write(&buf
, BigEndian
, &s
)
426 b
.SetBytes(int64(dataSize(reflect
.ValueOf(s
))))
429 for i
:= 0; i
< b
.N
; i
++ {
430 bsr
.remain
= buf
.Bytes()
431 Read(bsr
, BigEndian
, &t
)
434 if b
.N
> 0 && !reflect
.DeepEqual(s
, t
) {
435 b
.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t
, s
)
439 func BenchmarkReadInts(b
*testing
.B
) {
441 bsr
:= &byteSliceReader
{}
442 var r io
.Reader
= bsr
443 b
.SetBytes(2 * (1 + 2 + 4 + 8))
445 for i
:= 0; i
< b
.N
; i
++ {
447 Read(r
, BigEndian
, &ls
.Int8
)
448 Read(r
, BigEndian
, &ls
.Int16
)
449 Read(r
, BigEndian
, &ls
.Int32
)
450 Read(r
, BigEndian
, &ls
.Int64
)
451 Read(r
, BigEndian
, &ls
.Uint8
)
452 Read(r
, BigEndian
, &ls
.Uint16
)
453 Read(r
, BigEndian
, &ls
.Uint32
)
454 Read(r
, BigEndian
, &ls
.Uint64
)
462 want
.Array
= [4]uint8{0, 0, 0, 0}
464 want
.BoolArray
= [4]bool{false, false, false, false}
465 if b
.N
> 0 && !reflect
.DeepEqual(ls
, want
) {
466 b
.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls
, want
)
470 func BenchmarkWriteInts(b
*testing
.B
) {
471 buf
:= new(bytes
.Buffer
)
472 var w io
.Writer
= buf
473 b
.SetBytes(2 * (1 + 2 + 4 + 8))
475 for i
:= 0; i
< b
.N
; i
++ {
477 Write(w
, BigEndian
, s
.Int8
)
478 Write(w
, BigEndian
, s
.Int16
)
479 Write(w
, BigEndian
, s
.Int32
)
480 Write(w
, BigEndian
, s
.Int64
)
481 Write(w
, BigEndian
, s
.Uint8
)
482 Write(w
, BigEndian
, s
.Uint16
)
483 Write(w
, BigEndian
, s
.Uint32
)
484 Write(w
, BigEndian
, s
.Uint64
)
487 if b
.N
> 0 && !bytes
.Equal(buf
.Bytes(), big
[:30]) {
488 b
.Fatalf("first half doesn't match: %x %x", buf
.Bytes(), big
[:30])
492 func BenchmarkWriteSlice1000Int32s(b
*testing
.B
) {
493 slice
:= make([]int32, 1000)
494 buf
:= new(bytes
.Buffer
)
495 var w io
.Writer
= buf
498 for i
:= 0; i
< b
.N
; i
++ {
500 Write(w
, BigEndian
, slice
)
505 func BenchmarkPutUint16(b
*testing
.B
) {
507 for i
:= 0; i
< b
.N
; i
++ {
508 BigEndian
.PutUint16(putbuf
[:], uint16(i
))
512 func BenchmarkPutUint32(b
*testing
.B
) {
514 for i
:= 0; i
< b
.N
; i
++ {
515 BigEndian
.PutUint32(putbuf
[:], uint32(i
))
519 func BenchmarkPutUint64(b
*testing
.B
) {
521 for i
:= 0; i
< b
.N
; i
++ {
522 BigEndian
.PutUint64(putbuf
[:], uint64(i
))
525 func BenchmarkLittleEndianPutUint16(b
*testing
.B
) {
527 for i
:= 0; i
< b
.N
; i
++ {
528 LittleEndian
.PutUint16(putbuf
[:], uint16(i
))
532 func BenchmarkLittleEndianPutUint32(b
*testing
.B
) {
534 for i
:= 0; i
< b
.N
; i
++ {
535 LittleEndian
.PutUint32(putbuf
[:], uint32(i
))
539 func BenchmarkLittleEndianPutUint64(b
*testing
.B
) {
541 for i
:= 0; i
< b
.N
; i
++ {
542 LittleEndian
.PutUint64(putbuf
[:], uint64(i
))