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