1
2
3
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
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"
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
277 var p BlankFieldsProbe
278 if err := Read(buf, LittleEndian, &p); err != nil {
279 t.Error(err)
280 }
281
282
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
288 if err := Write(buf, LittleEndian, &p); err != nil {
289 t.Error(err)
290 }
291
292
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
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 func TestSizeInvalid(t *testing.T) {
355 testcases := []any{
356 int(0),
357 new(int),
358 (*int)(nil),
359 [1]uint{},
360 new([1]uint),
361 (*[1]uint)(nil),
362 []int{},
363 []int(nil),
364 new([]int),
365 (*[]int)(nil),
366 }
367 for _, tc := range testcases {
368 if got := Size(tc); got != -1 {
369 t.Errorf("Size(%T) = %d, want -1", tc, got)
370 }
371 }
372 }
373
374
375
376
377
378 type Unexported struct {
379 a int32
380 }
381
382 func TestUnexportedRead(t *testing.T) {
383 var buf bytes.Buffer
384 u1 := Unexported{a: 1}
385 if err := Write(&buf, LittleEndian, &u1); err != nil {
386 t.Fatal(err)
387 }
388
389 defer func() {
390 if recover() == nil {
391 t.Fatal("did not panic")
392 }
393 }()
394 var u2 Unexported
395 Read(&buf, LittleEndian, &u2)
396 }
397
398 func TestReadErrorMsg(t *testing.T) {
399 var buf bytes.Buffer
400 read := func(data any) {
401 err := Read(&buf, LittleEndian, data)
402 want := "binary.Read: invalid type " + reflect.TypeOf(data).String()
403 if err == nil {
404 t.Errorf("%T: got no error; want %q", data, want)
405 return
406 }
407 if got := err.Error(); got != want {
408 t.Errorf("%T: got %q; want %q", data, got, want)
409 }
410 }
411 read(0)
412 s := new(struct{})
413 read(&s)
414 p := &s
415 read(&p)
416 }
417
418 func TestReadTruncated(t *testing.T) {
419 const data = "0123456789abcdef"
420
421 var b1 = make([]int32, 4)
422 var b2 struct {
423 A, B, C, D byte
424 E int32
425 F float64
426 }
427
428 for i := 0; i <= len(data); i++ {
429 var errWant error
430 switch i {
431 case 0:
432 errWant = io.EOF
433 case len(data):
434 errWant = nil
435 default:
436 errWant = io.ErrUnexpectedEOF
437 }
438
439 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b1); err != errWant {
440 t.Errorf("Read(%d) with slice: got %v, want %v", i, err, errWant)
441 }
442 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b2); err != errWant {
443 t.Errorf("Read(%d) with struct: got %v, want %v", i, err, errWant)
444 }
445 }
446 }
447
448 func testUint64SmallSliceLengthPanics() (panicked bool) {
449 defer func() {
450 panicked = recover() != nil
451 }()
452 b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
453 LittleEndian.Uint64(b[:4])
454 return false
455 }
456
457 func testPutUint64SmallSliceLengthPanics() (panicked bool) {
458 defer func() {
459 panicked = recover() != nil
460 }()
461 b := [8]byte{}
462 LittleEndian.PutUint64(b[:4], 0x0102030405060708)
463 return false
464 }
465
466 func TestByteOrder(t *testing.T) {
467 type byteOrder interface {
468 ByteOrder
469 AppendByteOrder
470 }
471 buf := make([]byte, 8)
472 for _, order := range []byteOrder{LittleEndian, BigEndian} {
473 const offset = 3
474 for _, value := range []uint64{
475 0x0000000000000000,
476 0x0123456789abcdef,
477 0xfedcba9876543210,
478 0xffffffffffffffff,
479 0xaaaaaaaaaaaaaaaa,
480 math.Float64bits(math.Pi),
481 math.Float64bits(math.E),
482 } {
483 want16 := uint16(value)
484 order.PutUint16(buf[:2], want16)
485 if got := order.Uint16(buf[:2]); got != want16 {
486 t.Errorf("PutUint16: Uint16 = %v, want %v", got, want16)
487 }
488 buf = order.AppendUint16(buf[:offset], want16)
489 if got := order.Uint16(buf[offset:]); got != want16 {
490 t.Errorf("AppendUint16: Uint16 = %v, want %v", got, want16)
491 }
492 if len(buf) != offset+2 {
493 t.Errorf("AppendUint16: len(buf) = %d, want %d", len(buf), offset+2)
494 }
495
496 want32 := uint32(value)
497 order.PutUint32(buf[:4], want32)
498 if got := order.Uint32(buf[:4]); got != want32 {
499 t.Errorf("PutUint32: Uint32 = %v, want %v", got, want32)
500 }
501 buf = order.AppendUint32(buf[:offset], want32)
502 if got := order.Uint32(buf[offset:]); got != want32 {
503 t.Errorf("AppendUint32: Uint32 = %v, want %v", got, want32)
504 }
505 if len(buf) != offset+4 {
506 t.Errorf("AppendUint32: len(buf) = %d, want %d", len(buf), offset+4)
507 }
508
509 want64 := uint64(value)
510 order.PutUint64(buf[:8], want64)
511 if got := order.Uint64(buf[:8]); got != want64 {
512 t.Errorf("PutUint64: Uint64 = %v, want %v", got, want64)
513 }
514 buf = order.AppendUint64(buf[:offset], want64)
515 if got := order.Uint64(buf[offset:]); got != want64 {
516 t.Errorf("AppendUint64: Uint64 = %v, want %v", got, want64)
517 }
518 if len(buf) != offset+8 {
519 t.Errorf("AppendUint64: len(buf) = %d, want %d", len(buf), offset+8)
520 }
521 }
522 }
523 }
524
525 func TestEarlyBoundsChecks(t *testing.T) {
526 if testUint64SmallSliceLengthPanics() != true {
527 t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't")
528 }
529 if testPutUint64SmallSliceLengthPanics() != true {
530 t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't")
531 }
532 }
533
534 func TestReadInvalidDestination(t *testing.T) {
535 testReadInvalidDestination(t, BigEndian)
536 testReadInvalidDestination(t, LittleEndian)
537 }
538
539 func testReadInvalidDestination(t *testing.T, order ByteOrder) {
540 destinations := []any{
541 int8(0),
542 int16(0),
543 int32(0),
544 int64(0),
545
546 uint8(0),
547 uint16(0),
548 uint32(0),
549 uint64(0),
550
551 bool(false),
552 }
553
554 for _, dst := range destinations {
555 err := Read(bytes.NewReader([]byte{1, 2, 3, 4, 5, 6, 7, 8}), order, dst)
556 want := fmt.Sprintf("binary.Read: invalid type %T", dst)
557 if err == nil || err.Error() != want {
558 t.Fatalf("for type %T: got %q; want %q", dst, err, want)
559 }
560 }
561 }
562
563 func TestNoFixedSize(t *testing.T) {
564 type Person struct {
565 Age int
566 Weight float64
567 Height float64
568 }
569
570 person := Person{
571 Age: 27,
572 Weight: 67.3,
573 Height: 177.8,
574 }
575
576 buf := new(bytes.Buffer)
577 err := Write(buf, LittleEndian, &person)
578 if err == nil {
579 t.Fatal("binary.Write: unexpected success as size of type *binary.Person is not fixed")
580 }
581 errs := "binary.Write: some values are not fixed-sized in type *binary.Person"
582 if err.Error() != errs {
583 t.Fatalf("got %q, want %q", err, errs)
584 }
585 }
586
587 type byteSliceReader struct {
588 remain []byte
589 }
590
591 func (br *byteSliceReader) Read(p []byte) (int, error) {
592 n := copy(p, br.remain)
593 br.remain = br.remain[n:]
594 return n, nil
595 }
596
597 func BenchmarkReadSlice1000Int32s(b *testing.B) {
598 bsr := &byteSliceReader{}
599 slice := make([]int32, 1000)
600 buf := make([]byte, len(slice)*4)
601 b.SetBytes(int64(len(buf)))
602 b.ResetTimer()
603 for i := 0; i < b.N; i++ {
604 bsr.remain = buf
605 Read(bsr, BigEndian, slice)
606 }
607 }
608
609 func BenchmarkReadStruct(b *testing.B) {
610 bsr := &byteSliceReader{}
611 var buf bytes.Buffer
612 Write(&buf, BigEndian, &s)
613 b.SetBytes(int64(dataSize(reflect.ValueOf(s))))
614 t := s
615 b.ResetTimer()
616 for i := 0; i < b.N; i++ {
617 bsr.remain = buf.Bytes()
618 Read(bsr, BigEndian, &t)
619 }
620 b.StopTimer()
621 if b.N > 0 && !reflect.DeepEqual(s, t) {
622 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t, s)
623 }
624 }
625
626 func BenchmarkWriteStruct(b *testing.B) {
627 b.SetBytes(int64(Size(&s)))
628 b.ResetTimer()
629 for i := 0; i < b.N; i++ {
630 Write(io.Discard, BigEndian, &s)
631 }
632 }
633
634 func BenchmarkReadInts(b *testing.B) {
635 var ls Struct
636 bsr := &byteSliceReader{}
637 var r io.Reader = bsr
638 b.SetBytes(2 * (1 + 2 + 4 + 8))
639 b.ResetTimer()
640 for i := 0; i < b.N; i++ {
641 bsr.remain = big
642 Read(r, BigEndian, &ls.Int8)
643 Read(r, BigEndian, &ls.Int16)
644 Read(r, BigEndian, &ls.Int32)
645 Read(r, BigEndian, &ls.Int64)
646 Read(r, BigEndian, &ls.Uint8)
647 Read(r, BigEndian, &ls.Uint16)
648 Read(r, BigEndian, &ls.Uint32)
649 Read(r, BigEndian, &ls.Uint64)
650 }
651 b.StopTimer()
652 want := s
653 want.Float32 = 0
654 want.Float64 = 0
655 want.Complex64 = 0
656 want.Complex128 = 0
657 want.Array = [4]uint8{0, 0, 0, 0}
658 want.Bool = false
659 want.BoolArray = [4]bool{false, false, false, false}
660 if b.N > 0 && !reflect.DeepEqual(ls, want) {
661 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
662 }
663 }
664
665 func BenchmarkWriteInts(b *testing.B) {
666 buf := new(bytes.Buffer)
667 var w io.Writer = buf
668 b.SetBytes(2 * (1 + 2 + 4 + 8))
669 b.ResetTimer()
670 for i := 0; i < b.N; i++ {
671 buf.Reset()
672 Write(w, BigEndian, s.Int8)
673 Write(w, BigEndian, s.Int16)
674 Write(w, BigEndian, s.Int32)
675 Write(w, BigEndian, s.Int64)
676 Write(w, BigEndian, s.Uint8)
677 Write(w, BigEndian, s.Uint16)
678 Write(w, BigEndian, s.Uint32)
679 Write(w, BigEndian, s.Uint64)
680 }
681 b.StopTimer()
682 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) {
683 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
684 }
685 }
686
687 func BenchmarkWriteSlice1000Int32s(b *testing.B) {
688 slice := make([]int32, 1000)
689 buf := new(bytes.Buffer)
690 var w io.Writer = buf
691 b.SetBytes(4 * 1000)
692 b.ResetTimer()
693 for i := 0; i < b.N; i++ {
694 buf.Reset()
695 Write(w, BigEndian, slice)
696 }
697 b.StopTimer()
698 }
699
700 func BenchmarkPutUint16(b *testing.B) {
701 b.SetBytes(2)
702 for i := 0; i < b.N; i++ {
703 BigEndian.PutUint16(putbuf[:2], uint16(i))
704 }
705 }
706
707 func BenchmarkAppendUint16(b *testing.B) {
708 b.SetBytes(2)
709 for i := 0; i < b.N; i++ {
710 putbuf = BigEndian.AppendUint16(putbuf[:0], uint16(i))
711 }
712 }
713
714 func BenchmarkPutUint32(b *testing.B) {
715 b.SetBytes(4)
716 for i := 0; i < b.N; i++ {
717 BigEndian.PutUint32(putbuf[:4], uint32(i))
718 }
719 }
720
721 func BenchmarkAppendUint32(b *testing.B) {
722 b.SetBytes(4)
723 for i := 0; i < b.N; i++ {
724 putbuf = BigEndian.AppendUint32(putbuf[:0], uint32(i))
725 }
726 }
727
728 func BenchmarkPutUint64(b *testing.B) {
729 b.SetBytes(8)
730 for i := 0; i < b.N; i++ {
731 BigEndian.PutUint64(putbuf[:8], uint64(i))
732 }
733 }
734
735 func BenchmarkAppendUint64(b *testing.B) {
736 b.SetBytes(8)
737 for i := 0; i < b.N; i++ {
738 putbuf = BigEndian.AppendUint64(putbuf[:0], uint64(i))
739 }
740 }
741
742 func BenchmarkLittleEndianPutUint16(b *testing.B) {
743 b.SetBytes(2)
744 for i := 0; i < b.N; i++ {
745 LittleEndian.PutUint16(putbuf[:2], uint16(i))
746 }
747 }
748
749 func BenchmarkLittleEndianAppendUint16(b *testing.B) {
750 b.SetBytes(2)
751 for i := 0; i < b.N; i++ {
752 putbuf = LittleEndian.AppendUint16(putbuf[:0], uint16(i))
753 }
754 }
755
756 func BenchmarkLittleEndianPutUint32(b *testing.B) {
757 b.SetBytes(4)
758 for i := 0; i < b.N; i++ {
759 LittleEndian.PutUint32(putbuf[:4], uint32(i))
760 }
761 }
762
763 func BenchmarkLittleEndianAppendUint32(b *testing.B) {
764 b.SetBytes(4)
765 for i := 0; i < b.N; i++ {
766 putbuf = LittleEndian.AppendUint32(putbuf[:0], uint32(i))
767 }
768 }
769
770 func BenchmarkLittleEndianPutUint64(b *testing.B) {
771 b.SetBytes(8)
772 for i := 0; i < b.N; i++ {
773 LittleEndian.PutUint64(putbuf[:8], uint64(i))
774 }
775 }
776
777 func BenchmarkLittleEndianAppendUint64(b *testing.B) {
778 b.SetBytes(8)
779 for i := 0; i < b.N; i++ {
780 putbuf = LittleEndian.AppendUint64(putbuf[:0], uint64(i))
781 }
782 }
783
784 func BenchmarkReadFloats(b *testing.B) {
785 var ls Struct
786 bsr := &byteSliceReader{}
787 var r io.Reader = bsr
788 b.SetBytes(4 + 8)
789 b.ResetTimer()
790 for i := 0; i < b.N; i++ {
791 bsr.remain = big[30:]
792 Read(r, BigEndian, &ls.Float32)
793 Read(r, BigEndian, &ls.Float64)
794 }
795 b.StopTimer()
796 want := s
797 want.Int8 = 0
798 want.Int16 = 0
799 want.Int32 = 0
800 want.Int64 = 0
801 want.Uint8 = 0
802 want.Uint16 = 0
803 want.Uint32 = 0
804 want.Uint64 = 0
805 want.Complex64 = 0
806 want.Complex128 = 0
807 want.Array = [4]uint8{0, 0, 0, 0}
808 want.Bool = false
809 want.BoolArray = [4]bool{false, false, false, false}
810 if b.N > 0 && !reflect.DeepEqual(ls, want) {
811 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
812 }
813 }
814
815 func BenchmarkWriteFloats(b *testing.B) {
816 buf := new(bytes.Buffer)
817 var w io.Writer = buf
818 b.SetBytes(4 + 8)
819 b.ResetTimer()
820 for i := 0; i < b.N; i++ {
821 buf.Reset()
822 Write(w, BigEndian, s.Float32)
823 Write(w, BigEndian, s.Float64)
824 }
825 b.StopTimer()
826 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[30:30+4+8]) {
827 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[30:30+4+8])
828 }
829 }
830
831 func BenchmarkReadSlice1000Float32s(b *testing.B) {
832 bsr := &byteSliceReader{}
833 slice := make([]float32, 1000)
834 buf := make([]byte, len(slice)*4)
835 b.SetBytes(int64(len(buf)))
836 b.ResetTimer()
837 for i := 0; i < b.N; i++ {
838 bsr.remain = buf
839 Read(bsr, BigEndian, slice)
840 }
841 }
842
843 func BenchmarkWriteSlice1000Float32s(b *testing.B) {
844 slice := make([]float32, 1000)
845 buf := new(bytes.Buffer)
846 var w io.Writer = buf
847 b.SetBytes(4 * 1000)
848 b.ResetTimer()
849 for i := 0; i < b.N; i++ {
850 buf.Reset()
851 Write(w, BigEndian, slice)
852 }
853 b.StopTimer()
854 }
855
856 func BenchmarkReadSlice1000Uint8s(b *testing.B) {
857 bsr := &byteSliceReader{}
858 slice := make([]uint8, 1000)
859 buf := make([]byte, len(slice))
860 b.SetBytes(int64(len(buf)))
861 b.ResetTimer()
862 for i := 0; i < b.N; i++ {
863 bsr.remain = buf
864 Read(bsr, BigEndian, slice)
865 }
866 }
867
868 func BenchmarkWriteSlice1000Uint8s(b *testing.B) {
869 slice := make([]uint8, 1000)
870 buf := new(bytes.Buffer)
871 var w io.Writer = buf
872 b.SetBytes(1000)
873 b.ResetTimer()
874 for i := 0; i < b.N; i++ {
875 buf.Reset()
876 Write(w, BigEndian, slice)
877 }
878 }
879
880 func TestNativeEndian(t *testing.T) {
881 const val = 0x12345678
882 i := uint32(val)
883 s := unsafe.Slice((*byte)(unsafe.Pointer(&i)), unsafe.Sizeof(i))
884 if v := NativeEndian.Uint32(s); v != val {
885 t.Errorf("NativeEndian.Uint32 returned %#x, expected %#x", v, val)
886 }
887 }
888
View as plain text