libgo: update to go1.9
[official-gcc.git] / libgo / go / encoding / binary / binary_test.go
blob0547bee43706ed6b461d78f864125dfe523cc6b1
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}
113 func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want interface{}) {
114 if err != nil {
115 t.Errorf("%v %v: %v", dir, order, err)
116 return
118 if !reflect.DeepEqual(have, want) {
119 t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want)
123 func testRead(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
124 var s2 Struct
125 err := Read(bytes.NewReader(b), order, &s2)
126 checkResult(t, "Read", order, err, s2, s1)
129 func testWrite(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
130 buf := new(bytes.Buffer)
131 err := Write(buf, order, s1)
132 checkResult(t, "Write", order, err, buf.Bytes(), b)
135 func TestLittleEndianRead(t *testing.T) { testRead(t, LittleEndian, little, s) }
136 func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, s) }
137 func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
139 func TestBigEndianRead(t *testing.T) { testRead(t, BigEndian, big, s) }
140 func TestBigEndianWrite(t *testing.T) { testWrite(t, BigEndian, big, s) }
141 func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
143 func TestReadSlice(t *testing.T) {
144 slice := make([]int32, 2)
145 err := Read(bytes.NewReader(src), BigEndian, slice)
146 checkResult(t, "ReadSlice", BigEndian, err, slice, res)
149 func TestWriteSlice(t *testing.T) {
150 buf := new(bytes.Buffer)
151 err := Write(buf, BigEndian, res)
152 checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
155 func TestReadBool(t *testing.T) {
156 var res bool
157 var err error
158 err = Read(bytes.NewReader([]byte{0}), BigEndian, &res)
159 checkResult(t, "ReadBool", BigEndian, err, res, false)
160 res = false
161 err = Read(bytes.NewReader([]byte{1}), BigEndian, &res)
162 checkResult(t, "ReadBool", BigEndian, err, res, true)
163 res = false
164 err = Read(bytes.NewReader([]byte{2}), BigEndian, &res)
165 checkResult(t, "ReadBool", BigEndian, err, res, true)
168 func TestReadBoolSlice(t *testing.T) {
169 slice := make([]bool, 4)
170 err := Read(bytes.NewReader([]byte{0, 1, 2, 255}), BigEndian, slice)
171 checkResult(t, "ReadBoolSlice", BigEndian, err, slice, []bool{false, true, true, true})
174 // Addresses of arrays are easier to manipulate with reflection than are slices.
175 var intArrays = []interface{}{
176 &[100]int8{},
177 &[100]int16{},
178 &[100]int32{},
179 &[100]int64{},
180 &[100]uint8{},
181 &[100]uint16{},
182 &[100]uint32{},
183 &[100]uint64{},
186 func TestSliceRoundTrip(t *testing.T) {
187 buf := new(bytes.Buffer)
188 for _, array := range intArrays {
189 src := reflect.ValueOf(array).Elem()
190 unsigned := false
191 switch src.Index(0).Kind() {
192 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
193 unsigned = true
195 for i := 0; i < src.Len(); i++ {
196 if unsigned {
197 src.Index(i).SetUint(uint64(i * 0x07654321))
198 } else {
199 src.Index(i).SetInt(int64(i * 0x07654321))
202 buf.Reset()
203 srcSlice := src.Slice(0, src.Len())
204 err := Write(buf, BigEndian, srcSlice.Interface())
205 if err != nil {
206 t.Fatal(err)
208 dst := reflect.New(src.Type()).Elem()
209 dstSlice := dst.Slice(0, dst.Len())
210 err = Read(buf, BigEndian, dstSlice.Interface())
211 if err != nil {
212 t.Fatal(err)
214 if !reflect.DeepEqual(src.Interface(), dst.Interface()) {
215 t.Fatal(src)
220 func TestWriteT(t *testing.T) {
221 buf := new(bytes.Buffer)
222 ts := T{}
223 if err := Write(buf, BigEndian, ts); err == nil {
224 t.Errorf("WriteT: have err == nil, want non-nil")
227 tv := reflect.Indirect(reflect.ValueOf(ts))
228 for i, n := 0, tv.NumField(); i < n; i++ {
229 typ := tv.Field(i).Type().String()
230 if typ == "[4]int" {
231 typ = "int" // the problem is int, not the [4]
233 if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil {
234 t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type())
235 } else if !strings.Contains(err.Error(), typ) {
236 t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ)
241 type BlankFields struct {
242 A uint32
243 _ int32
244 B float64
245 _ [4]int16
246 C byte
247 _ [7]byte
248 _ struct {
249 f [8]float32
253 type BlankFieldsProbe struct {
254 A uint32
255 P0 int32
256 B float64
257 P1 [4]int16
258 C byte
259 P2 [7]byte
260 P3 struct {
261 F [8]float32
265 func TestBlankFields(t *testing.T) {
266 buf := new(bytes.Buffer)
267 b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42}
268 if err := Write(buf, LittleEndian, &b1); err != nil {
269 t.Error(err)
272 // zero values must have been written for blank fields
273 var p BlankFieldsProbe
274 if err := Read(buf, LittleEndian, &p); err != nil {
275 t.Error(err)
278 // quick test: only check first value of slices
279 if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 {
280 t.Errorf("non-zero values for originally blank fields: %#v", p)
283 // write p and see if we can probe only some fields
284 if err := Write(buf, LittleEndian, &p); err != nil {
285 t.Error(err)
288 // read should ignore blank fields in b2
289 var b2 BlankFields
290 if err := Read(buf, LittleEndian, &b2); err != nil {
291 t.Error(err)
293 if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C {
294 t.Errorf("%#v != %#v", b1, b2)
298 // An attempt to read into a struct with an unexported field will
299 // panic. This is probably not the best choice, but at this point
300 // anything else would be an API change.
302 type Unexported struct {
303 a int32
306 func TestUnexportedRead(t *testing.T) {
307 var buf bytes.Buffer
308 u1 := Unexported{a: 1}
309 if err := Write(&buf, LittleEndian, &u1); err != nil {
310 t.Fatal(err)
313 defer func() {
314 if recover() == nil {
315 t.Fatal("did not panic")
318 var u2 Unexported
319 Read(&buf, LittleEndian, &u2)
322 func TestReadErrorMsg(t *testing.T) {
323 var buf bytes.Buffer
324 read := func(data interface{}) {
325 err := Read(&buf, LittleEndian, data)
326 want := "binary.Read: invalid type " + reflect.TypeOf(data).String()
327 if err == nil {
328 t.Errorf("%T: got no error; want %q", data, want)
329 return
331 if got := err.Error(); got != want {
332 t.Errorf("%T: got %q; want %q", data, got, want)
335 read(0)
336 s := new(struct{})
337 read(&s)
338 p := &s
339 read(&p)
342 func TestReadTruncated(t *testing.T) {
343 const data = "0123456789abcdef"
345 var b1 = make([]int32, 4)
346 var b2 struct {
347 A, B, C, D byte
348 E int32
349 F float64
352 for i := 0; i <= len(data); i++ {
353 var errWant error
354 switch i {
355 case 0:
356 errWant = io.EOF
357 case len(data):
358 errWant = nil
359 default:
360 errWant = io.ErrUnexpectedEOF
363 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b1); err != errWant {
364 t.Errorf("Read(%d) with slice: got %v, want %v", i, err, errWant)
366 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b2); err != errWant {
367 t.Errorf("Read(%d) with struct: got %v, want %v", i, err, errWant)
372 func testUint64SmallSliceLengthPanics() (panicked bool) {
373 defer func() {
374 panicked = recover() != nil
376 b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
377 LittleEndian.Uint64(b[:4])
378 return false
381 func testPutUint64SmallSliceLengthPanics() (panicked bool) {
382 defer func() {
383 panicked = recover() != nil
385 b := [8]byte{}
386 LittleEndian.PutUint64(b[:4], 0x0102030405060708)
387 return false
390 func TestEarlyBoundsChecks(t *testing.T) {
391 if testUint64SmallSliceLengthPanics() != true {
392 t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't")
394 if testPutUint64SmallSliceLengthPanics() != true {
395 t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't")
399 type byteSliceReader struct {
400 remain []byte
403 func (br *byteSliceReader) Read(p []byte) (int, error) {
404 n := copy(p, br.remain)
405 br.remain = br.remain[n:]
406 return n, nil
409 func BenchmarkReadSlice1000Int32s(b *testing.B) {
410 bsr := &byteSliceReader{}
411 slice := make([]int32, 1000)
412 buf := make([]byte, len(slice)*4)
413 b.SetBytes(int64(len(buf)))
414 b.ResetTimer()
415 for i := 0; i < b.N; i++ {
416 bsr.remain = buf
417 Read(bsr, BigEndian, slice)
421 func BenchmarkReadStruct(b *testing.B) {
422 bsr := &byteSliceReader{}
423 var buf bytes.Buffer
424 Write(&buf, BigEndian, &s)
425 b.SetBytes(int64(dataSize(reflect.ValueOf(s))))
426 t := s
427 b.ResetTimer()
428 for i := 0; i < b.N; i++ {
429 bsr.remain = buf.Bytes()
430 Read(bsr, BigEndian, &t)
432 b.StopTimer()
433 if b.N > 0 && !reflect.DeepEqual(s, t) {
434 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t, s)
438 func BenchmarkReadInts(b *testing.B) {
439 var ls Struct
440 bsr := &byteSliceReader{}
441 var r io.Reader = bsr
442 b.SetBytes(2 * (1 + 2 + 4 + 8))
443 b.ResetTimer()
444 for i := 0; i < b.N; i++ {
445 bsr.remain = big
446 Read(r, BigEndian, &ls.Int8)
447 Read(r, BigEndian, &ls.Int16)
448 Read(r, BigEndian, &ls.Int32)
449 Read(r, BigEndian, &ls.Int64)
450 Read(r, BigEndian, &ls.Uint8)
451 Read(r, BigEndian, &ls.Uint16)
452 Read(r, BigEndian, &ls.Uint32)
453 Read(r, BigEndian, &ls.Uint64)
455 b.StopTimer()
456 want := s
457 want.Float32 = 0
458 want.Float64 = 0
459 want.Complex64 = 0
460 want.Complex128 = 0
461 want.Array = [4]uint8{0, 0, 0, 0}
462 want.Bool = false
463 want.BoolArray = [4]bool{false, false, false, false}
464 if b.N > 0 && !reflect.DeepEqual(ls, want) {
465 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
469 func BenchmarkWriteInts(b *testing.B) {
470 buf := new(bytes.Buffer)
471 var w io.Writer = buf
472 b.SetBytes(2 * (1 + 2 + 4 + 8))
473 b.ResetTimer()
474 for i := 0; i < b.N; i++ {
475 buf.Reset()
476 Write(w, BigEndian, s.Int8)
477 Write(w, BigEndian, s.Int16)
478 Write(w, BigEndian, s.Int32)
479 Write(w, BigEndian, s.Int64)
480 Write(w, BigEndian, s.Uint8)
481 Write(w, BigEndian, s.Uint16)
482 Write(w, BigEndian, s.Uint32)
483 Write(w, BigEndian, s.Uint64)
485 b.StopTimer()
486 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) {
487 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
491 func BenchmarkWriteSlice1000Int32s(b *testing.B) {
492 slice := make([]int32, 1000)
493 buf := new(bytes.Buffer)
494 var w io.Writer = buf
495 b.SetBytes(4 * 1000)
496 b.ResetTimer()
497 for i := 0; i < b.N; i++ {
498 buf.Reset()
499 Write(w, BigEndian, slice)
501 b.StopTimer()
504 func BenchmarkPutUint16(b *testing.B) {
505 buf := [2]byte{}
506 b.SetBytes(2)
507 for i := 0; i < b.N; i++ {
508 BigEndian.PutUint16(buf[:], uint16(i))
512 func BenchmarkPutUint32(b *testing.B) {
513 buf := [4]byte{}
514 b.SetBytes(4)
515 for i := 0; i < b.N; i++ {
516 BigEndian.PutUint32(buf[:], uint32(i))
520 func BenchmarkPutUint64(b *testing.B) {
521 buf := [8]byte{}
522 b.SetBytes(8)
523 for i := 0; i < b.N; i++ {
524 BigEndian.PutUint64(buf[:], uint64(i))