github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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 "fmt" 10 "io" 11 "math" 12 "reflect" 13 "strings" 14 "sync" 15 "testing" 16 "unsafe" 17 ) 18 19 type Struct struct { 20 Int8 int8 21 Int16 int16 22 Int32 int32 23 Int64 int64 24 Uint8 uint8 25 Uint16 uint16 26 Uint32 uint32 27 Uint64 uint64 28 Float32 float32 29 Float64 float64 30 Complex64 complex64 31 Complex128 complex128 32 Array [4]uint8 33 Bool bool 34 BoolArray [4]bool 35 } 36 37 type T struct { 38 Int int 39 Uint uint 40 Uintptr uintptr 41 Array [4]int 42 } 43 44 var s = Struct{ 45 0x01, 46 0x0203, 47 0x04050607, 48 0x08090a0b0c0d0e0f, 49 0x10, 50 0x1112, 51 0x13141516, 52 0x1718191a1b1c1d1e, 53 54 math.Float32frombits(0x1f202122), 55 math.Float64frombits(0x232425262728292a), 56 complex( 57 math.Float32frombits(0x2b2c2d2e), 58 math.Float32frombits(0x2f303132), 59 ), 60 complex( 61 math.Float64frombits(0x333435363738393a), 62 math.Float64frombits(0x3b3c3d3e3f404142), 63 ), 64 65 [4]uint8{0x43, 0x44, 0x45, 0x46}, 66 67 true, 68 [4]bool{true, false, true, false}, 69 } 70 71 var big = []byte{ 72 1, 73 2, 3, 74 4, 5, 6, 7, 75 8, 9, 10, 11, 12, 13, 14, 15, 76 16, 77 17, 18, 78 19, 20, 21, 22, 79 23, 24, 25, 26, 27, 28, 29, 30, 80 81 31, 32, 33, 34, 82 35, 36, 37, 38, 39, 40, 41, 42, 83 43, 44, 45, 46, 47, 48, 49, 50, 84 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 85 86 67, 68, 69, 70, 87 88 1, 89 1, 0, 1, 0, 90 } 91 92 var little = []byte{ 93 1, 94 3, 2, 95 7, 6, 5, 4, 96 15, 14, 13, 12, 11, 10, 9, 8, 97 16, 98 18, 17, 99 22, 21, 20, 19, 100 30, 29, 28, 27, 26, 25, 24, 23, 101 102 34, 33, 32, 31, 103 42, 41, 40, 39, 38, 37, 36, 35, 104 46, 45, 44, 43, 50, 49, 48, 47, 105 58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59, 106 107 67, 68, 69, 70, 108 109 1, 110 1, 0, 1, 0, 111 } 112 113 var src = []byte{1, 2, 3, 4, 5, 6, 7, 8} 114 var res = []int32{0x01020304, 0x05060708} 115 var putbuf = []byte{0, 0, 0, 0, 0, 0, 0, 0} 116 117 func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, want any) { 118 if err != nil { 119 t.Errorf("%v %v: %v", dir, order, err) 120 return 121 } 122 if !reflect.DeepEqual(have, want) { 123 t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want) 124 } 125 } 126 127 func testRead(t *testing.T, order ByteOrder, b []byte, s1 any) { 128 var s2 Struct 129 err := Read(bytes.NewReader(b), order, &s2) 130 checkResult(t, "Read", order, err, s2, s1) 131 } 132 133 func testWrite(t *testing.T, order ByteOrder, b []byte, s1 any) { 134 buf := new(bytes.Buffer) 135 err := Write(buf, order, s1) 136 checkResult(t, "Write", order, err, buf.Bytes(), b) 137 } 138 139 func TestLittleEndianRead(t *testing.T) { testRead(t, LittleEndian, little, s) } 140 func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, s) } 141 func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) } 142 143 func TestBigEndianRead(t *testing.T) { testRead(t, BigEndian, big, s) } 144 func TestBigEndianWrite(t *testing.T) { testWrite(t, BigEndian, big, s) } 145 func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) } 146 147 func TestReadSlice(t *testing.T) { 148 slice := make([]int32, 2) 149 err := Read(bytes.NewReader(src), BigEndian, slice) 150 checkResult(t, "ReadSlice", BigEndian, err, slice, res) 151 } 152 153 func TestWriteSlice(t *testing.T) { 154 buf := new(bytes.Buffer) 155 err := Write(buf, BigEndian, res) 156 checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src) 157 } 158 159 func TestReadBool(t *testing.T) { 160 var res bool 161 var err error 162 err = Read(bytes.NewReader([]byte{0}), BigEndian, &res) 163 checkResult(t, "ReadBool", BigEndian, err, res, false) 164 res = false 165 err = Read(bytes.NewReader([]byte{1}), BigEndian, &res) 166 checkResult(t, "ReadBool", BigEndian, err, res, true) 167 res = false 168 err = Read(bytes.NewReader([]byte{2}), BigEndian, &res) 169 checkResult(t, "ReadBool", BigEndian, err, res, true) 170 } 171 172 func TestReadBoolSlice(t *testing.T) { 173 slice := make([]bool, 4) 174 err := Read(bytes.NewReader([]byte{0, 1, 2, 255}), BigEndian, slice) 175 checkResult(t, "ReadBoolSlice", BigEndian, err, slice, []bool{false, true, true, true}) 176 } 177 178 // Addresses of arrays are easier to manipulate with reflection than are slices. 179 var intArrays = []any{ 180 &[100]int8{}, 181 &[100]int16{}, 182 &[100]int32{}, 183 &[100]int64{}, 184 &[100]uint8{}, 185 &[100]uint16{}, 186 &[100]uint32{}, 187 &[100]uint64{}, 188 } 189 190 func TestSliceRoundTrip(t *testing.T) { 191 buf := new(bytes.Buffer) 192 for _, array := range intArrays { 193 src := reflect.ValueOf(array).Elem() 194 unsigned := false 195 switch src.Index(0).Kind() { 196 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 197 unsigned = true 198 } 199 for i := 0; i < src.Len(); i++ { 200 if unsigned { 201 src.Index(i).SetUint(uint64(i * 0x07654321)) 202 } else { 203 src.Index(i).SetInt(int64(i * 0x07654321)) 204 } 205 } 206 buf.Reset() 207 srcSlice := src.Slice(0, src.Len()) 208 err := Write(buf, BigEndian, srcSlice.Interface()) 209 if err != nil { 210 t.Fatal(err) 211 } 212 dst := reflect.New(src.Type()).Elem() 213 dstSlice := dst.Slice(0, dst.Len()) 214 err = Read(buf, BigEndian, dstSlice.Interface()) 215 if err != nil { 216 t.Fatal(err) 217 } 218 if !reflect.DeepEqual(src.Interface(), dst.Interface()) { 219 t.Fatal(src) 220 } 221 } 222 } 223 224 func TestWriteT(t *testing.T) { 225 buf := new(bytes.Buffer) 226 ts := T{} 227 if err := Write(buf, BigEndian, ts); err == nil { 228 t.Errorf("WriteT: have err == nil, want non-nil") 229 } 230 231 tv := reflect.Indirect(reflect.ValueOf(ts)) 232 for i, n := 0, tv.NumField(); i < n; i++ { 233 typ := tv.Field(i).Type().String() 234 if typ == "[4]int" { 235 typ = "int" // the problem is int, not the [4] 236 } 237 if err := Write(buf, BigEndian, tv.Field(i).Interface()); err == nil { 238 t.Errorf("WriteT.%v: have err == nil, want non-nil", tv.Field(i).Type()) 239 } else if !strings.Contains(err.Error(), typ) { 240 t.Errorf("WriteT: have err == %q, want it to mention %s", err, typ) 241 } 242 } 243 } 244 245 type BlankFields struct { 246 A uint32 247 _ int32 248 B float64 249 _ [4]int16 250 C byte 251 _ [7]byte 252 _ struct { 253 f [8]float32 254 } 255 } 256 257 type BlankFieldsProbe struct { 258 A uint32 259 P0 int32 260 B float64 261 P1 [4]int16 262 C byte 263 P2 [7]byte 264 P3 struct { 265 F [8]float32 266 } 267 } 268 269 func TestBlankFields(t *testing.T) { 270 buf := new(bytes.Buffer) 271 b1 := BlankFields{A: 1234567890, B: 2.718281828, C: 42} 272 if err := Write(buf, LittleEndian, &b1); err != nil { 273 t.Error(err) 274 } 275 276 // zero values must have been written for blank fields 277 var p BlankFieldsProbe 278 if err := Read(buf, LittleEndian, &p); err != nil { 279 t.Error(err) 280 } 281 282 // quick test: only check first value of slices 283 if p.P0 != 0 || p.P1[0] != 0 || p.P2[0] != 0 || p.P3.F[0] != 0 { 284 t.Errorf("non-zero values for originally blank fields: %#v", p) 285 } 286 287 // write p and see if we can probe only some fields 288 if err := Write(buf, LittleEndian, &p); err != nil { 289 t.Error(err) 290 } 291 292 // read should ignore blank fields in b2 293 var b2 BlankFields 294 if err := Read(buf, LittleEndian, &b2); err != nil { 295 t.Error(err) 296 } 297 if b1.A != b2.A || b1.B != b2.B || b1.C != b2.C { 298 t.Errorf("%#v != %#v", b1, b2) 299 } 300 } 301 302 func TestSizeStructCache(t *testing.T) { 303 // Reset the cache, otherwise multiple test runs fail. 304 structSize = sync.Map{} 305 306 count := func() int { 307 var i int 308 structSize.Range(func(_, _ any) bool { 309 i++ 310 return true 311 }) 312 return i 313 } 314 315 var total int 316 added := func() int { 317 delta := count() - total 318 total += delta 319 return delta 320 } 321 322 type foo struct { 323 A uint32 324 } 325 326 type bar struct { 327 A Struct 328 B foo 329 C Struct 330 } 331 332 testcases := []struct { 333 val any 334 want int 335 }{ 336 {new(foo), 1}, 337 {new(bar), 1}, 338 {new(bar), 0}, 339 {new(struct{ A Struct }), 1}, 340 {new(struct{ A Struct }), 0}, 341 } 342 343 for _, tc := range testcases { 344 if Size(tc.val) == -1 { 345 t.Fatalf("Can't get the size of %T", tc.val) 346 } 347 348 if n := added(); n != tc.want { 349 t.Errorf("Sizing %T added %d entries to the cache, want %d", tc.val, n, tc.want) 350 } 351 } 352 } 353 354 // An attempt to read into a struct with an unexported field will 355 // panic. This is probably not the best choice, but at this point 356 // anything else would be an API change. 357 358 type Unexported struct { 359 a int32 360 } 361 362 func TestUnexportedRead(t *testing.T) { 363 var buf bytes.Buffer 364 u1 := Unexported{a: 1} 365 if err := Write(&buf, LittleEndian, &u1); err != nil { 366 t.Fatal(err) 367 } 368 369 defer func() { 370 if recover() == nil { 371 t.Fatal("did not panic") 372 } 373 }() 374 var u2 Unexported 375 Read(&buf, LittleEndian, &u2) 376 } 377 378 func TestReadErrorMsg(t *testing.T) { 379 var buf bytes.Buffer 380 read := func(data any) { 381 err := Read(&buf, LittleEndian, data) 382 want := "binary.Read: invalid type " + reflect.TypeOf(data).String() 383 if err == nil { 384 t.Errorf("%T: got no error; want %q", data, want) 385 return 386 } 387 if got := err.Error(); got != want { 388 t.Errorf("%T: got %q; want %q", data, got, want) 389 } 390 } 391 read(0) 392 s := new(struct{}) 393 read(&s) 394 p := &s 395 read(&p) 396 } 397 398 func TestReadTruncated(t *testing.T) { 399 const data = "0123456789abcdef" 400 401 var b1 = make([]int32, 4) 402 var b2 struct { 403 A, B, C, D byte 404 E int32 405 F float64 406 } 407 408 for i := 0; i <= len(data); i++ { 409 var errWant error 410 switch i { 411 case 0: 412 errWant = io.EOF 413 case len(data): 414 errWant = nil 415 default: 416 errWant = io.ErrUnexpectedEOF 417 } 418 419 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b1); err != errWant { 420 t.Errorf("Read(%d) with slice: got %v, want %v", i, err, errWant) 421 } 422 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b2); err != errWant { 423 t.Errorf("Read(%d) with struct: got %v, want %v", i, err, errWant) 424 } 425 } 426 } 427 428 func testUint64SmallSliceLengthPanics() (panicked bool) { 429 defer func() { 430 panicked = recover() != nil 431 }() 432 b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} 433 LittleEndian.Uint64(b[:4]) 434 return false 435 } 436 437 func testPutUint64SmallSliceLengthPanics() (panicked bool) { 438 defer func() { 439 panicked = recover() != nil 440 }() 441 b := [8]byte{} 442 LittleEndian.PutUint64(b[:4], 0x0102030405060708) 443 return false 444 } 445 446 func TestByteOrder(t *testing.T) { 447 type byteOrder interface { 448 ByteOrder 449 AppendByteOrder 450 } 451 buf := make([]byte, 8) 452 for _, order := range []byteOrder{LittleEndian, BigEndian} { 453 const offset = 3 454 for _, value := range []uint64{ 455 0x0000000000000000, 456 0x0123456789abcdef, 457 0xfedcba9876543210, 458 0xffffffffffffffff, 459 0xaaaaaaaaaaaaaaaa, 460 math.Float64bits(math.Pi), 461 math.Float64bits(math.E), 462 } { 463 want16 := uint16(value) 464 order.PutUint16(buf[:2], want16) 465 if got := order.Uint16(buf[:2]); got != want16 { 466 t.Errorf("PutUint16: Uint16 = %v, want %v", got, want16) 467 } 468 buf = order.AppendUint16(buf[:offset], want16) 469 if got := order.Uint16(buf[offset:]); got != want16 { 470 t.Errorf("AppendUint16: Uint16 = %v, want %v", got, want16) 471 } 472 if len(buf) != offset+2 { 473 t.Errorf("AppendUint16: len(buf) = %d, want %d", len(buf), offset+2) 474 } 475 476 want32 := uint32(value) 477 order.PutUint32(buf[:4], want32) 478 if got := order.Uint32(buf[:4]); got != want32 { 479 t.Errorf("PutUint32: Uint32 = %v, want %v", got, want32) 480 } 481 buf = order.AppendUint32(buf[:offset], want32) 482 if got := order.Uint32(buf[offset:]); got != want32 { 483 t.Errorf("AppendUint32: Uint32 = %v, want %v", got, want32) 484 } 485 if len(buf) != offset+4 { 486 t.Errorf("AppendUint32: len(buf) = %d, want %d", len(buf), offset+4) 487 } 488 489 want64 := uint64(value) 490 order.PutUint64(buf[:8], want64) 491 if got := order.Uint64(buf[:8]); got != want64 { 492 t.Errorf("PutUint64: Uint64 = %v, want %v", got, want64) 493 } 494 buf = order.AppendUint64(buf[:offset], want64) 495 if got := order.Uint64(buf[offset:]); got != want64 { 496 t.Errorf("AppendUint64: Uint64 = %v, want %v", got, want64) 497 } 498 if len(buf) != offset+8 { 499 t.Errorf("AppendUint64: len(buf) = %d, want %d", len(buf), offset+8) 500 } 501 } 502 } 503 } 504 505 func TestEarlyBoundsChecks(t *testing.T) { 506 if testUint64SmallSliceLengthPanics() != true { 507 t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't") 508 } 509 if testPutUint64SmallSliceLengthPanics() != true { 510 t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't") 511 } 512 } 513 514 func TestReadInvalidDestination(t *testing.T) { 515 testReadInvalidDestination(t, BigEndian) 516 testReadInvalidDestination(t, LittleEndian) 517 } 518 519 func testReadInvalidDestination(t *testing.T, order ByteOrder) { 520 destinations := []any{ 521 int8(0), 522 int16(0), 523 int32(0), 524 int64(0), 525 526 uint8(0), 527 uint16(0), 528 uint32(0), 529 uint64(0), 530 531 bool(false), 532 } 533 534 for _, dst := range destinations { 535 err := Read(bytes.NewReader([]byte{1, 2, 3, 4, 5, 6, 7, 8}), order, dst) 536 want := fmt.Sprintf("binary.Read: invalid type %T", dst) 537 if err == nil || err.Error() != want { 538 t.Fatalf("for type %T: got %q; want %q", dst, err, want) 539 } 540 } 541 } 542 543 func TestNoFixedSize(t *testing.T) { 544 type Person struct { 545 Age int 546 Weight float64 547 Height float64 548 } 549 550 person := Person{ 551 Age: 27, 552 Weight: 67.3, 553 Height: 177.8, 554 } 555 556 buf := new(bytes.Buffer) 557 err := Write(buf, LittleEndian, &person) 558 if err == nil { 559 t.Fatal("binary.Write: unexpected success as size of type *binary.Person is not fixed") 560 } 561 errs := "binary.Write: some values are not fixed-sized in type *binary.Person" 562 if err.Error() != errs { 563 t.Fatalf("got %q, want %q", err, errs) 564 } 565 } 566 567 type byteSliceReader struct { 568 remain []byte 569 } 570 571 func (br *byteSliceReader) Read(p []byte) (int, error) { 572 n := copy(p, br.remain) 573 br.remain = br.remain[n:] 574 return n, nil 575 } 576 577 func BenchmarkReadSlice1000Int32s(b *testing.B) { 578 bsr := &byteSliceReader{} 579 slice := make([]int32, 1000) 580 buf := make([]byte, len(slice)*4) 581 b.SetBytes(int64(len(buf))) 582 b.ResetTimer() 583 for i := 0; i < b.N; i++ { 584 bsr.remain = buf 585 Read(bsr, BigEndian, slice) 586 } 587 } 588 589 func BenchmarkReadStruct(b *testing.B) { 590 bsr := &byteSliceReader{} 591 var buf bytes.Buffer 592 Write(&buf, BigEndian, &s) 593 b.SetBytes(int64(dataSize(reflect.ValueOf(s)))) 594 t := s 595 b.ResetTimer() 596 for i := 0; i < b.N; i++ { 597 bsr.remain = buf.Bytes() 598 Read(bsr, BigEndian, &t) 599 } 600 b.StopTimer() 601 if b.N > 0 && !reflect.DeepEqual(s, t) { 602 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t, s) 603 } 604 } 605 606 func BenchmarkWriteStruct(b *testing.B) { 607 b.SetBytes(int64(Size(&s))) 608 b.ResetTimer() 609 for i := 0; i < b.N; i++ { 610 Write(io.Discard, BigEndian, &s) 611 } 612 } 613 614 func BenchmarkReadInts(b *testing.B) { 615 var ls Struct 616 bsr := &byteSliceReader{} 617 var r io.Reader = bsr 618 b.SetBytes(2 * (1 + 2 + 4 + 8)) 619 b.ResetTimer() 620 for i := 0; i < b.N; i++ { 621 bsr.remain = big 622 Read(r, BigEndian, &ls.Int8) 623 Read(r, BigEndian, &ls.Int16) 624 Read(r, BigEndian, &ls.Int32) 625 Read(r, BigEndian, &ls.Int64) 626 Read(r, BigEndian, &ls.Uint8) 627 Read(r, BigEndian, &ls.Uint16) 628 Read(r, BigEndian, &ls.Uint32) 629 Read(r, BigEndian, &ls.Uint64) 630 } 631 b.StopTimer() 632 want := s 633 want.Float32 = 0 634 want.Float64 = 0 635 want.Complex64 = 0 636 want.Complex128 = 0 637 want.Array = [4]uint8{0, 0, 0, 0} 638 want.Bool = false 639 want.BoolArray = [4]bool{false, false, false, false} 640 if b.N > 0 && !reflect.DeepEqual(ls, want) { 641 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want) 642 } 643 } 644 645 func BenchmarkWriteInts(b *testing.B) { 646 buf := new(bytes.Buffer) 647 var w io.Writer = buf 648 b.SetBytes(2 * (1 + 2 + 4 + 8)) 649 b.ResetTimer() 650 for i := 0; i < b.N; i++ { 651 buf.Reset() 652 Write(w, BigEndian, s.Int8) 653 Write(w, BigEndian, s.Int16) 654 Write(w, BigEndian, s.Int32) 655 Write(w, BigEndian, s.Int64) 656 Write(w, BigEndian, s.Uint8) 657 Write(w, BigEndian, s.Uint16) 658 Write(w, BigEndian, s.Uint32) 659 Write(w, BigEndian, s.Uint64) 660 } 661 b.StopTimer() 662 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) { 663 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30]) 664 } 665 } 666 667 func BenchmarkWriteSlice1000Int32s(b *testing.B) { 668 slice := make([]int32, 1000) 669 buf := new(bytes.Buffer) 670 var w io.Writer = buf 671 b.SetBytes(4 * 1000) 672 b.ResetTimer() 673 for i := 0; i < b.N; i++ { 674 buf.Reset() 675 Write(w, BigEndian, slice) 676 } 677 b.StopTimer() 678 } 679 680 func BenchmarkPutUint16(b *testing.B) { 681 b.SetBytes(2) 682 for i := 0; i < b.N; i++ { 683 BigEndian.PutUint16(putbuf[:2], uint16(i)) 684 } 685 } 686 687 func BenchmarkAppendUint16(b *testing.B) { 688 b.SetBytes(2) 689 for i := 0; i < b.N; i++ { 690 putbuf = BigEndian.AppendUint16(putbuf[:0], uint16(i)) 691 } 692 } 693 694 func BenchmarkPutUint32(b *testing.B) { 695 b.SetBytes(4) 696 for i := 0; i < b.N; i++ { 697 BigEndian.PutUint32(putbuf[:4], uint32(i)) 698 } 699 } 700 701 func BenchmarkAppendUint32(b *testing.B) { 702 b.SetBytes(4) 703 for i := 0; i < b.N; i++ { 704 putbuf = BigEndian.AppendUint32(putbuf[:0], uint32(i)) 705 } 706 } 707 708 func BenchmarkPutUint64(b *testing.B) { 709 b.SetBytes(8) 710 for i := 0; i < b.N; i++ { 711 BigEndian.PutUint64(putbuf[:8], uint64(i)) 712 } 713 } 714 715 func BenchmarkAppendUint64(b *testing.B) { 716 b.SetBytes(8) 717 for i := 0; i < b.N; i++ { 718 putbuf = BigEndian.AppendUint64(putbuf[:0], uint64(i)) 719 } 720 } 721 722 func BenchmarkLittleEndianPutUint16(b *testing.B) { 723 b.SetBytes(2) 724 for i := 0; i < b.N; i++ { 725 LittleEndian.PutUint16(putbuf[:2], uint16(i)) 726 } 727 } 728 729 func BenchmarkLittleEndianAppendUint16(b *testing.B) { 730 b.SetBytes(2) 731 for i := 0; i < b.N; i++ { 732 putbuf = LittleEndian.AppendUint16(putbuf[:0], uint16(i)) 733 } 734 } 735 736 func BenchmarkLittleEndianPutUint32(b *testing.B) { 737 b.SetBytes(4) 738 for i := 0; i < b.N; i++ { 739 LittleEndian.PutUint32(putbuf[:4], uint32(i)) 740 } 741 } 742 743 func BenchmarkLittleEndianAppendUint32(b *testing.B) { 744 b.SetBytes(4) 745 for i := 0; i < b.N; i++ { 746 putbuf = LittleEndian.AppendUint32(putbuf[:0], uint32(i)) 747 } 748 } 749 750 func BenchmarkLittleEndianPutUint64(b *testing.B) { 751 b.SetBytes(8) 752 for i := 0; i < b.N; i++ { 753 LittleEndian.PutUint64(putbuf[:8], uint64(i)) 754 } 755 } 756 757 func BenchmarkLittleEndianAppendUint64(b *testing.B) { 758 b.SetBytes(8) 759 for i := 0; i < b.N; i++ { 760 putbuf = LittleEndian.AppendUint64(putbuf[:0], uint64(i)) 761 } 762 } 763 764 func BenchmarkReadFloats(b *testing.B) { 765 var ls Struct 766 bsr := &byteSliceReader{} 767 var r io.Reader = bsr 768 b.SetBytes(4 + 8) 769 b.ResetTimer() 770 for i := 0; i < b.N; i++ { 771 bsr.remain = big[30:] 772 Read(r, BigEndian, &ls.Float32) 773 Read(r, BigEndian, &ls.Float64) 774 } 775 b.StopTimer() 776 want := s 777 want.Int8 = 0 778 want.Int16 = 0 779 want.Int32 = 0 780 want.Int64 = 0 781 want.Uint8 = 0 782 want.Uint16 = 0 783 want.Uint32 = 0 784 want.Uint64 = 0 785 want.Complex64 = 0 786 want.Complex128 = 0 787 want.Array = [4]uint8{0, 0, 0, 0} 788 want.Bool = false 789 want.BoolArray = [4]bool{false, false, false, false} 790 if b.N > 0 && !reflect.DeepEqual(ls, want) { 791 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want) 792 } 793 } 794 795 func BenchmarkWriteFloats(b *testing.B) { 796 buf := new(bytes.Buffer) 797 var w io.Writer = buf 798 b.SetBytes(4 + 8) 799 b.ResetTimer() 800 for i := 0; i < b.N; i++ { 801 buf.Reset() 802 Write(w, BigEndian, s.Float32) 803 Write(w, BigEndian, s.Float64) 804 } 805 b.StopTimer() 806 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[30:30+4+8]) { 807 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[30:30+4+8]) 808 } 809 } 810 811 func BenchmarkReadSlice1000Float32s(b *testing.B) { 812 bsr := &byteSliceReader{} 813 slice := make([]float32, 1000) 814 buf := make([]byte, len(slice)*4) 815 b.SetBytes(int64(len(buf))) 816 b.ResetTimer() 817 for i := 0; i < b.N; i++ { 818 bsr.remain = buf 819 Read(bsr, BigEndian, slice) 820 } 821 } 822 823 func BenchmarkWriteSlice1000Float32s(b *testing.B) { 824 slice := make([]float32, 1000) 825 buf := new(bytes.Buffer) 826 var w io.Writer = buf 827 b.SetBytes(4 * 1000) 828 b.ResetTimer() 829 for i := 0; i < b.N; i++ { 830 buf.Reset() 831 Write(w, BigEndian, slice) 832 } 833 b.StopTimer() 834 } 835 836 func BenchmarkReadSlice1000Uint8s(b *testing.B) { 837 bsr := &byteSliceReader{} 838 slice := make([]uint8, 1000) 839 buf := make([]byte, len(slice)) 840 b.SetBytes(int64(len(buf))) 841 b.ResetTimer() 842 for i := 0; i < b.N; i++ { 843 bsr.remain = buf 844 Read(bsr, BigEndian, slice) 845 } 846 } 847 848 func BenchmarkWriteSlice1000Uint8s(b *testing.B) { 849 slice := make([]uint8, 1000) 850 buf := new(bytes.Buffer) 851 var w io.Writer = buf 852 b.SetBytes(1000) 853 b.ResetTimer() 854 for i := 0; i < b.N; i++ { 855 buf.Reset() 856 Write(w, BigEndian, slice) 857 } 858 } 859 860 func TestNativeEndian(t *testing.T) { 861 const val = 0x12345678 862 i := uint32(val) 863 s := unsafe.Slice((*byte)(unsafe.Pointer(&i)), unsafe.Sizeof(i)) 864 if v := NativeEndian.Uint32(s); v != val { 865 t.Errorf("NativeEndian.Uint32 returned %#x, expected %#x", v, val) 866 } 867 }