go-hep.org/x/hep@v0.38.1/groot/rbytes/wbuffer_test.go (about) 1 // Copyright ©2018 The go-hep 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 rbytes 6 7 import ( 8 "fmt" 9 "math" 10 "reflect" 11 "strings" 12 "testing" 13 ) 14 15 func TestWBufferGrow(t *testing.T) { 16 buf := new(WBuffer) 17 if len(buf.w.p) != 0 { 18 t.Fatalf("got=%d, want 0-size buffer", len(buf.w.p)) 19 } 20 21 buf.w.grow(8) 22 if got, want := len(buf.w.p), 8; got != want { 23 t.Fatalf("got=%d, want=%d buffer len-size", got, want) 24 } 25 26 buf.w.grow(8) 27 if got, want := len(buf.w.p), 2*8; got != want { 28 t.Fatalf("got=%d, want=%d buffer len-size", got, want) 29 } 30 31 buf.w.grow(1) 32 if got, want := len(buf.w.p), 2*8+1; got != want { 33 t.Fatalf("got=%d, want=%d buffer len-size", got, want) 34 } 35 36 buf.w.grow(0) 37 if got, want := len(buf.w.p), 2*8+1; got != want { 38 t.Fatalf("got=%d, want=%d buffer len-size", got, want) 39 } 40 if got, want := cap(buf.w.p), 8*1024; got != want { 41 t.Fatalf("got=%d, want=%d buffer cap-size", got, want) 42 } 43 44 const n = 10 * 1024 45 buf.w.grow(n) 46 if got, want := len(buf.w.p), 2*8+1+n; got != want { 47 t.Fatalf("got=%d, want=%d buffer len-size", got, want) 48 } 49 if got, want := cap(buf.w.p), 8*4*1024; got != want { 50 t.Fatalf("got=%d, want=%d buffer cap-size", got, want) 51 } 52 53 defer func() { 54 e := recover() 55 if e == nil { 56 t.Fatalf("expected a panic") 57 } 58 }() 59 60 buf.w.grow(-1) 61 } 62 63 func TestWBuffer_WriteBool(t *testing.T) { 64 wbuf := NewWBuffer(nil, nil, 0, nil) 65 want := true 66 wbuf.WriteBool(want) 67 rbuf := NewRBuffer(wbuf.w.p, nil, 0, nil) 68 got := rbuf.ReadBool() 69 if got != want { 70 t.Fatalf("Invalid value. got:%v, want:%v", got, want) 71 } 72 } 73 74 func TestWBuffer_WriteString(t *testing.T) { 75 for _, i := range []int{0, 1, 2, 8, 16, 32, 64, 128, 253, 254, 255, 256, 512} { 76 t.Run(fmt.Sprintf("str-%03d", i), func(t *testing.T) { 77 wbuf := NewWBuffer(nil, nil, 0, nil) 78 want := strings.Repeat("=", i) 79 wbuf.WriteString(want) 80 rbuf := NewRBuffer(wbuf.w.p, nil, 0, nil) 81 got := rbuf.ReadString() 82 if got != want { 83 t.Fatalf("Invalid value for len=%d.\ngot: %q\nwant:%q", i, got, want) 84 } 85 }) 86 } 87 } 88 89 func TestWBuffer_WriteCString(t *testing.T) { 90 wbuf := NewWBuffer(nil, nil, 0, nil) 91 want := "hello" 92 cstr := string(append([]byte(want), 0)) 93 wbuf.WriteCString(cstr) 94 rbuf := NewRBuffer(wbuf.w.p, nil, 0, nil) 95 96 got := rbuf.ReadCString(len(cstr)) 97 if want != got { 98 t.Fatalf("got=%q, want=%q", got, want) 99 } 100 } 101 102 func TestWBufferEmpty(t *testing.T) { 103 wbuf := new(WBuffer) 104 wbuf.WriteString(string([]byte{1, 2, 3, 4, 5})) 105 if wbuf.Err() != nil { 106 t.Fatalf("err: %v, buf=%v", wbuf.Err(), wbuf.w.p) 107 } 108 } 109 110 func TestWBuffer_Write(t *testing.T) { 111 for _, tc := range []struct { 112 name string 113 want any 114 wfct func(*WBuffer, any) 115 rfct func(*RBuffer) any 116 cmp func(a, b any) bool 117 }{ 118 { 119 name: "bool-true", 120 want: true, 121 wfct: func(w *WBuffer, v any) { 122 w.WriteBool(v.(bool)) 123 }, 124 rfct: func(r *RBuffer) any { 125 return r.ReadBool() 126 }, 127 }, 128 { 129 name: "bool-false", 130 want: false, 131 wfct: func(w *WBuffer, v any) { 132 w.WriteBool(v.(bool)) 133 }, 134 rfct: func(r *RBuffer) any { 135 return r.ReadBool() 136 }, 137 }, 138 { 139 name: "int8", 140 want: int8(42), 141 wfct: func(w *WBuffer, v any) { 142 w.WriteI8(v.(int8)) 143 }, 144 rfct: func(r *RBuffer) any { 145 return r.ReadI8() 146 }, 147 }, 148 { 149 name: "int16", 150 want: int16(42), 151 wfct: func(w *WBuffer, v any) { 152 w.WriteI16(v.(int16)) 153 }, 154 rfct: func(r *RBuffer) any { 155 return r.ReadI16() 156 }, 157 }, 158 { 159 name: "int32", 160 want: int32(42), 161 wfct: func(w *WBuffer, v any) { 162 w.WriteI32(v.(int32)) 163 }, 164 rfct: func(r *RBuffer) any { 165 return r.ReadI32() 166 }, 167 }, 168 { 169 name: "int64", 170 want: int64(42), 171 wfct: func(w *WBuffer, v any) { 172 w.WriteI64(v.(int64)) 173 }, 174 rfct: func(r *RBuffer) any { 175 return r.ReadI64() 176 }, 177 }, 178 { 179 name: "uint8", 180 want: uint8(42), 181 wfct: func(w *WBuffer, v any) { 182 w.WriteU8(v.(uint8)) 183 }, 184 rfct: func(r *RBuffer) any { 185 return r.ReadU8() 186 }, 187 }, 188 { 189 name: "uint16", 190 want: uint16(42), 191 wfct: func(w *WBuffer, v any) { 192 w.WriteU16(v.(uint16)) 193 }, 194 rfct: func(r *RBuffer) any { 195 return r.ReadU16() 196 }, 197 }, 198 { 199 name: "uint32", 200 want: uint32(42), 201 wfct: func(w *WBuffer, v any) { 202 w.WriteU32(v.(uint32)) 203 }, 204 rfct: func(r *RBuffer) any { 205 return r.ReadU32() 206 }, 207 }, 208 { 209 name: "uint64", 210 want: uint64(42), 211 wfct: func(w *WBuffer, v any) { 212 w.WriteU64(v.(uint64)) 213 }, 214 rfct: func(r *RBuffer) any { 215 return r.ReadU64() 216 }, 217 }, 218 { 219 name: "float32", 220 want: float32(42), 221 wfct: func(w *WBuffer, v any) { 222 w.WriteF32(v.(float32)) 223 }, 224 rfct: func(r *RBuffer) any { 225 return r.ReadF32() 226 }, 227 }, 228 { 229 name: "float32-nan", 230 want: float32(math.NaN()), 231 wfct: func(w *WBuffer, v any) { 232 w.WriteF32(v.(float32)) 233 }, 234 rfct: func(r *RBuffer) any { 235 return r.ReadF32() 236 }, 237 cmp: func(a, b any) bool { 238 return math.IsNaN(float64(a.(float32))) && math.IsNaN(float64(b.(float32))) 239 }, 240 }, 241 { 242 name: "float32-inf", 243 want: float32(math.Inf(-1)), 244 wfct: func(w *WBuffer, v any) { 245 w.WriteF32(v.(float32)) 246 }, 247 rfct: func(r *RBuffer) any { 248 return r.ReadF32() 249 }, 250 cmp: func(a, b any) bool { 251 return math.IsInf(float64(a.(float32)), -1) && math.IsInf(float64(b.(float32)), -1) 252 }, 253 }, 254 { 255 name: "float32+inf", 256 want: float32(math.Inf(+1)), 257 wfct: func(w *WBuffer, v any) { 258 w.WriteF32(v.(float32)) 259 }, 260 rfct: func(r *RBuffer) any { 261 return r.ReadF32() 262 }, 263 cmp: func(a, b any) bool { 264 return math.IsInf(float64(a.(float32)), +1) && math.IsInf(float64(b.(float32)), +1) 265 }, 266 }, 267 { 268 name: "float64", 269 want: float64(42), 270 wfct: func(w *WBuffer, v any) { 271 w.WriteF64(v.(float64)) 272 }, 273 rfct: func(r *RBuffer) any { 274 return r.ReadF64() 275 }, 276 }, 277 { 278 name: "float64-nan", 279 want: math.NaN(), 280 wfct: func(w *WBuffer, v any) { 281 w.WriteF64(v.(float64)) 282 }, 283 rfct: func(r *RBuffer) any { 284 return r.ReadF64() 285 }, 286 cmp: func(a, b any) bool { 287 return math.IsNaN(a.(float64)) && math.IsNaN(b.(float64)) 288 }, 289 }, 290 { 291 name: "float64-inf", 292 want: math.Inf(-1), 293 wfct: func(w *WBuffer, v any) { 294 w.WriteF64(v.(float64)) 295 }, 296 rfct: func(r *RBuffer) any { 297 return r.ReadF64() 298 }, 299 cmp: func(a, b any) bool { 300 return math.IsInf(a.(float64), -1) && math.IsInf(b.(float64), -1) 301 }, 302 }, 303 { 304 name: "float64+inf", 305 want: math.Inf(+1), 306 wfct: func(w *WBuffer, v any) { 307 w.WriteF64(v.(float64)) 308 }, 309 rfct: func(r *RBuffer) any { 310 return r.ReadF64() 311 }, 312 cmp: func(a, b any) bool { 313 return math.IsInf(a.(float64), +1) && math.IsInf(b.(float64), +1) 314 }, 315 }, 316 { 317 name: "cstring-1", 318 want: "hello world", 319 wfct: func(w *WBuffer, v any) { 320 w.WriteCString(v.(string)) 321 }, 322 rfct: func(r *RBuffer) any { 323 return r.ReadCString(len("hello world")) 324 }, 325 }, 326 { 327 name: "cstring-2", 328 want: "hello world", 329 wfct: func(w *WBuffer, v any) { 330 w.WriteCString(v.(string)) 331 }, 332 rfct: func(r *RBuffer) any { 333 return r.ReadCString(len("hello world") + 1) 334 }, 335 }, 336 { 337 name: "cstring-3", 338 want: "hello world", 339 wfct: func(w *WBuffer, v any) { 340 w.WriteCString(v.(string)) 341 }, 342 rfct: func(r *RBuffer) any { 343 return r.ReadCString(len("hello world") + 10) 344 }, 345 }, 346 { 347 name: "cstring-4", 348 want: "hello", 349 wfct: func(w *WBuffer, v any) { 350 w.WriteCString(v.(string)) 351 }, 352 rfct: func(r *RBuffer) any { 353 return r.ReadCString(len("hello")) 354 }, 355 }, 356 { 357 name: "cstring-5", 358 want: string([]byte{1, 2, 3, 4}), 359 wfct: func(w *WBuffer, v any) { 360 w.WriteCString(v.(string)) 361 }, 362 rfct: func(r *RBuffer) any { 363 return r.ReadCString(len([]byte{1, 2, 3, 4, 0, 1})) 364 }, 365 }, 366 { 367 name: "std::string-1", 368 want: "hello", 369 wfct: func(w *WBuffer, v any) { 370 w.WriteStdString(v.(string)) 371 }, 372 rfct: func(r *RBuffer) any { 373 return r.ReadStdString() 374 }, 375 }, 376 { 377 name: "std::string-2", 378 want: strings.Repeat("hello", 256), 379 wfct: func(w *WBuffer, v any) { 380 w.WriteStdString(v.(string)) 381 }, 382 rfct: func(r *RBuffer) any { 383 return r.ReadStdString() 384 }, 385 }, 386 { 387 name: "static-arr-i32", 388 want: []int32{1, 2, 0, 2, 1}, 389 wfct: func(w *WBuffer, v any) { 390 w.WriteStaticArrayI32(v.([]int32)) 391 }, 392 rfct: func(r *RBuffer) any { 393 return r.ReadStaticArrayI32() 394 }, 395 }, 396 { 397 name: "fast-arr-bool", 398 want: []bool{true, false, false, true, false}, 399 wfct: func(w *WBuffer, v any) { 400 w.WriteArrayBool(v.([]bool)) 401 }, 402 rfct: func(r *RBuffer) any { 403 sli := make([]bool, 5) 404 r.ReadArrayBool(sli) 405 return sli 406 }, 407 }, 408 { 409 name: "fast-arr-i8", 410 want: []int8{1, 2, 0, 2, 1}, 411 wfct: func(w *WBuffer, v any) { 412 w.WriteArrayI8(v.([]int8)) 413 }, 414 rfct: func(r *RBuffer) any { 415 sli := make([]int8, 5) 416 r.ReadArrayI8(sli) 417 return sli 418 }, 419 }, 420 { 421 name: "fast-arr-i16", 422 want: []int16{1, 2, 0, 2, 1}, 423 wfct: func(w *WBuffer, v any) { 424 w.WriteArrayI16(v.([]int16)) 425 }, 426 rfct: func(r *RBuffer) any { 427 sli := make([]int16, 5) 428 r.ReadArrayI16(sli) 429 return sli 430 }, 431 }, 432 { 433 name: "fast-arr-i32", 434 want: []int32{1, 2, 0, 2, 1}, 435 wfct: func(w *WBuffer, v any) { 436 w.WriteArrayI32(v.([]int32)) 437 }, 438 rfct: func(r *RBuffer) any { 439 sli := make([]int32, 5) 440 r.ReadArrayI32(sli) 441 return sli 442 }, 443 }, 444 { 445 name: "fast-arr-i64", 446 want: []int64{1, 2, 0, 2, 1}, 447 wfct: func(w *WBuffer, v any) { 448 w.WriteArrayI64(v.([]int64)) 449 }, 450 rfct: func(r *RBuffer) any { 451 sli := make([]int64, 5) 452 r.ReadArrayI64(sli) 453 return sli 454 }, 455 }, 456 { 457 name: "fast-arr-u8", 458 want: []uint8{1, 2, 0, 2, 1}, 459 wfct: func(w *WBuffer, v any) { 460 w.WriteArrayU8(v.([]uint8)) 461 }, 462 rfct: func(r *RBuffer) any { 463 sli := make([]uint8, 5) 464 r.ReadArrayU8(sli) 465 return sli 466 }, 467 }, 468 { 469 name: "fast-arr-u16", 470 want: []uint16{1, 2, 0, 2, 1}, 471 wfct: func(w *WBuffer, v any) { 472 w.WriteArrayU16(v.([]uint16)) 473 }, 474 rfct: func(r *RBuffer) any { 475 sli := make([]uint16, 5) 476 r.ReadArrayU16(sli) 477 return sli 478 }, 479 }, 480 { 481 name: "fast-arr-u32", 482 want: []uint32{1, 2, 0, 2, 1}, 483 wfct: func(w *WBuffer, v any) { 484 w.WriteArrayU32(v.([]uint32)) 485 }, 486 rfct: func(r *RBuffer) any { 487 sli := make([]uint32, 5) 488 r.ReadArrayU32(sli) 489 return sli 490 }, 491 }, 492 { 493 name: "fast-arr-u64", 494 want: []uint64{1, 2, 0, 2, 1}, 495 wfct: func(w *WBuffer, v any) { 496 w.WriteArrayU64(v.([]uint64)) 497 }, 498 rfct: func(r *RBuffer) any { 499 sli := make([]uint64, 5) 500 r.ReadArrayU64(sli) 501 return sli 502 }, 503 }, 504 { 505 name: "fast-arr-f32", 506 want: []float32{1, 2, 0, 2, 1}, 507 wfct: func(w *WBuffer, v any) { 508 w.WriteArrayF32(v.([]float32)) 509 }, 510 rfct: func(r *RBuffer) any { 511 sli := make([]float32, 5) 512 r.ReadArrayF32(sli) 513 return sli 514 }, 515 }, 516 { 517 name: "fast-arr-f32-nan+inf-inf", 518 want: []float32{1, float32(math.Inf(+1)), 0, float32(math.NaN()), float32(math.Inf(-1))}, 519 wfct: func(w *WBuffer, v any) { 520 w.WriteArrayF32(v.([]float32)) 521 }, 522 rfct: func(r *RBuffer) any { 523 sli := make([]float32, 5) 524 r.ReadArrayF32(sli) 525 return sli 526 }, 527 cmp: func(a, b any) bool { 528 aa := a.([]float32) 529 bb := b.([]float32) 530 if len(aa) != len(bb) { 531 return false 532 } 533 for i := range aa { 534 va := float64(aa[i]) 535 vb := float64(bb[i]) 536 switch { 537 case math.IsNaN(va): 538 if !math.IsNaN(vb) { 539 return false 540 } 541 case math.IsNaN(vb): 542 if !math.IsNaN(va) { 543 return false 544 } 545 case math.IsInf(va, -1): 546 if !math.IsInf(vb, -1) { 547 return false 548 } 549 case math.IsInf(vb, -1): 550 if !math.IsInf(va, -1) { 551 return false 552 } 553 case math.IsInf(va, +1): 554 if !math.IsInf(vb, +1) { 555 return false 556 } 557 case math.IsInf(vb, +1): 558 if !math.IsInf(va, +1) { 559 return false 560 } 561 case va != vb: 562 return false 563 } 564 } 565 return true 566 }, 567 }, 568 { 569 name: "fast-arr-f64", 570 want: []float64{1, 2, 0, 2, 1}, 571 wfct: func(w *WBuffer, v any) { 572 w.WriteArrayF64(v.([]float64)) 573 }, 574 rfct: func(r *RBuffer) any { 575 sli := make([]float64, 5) 576 r.ReadArrayF64(sli) 577 return sli 578 }, 579 }, 580 { 581 name: "fast-arr-f64-nan+inf-inf", 582 want: []float64{1, math.Inf(+1), 0, math.NaN(), math.Inf(-1)}, 583 wfct: func(w *WBuffer, v any) { 584 w.WriteArrayF64(v.([]float64)) 585 }, 586 rfct: func(r *RBuffer) any { 587 sli := make([]float64, 5) 588 r.ReadArrayF64(sli) 589 return sli 590 }, 591 cmp: func(a, b any) bool { 592 aa := a.([]float64) 593 bb := b.([]float64) 594 if len(aa) != len(bb) { 595 return false 596 } 597 for i := range aa { 598 va := aa[i] 599 vb := bb[i] 600 switch { 601 case math.IsNaN(va): 602 if !math.IsNaN(vb) { 603 return false 604 } 605 case math.IsNaN(vb): 606 if !math.IsNaN(va) { 607 return false 608 } 609 case math.IsInf(va, -1): 610 if !math.IsInf(vb, -1) { 611 return false 612 } 613 case math.IsInf(vb, -1): 614 if !math.IsInf(va, -1) { 615 return false 616 } 617 case math.IsInf(va, +1): 618 if !math.IsInf(vb, +1) { 619 return false 620 } 621 case math.IsInf(vb, +1): 622 if !math.IsInf(va, +1) { 623 return false 624 } 625 case va != vb: 626 return false 627 } 628 } 629 return true 630 }, 631 }, 632 { 633 name: "fast-arr-str", 634 want: []string{"hello", "world"}, 635 wfct: func(w *WBuffer, v any) { 636 w.WriteArrayString(v.([]string)) 637 }, 638 rfct: func(r *RBuffer) any { 639 sli := make([]string, 2) 640 r.ReadArrayString(sli) 641 return sli 642 }, 643 }, 644 } { 645 t.Run(tc.name, func(t *testing.T) { 646 wbuf := NewWBuffer(nil, nil, 0, nil) 647 tc.wfct(wbuf, tc.want) 648 if wbuf.Err() != nil { 649 t.Fatalf("error writing to buffer: %v", wbuf.Err()) 650 } 651 rbuf := NewRBuffer(wbuf.w.p, nil, 0, nil) 652 if rbuf.Err() != nil { 653 t.Fatalf("error reading from buffer: %v", rbuf.Err()) 654 } 655 got := tc.rfct(rbuf) 656 cmp := reflect.DeepEqual 657 if tc.cmp != nil { 658 cmp = tc.cmp 659 } 660 if !cmp(tc.want, got) { 661 t.Fatalf("error.\ngot = %v (%T)\nwant= %v (%T)", got, got, tc.want, tc.want) 662 } 663 }) 664 } 665 }