binary_test.go 5.07 KB
Newer Older
Russ Cox's avatar
Russ Cox committed
1 2 3 4 5 6 7
// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package binary

import (
8
	"bytes"
Russ Cox's avatar
Russ Cox committed
9
	"io"
10 11 12
	"math"
	"reflect"
	"testing"
Russ Cox's avatar
Russ Cox committed
13 14 15
)

type Struct struct {
Roger Peppe's avatar
Roger Peppe committed
16 17 18 19 20 21 22 23 24 25 26 27 28
	Int8       int8
	Int16      int16
	Int32      int32
	Int64      int64
	Uint8      uint8
	Uint16     uint16
	Uint32     uint32
	Uint64     uint64
	Float32    float32
	Float64    float64
	Complex64  complex64
	Complex128 complex128
	Array      [4]uint8
Russ Cox's avatar
Russ Cox committed
29 30
}

31 32 33 34 35 36 37
type T struct {
	Int     int
	Uint    uint
	Uintptr uintptr
	Array   [4]int
}

Russ Cox's avatar
Russ Cox committed
38
var s = Struct{
Russ Cox's avatar
Russ Cox committed
39 40 41 42 43 44 45 46
	0x01,
	0x0203,
	0x04050607,
	0x08090a0b0c0d0e0f,
	0x10,
	0x1112,
	0x13141516,
	0x1718191a1b1c1d1e,
Roger Peppe's avatar
Roger Peppe committed
47 48 49

	math.Float32frombits(0x1f202122),
	math.Float64frombits(0x232425262728292a),
50
	complex(
Roger Peppe's avatar
Roger Peppe committed
51 52 53
		math.Float32frombits(0x2b2c2d2e),
		math.Float32frombits(0x2f303132),
	),
54
	complex(
Roger Peppe's avatar
Roger Peppe committed
55 56 57 58 59
		math.Float64frombits(0x333435363738393a),
		math.Float64frombits(0x3b3c3d3e3f404142),
	),

	[4]uint8{0x43, 0x44, 0x45, 0x46},
Russ Cox's avatar
Russ Cox committed
60 61 62 63 64 65 66 67 68 69 70
}

var big = []byte{
	1,
	2, 3,
	4, 5, 6, 7,
	8, 9, 10, 11, 12, 13, 14, 15,
	16,
	17, 18,
	19, 20, 21, 22,
	23, 24, 25, 26, 27, 28, 29, 30,
Roger Peppe's avatar
Roger Peppe committed
71 72 73 74 75 76 77

	31, 32, 33, 34,
	35, 36, 37, 38, 39, 40, 41, 42,
	43, 44, 45, 46, 47, 48, 49, 50,
	51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,

	67, 68, 69, 70,
Russ Cox's avatar
Russ Cox committed
78 79 80 81 82 83 84 85 86 87 88
}

var little = []byte{
	1,
	3, 2,
	7, 6, 5, 4,
	15, 14, 13, 12, 11, 10, 9, 8,
	16,
	18, 17,
	22, 21, 20, 19,
	30, 29, 28, 27, 26, 25, 24, 23,
Roger Peppe's avatar
Roger Peppe committed
89 90 91 92 93 94 95

	34, 33, 32, 31,
	42, 41, 40, 39, 38, 37, 36, 35,
	46, 45, 44, 43, 50, 49, 48, 47,
	58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59,

	67, 68, 69, 70,
Russ Cox's avatar
Russ Cox committed
96 97
}

98 99 100
var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
var res = []int32{0x01020304, 0x05060708}

101
func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want interface{}) {
Russ Cox's avatar
Russ Cox committed
102
	if err != nil {
103 104
		t.Errorf("%v %v: %v", dir, order, err)
		return
Russ Cox's avatar
Russ Cox committed
105
	}
106 107
	if !reflect.DeepEqual(have, want) {
		t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want)
Russ Cox's avatar
Russ Cox committed
108
	}
109
}
Russ Cox's avatar
Russ Cox committed
110

111
func testRead(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
112 113 114
	var s2 Struct
	err := Read(bytes.NewBuffer(b), order, &s2)
	checkResult(t, "Read", order, err, s2, s1)
115 116 117
}

func testWrite(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
118 119 120
	buf := new(bytes.Buffer)
	err := Write(buf, order, s1)
	checkResult(t, "Write", order, err, buf.Bytes(), b)
Russ Cox's avatar
Russ Cox committed
121
}
122

123
func TestBigEndianRead(t *testing.T) { testRead(t, BigEndian, big, s) }
124

125
func TestLittleEndianRead(t *testing.T) { testRead(t, LittleEndian, little, s) }
126

127
func TestBigEndianWrite(t *testing.T) { testWrite(t, BigEndian, big, s) }
128

129
func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, s) }
130

131
func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
132

133
func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
134 135

func TestReadSlice(t *testing.T) {
136 137 138
	slice := make([]int32, 2)
	err := Read(bytes.NewBuffer(src), BigEndian, slice)
	checkResult(t, "ReadSlice", BigEndian, err, slice, res)
139 140 141
}

func TestWriteSlice(t *testing.T) {
142 143 144
	buf := new(bytes.Buffer)
	err := Write(buf, BigEndian, res)
	checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
145
}
146 147 148 149 150 151 152 153 154

func TestWriteT(t *testing.T) {
	buf := new(bytes.Buffer)
	ts := T{}
	err := Write(buf, BigEndian, ts)
	if err == nil {
		t.Errorf("WriteT: have nil, want non-nil")
	}

Russ Cox's avatar
Russ Cox committed
155
	tv := reflect.Indirect(reflect.ValueOf(ts))
156 157 158 159 160 161 162
	for i, n := 0, tv.NumField(); i < n; i++ {
		err = Write(buf, BigEndian, tv.Field(i).Interface())
		if err == nil {
			t.Errorf("WriteT.%v: have nil, want non-nil", tv.Field(i).Type())
		}
	}
}
163 164 165 166 167

type byteSliceReader struct {
	remain []byte
}

168
func (br *byteSliceReader) Read(p []byte) (int, error) {
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
	n := copy(p, br.remain)
	br.remain = br.remain[n:]
	return n, nil
}

func BenchmarkRead(b *testing.B) {
	var ls Struct
	bsr := &byteSliceReader{}
	var r io.Reader = bsr

	for i := 0; i < b.N; i++ {
		bsr.remain = big
		Read(r, BigEndian, &ls.Int8)
		Read(r, BigEndian, &ls.Int16)
		Read(r, BigEndian, &ls.Int32)
		Read(r, BigEndian, &ls.Int64)
		Read(r, BigEndian, &ls.Uint8)
		Read(r, BigEndian, &ls.Uint16)
		Read(r, BigEndian, &ls.Uint32)
		Read(r, BigEndian, &ls.Uint64)
	}

	want := s
	want.Float32 = 0
	want.Float64 = 0
	want.Complex64 = 0
	want.Complex128 = 0
	for i := range want.Array {
		want.Array[i] = 0
	}
	if !reflect.DeepEqual(ls, want) {
		panic("no match")
	}
}
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234

func BenchmarkWrite(b *testing.B) {
	buf := new(bytes.Buffer)
	var w io.Writer = buf

	for i := 0; i < b.N; i++ {
		buf.Reset()
		Write(w, BigEndian, &s.Int8)
		Write(w, BigEndian, &s.Int16)
		Write(w, BigEndian, &s.Int32)
		Write(w, BigEndian, &s.Int64)
		Write(w, BigEndian, &s.Uint8)
		Write(w, BigEndian, &s.Uint16)
		Write(w, BigEndian, &s.Uint32)
		Write(w, BigEndian, &s.Uint64)
		Write(w, BigEndian, s.Int8)
		Write(w, BigEndian, s.Int16)
		Write(w, BigEndian, s.Int32)
		Write(w, BigEndian, s.Int64)
		Write(w, BigEndian, s.Uint8)
		Write(w, BigEndian, s.Uint16)
		Write(w, BigEndian, s.Uint32)
		Write(w, BigEndian, s.Uint64)
	}

	if !bytes.Equal(buf.Bytes()[:30], big[:30]) {
		panic("first half doesn't match")
	}
	if !bytes.Equal(buf.Bytes()[30:], big[:30]) {
		panic("second half doesn't match")
	}
}