github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/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 func TestSizeInvalid(t *testing.T) { 355 testcases := []any{ 356 int(0), 357 new(int), 358 (*int)(nil), 359 [1]uint{}, 360 new([1]uint), 361 (*[1]uint)(nil), 362 []int{}, 363 []int(nil), 364 new([]int), 365 (*[]int)(nil), 366 } 367 for _, tc := range testcases { 368 if got := Size(tc); got != -1 { 369 t.Errorf("Size(%T) = %d, want -1", tc, got) 370 } 371 } 372 } 373 374 // An attempt to read into a struct with an unexported field will 375 // panic. This is probably not the best choice, but at this point 376 // anything else would be an API change. 377 378 type Unexported struct { 379 a int32 380 } 381 382 func TestUnexportedRead(t *testing.T) { 383 var buf bytes.Buffer 384 u1 := Unexported{a: 1} 385 if err := Write(&buf, LittleEndian, &u1); err != nil { 386 t.Fatal(err) 387 } 388 389 defer func() { 390 if recover() == nil { 391 t.Fatal("did not panic") 392 } 393 }() 394 var u2 Unexported 395 Read(&buf, LittleEndian, &u2) 396 } 397 398 func TestReadErrorMsg(t *testing.T) { 399 var buf bytes.Buffer 400 read := func(data any) { 401 err := Read(&buf, LittleEndian, data) 402 want := "binary.Read: invalid type " + reflect.TypeOf(data).String() 403 if err == nil { 404 t.Errorf("%T: got no error; want %q", data, want) 405 return 406 } 407 if got := err.Error(); got != want { 408 t.Errorf("%T: got %q; want %q", data, got, want) 409 } 410 } 411 read(0) 412 s := new(struct{}) 413 read(&s) 414 p := &s 415 read(&p) 416 } 417 418 func TestReadTruncated(t *testing.T) { 419 const data = "0123456789abcdef" 420 421 var b1 = make([]int32, 4) 422 var b2 struct { 423 A, B, C, D byte 424 E int32 425 F float64 426 } 427 428 for i := 0; i <= len(data); i++ { 429 var errWant error 430 switch i { 431 case 0: 432 errWant = io.EOF 433 case len(data): 434 errWant = nil 435 default: 436 errWant = io.ErrUnexpectedEOF 437 } 438 439 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b1); err != errWant { 440 t.Errorf("Read(%d) with slice: got %v, want %v", i, err, errWant) 441 } 442 if err := Read(strings.NewReader(data[:i]), LittleEndian, &b2); err != errWant { 443 t.Errorf("Read(%d) with struct: got %v, want %v", i, err, errWant) 444 } 445 } 446 } 447 448 func testUint64SmallSliceLengthPanics() (panicked bool) { 449 defer func() { 450 panicked = recover() != nil 451 }() 452 b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8} 453 LittleEndian.Uint64(b[:4]) 454 return false 455 } 456 457 func testPutUint64SmallSliceLengthPanics() (panicked bool) { 458 defer func() { 459 panicked = recover() != nil 460 }() 461 b := [8]byte{} 462 LittleEndian.PutUint64(b[:4], 0x0102030405060708) 463 return false 464 } 465 466 func TestByteOrder(t *testing.T) { 467 type byteOrder interface { 468 ByteOrder 469 AppendByteOrder 470 } 471 buf := make([]byte, 8) 472 for _, order := range []byteOrder{LittleEndian, BigEndian} { 473 const offset = 3 474 for _, value := range []uint64{ 475 0x0000000000000000, 476 0x0123456789abcdef, 477 0xfedcba9876543210, 478 0xffffffffffffffff, 479 0xaaaaaaaaaaaaaaaa, 480 math.Float64bits(math.Pi), 481 math.Float64bits(math.E), 482 } { 483 want16 := uint16(value) 484 order.PutUint16(buf[:2], want16) 485 if got := order.Uint16(buf[:2]); got != want16 { 486 t.Errorf("PutUint16: Uint16 = %v, want %v", got, want16) 487 } 488 buf = order.AppendUint16(buf[:offset], want16) 489 if got := order.Uint16(buf[offset:]); got != want16 { 490 t.Errorf("AppendUint16: Uint16 = %v, want %v", got, want16) 491 } 492 if len(buf) != offset+2 { 493 t.Errorf("AppendUint16: len(buf) = %d, want %d", len(buf), offset+2) 494 } 495 496 want32 := uint32(value) 497 order.PutUint32(buf[:4], want32) 498 if got := order.Uint32(buf[:4]); got != want32 { 499 t.Errorf("PutUint32: Uint32 = %v, want %v", got, want32) 500 } 501 buf = order.AppendUint32(buf[:offset], want32) 502 if got := order.Uint32(buf[offset:]); got != want32 { 503 t.Errorf("AppendUint32: Uint32 = %v, want %v", got, want32) 504 } 505 if len(buf) != offset+4 { 506 t.Errorf("AppendUint32: len(buf) = %d, want %d", len(buf), offset+4) 507 } 508 509 want64 := uint64(value) 510 order.PutUint64(buf[:8], want64) 511 if got := order.Uint64(buf[:8]); got != want64 { 512 t.Errorf("PutUint64: Uint64 = %v, want %v", got, want64) 513 } 514 buf = order.AppendUint64(buf[:offset], want64) 515 if got := order.Uint64(buf[offset:]); got != want64 { 516 t.Errorf("AppendUint64: Uint64 = %v, want %v", got, want64) 517 } 518 if len(buf) != offset+8 { 519 t.Errorf("AppendUint64: len(buf) = %d, want %d", len(buf), offset+8) 520 } 521 } 522 } 523 } 524 525 func TestEarlyBoundsChecks(t *testing.T) { 526 if testUint64SmallSliceLengthPanics() != true { 527 t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't") 528 } 529 if testPutUint64SmallSliceLengthPanics() != true { 530 t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't") 531 } 532 } 533 534 func TestReadInvalidDestination(t *testing.T) { 535 testReadInvalidDestination(t, BigEndian) 536 testReadInvalidDestination(t, LittleEndian) 537 } 538 539 func testReadInvalidDestination(t *testing.T, order ByteOrder) { 540 destinations := []any{ 541 int8(0), 542 int16(0), 543 int32(0), 544 int64(0), 545 546 uint8(0), 547 uint16(0), 548 uint32(0), 549 uint64(0), 550 551 bool(false), 552 } 553 554 for _, dst := range destinations { 555 err := Read(bytes.NewReader([]byte{1, 2, 3, 4, 5, 6, 7, 8}), order, dst) 556 want := fmt.Sprintf("binary.Read: invalid type %T", dst) 557 if err == nil || err.Error() != want { 558 t.Fatalf("for type %T: got %q; want %q", dst, err, want) 559 } 560 } 561 } 562 563 func TestNoFixedSize(t *testing.T) { 564 type Person struct { 565 Age int 566 Weight float64 567 Height float64 568 } 569 570 person := Person{ 571 Age: 27, 572 Weight: 67.3, 573 Height: 177.8, 574 } 575 576 buf := new(bytes.Buffer) 577 err := Write(buf, LittleEndian, &person) 578 if err == nil { 579 t.Fatal("binary.Write: unexpected success as size of type *binary.Person is not fixed") 580 } 581 errs := "binary.Write: some values are not fixed-sized in type *binary.Person" 582 if err.Error() != errs { 583 t.Fatalf("got %q, want %q", err, errs) 584 } 585 } 586 587 type byteSliceReader struct { 588 remain []byte 589 } 590 591 func (br *byteSliceReader) Read(p []byte) (int, error) { 592 n := copy(p, br.remain) 593 br.remain = br.remain[n:] 594 return n, nil 595 } 596 597 func BenchmarkReadSlice1000Int32s(b *testing.B) { 598 bsr := &byteSliceReader{} 599 slice := make([]int32, 1000) 600 buf := make([]byte, len(slice)*4) 601 b.SetBytes(int64(len(buf))) 602 b.ResetTimer() 603 for i := 0; i < b.N; i++ { 604 bsr.remain = buf 605 Read(bsr, BigEndian, slice) 606 } 607 } 608 609 func BenchmarkReadStruct(b *testing.B) { 610 bsr := &byteSliceReader{} 611 var buf bytes.Buffer 612 Write(&buf, BigEndian, &s) 613 b.SetBytes(int64(dataSize(reflect.ValueOf(s)))) 614 t := s 615 b.ResetTimer() 616 for i := 0; i < b.N; i++ { 617 bsr.remain = buf.Bytes() 618 Read(bsr, BigEndian, &t) 619 } 620 b.StopTimer() 621 if b.N > 0 && !reflect.DeepEqual(s, t) { 622 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t, s) 623 } 624 } 625 626 func BenchmarkWriteStruct(b *testing.B) { 627 b.SetBytes(int64(Size(&s))) 628 b.ResetTimer() 629 for i := 0; i < b.N; i++ { 630 Write(io.Discard, BigEndian, &s) 631 } 632 } 633 634 func BenchmarkWriteSlice1000Structs(b *testing.B) { 635 slice := make([]Struct, 1000) 636 buf := new(bytes.Buffer) 637 var w io.Writer = buf 638 b.SetBytes(int64(Size(slice))) 639 b.ResetTimer() 640 for i := 0; i < b.N; i++ { 641 buf.Reset() 642 Write(w, BigEndian, slice) 643 } 644 b.StopTimer() 645 } 646 647 func BenchmarkReadSlice1000Structs(b *testing.B) { 648 bsr := &byteSliceReader{} 649 slice := make([]Struct, 1000) 650 buf := make([]byte, Size(slice)) 651 b.SetBytes(int64(len(buf))) 652 b.ResetTimer() 653 for i := 0; i < b.N; i++ { 654 bsr.remain = buf 655 Read(bsr, BigEndian, slice) 656 } 657 } 658 659 func BenchmarkReadInts(b *testing.B) { 660 var ls Struct 661 bsr := &byteSliceReader{} 662 var r io.Reader = bsr 663 b.SetBytes(2 * (1 + 2 + 4 + 8)) 664 b.ResetTimer() 665 for i := 0; i < b.N; i++ { 666 bsr.remain = big 667 Read(r, BigEndian, &ls.Int8) 668 Read(r, BigEndian, &ls.Int16) 669 Read(r, BigEndian, &ls.Int32) 670 Read(r, BigEndian, &ls.Int64) 671 Read(r, BigEndian, &ls.Uint8) 672 Read(r, BigEndian, &ls.Uint16) 673 Read(r, BigEndian, &ls.Uint32) 674 Read(r, BigEndian, &ls.Uint64) 675 } 676 b.StopTimer() 677 want := s 678 want.Float32 = 0 679 want.Float64 = 0 680 want.Complex64 = 0 681 want.Complex128 = 0 682 want.Array = [4]uint8{0, 0, 0, 0} 683 want.Bool = false 684 want.BoolArray = [4]bool{false, false, false, false} 685 if b.N > 0 && !reflect.DeepEqual(ls, want) { 686 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want) 687 } 688 } 689 690 func BenchmarkWriteInts(b *testing.B) { 691 buf := new(bytes.Buffer) 692 var w io.Writer = buf 693 b.SetBytes(2 * (1 + 2 + 4 + 8)) 694 b.ResetTimer() 695 for i := 0; i < b.N; i++ { 696 buf.Reset() 697 Write(w, BigEndian, s.Int8) 698 Write(w, BigEndian, s.Int16) 699 Write(w, BigEndian, s.Int32) 700 Write(w, BigEndian, s.Int64) 701 Write(w, BigEndian, s.Uint8) 702 Write(w, BigEndian, s.Uint16) 703 Write(w, BigEndian, s.Uint32) 704 Write(w, BigEndian, s.Uint64) 705 } 706 b.StopTimer() 707 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) { 708 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30]) 709 } 710 } 711 712 func BenchmarkWriteSlice1000Int32s(b *testing.B) { 713 slice := make([]int32, 1000) 714 buf := new(bytes.Buffer) 715 var w io.Writer = buf 716 b.SetBytes(4 * 1000) 717 b.ResetTimer() 718 for i := 0; i < b.N; i++ { 719 buf.Reset() 720 Write(w, BigEndian, slice) 721 } 722 b.StopTimer() 723 } 724 725 func BenchmarkPutUint16(b *testing.B) { 726 b.SetBytes(2) 727 for i := 0; i < b.N; i++ { 728 BigEndian.PutUint16(putbuf[:2], uint16(i)) 729 } 730 } 731 732 func BenchmarkAppendUint16(b *testing.B) { 733 b.SetBytes(2) 734 for i := 0; i < b.N; i++ { 735 putbuf = BigEndian.AppendUint16(putbuf[:0], uint16(i)) 736 } 737 } 738 739 func BenchmarkPutUint32(b *testing.B) { 740 b.SetBytes(4) 741 for i := 0; i < b.N; i++ { 742 BigEndian.PutUint32(putbuf[:4], uint32(i)) 743 } 744 } 745 746 func BenchmarkAppendUint32(b *testing.B) { 747 b.SetBytes(4) 748 for i := 0; i < b.N; i++ { 749 putbuf = BigEndian.AppendUint32(putbuf[:0], uint32(i)) 750 } 751 } 752 753 func BenchmarkPutUint64(b *testing.B) { 754 b.SetBytes(8) 755 for i := 0; i < b.N; i++ { 756 BigEndian.PutUint64(putbuf[:8], uint64(i)) 757 } 758 } 759 760 func BenchmarkAppendUint64(b *testing.B) { 761 b.SetBytes(8) 762 for i := 0; i < b.N; i++ { 763 putbuf = BigEndian.AppendUint64(putbuf[:0], uint64(i)) 764 } 765 } 766 767 func BenchmarkLittleEndianPutUint16(b *testing.B) { 768 b.SetBytes(2) 769 for i := 0; i < b.N; i++ { 770 LittleEndian.PutUint16(putbuf[:2], uint16(i)) 771 } 772 } 773 774 func BenchmarkLittleEndianAppendUint16(b *testing.B) { 775 b.SetBytes(2) 776 for i := 0; i < b.N; i++ { 777 putbuf = LittleEndian.AppendUint16(putbuf[:0], uint16(i)) 778 } 779 } 780 781 func BenchmarkLittleEndianPutUint32(b *testing.B) { 782 b.SetBytes(4) 783 for i := 0; i < b.N; i++ { 784 LittleEndian.PutUint32(putbuf[:4], uint32(i)) 785 } 786 } 787 788 func BenchmarkLittleEndianAppendUint32(b *testing.B) { 789 b.SetBytes(4) 790 for i := 0; i < b.N; i++ { 791 putbuf = LittleEndian.AppendUint32(putbuf[:0], uint32(i)) 792 } 793 } 794 795 func BenchmarkLittleEndianPutUint64(b *testing.B) { 796 b.SetBytes(8) 797 for i := 0; i < b.N; i++ { 798 LittleEndian.PutUint64(putbuf[:8], uint64(i)) 799 } 800 } 801 802 func BenchmarkLittleEndianAppendUint64(b *testing.B) { 803 b.SetBytes(8) 804 for i := 0; i < b.N; i++ { 805 putbuf = LittleEndian.AppendUint64(putbuf[:0], uint64(i)) 806 } 807 } 808 809 func BenchmarkReadFloats(b *testing.B) { 810 var ls Struct 811 bsr := &byteSliceReader{} 812 var r io.Reader = bsr 813 b.SetBytes(4 + 8) 814 b.ResetTimer() 815 for i := 0; i < b.N; i++ { 816 bsr.remain = big[30:] 817 Read(r, BigEndian, &ls.Float32) 818 Read(r, BigEndian, &ls.Float64) 819 } 820 b.StopTimer() 821 want := s 822 want.Int8 = 0 823 want.Int16 = 0 824 want.Int32 = 0 825 want.Int64 = 0 826 want.Uint8 = 0 827 want.Uint16 = 0 828 want.Uint32 = 0 829 want.Uint64 = 0 830 want.Complex64 = 0 831 want.Complex128 = 0 832 want.Array = [4]uint8{0, 0, 0, 0} 833 want.Bool = false 834 want.BoolArray = [4]bool{false, false, false, false} 835 if b.N > 0 && !reflect.DeepEqual(ls, want) { 836 b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want) 837 } 838 } 839 840 func BenchmarkWriteFloats(b *testing.B) { 841 buf := new(bytes.Buffer) 842 var w io.Writer = buf 843 b.SetBytes(4 + 8) 844 b.ResetTimer() 845 for i := 0; i < b.N; i++ { 846 buf.Reset() 847 Write(w, BigEndian, s.Float32) 848 Write(w, BigEndian, s.Float64) 849 } 850 b.StopTimer() 851 if b.N > 0 && !bytes.Equal(buf.Bytes(), big[30:30+4+8]) { 852 b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[30:30+4+8]) 853 } 854 } 855 856 func BenchmarkReadSlice1000Float32s(b *testing.B) { 857 bsr := &byteSliceReader{} 858 slice := make([]float32, 1000) 859 buf := make([]byte, len(slice)*4) 860 b.SetBytes(int64(len(buf))) 861 b.ResetTimer() 862 for i := 0; i < b.N; i++ { 863 bsr.remain = buf 864 Read(bsr, BigEndian, slice) 865 } 866 } 867 868 func BenchmarkWriteSlice1000Float32s(b *testing.B) { 869 slice := make([]float32, 1000) 870 buf := new(bytes.Buffer) 871 var w io.Writer = buf 872 b.SetBytes(4 * 1000) 873 b.ResetTimer() 874 for i := 0; i < b.N; i++ { 875 buf.Reset() 876 Write(w, BigEndian, slice) 877 } 878 b.StopTimer() 879 } 880 881 func BenchmarkReadSlice1000Uint8s(b *testing.B) { 882 bsr := &byteSliceReader{} 883 slice := make([]uint8, 1000) 884 buf := make([]byte, len(slice)) 885 b.SetBytes(int64(len(buf))) 886 b.ResetTimer() 887 for i := 0; i < b.N; i++ { 888 bsr.remain = buf 889 Read(bsr, BigEndian, slice) 890 } 891 } 892 893 func BenchmarkWriteSlice1000Uint8s(b *testing.B) { 894 slice := make([]uint8, 1000) 895 buf := new(bytes.Buffer) 896 var w io.Writer = buf 897 b.SetBytes(1000) 898 b.ResetTimer() 899 for i := 0; i < b.N; i++ { 900 buf.Reset() 901 Write(w, BigEndian, slice) 902 } 903 } 904 905 func TestNativeEndian(t *testing.T) { 906 const val = 0x12345678 907 i := uint32(val) 908 s := unsafe.Slice((*byte)(unsafe.Pointer(&i)), unsafe.Sizeof(i)) 909 if v := NativeEndian.Uint32(s); v != val { 910 t.Errorf("NativeEndian.Uint32 returned %#x, expected %#x", v, val) 911 } 912 }