github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/encoding/binary/binary_test.go (about) 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. 4 5 package binary 6 7 import ( 8 "bytes" 9 "io" 10 "math" 11 "reflect" 12 "strings" 13 "testing" 14 ) 15 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 } 31 32 type T struct { 33 Int int 34 Uint uint 35 Uintptr uintptr 36 Array [4]int 37 } 38 39 var s = Struct{ 40 0x01, 41 0x0203, 42 0x04050607, 43 0x08090a0b0c0d0e0f, 44 0x10, 45 0x1112, 46 0x13141516, 47 0x1718191a1b1c1d1e, 48 49 math.Float32frombits(0x1f202122), 50 math.Float64frombits(0x232425262728292a), 51 complex( 52 math.Float32frombits(0x2b2c2d2e), 53 math.Float32frombits(0x2f303132), 54 ), 55 complex( 56 math.Float64frombits(0x333435363738393a), 57 math.Float64frombits(0x3b3c3d3e3f404142), 58 ), 59 60 [4]uint8{0x43, 0x44, 0x45, 0x46}, 61 } 62 63 var big = []byte{ 64 1, 65 2, 3, 66 4, 5, 6, 7, 67 8, 9, 10, 11, 12, 13, 14, 15, 68 16, 69 17, 18, 70 19, 20, 21, 22, 71 23, 24, 25, 26, 27, 28, 29, 30, 72 73 31, 32, 33, 34, 74 35, 36, 37, 38, 39, 40, 41, 42, 75 43, 44, 45, 46, 47, 48, 49, 50, 76 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 77 78 67, 68, 69, 70, 79 } 80 81 var little = []byte{ 82 1, 83 3, 2, 84 7, 6, 5, 4, 85 15, 14, 13, 12, 11, 10, 9, 8, 86 16, 87 18, 17, 88 22, 21, 20, 19, 89 30, 29, 28, 27, 26, 25, 24, 23, 90 91 34, 33, 32, 31, 92 42, 41, 40, 39, 38, 37, 36, 35, 93 46, 45, 44, 43, 50, 49, 48, 47, 94 58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59, 95 96 67, 68, 69, 70, 97 } 98 99 var src = []byte{1, 2, 3, 4, 5, 6, 7, 8} 100 var res = []int32{0x01020304, 0x05060708} 101 102 func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want interface{}) { 103 if err != nil { 104 t.Errorf("%v %v: %v", dir, order, err) 105 return 106 } 107 if !reflect.DeepEqual(have, want) { 108 t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want) 109 } 110 } 111 112 func testRead(t *testing.T, order ByteOrder, b []byte, s1 interface{}) { 113 var s2 Struct 114 err := Read(bytes.NewBuffer(b), order, &s2) 115 checkResult(t, "Read", order, err, s2, s1) 116 } 117 118 func testWrite(t *testing.T, order ByteOrder, b []byte, s1 interface{}) { 119 buf := new(bytes.Buffer) 120 err := Write(buf, order, s1) 121 checkResult(t, "Write", order, err, buf.Bytes(), b) 122 } 123 124 func TestLittleEndianRead(t *testing.T) { testRead(t, LittleEndian, little, s) } 125 func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, s) } 126 func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) } 127 128 func TestBigEndianRead(t *testing.T) { testRead(t, BigEndian, big, s) } 129 func TestBigEndianWrite(t *testing.T) { testWrite(t, BigEndian, big, s) } 130 func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) } 131 132 func TestReadSlice(t *testing.T) { 133 slice := make([]int32, 2) 134 err := Read(bytes.NewBuffer(src), BigEndian, slice) 135 checkResult(t, "ReadSlice", BigEndian, err, slice, res) 136 } 137 138 func TestWriteSlice(t *testing.T) { 139 buf := new(bytes.Buffer) 140 err := Write(buf, BigEndian, res) 141 checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src) 142 } 143 144 func TestWriteT(t *testing.T) { 145 buf := new(bytes.Buffer) 146 ts := T{} 147 if err := Write(buf, BigEndian, ts); err == nil { 148 t.Errorf("WriteT: have err == nil, want non-nil") 149 } 150 151 tv := reflect.Indirect(reflect.ValueOf(ts)) 152 for i, n := 0, tv.NumField(); i < n; i++ { 153 typ := tv.Field(i).Type().String() 154 if typ == "[4]int" { 155 typ = "int" // the problem is int, not the [4] 156 } 157 if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil { 158 t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type()) 159 } else if !strings.Contains(err.Error(), typ) { 160 t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ) 161 } 162 } 163 } 164 165 type BlankFields struct { 166 A uint32 167 _ int32 168 B float64 169 _ [4]int16 170 C byte 171 _ [7]byte 172 _ struct { 173 f [8]float32 174 } 175 } 176 177 type BlankFieldsProbe struct { 178 A uint32 179 P0 int32 180 B float64 181 P1 [4]int16 182 C byte 183 P2 [7]byte 184 P3 struct { 185 F [8]float32 186 } 187 } 188 189 func TestBlankFields(t *testing.T) { 190 buf := new(bytes.Buffer) 191 b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42} 192 if err := Write(buf, LittleEndian, &b1); err != nil { 193 t.Error(err) 194 } 195 196 // zero values must have been written for blank fields 197 var p BlankFieldsProbe 198 if err := Read(buf, LittleEndian, &p); err != nil { 199 t.Error(err) 200 } 201 202 // quick test: only check first value of slices 203 if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 { 204 t.Errorf("non-zero values for originally blank fields: %#v", p) 205 } 206 207 // write p and see if we can probe only some fields 208 if err := Write(buf, LittleEndian, &p); err != nil { 209 t.Error(err) 210 } 211 212 // read should ignore blank fields in b2 213 var b2 BlankFields 214 if err := Read(buf, LittleEndian, &b2); err != nil { 215 t.Error(err) 216 } 217 if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C { 218 t.Errorf("%#v != %#v", b1, b2) 219 } 220 } 221 222 type byteSliceReader struct { 223 remain []byte 224 } 225 226 func (br *byteSliceReader) Read(p []byte) (int, error) { 227 n := copy(p, br.remain) 228 br.remain = br.remain[n:] 229 return n, nil 230 } 231 232 func BenchmarkReadSlice1000Int32s(b *testing.B) { 233 bsr := &byteSliceReader{} 234 slice := make([]int32, 1000) 235 buf := make([]byte, len(slice)*4) 236 b.SetBytes(int64(len(buf))) 237 b.ResetTimer() 238 for i := 0; i < b.N; i++ { 239 bsr.remain = buf 240 Read(bsr, BigEndian, slice) 241 } 242 } 243 244 func BenchmarkReadStruct(b *testing.B) { 245 bsr := &byteSliceReader{} 246 var buf bytes.Buffer 247 Write(&buf, BigEndian, &s) 248 n, _ := dataSize(reflect.ValueOf(s)) 249 b.SetBytes(int64(n)) 250 t := s 251 b.ResetTimer() 252 for i := 0; i < b.N; i++ { 253 bsr.remain = buf.Bytes() 254 Read(bsr, BigEndian, &t) 255 } 256 b.StopTimer() 257 if !reflect.DeepEqual(s, t) { 258 b.Fatal("no match") 259 } 260 } 261 262 func BenchmarkReadInts(b *testing.B) { 263 var ls Struct 264 bsr := &byteSliceReader{} 265 var r io.Reader = bsr 266 b.SetBytes(2 * (1 + 2 + 4 + 8)) 267 b.ResetTimer() 268 for i := 0; i < b.N; i++ { 269 bsr.remain = big 270 Read(r, BigEndian, &ls.Int8) 271 Read(r, BigEndian, &ls.Int16) 272 Read(r, BigEndian, &ls.Int32) 273 Read(r, BigEndian, &ls.Int64) 274 Read(r, BigEndian, &ls.Uint8) 275 Read(r, BigEndian, &ls.Uint16) 276 Read(r, BigEndian, &ls.Uint32) 277 Read(r, BigEndian, &ls.Uint64) 278 } 279 280 want := s 281 want.Float32 = 0 282 want.Float64 = 0 283 want.Complex64 = 0 284 want.Complex128 = 0 285 for i := range want.Array { 286 want.Array[i] = 0 287 } 288 b.StopTimer() 289 if !reflect.DeepEqual(ls, want) { 290 panic("no match") 291 } 292 } 293 294 func BenchmarkWriteInts(b *testing.B) { 295 buf := new(bytes.Buffer) 296 var w io.Writer = buf 297 b.SetBytes(2 * (1 + 2 + 4 + 8)) 298 b.ResetTimer() 299 for i := 0; i < b.N; i++ { 300 buf.Reset() 301 Write(w, BigEndian, s.Int8) 302 Write(w, BigEndian, s.Int16) 303 Write(w, BigEndian, s.Int32) 304 Write(w, BigEndian, s.Int64) 305 Write(w, BigEndian, s.Uint8) 306 Write(w, BigEndian, s.Uint16) 307 Write(w, BigEndian, s.Uint32) 308 Write(w, BigEndian, s.Uint64) 309 } 310 b.StopTimer() 311 if !bytes.Equal(buf.Bytes(), big[:30]) { 312 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30]) 313 } 314 }