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 BenchmarkWriteSlice1000Structs(b *testing.B) {
635 slice := make([]Struct, 1000)
636 buf := new(bytes.Buffer)
637 var w io.Writer = buf
638 b.SetBytes(int64(Size(slice)))
639 b.ResetTimer()
640 for i := 0; i < b.N; i++ {
641 buf.Reset()
642 Write(w, BigEndian, slice)
643 }
644 b.StopTimer()
645 }
646
647 func BenchmarkReadSlice1000Structs(b *testing.B) {
648 bsr := &byteSliceReader{}
649 slice := make([]Struct, 1000)
650 buf := make([]byte, Size(slice))
651 b.SetBytes(int64(len(buf)))
652 b.ResetTimer()
653 for i := 0; i < b.N; i++ {
654 bsr.remain = buf
655 Read(bsr, BigEndian, slice)
656 }
657 }
658
659 func BenchmarkReadInts(b *testing.B) {
660 var ls Struct
661 bsr := &byteSliceReader{}
662 var r io.Reader = bsr
663 b.SetBytes(2 * (1 + 2 + 4 + 8))
664 b.ResetTimer()
665 for i := 0; i < b.N; i++ {
666 bsr.remain = big
667 Read(r, BigEndian, &ls.Int8)
668 Read(r, BigEndian, &ls.Int16)
669 Read(r, BigEndian, &ls.Int32)
670 Read(r, BigEndian, &ls.Int64)
671 Read(r, BigEndian, &ls.Uint8)
672 Read(r, BigEndian, &ls.Uint16)
673 Read(r, BigEndian, &ls.Uint32)
674 Read(r, BigEndian, &ls.Uint64)
675 }
676 b.StopTimer()
677 want := s
678 want.Float32 = 0
679 want.Float64 = 0
680 want.Complex64 = 0
681 want.Complex128 = 0
682 want.Array = [4]uint8{0, 0, 0, 0}
683 want.Bool = false
684 want.BoolArray = [4]bool{false, false, false, false}
685 if b.N > 0 && !reflect.DeepEqual(ls, want) {
686 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
687 }
688 }
689
690 func BenchmarkWriteInts(b *testing.B) {
691 buf := new(bytes.Buffer)
692 var w io.Writer = buf
693 b.SetBytes(2 * (1 + 2 + 4 + 8))
694 b.ResetTimer()
695 for i := 0; i < b.N; i++ {
696 buf.Reset()
697 Write(w, BigEndian, s.Int8)
698 Write(w, BigEndian, s.Int16)
699 Write(w, BigEndian, s.Int32)
700 Write(w, BigEndian, s.Int64)
701 Write(w, BigEndian, s.Uint8)
702 Write(w, BigEndian, s.Uint16)
703 Write(w, BigEndian, s.Uint32)
704 Write(w, BigEndian, s.Uint64)
705 }
706 b.StopTimer()
707 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) {
708 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
709 }
710 }
711
712 func BenchmarkWriteSlice1000Int32s(b *testing.B) {
713 slice := make([]int32, 1000)
714 buf := new(bytes.Buffer)
715 var w io.Writer = buf
716 b.SetBytes(4 * 1000)
717 b.ResetTimer()
718 for i := 0; i < b.N; i++ {
719 buf.Reset()
720 Write(w, BigEndian, slice)
721 }
722 b.StopTimer()
723 }
724
725 func BenchmarkPutUint16(b *testing.B) {
726 b.SetBytes(2)
727 for i := 0; i < b.N; i++ {
728 BigEndian.PutUint16(putbuf[:2], uint16(i))
729 }
730 }
731
732 func BenchmarkAppendUint16(b *testing.B) {
733 b.SetBytes(2)
734 for i := 0; i < b.N; i++ {
735 putbuf = BigEndian.AppendUint16(putbuf[:0], uint16(i))
736 }
737 }
738
739 func BenchmarkPutUint32(b *testing.B) {
740 b.SetBytes(4)
741 for i := 0; i < b.N; i++ {
742 BigEndian.PutUint32(putbuf[:4], uint32(i))
743 }
744 }
745
746 func BenchmarkAppendUint32(b *testing.B) {
747 b.SetBytes(4)
748 for i := 0; i < b.N; i++ {
749 putbuf = BigEndian.AppendUint32(putbuf[:0], uint32(i))
750 }
751 }
752
753 func BenchmarkPutUint64(b *testing.B) {
754 b.SetBytes(8)
755 for i := 0; i < b.N; i++ {
756 BigEndian.PutUint64(putbuf[:8], uint64(i))
757 }
758 }
759
760 func BenchmarkAppendUint64(b *testing.B) {
761 b.SetBytes(8)
762 for i := 0; i < b.N; i++ {
763 putbuf = BigEndian.AppendUint64(putbuf[:0], uint64(i))
764 }
765 }
766
767 func BenchmarkLittleEndianPutUint16(b *testing.B) {
768 b.SetBytes(2)
769 for i := 0; i < b.N; i++ {
770 LittleEndian.PutUint16(putbuf[:2], uint16(i))
771 }
772 }
773
774 func BenchmarkLittleEndianAppendUint16(b *testing.B) {
775 b.SetBytes(2)
776 for i := 0; i < b.N; i++ {
777 putbuf = LittleEndian.AppendUint16(putbuf[:0], uint16(i))
778 }
779 }
780
781 func BenchmarkLittleEndianPutUint32(b *testing.B) {
782 b.SetBytes(4)
783 for i := 0; i < b.N; i++ {
784 LittleEndian.PutUint32(putbuf[:4], uint32(i))
785 }
786 }
787
788 func BenchmarkLittleEndianAppendUint32(b *testing.B) {
789 b.SetBytes(4)
790 for i := 0; i < b.N; i++ {
791 putbuf = LittleEndian.AppendUint32(putbuf[:0], uint32(i))
792 }
793 }
794
795 func BenchmarkLittleEndianPutUint64(b *testing.B) {
796 b.SetBytes(8)
797 for i := 0; i < b.N; i++ {
798 LittleEndian.PutUint64(putbuf[:8], uint64(i))
799 }
800 }
801
802 func BenchmarkLittleEndianAppendUint64(b *testing.B) {
803 b.SetBytes(8)
804 for i := 0; i < b.N; i++ {
805 putbuf = LittleEndian.AppendUint64(putbuf[:0], uint64(i))
806 }
807 }
808
809 func BenchmarkReadFloats(b *testing.B) {
810 var ls Struct
811 bsr := &byteSliceReader{}
812 var r io.Reader = bsr
813 b.SetBytes(4 + 8)
814 b.ResetTimer()
815 for i := 0; i < b.N; i++ {
816 bsr.remain = big[30:]
817 Read(r, BigEndian, &ls.Float32)
818 Read(r, BigEndian, &ls.Float64)
819 }
820 b.StopTimer()
821 want := s
822 want.Int8 = 0
823 want.Int16 = 0
824 want.Int32 = 0
825 want.Int64 = 0
826 want.Uint8 = 0
827 want.Uint16 = 0
828 want.Uint32 = 0
829 want.Uint64 = 0
830 want.Complex64 = 0
831 want.Complex128 = 0
832 want.Array = [4]uint8{0, 0, 0, 0}
833 want.Bool = false
834 want.BoolArray = [4]bool{false, false, false, false}
835 if b.N > 0 && !reflect.DeepEqual(ls, want) {
836 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
837 }
838 }
839
840 func BenchmarkWriteFloats(b *testing.B) {
841 buf := new(bytes.Buffer)
842 var w io.Writer = buf
843 b.SetBytes(4 + 8)
844 b.ResetTimer()
845 for i := 0; i < b.N; i++ {
846 buf.Reset()
847 Write(w, BigEndian, s.Float32)
848 Write(w, BigEndian, s.Float64)
849 }
850 b.StopTimer()
851 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[30:30+4+8]) {
852 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[30:30+4+8])
853 }
854 }
855
856 func BenchmarkReadSlice1000Float32s(b *testing.B) {
857 bsr := &byteSliceReader{}
858 slice := make([]float32, 1000)
859 buf := make([]byte, len(slice)*4)
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 BenchmarkWriteSlice1000Float32s(b *testing.B) {
869 slice := make([]float32, 1000)
870 buf := new(bytes.Buffer)
871 var w io.Writer = buf
872 b.SetBytes(4 * 1000)
873 b.ResetTimer()
874 for i := 0; i < b.N; i++ {
875 buf.Reset()
876 Write(w, BigEndian, slice)
877 }
878 b.StopTimer()
879 }
880
881 func BenchmarkReadSlice1000Uint8s(b *testing.B) {
882 bsr := &byteSliceReader{}
883 slice := make([]uint8, 1000)
884 buf := make([]byte, len(slice))
885 b.SetBytes(int64(len(buf)))
886 b.ResetTimer()
887 for i := 0; i < b.N; i++ {
888 bsr.remain = buf
889 Read(bsr, BigEndian, slice)
890 }
891 }
892
893 func BenchmarkWriteSlice1000Uint8s(b *testing.B) {
894 slice := make([]uint8, 1000)
895 buf := new(bytes.Buffer)
896 var w io.Writer = buf
897 b.SetBytes(1000)
898 b.ResetTimer()
899 for i := 0; i < b.N; i++ {
900 buf.Reset()
901 Write(w, BigEndian, slice)
902 }
903 }
904
905 func TestNativeEndian(t *testing.T) {
906 const val = 0x12345678
907 i := uint32(val)
908 s := unsafe.Slice((*byte)(unsafe.Pointer(&i)), unsafe.Sizeof(i))
909 if v := NativeEndian.Uint32(s); v != val {
910 t.Errorf("NativeEndian.Uint32 returned %#x, expected %#x", v, val)
911 }
912 }
913
View as plain text