re PR c++/88261 (ICE: verify_gimple failed (error: non-trivial conversion at assignment))
[official-gcc.git] / libgo / go / encoding / binary / binary_test.go
blobaf402575e458cf6d4ac6822532cfc402428a9129
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 "io"
10 "math"
11 "reflect"
12 "strings"
13 "testing"
16 type Struct struct {
17 Int8 int8
18 Int16 int16
19 Int32 int32
20 Int64 int64
21 Uint8 uint8
22 Uint16 uint16
23 Uint32 uint32
24 Uint64 uint64
25 Float32 float32
26 Float64 float64
27 Complex64 complex64
28 Complex128 complex128
29 Array [4]uint8
30 Bool bool
31 BoolArray [4]bool
34 type T struct {
35 Int int
36 Uint uint
37 Uintptr uintptr
38 Array [4]int
41 var s = Struct{
42 0x01,
43 0x0203,
44 0x04050607,
45 0x08090a0b0c0d0e0f,
46 0x10,
47 0x1112,
48 0x13141516,
49 0x1718191a1b1c1d1e,
51 math.Float32frombits(0x1f202122),
52 math.Float64frombits(0x232425262728292a),
53 complex(
54 math.Float32frombits(0x2b2c2d2e),
55 math.Float32frombits(0x2f303132),
57 complex(
58 math.Float64frombits(0x333435363738393a),
59 math.Float64frombits(0x3b3c3d3e3f404142),
62 [4]uint8{0x43, 0x44, 0x45, 0x46},
64 true,
65 [4]bool{true, false, true, false},
68 var big = []byte{
70 2, 3,
71 4, 5, 6, 7,
72 8, 9, 10, 11, 12, 13, 14, 15,
73 16,
74 17, 18,
75 19, 20, 21, 22,
76 23, 24, 25, 26, 27, 28, 29, 30,
78 31, 32, 33, 34,
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,
83 67, 68, 69, 70,
86 1, 0, 1, 0,
89 var little = []byte{
91 3, 2,
92 7, 6, 5, 4,
93 15, 14, 13, 12, 11, 10, 9, 8,
94 16,
95 18, 17,
96 22, 21, 20, 19,
97 30, 29, 28, 27, 26, 25, 24, 23,
99 34, 33, 32, 31,
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,
104 67, 68, 69, 70,
107 1, 0, 1, 0,
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{}) {
115 if err != nil {
116 t.Errorf("%v %v: %v", dir, order, err)
117 return
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{}) {
125 var s2 Struct
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) {
157 var res bool
158 var err error
159 err = Read(bytes.NewReader([]byte{0}), BigEndian, &res)
160 checkResult(t, "ReadBool", BigEndian, err, res, false)
161 res = false
162 err = Read(bytes.NewReader([]byte{1}), BigEndian, &res)
163 checkResult(t, "ReadBool", BigEndian, err, res, true)
164 res = false
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{}{
177 &[100]int8{},
178 &[100]int16{},
179 &[100]int32{},
180 &[100]int64{},
181 &[100]uint8{},
182 &[100]uint16{},
183 &[100]uint32{},
184 &[100]uint64{},
187 func TestSliceRoundTrip(t *testing.T) {
188 buf := new(bytes.Buffer)
189 for _, array := range intArrays {
190 src := reflect.ValueOf(array).Elem()
191 unsigned := false
192 switch src.Index(0).Kind() {
193 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
194 unsigned = true
196 for i := 0; i < src.Len(); i++ {
197 if unsigned {
198 src.Index(i).SetUint(uint64(i * 0x07654321))
199 } else {
200 src.Index(i).SetInt(int64(i * 0x07654321))
203 buf.Reset()
204 srcSlice := src.Slice(0, src.Len())
205 err := Write(buf, BigEndian, srcSlice.Interface())
206 if err != nil {
207 t.Fatal(err)
209 dst := reflect.New(src.Type()).Elem()
210 dstSlice := dst.Slice(0, dst.Len())
211 err = Read(buf, BigEndian, dstSlice.Interface())
212 if err != nil {
213 t.Fatal(err)
215 if !reflect.DeepEqual(src.Interface(), dst.Interface()) {
216 t.Fatal(src)
221 func TestWriteT(t *testing.T) {
222 buf := new(bytes.Buffer)
223 ts := T{}
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()
231 if typ == "[4]int" {
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 {
243 A uint32
244 _ int32
245 B float64
246 _ [4]int16
247 C byte
248 _ [7]byte
249 _ struct {
250 f [8]float32
254 type BlankFieldsProbe struct {
255 A uint32
256 P0 int32
257 B float64
258 P1 [4]int16
259 C byte
260 P2 [7]byte
261 P3 struct {
262 F [8]float32
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 {
270 t.Error(err)
273 // zero values must have been written for blank fields
274 var p BlankFieldsProbe
275 if err := Read(buf, LittleEndian, &p); err != nil {
276 t.Error(err)
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 {
286 t.Error(err)
289 // read should ignore blank fields in b2
290 var b2 BlankFields
291 if err := Read(buf, LittleEndian, &b2); err != nil {
292 t.Error(err)
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 {
304 a int32
307 func TestUnexportedRead(t *testing.T) {
308 var buf bytes.Buffer
309 u1 := Unexported{a: 1}
310 if err := Write(&buf, LittleEndian, &u1); err != nil {
311 t.Fatal(err)
314 defer func() {
315 if recover() == nil {
316 t.Fatal("did not panic")
319 var u2 Unexported
320 Read(&buf, LittleEndian, &u2)
323 func TestReadErrorMsg(t *testing.T) {
324 var buf bytes.Buffer
325 read := func(data interface{}) {
326 err := Read(&buf, LittleEndian, data)
327 want := "binary.Read: invalid type " + reflect.TypeOf(data).String()
328 if err == nil {
329 t.Errorf("%T: got no error; want %q", data, want)
330 return
332 if got := err.Error(); got != want {
333 t.Errorf("%T: got %q; want %q", data, got, want)
336 read(0)
337 s := new(struct{})
338 read(&s)
339 p := &s
340 read(&p)
343 func TestReadTruncated(t *testing.T) {
344 const data = "0123456789abcdef"
346 var b1 = make([]int32, 4)
347 var b2 struct {
348 A, B, C, D byte
349 E int32
350 F float64
353 for i := 0; i <= len(data); i++ {
354 var errWant error
355 switch i {
356 case 0:
357 errWant = io.EOF
358 case len(data):
359 errWant = nil
360 default:
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) {
374 defer func() {
375 panicked = recover() != nil
377 b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
378 LittleEndian.Uint64(b[:4])
379 return false
382 func testPutUint64SmallSliceLengthPanics() (panicked bool) {
383 defer func() {
384 panicked = recover() != nil
386 b := [8]byte{}
387 LittleEndian.PutUint64(b[:4], 0x0102030405060708)
388 return false
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 {
401 remain []byte
404 func (br *byteSliceReader) Read(p []byte) (int, error) {
405 n := copy(p, br.remain)
406 br.remain = br.remain[n:]
407 return n, nil
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)))
415 b.ResetTimer()
416 for i := 0; i < b.N; i++ {
417 bsr.remain = buf
418 Read(bsr, BigEndian, slice)
422 func BenchmarkReadStruct(b *testing.B) {
423 bsr := &byteSliceReader{}
424 var buf bytes.Buffer
425 Write(&buf, BigEndian, &s)
426 b.SetBytes(int64(dataSize(reflect.ValueOf(s))))
427 t := s
428 b.ResetTimer()
429 for i := 0; i < b.N; i++ {
430 bsr.remain = buf.Bytes()
431 Read(bsr, BigEndian, &t)
433 b.StopTimer()
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) {
440 var ls Struct
441 bsr := &byteSliceReader{}
442 var r io.Reader = bsr
443 b.SetBytes(2 * (1 + 2 + 4 + 8))
444 b.ResetTimer()
445 for i := 0; i < b.N; i++ {
446 bsr.remain = big
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)
456 b.StopTimer()
457 want := s
458 want.Float32 = 0
459 want.Float64 = 0
460 want.Complex64 = 0
461 want.Complex128 = 0
462 want.Array = [4]uint8{0, 0, 0, 0}
463 want.Bool = false
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))
474 b.ResetTimer()
475 for i := 0; i < b.N; i++ {
476 buf.Reset()
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)
486 b.StopTimer()
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
496 b.SetBytes(4 * 1000)
497 b.ResetTimer()
498 for i := 0; i < b.N; i++ {
499 buf.Reset()
500 Write(w, BigEndian, slice)
502 b.StopTimer()
505 func BenchmarkPutUint16(b *testing.B) {
506 b.SetBytes(2)
507 for i := 0; i < b.N; i++ {
508 BigEndian.PutUint16(putbuf[:], uint16(i))
512 func BenchmarkPutUint32(b *testing.B) {
513 b.SetBytes(4)
514 for i := 0; i < b.N; i++ {
515 BigEndian.PutUint32(putbuf[:], uint32(i))
519 func BenchmarkPutUint64(b *testing.B) {
520 b.SetBytes(8)
521 for i := 0; i < b.N; i++ {
522 BigEndian.PutUint64(putbuf[:], uint64(i))
525 func BenchmarkLittleEndianPutUint16(b *testing.B) {
526 b.SetBytes(2)
527 for i := 0; i < b.N; i++ {
528 LittleEndian.PutUint16(putbuf[:], uint16(i))
532 func BenchmarkLittleEndianPutUint32(b *testing.B) {
533 b.SetBytes(4)
534 for i := 0; i < b.N; i++ {
535 LittleEndian.PutUint32(putbuf[:], uint32(i))
539 func BenchmarkLittleEndianPutUint64(b *testing.B) {
540 b.SetBytes(8)
541 for i := 0; i < b.N; i++ {
542 LittleEndian.PutUint64(putbuf[:], uint64(i))