AVR: target/116295 - Fix unrecognizable insn with __flash read.
[official-gcc.git] / libgo / go / encoding / binary / binary_test.go
blob9e1b5f12db404fa0ca31a130ef6a82b10bda2ead
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.
5 package binary
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 "math"
12 "reflect"
13 "strings"
14 "sync"
15 "testing"
18 type Struct struct {
19 Int8 int8
20 Int16 int16
21 Int32 int32
22 Int64 int64
23 Uint8 uint8
24 Uint16 uint16
25 Uint32 uint32
26 Uint64 uint64
27 Float32 float32
28 Float64 float64
29 Complex64 complex64
30 Complex128 complex128
31 Array [4]uint8
32 Bool bool
33 BoolArray [4]bool
36 type T struct {
37 Int int
38 Uint uint
39 Uintptr uintptr
40 Array [4]int
43 var s = Struct{
44 0x01,
45 0x0203,
46 0x04050607,
47 0x08090a0b0c0d0e0f,
48 0x10,
49 0x1112,
50 0x13141516,
51 0x1718191a1b1c1d1e,
53 math.Float32frombits(0x1f202122),
54 math.Float64frombits(0x232425262728292a),
55 complex(
56 math.Float32frombits(0x2b2c2d2e),
57 math.Float32frombits(0x2f303132),
59 complex(
60 math.Float64frombits(0x333435363738393a),
61 math.Float64frombits(0x3b3c3d3e3f404142),
64 [4]uint8{0x43, 0x44, 0x45, 0x46},
66 true,
67 [4]bool{true, false, true, false},
70 var big = []byte{
72 2, 3,
73 4, 5, 6, 7,
74 8, 9, 10, 11, 12, 13, 14, 15,
75 16,
76 17, 18,
77 19, 20, 21, 22,
78 23, 24, 25, 26, 27, 28, 29, 30,
80 31, 32, 33, 34,
81 35, 36, 37, 38, 39, 40, 41, 42,
82 43, 44, 45, 46, 47, 48, 49, 50,
83 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
85 67, 68, 69, 70,
88 1, 0, 1, 0,
91 var little = []byte{
93 3, 2,
94 7, 6, 5, 4,
95 15, 14, 13, 12, 11, 10, 9, 8,
96 16,
97 18, 17,
98 22, 21, 20, 19,
99 30, 29, 28, 27, 26, 25, 24, 23,
101 34, 33, 32, 31,
102 42, 41, 40, 39, 38, 37, 36, 35,
103 46, 45, 44, 43, 50, 49, 48, 47,
104 58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59,
106 67, 68, 69, 70,
109 1, 0, 1, 0,
112 var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
113 var res = []int32{0x01020304, 0x05060708}
114 var putbuf = []byte{0, 0, 0, 0, 0, 0, 0, 0}
116 func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want any) {
117 if err != nil {
118 t.Errorf("%v %v: %v", dir, order, err)
119 return
121 if !reflect.DeepEqual(have, want) {
122 t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want)
126 func testRead(t *testing.T, order ByteOrder, b []byte, s1 any) {
127 var s2 Struct
128 err := Read(bytes.NewReader(b), order, &s2)
129 checkResult(t, "Read", order, err, s2, s1)
132 func testWrite(t *testing.T, order ByteOrder, b []byte, s1 any) {
133 buf := new(bytes.Buffer)
134 err := Write(buf, order, s1)
135 checkResult(t, "Write", order, err, buf.Bytes(), b)
138 func TestLittleEndianRead(t *testing.T) { testRead(t, LittleEndian, little, s) }
139 func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, s) }
140 func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
142 func TestBigEndianRead(t *testing.T) { testRead(t, BigEndian, big, s) }
143 func TestBigEndianWrite(t *testing.T) { testWrite(t, BigEndian, big, s) }
144 func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
146 func TestReadSlice(t *testing.T) {
147 slice := make([]int32, 2)
148 err := Read(bytes.NewReader(src), BigEndian, slice)
149 checkResult(t, "ReadSlice", BigEndian, err, slice, res)
152 func TestWriteSlice(t *testing.T) {
153 buf := new(bytes.Buffer)
154 err := Write(buf, BigEndian, res)
155 checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
158 func TestReadBool(t *testing.T) {
159 var res bool
160 var err error
161 err = Read(bytes.NewReader([]byte{0}), BigEndian, &res)
162 checkResult(t, "ReadBool", BigEndian, err, res, false)
163 res = false
164 err = Read(bytes.NewReader([]byte{1}), BigEndian, &res)
165 checkResult(t, "ReadBool", BigEndian, err, res, true)
166 res = false
167 err = Read(bytes.NewReader([]byte{2}), BigEndian, &res)
168 checkResult(t, "ReadBool", BigEndian, err, res, true)
171 func TestReadBoolSlice(t *testing.T) {
172 slice := make([]bool, 4)
173 err := Read(bytes.NewReader([]byte{0, 1, 2, 255}), BigEndian, slice)
174 checkResult(t, "ReadBoolSlice", BigEndian, err, slice, []bool{false, true, true, true})
177 // Addresses of arrays are easier to manipulate with reflection than are slices.
178 var intArrays = []any{
179 &[100]int8{},
180 &[100]int16{},
181 &[100]int32{},
182 &[100]int64{},
183 &[100]uint8{},
184 &[100]uint16{},
185 &[100]uint32{},
186 &[100]uint64{},
189 func TestSliceRoundTrip(t *testing.T) {
190 buf := new(bytes.Buffer)
191 for _, array := range intArrays {
192 src := reflect.ValueOf(array).Elem()
193 unsigned := false
194 switch src.Index(0).Kind() {
195 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
196 unsigned = true
198 for i := 0; i < src.Len(); i++ {
199 if unsigned {
200 src.Index(i).SetUint(uint64(i * 0x07654321))
201 } else {
202 src.Index(i).SetInt(int64(i * 0x07654321))
205 buf.Reset()
206 srcSlice := src.Slice(0, src.Len())
207 err := Write(buf, BigEndian, srcSlice.Interface())
208 if err != nil {
209 t.Fatal(err)
211 dst := reflect.New(src.Type()).Elem()
212 dstSlice := dst.Slice(0, dst.Len())
213 err = Read(buf, BigEndian, dstSlice.Interface())
214 if err != nil {
215 t.Fatal(err)
217 if !reflect.DeepEqual(src.Interface(), dst.Interface()) {
218 t.Fatal(src)
223 func TestWriteT(t *testing.T) {
224 buf := new(bytes.Buffer)
225 ts := T{}
226 if err := Write(buf, BigEndian, ts); err == nil {
227 t.Errorf("WriteT: have err == nil, want non-nil")
230 tv := reflect.Indirect(reflect.ValueOf(ts))
231 for i, n := 0, tv.NumField(); i < n; i++ {
232 typ := tv.Field(i).Type().String()
233 if typ == "[4]int" {
234 typ = "int" // the problem is int, not the [4]
236 if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil {
237 t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type())
238 } else if !strings.Contains(err.Error(), typ) {
239 t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ)
244 type BlankFields struct {
245 A uint32
246 _ int32
247 B float64
248 _ [4]int16
249 C byte
250 _ [7]byte
251 _ struct {
252 f [8]float32
256 type BlankFieldsProbe struct {
257 A uint32
258 P0 int32
259 B float64
260 P1 [4]int16
261 C byte
262 P2 [7]byte
263 P3 struct {
264 F [8]float32
268 func TestBlankFields(t *testing.T) {
269 buf := new(bytes.Buffer)
270 b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42}
271 if err := Write(buf, LittleEndian, &b1); err != nil {
272 t.Error(err)
275 // zero values must have been written for blank fields
276 var p BlankFieldsProbe
277 if err := Read(buf, LittleEndian, &p); err != nil {
278 t.Error(err)
281 // quick test: only check first value of slices
282 if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 {
283 t.Errorf("non-zero values for originally blank fields: %#v", p)
286 // write p and see if we can probe only some fields
287 if err := Write(buf, LittleEndian, &p); err != nil {
288 t.Error(err)
291 // read should ignore blank fields in b2
292 var b2 BlankFields
293 if err := Read(buf, LittleEndian, &b2); err != nil {
294 t.Error(err)
296 if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C {
297 t.Errorf("%#v != %#v", b1, b2)
301 func TestSizeStructCache(t *testing.T) {
302 // Reset the cache, otherwise multiple test runs fail.
303 structSize = sync.Map{}
305 count := func() int {
306 var i int
307 structSize.Range(func(_, _ any) bool {
309 return true
311 return i
314 var total int
315 added := func() int {
316 delta := count() - total
317 total += delta
318 return delta
321 type foo struct {
322 A uint32
325 type bar struct {
326 A Struct
327 B foo
328 C Struct
331 testcases := []struct {
332 val any
333 want int
335 {new(foo), 1},
336 {new(bar), 1},
337 {new(bar), 0},
338 {new(struct{ A Struct }), 1},
339 {new(struct{ A Struct }), 0},
342 for _, tc := range testcases {
343 if Size(tc.val) == -1 {
344 t.Fatalf("Can't get the size of %T", tc.val)
347 if n := added(); n != tc.want {
348 t.Errorf("Sizing %T added %d entries to the cache, want %d", tc.val, n, tc.want)
353 // An attempt to read into a struct with an unexported field will
354 // panic. This is probably not the best choice, but at this point
355 // anything else would be an API change.
357 type Unexported struct {
358 a int32
361 func TestUnexportedRead(t *testing.T) {
362 var buf bytes.Buffer
363 u1 := Unexported{a: 1}
364 if err := Write(&buf, LittleEndian, &u1); err != nil {
365 t.Fatal(err)
368 defer func() {
369 if recover() == nil {
370 t.Fatal("did not panic")
373 var u2 Unexported
374 Read(&buf, LittleEndian, &u2)
377 func TestReadErrorMsg(t *testing.T) {
378 var buf bytes.Buffer
379 read := func(data any) {
380 err := Read(&buf, LittleEndian, data)
381 want := "binary.Read: invalid type " + reflect.TypeOf(data).String()
382 if err == nil {
383 t.Errorf("%T: got no error; want %q", data, want)
384 return
386 if got := err.Error(); got != want {
387 t.Errorf("%T: got %q; want %q", data, got, want)
390 read(0)
391 s := new(struct{})
392 read(&s)
393 p := &s
394 read(&p)
397 func TestReadTruncated(t *testing.T) {
398 const data = "0123456789abcdef"
400 var b1 = make([]int32, 4)
401 var b2 struct {
402 A, B, C, D byte
403 E int32
404 F float64
407 for i := 0; i <= len(data); i++ {
408 var errWant error
409 switch i {
410 case 0:
411 errWant = io.EOF
412 case len(data):
413 errWant = nil
414 default:
415 errWant = io.ErrUnexpectedEOF
418 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b1); err != errWant {
419 t.Errorf("Read(%d) with slice: got %v, want %v", i, err, errWant)
421 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b2); err != errWant {
422 t.Errorf("Read(%d) with struct: got %v, want %v", i, err, errWant)
427 func testUint64SmallSliceLengthPanics() (panicked bool) {
428 defer func() {
429 panicked = recover() != nil
431 b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
432 LittleEndian.Uint64(b[:4])
433 return false
436 func testPutUint64SmallSliceLengthPanics() (panicked bool) {
437 defer func() {
438 panicked = recover() != nil
440 b := [8]byte{}
441 LittleEndian.PutUint64(b[:4], 0x0102030405060708)
442 return false
445 func TestEarlyBoundsChecks(t *testing.T) {
446 if testUint64SmallSliceLengthPanics() != true {
447 t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't")
449 if testPutUint64SmallSliceLengthPanics() != true {
450 t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't")
454 func TestReadInvalidDestination(t *testing.T) {
455 testReadInvalidDestination(t, BigEndian)
456 testReadInvalidDestination(t, LittleEndian)
459 func testReadInvalidDestination(t *testing.T, order ByteOrder) {
460 destinations := []any{
461 int8(0),
462 int16(0),
463 int32(0),
464 int64(0),
466 uint8(0),
467 uint16(0),
468 uint32(0),
469 uint64(0),
471 bool(false),
474 for _, dst := range destinations {
475 err := Read(bytes.NewReader([]byte{1, 2, 3, 4, 5, 6, 7, 8}), order, dst)
476 want := fmt.Sprintf("binary.Read: invalid type %T", dst)
477 if err == nil || err.Error() != want {
478 t.Fatalf("for type %T: got %q; want %q", dst, err, want)
483 type byteSliceReader struct {
484 remain []byte
487 func (br *byteSliceReader) Read(p []byte) (int, error) {
488 n := copy(p, br.remain)
489 br.remain = br.remain[n:]
490 return n, nil
493 func BenchmarkReadSlice1000Int32s(b *testing.B) {
494 bsr := &byteSliceReader{}
495 slice := make([]int32, 1000)
496 buf := make([]byte, len(slice)*4)
497 b.SetBytes(int64(len(buf)))
498 b.ResetTimer()
499 for i := 0; i < b.N; i++ {
500 bsr.remain = buf
501 Read(bsr, BigEndian, slice)
505 func BenchmarkReadStruct(b *testing.B) {
506 bsr := &byteSliceReader{}
507 var buf bytes.Buffer
508 Write(&buf, BigEndian, &s)
509 b.SetBytes(int64(dataSize(reflect.ValueOf(s))))
510 t := s
511 b.ResetTimer()
512 for i := 0; i < b.N; i++ {
513 bsr.remain = buf.Bytes()
514 Read(bsr, BigEndian, &t)
516 b.StopTimer()
517 if b.N > 0 && !reflect.DeepEqual(s, t) {
518 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t, s)
522 func BenchmarkWriteStruct(b *testing.B) {
523 b.SetBytes(int64(Size(&s)))
524 b.ResetTimer()
525 for i := 0; i < b.N; i++ {
526 Write(io.Discard, BigEndian, &s)
530 func BenchmarkReadInts(b *testing.B) {
531 var ls Struct
532 bsr := &byteSliceReader{}
533 var r io.Reader = bsr
534 b.SetBytes(2 * (1 + 2 + 4 + 8))
535 b.ResetTimer()
536 for i := 0; i < b.N; i++ {
537 bsr.remain = big
538 Read(r, BigEndian, &ls.Int8)
539 Read(r, BigEndian, &ls.Int16)
540 Read(r, BigEndian, &ls.Int32)
541 Read(r, BigEndian, &ls.Int64)
542 Read(r, BigEndian, &ls.Uint8)
543 Read(r, BigEndian, &ls.Uint16)
544 Read(r, BigEndian, &ls.Uint32)
545 Read(r, BigEndian, &ls.Uint64)
547 b.StopTimer()
548 want := s
549 want.Float32 = 0
550 want.Float64 = 0
551 want.Complex64 = 0
552 want.Complex128 = 0
553 want.Array = [4]uint8{0, 0, 0, 0}
554 want.Bool = false
555 want.BoolArray = [4]bool{false, false, false, false}
556 if b.N > 0 && !reflect.DeepEqual(ls, want) {
557 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
561 func BenchmarkWriteInts(b *testing.B) {
562 buf := new(bytes.Buffer)
563 var w io.Writer = buf
564 b.SetBytes(2 * (1 + 2 + 4 + 8))
565 b.ResetTimer()
566 for i := 0; i < b.N; i++ {
567 buf.Reset()
568 Write(w, BigEndian, s.Int8)
569 Write(w, BigEndian, s.Int16)
570 Write(w, BigEndian, s.Int32)
571 Write(w, BigEndian, s.Int64)
572 Write(w, BigEndian, s.Uint8)
573 Write(w, BigEndian, s.Uint16)
574 Write(w, BigEndian, s.Uint32)
575 Write(w, BigEndian, s.Uint64)
577 b.StopTimer()
578 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) {
579 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
583 func BenchmarkWriteSlice1000Int32s(b *testing.B) {
584 slice := make([]int32, 1000)
585 buf := new(bytes.Buffer)
586 var w io.Writer = buf
587 b.SetBytes(4 * 1000)
588 b.ResetTimer()
589 for i := 0; i < b.N; i++ {
590 buf.Reset()
591 Write(w, BigEndian, slice)
593 b.StopTimer()
596 func BenchmarkPutUint16(b *testing.B) {
597 b.SetBytes(2)
598 for i := 0; i < b.N; i++ {
599 BigEndian.PutUint16(putbuf[:], uint16(i))
603 func BenchmarkPutUint32(b *testing.B) {
604 b.SetBytes(4)
605 for i := 0; i < b.N; i++ {
606 BigEndian.PutUint32(putbuf[:], uint32(i))
610 func BenchmarkPutUint64(b *testing.B) {
611 b.SetBytes(8)
612 for i := 0; i < b.N; i++ {
613 BigEndian.PutUint64(putbuf[:], uint64(i))
616 func BenchmarkLittleEndianPutUint16(b *testing.B) {
617 b.SetBytes(2)
618 for i := 0; i < b.N; i++ {
619 LittleEndian.PutUint16(putbuf[:], uint16(i))
623 func BenchmarkLittleEndianPutUint32(b *testing.B) {
624 b.SetBytes(4)
625 for i := 0; i < b.N; i++ {
626 LittleEndian.PutUint32(putbuf[:], uint32(i))
630 func BenchmarkLittleEndianPutUint64(b *testing.B) {
631 b.SetBytes(8)
632 for i := 0; i < b.N; i++ {
633 LittleEndian.PutUint64(putbuf[:], uint64(i))
637 func BenchmarkReadFloats(b *testing.B) {
638 var ls Struct
639 bsr := &byteSliceReader{}
640 var r io.Reader = bsr
641 b.SetBytes(4 + 8)
642 b.ResetTimer()
643 for i := 0; i < b.N; i++ {
644 bsr.remain = big[30:]
645 Read(r, BigEndian, &ls.Float32)
646 Read(r, BigEndian, &ls.Float64)
648 b.StopTimer()
649 want := s
650 want.Int8 = 0
651 want.Int16 = 0
652 want.Int32 = 0
653 want.Int64 = 0
654 want.Uint8 = 0
655 want.Uint16 = 0
656 want.Uint32 = 0
657 want.Uint64 = 0
658 want.Complex64 = 0
659 want.Complex128 = 0
660 want.Array = [4]uint8{0, 0, 0, 0}
661 want.Bool = false
662 want.BoolArray = [4]bool{false, false, false, false}
663 if b.N > 0 && !reflect.DeepEqual(ls, want) {
664 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
668 func BenchmarkWriteFloats(b *testing.B) {
669 buf := new(bytes.Buffer)
670 var w io.Writer = buf
671 b.SetBytes(4 + 8)
672 b.ResetTimer()
673 for i := 0; i < b.N; i++ {
674 buf.Reset()
675 Write(w, BigEndian, s.Float32)
676 Write(w, BigEndian, s.Float64)
678 b.StopTimer()
679 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[30:30+4+8]) {
680 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[30:30+4+8])
684 func BenchmarkReadSlice1000Float32s(b *testing.B) {
685 bsr := &byteSliceReader{}
686 slice := make([]float32, 1000)
687 buf := make([]byte, len(slice)*4)
688 b.SetBytes(int64(len(buf)))
689 b.ResetTimer()
690 for i := 0; i < b.N; i++ {
691 bsr.remain = buf
692 Read(bsr, BigEndian, slice)
696 func BenchmarkWriteSlice1000Float32s(b *testing.B) {
697 slice := make([]float32, 1000)
698 buf := new(bytes.Buffer)
699 var w io.Writer = buf
700 b.SetBytes(4 * 1000)
701 b.ResetTimer()
702 for i := 0; i < b.N; i++ {
703 buf.Reset()
704 Write(w, BigEndian, slice)
706 b.StopTimer()
709 func BenchmarkReadSlice1000Uint8s(b *testing.B) {
710 bsr := &byteSliceReader{}
711 slice := make([]uint8, 1000)
712 buf := make([]byte, len(slice))
713 b.SetBytes(int64(len(buf)))
714 b.ResetTimer()
715 for i := 0; i < b.N; i++ {
716 bsr.remain = buf
717 Read(bsr, BigEndian, slice)
721 func BenchmarkWriteSlice1000Uint8s(b *testing.B) {
722 slice := make([]uint8, 1000)
723 buf := new(bytes.Buffer)
724 var w io.Writer = buf
725 b.SetBytes(1000)
726 b.ResetTimer()
727 for i := 0; i < b.N; i++ {
728 buf.Reset()
729 Write(w, BigEndian, slice)