github.com/xmidt-org/webpa-common@v1.11.9/semaphore/instrument_test.go (about) 1 package semaphore 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/go-kit/kit/metrics/generic" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestWithResources(t *testing.T) { 14 var ( 15 assert = assert.New(t) 16 io = new(instrumentOptions) 17 18 custom = generic.NewCounter("test") 19 ) 20 21 WithResources(nil)(io) 22 assert.NotNil(io.resources) 23 24 WithResources(custom)(io) 25 assert.Equal(custom, io.resources) 26 } 27 28 func TestWithFailures(t *testing.T) { 29 var ( 30 assert = assert.New(t) 31 io = new(instrumentOptions) 32 33 custom = generic.NewCounter("test") 34 ) 35 36 WithFailures(nil)(io) 37 assert.NotNil(io.failures) 38 39 WithFailures(custom)(io) 40 assert.Equal(custom, io.failures) 41 } 42 43 func TestWithClosed(t *testing.T) { 44 var ( 45 assert = assert.New(t) 46 io = new(instrumentOptions) 47 48 custom = generic.NewGauge("test") 49 ) 50 51 WithClosed(nil)(io) 52 assert.NotNil(io.closed) 53 54 WithClosed(custom)(io) 55 assert.Equal(custom, io.closed) 56 } 57 58 func testInstrumentNilSemaphore(t *testing.T) { 59 assert.Panics(t, 60 func() { 61 Instrument(nil) 62 }, 63 ) 64 } 65 66 func TestInstrument(t *testing.T) { 67 t.Run("NilSemaphore", testInstrumentNilSemaphore) 68 } 69 70 func testInstrumentCloseableNilSemaphore(t *testing.T) { 71 assert.Panics(t, 72 func() { 73 InstrumentCloseable(nil) 74 }, 75 ) 76 } 77 78 func TestInstrumentCloseable(t *testing.T) { 79 t.Run("NilSemaphore", testInstrumentCloseableNilSemaphore) 80 } 81 82 func testInstrumentedSemaphoreAcquireSuccess(t *testing.T) { 83 var ( 84 assert = assert.New(t) 85 resources = generic.NewCounter("test") 86 failures = generic.NewCounter("test") 87 s = Instrument(Mutex(), WithResources(resources), WithFailures(failures)) 88 89 result = make(chan error) 90 ) 91 92 go func() { 93 result <- s.Acquire() 94 }() 95 96 select { 97 case err := <-result: 98 assert.NoError(err) 99 assert.Equal(float64(1.0), resources.Value()) 100 assert.Zero(failures.Value()) 101 102 assert.NoError(s.Release()) 103 assert.Zero(resources.Value()) 104 assert.Zero(failures.Value()) 105 case <-time.After(time.Second): 106 assert.FailNow("Acquire blocked unexpectedly") 107 } 108 } 109 110 func testInstrumentedSemaphoreAcquireFail(t *testing.T) { 111 var ( 112 assert = assert.New(t) 113 resources = generic.NewCounter("test") 114 failures = generic.NewCounter("test") 115 cm = CloseableMutex() 116 s = Instrument(cm, WithResources(resources), WithFailures(failures)) 117 118 result = make(chan error) 119 ) 120 121 go func() { 122 cm.Close() 123 result <- s.Acquire() 124 }() 125 126 select { 127 case err := <-result: 128 assert.Equal(ErrClosed, err) 129 assert.Zero(resources.Value()) 130 assert.Equal(float64(1.0), failures.Value()) 131 132 assert.Equal(ErrClosed, s.Release()) // idempotent 133 assert.Zero(resources.Value()) 134 assert.Equal(float64(1.0), failures.Value()) 135 case <-time.After(time.Second): 136 assert.FailNow("Acquire blocked unexpectedly") 137 } 138 } 139 140 func testInstrumentedSemaphoreTryAcquire(t *testing.T) { 141 var ( 142 assert = assert.New(t) 143 require = require.New(t) 144 resources = generic.NewCounter("test") 145 failures = generic.NewCounter("test") 146 s = Instrument(Mutex(), WithResources(resources), WithFailures(failures)) 147 ) 148 149 assert.Zero(resources.Value()) 150 assert.Zero(failures.Value()) 151 152 require.True(s.TryAcquire()) 153 assert.Equal(float64(1.0), resources.Value()) 154 assert.Zero(failures.Value()) 155 156 require.False(s.TryAcquire()) 157 assert.Equal(float64(1.0), resources.Value()) 158 assert.Equal(float64(1.0), failures.Value()) 159 160 assert.NoError(s.Release()) 161 assert.Zero(resources.Value()) 162 assert.Equal(float64(1.0), failures.Value()) 163 } 164 165 func testInstrumentedSemaphoreAcquireWaitSuccess(t *testing.T) { 166 var ( 167 assert = assert.New(t) 168 resources = generic.NewCounter("test") 169 failures = generic.NewCounter("test") 170 s = Instrument(Mutex(), WithResources(resources), WithFailures(failures)) 171 172 ready = make(chan struct{}) 173 result = make(chan error) 174 timer = make(chan time.Time) 175 ) 176 177 go func() { 178 s.Acquire() 179 close(ready) 180 result <- s.AcquireWait(timer) 181 }() 182 183 select { 184 case <-ready: 185 assert.Equal(float64(1.0), resources.Value()) 186 assert.Zero(failures.Value()) 187 s.Release() 188 case <-time.After(time.Second): 189 assert.FailNow("Failed to spawn AcquireWait goroutine") 190 } 191 192 select { 193 case err := <-result: 194 assert.NoError(err) 195 assert.Equal(float64(1.0), resources.Value()) 196 assert.Zero(failures.Value()) 197 198 assert.NoError(s.Release()) 199 assert.Zero(resources.Value()) 200 assert.Zero(failures.Value()) 201 case <-time.After(time.Second): 202 assert.FailNow("AcquireWait blocked unexpectedly") 203 } 204 } 205 206 func testInstrumentedSemaphoreAcquireWaitTimeout(t *testing.T) { 207 var ( 208 assert = assert.New(t) 209 resources = generic.NewCounter("test") 210 failures = generic.NewCounter("test") 211 s = Instrument(Mutex(), WithResources(resources), WithFailures(failures)) 212 213 ready = make(chan struct{}) 214 result = make(chan error) 215 timer = make(chan time.Time) 216 ) 217 218 go func() { 219 s.Acquire() 220 close(ready) 221 result <- s.AcquireWait(timer) 222 }() 223 224 select { 225 case <-ready: 226 assert.Equal(float64(1.0), resources.Value()) 227 assert.Zero(failures.Value()) 228 timer <- time.Time{} 229 case <-time.After(time.Second): 230 assert.FailNow("Failed to spawn AcquireWait goroutine") 231 } 232 233 select { 234 case err := <-result: 235 assert.Equal(ErrTimeout, err) 236 assert.Equal(float64(1.0), resources.Value()) 237 assert.Equal(float64(1.0), failures.Value()) 238 239 s.Release() 240 assert.Zero(resources.Value()) 241 assert.Equal(float64(1.0), failures.Value()) 242 case <-time.After(time.Second): 243 assert.FailNow("AcquireWait blocked unexpectedly") 244 } 245 } 246 247 func testInstrumentedSemaphoreAcquireCtxSuccess(t *testing.T) { 248 var ( 249 assert = assert.New(t) 250 resources = generic.NewCounter("test") 251 failures = generic.NewCounter("test") 252 s = Instrument(Mutex(), WithResources(resources), WithFailures(failures)) 253 254 ready = make(chan struct{}) 255 result = make(chan error) 256 ctx, cancel = context.WithCancel(context.Background()) 257 ) 258 259 defer cancel() 260 261 go func() { 262 s.Acquire() 263 close(ready) 264 result <- s.AcquireCtx(ctx) 265 }() 266 267 select { 268 case <-ready: 269 assert.Equal(float64(1.0), resources.Value()) 270 assert.Zero(failures.Value()) 271 s.Release() 272 case <-time.After(time.Second): 273 assert.FailNow("Failed to spawn AcquireCtx goroutine") 274 } 275 276 select { 277 case err := <-result: 278 assert.NoError(err) 279 assert.Equal(float64(1.0), resources.Value()) 280 assert.Zero(failures.Value()) 281 282 s.Release() 283 assert.Zero(resources.Value()) 284 assert.Zero(failures.Value()) 285 case <-time.After(time.Second): 286 assert.FailNow("AcquireCtx blocked unexpectedly") 287 } 288 } 289 290 func testInstrumentedSemaphoreAcquireCtxCancel(t *testing.T) { 291 var ( 292 assert = assert.New(t) 293 resources = generic.NewCounter("test") 294 failures = generic.NewCounter("test") 295 s = Instrument(Mutex(), WithResources(resources), WithFailures(failures)) 296 297 ready = make(chan struct{}) 298 result = make(chan error) 299 ctx, cancel = context.WithCancel(context.Background()) 300 ) 301 302 defer cancel() 303 304 go func() { 305 s.Acquire() 306 close(ready) 307 result <- s.AcquireCtx(ctx) 308 }() 309 310 select { 311 case <-ready: 312 assert.Equal(float64(1.0), resources.Value()) 313 assert.Zero(failures.Value()) 314 cancel() 315 case <-time.After(time.Second): 316 assert.FailNow("Failed to spawn AcquireCtx goroutine") 317 } 318 319 select { 320 case err := <-result: 321 assert.Equal(ctx.Err(), err) 322 assert.Equal(float64(1.0), resources.Value()) 323 assert.Equal(float64(1.0), failures.Value()) 324 325 s.Release() 326 assert.Zero(resources.Value()) 327 assert.Equal(float64(1.0), failures.Value()) 328 case <-time.After(time.Second): 329 assert.FailNow("AcquireCtx blocked unexpectedly") 330 } 331 } 332 333 func TestInstrumentedSemaphore(t *testing.T) { 334 t.Run("Acquire", func(t *testing.T) { 335 t.Run("Success", testInstrumentedSemaphoreAcquireSuccess) 336 t.Run("Fail", testInstrumentedSemaphoreAcquireFail) 337 }) 338 339 t.Run("TryAcquire", testInstrumentedSemaphoreTryAcquire) 340 341 t.Run("AcquireWait", func(t *testing.T) { 342 t.Run("Success", testInstrumentedSemaphoreAcquireWaitSuccess) 343 t.Run("Timeout", testInstrumentedSemaphoreAcquireWaitTimeout) 344 }) 345 346 t.Run("AcquireCtx", func(t *testing.T) { 347 t.Run("Success", testInstrumentedSemaphoreAcquireCtxSuccess) 348 t.Run("Cancel", testInstrumentedSemaphoreAcquireCtxCancel) 349 }) 350 } 351 352 func testInstrumentedCloseableAcquire(t *testing.T) { 353 var ( 354 assert = assert.New(t) 355 resources = generic.NewCounter("test") 356 failures = generic.NewCounter("test") 357 closed = generic.NewGauge("test") 358 s = InstrumentCloseable(CloseableMutex(), WithResources(resources), WithFailures(failures), WithClosed(closed)) 359 360 result = make(chan error) 361 ) 362 363 assert.NotNil(s.Closed()) 364 assert.Equal(MetricOpen, closed.Value()) 365 366 go func() { 367 result <- s.Acquire() 368 }() 369 370 select { 371 case err := <-result: 372 assert.NoError(err) 373 assert.Equal(float64(1.0), resources.Value()) 374 assert.Zero(failures.Value()) 375 assert.Equal(MetricOpen, closed.Value()) 376 377 assert.NoError(s.Release()) 378 assert.Zero(resources.Value()) 379 assert.Zero(failures.Value()) 380 assert.Equal(MetricOpen, closed.Value()) 381 case <-time.After(time.Second): 382 assert.FailNow("Acquire blocked unexpectedly") 383 } 384 385 assert.NoError(s.Close()) 386 assert.Zero(resources.Value()) 387 assert.Zero(failures.Value()) 388 assert.Equal(MetricClosed, closed.Value()) 389 390 assert.Equal(ErrClosed, s.Acquire()) 391 assert.Zero(resources.Value()) 392 assert.Equal(float64(1.0), failures.Value()) 393 assert.Equal(MetricClosed, closed.Value()) 394 395 select { 396 case <-s.Closed(): 397 // passing 398 default: 399 assert.Fail("The Closed channel was not signaled") 400 } 401 } 402 403 func testInstrumentedCloseableTryAcquire(t *testing.T) { 404 var ( 405 assert = assert.New(t) 406 require = require.New(t) 407 resources = generic.NewCounter("test") 408 failures = generic.NewCounter("test") 409 closed = generic.NewGauge("test") 410 s = InstrumentCloseable(CloseableMutex(), WithResources(resources), WithFailures(failures), WithClosed(closed)) 411 ) 412 413 assert.Zero(resources.Value()) 414 assert.Zero(failures.Value()) 415 assert.Equal(MetricOpen, closed.Value()) 416 417 require.True(s.TryAcquire()) 418 assert.Equal(float64(1.0), resources.Value()) 419 assert.Zero(failures.Value()) 420 assert.Equal(MetricOpen, closed.Value()) 421 422 require.False(s.TryAcquire()) 423 assert.Equal(float64(1.0), resources.Value()) 424 assert.Equal(float64(1.0), failures.Value()) 425 assert.Equal(MetricOpen, closed.Value()) 426 427 assert.NoError(s.Release()) 428 assert.Zero(resources.Value()) 429 assert.Equal(float64(1.0), failures.Value()) 430 assert.Equal(MetricOpen, closed.Value()) 431 432 assert.NoError(s.Close()) 433 assert.Zero(resources.Value()) 434 assert.Equal(float64(1.0), failures.Value()) 435 assert.Equal(MetricClosed, closed.Value()) 436 437 assert.False(s.TryAcquire()) 438 assert.Zero(resources.Value()) 439 assert.Equal(float64(2.0), failures.Value()) 440 assert.Equal(MetricClosed, closed.Value()) 441 442 select { 443 case <-s.Closed(): 444 // passing 445 default: 446 assert.Fail("The Closed channel was not signaled") 447 } 448 } 449 450 func testInstrumentedCloseableAcquireWaitSuccess(t *testing.T) { 451 var ( 452 assert = assert.New(t) 453 resources = generic.NewCounter("test") 454 failures = generic.NewCounter("test") 455 closed = generic.NewGauge("test") 456 s = InstrumentCloseable(CloseableMutex(), WithResources(resources), WithFailures(failures), WithClosed(closed)) 457 458 ready = make(chan struct{}) 459 result = make(chan error) 460 timer = make(chan time.Time) 461 ) 462 463 assert.Equal(MetricOpen, closed.Value()) 464 465 go func() { 466 s.Acquire() 467 close(ready) 468 result <- s.AcquireWait(timer) 469 }() 470 471 select { 472 case <-ready: 473 assert.Equal(float64(1.0), resources.Value()) 474 assert.Zero(failures.Value()) 475 assert.Equal(MetricOpen, closed.Value()) 476 s.Release() 477 case <-time.After(time.Second): 478 assert.FailNow("Failed to spawn AcquireWait goroutine") 479 } 480 481 select { 482 case err := <-result: 483 assert.NoError(err) 484 assert.Equal(float64(1.0), resources.Value()) 485 assert.Zero(failures.Value()) 486 assert.Equal(MetricOpen, closed.Value()) 487 488 assert.NoError(s.Release()) 489 assert.Zero(resources.Value()) 490 assert.Zero(failures.Value()) 491 assert.Equal(MetricOpen, closed.Value()) 492 case <-time.After(time.Second): 493 assert.FailNow("AcquireWait blocked unexpectedly") 494 } 495 496 assert.NoError(s.Close()) 497 assert.Zero(resources.Value()) 498 assert.Zero(failures.Value()) 499 assert.Equal(MetricClosed, closed.Value()) 500 501 select { 502 case <-s.Closed(): 503 // passing 504 default: 505 assert.Fail("The Closed channel was not signaled") 506 } 507 } 508 509 func testInstrumentedCloseableAcquireWaitTimeout(t *testing.T) { 510 var ( 511 assert = assert.New(t) 512 resources = generic.NewCounter("test") 513 failures = generic.NewCounter("test") 514 closed = generic.NewGauge("test") 515 s = InstrumentCloseable(CloseableMutex(), WithResources(resources), WithFailures(failures), WithClosed(closed)) 516 517 ready = make(chan struct{}) 518 result = make(chan error) 519 timer = make(chan time.Time) 520 ) 521 522 assert.NotNil(s.Closed()) 523 assert.Equal(MetricOpen, closed.Value()) 524 525 go func() { 526 s.Acquire() 527 close(ready) 528 result <- s.AcquireWait(timer) 529 }() 530 531 select { 532 case <-ready: 533 assert.Equal(float64(1.0), resources.Value()) 534 assert.Zero(failures.Value()) 535 assert.Equal(MetricOpen, closed.Value()) 536 timer <- time.Time{} 537 case <-time.After(time.Second): 538 assert.FailNow("Failed to spawn AcquireWait goroutine") 539 } 540 541 select { 542 case err := <-result: 543 assert.Equal(ErrTimeout, err) 544 assert.Equal(float64(1.0), resources.Value()) 545 assert.Equal(float64(1.0), failures.Value()) 546 assert.Equal(MetricOpen, closed.Value()) 547 548 s.Release() 549 assert.Zero(resources.Value()) 550 assert.Equal(float64(1.0), failures.Value()) 551 assert.Equal(MetricOpen, closed.Value()) 552 case <-time.After(time.Second): 553 assert.FailNow("AcquireWait blocked unexpectedly") 554 } 555 556 assert.NoError(s.Close()) 557 assert.Zero(resources.Value()) 558 assert.Equal(float64(1.0), failures.Value()) 559 assert.Equal(MetricClosed, closed.Value()) 560 561 select { 562 case <-s.Closed(): 563 // passing 564 default: 565 assert.Fail("The Closed channel was not signaled") 566 } 567 } 568 569 func testInstrumentedCloseableAcquireWaitClose(t *testing.T) { 570 var ( 571 assert = assert.New(t) 572 resources = generic.NewCounter("test") 573 failures = generic.NewCounter("test") 574 closed = generic.NewGauge("test") 575 s = InstrumentCloseable(CloseableMutex(), WithResources(resources), WithFailures(failures), WithClosed(closed)) 576 577 ready = make(chan struct{}) 578 result = make(chan error) 579 timer = make(chan time.Time) 580 ) 581 582 assert.NotNil(s.Closed()) 583 assert.Equal(MetricOpen, closed.Value()) 584 585 go func() { 586 s.Acquire() 587 close(ready) 588 result <- s.AcquireWait(timer) 589 }() 590 591 select { 592 case <-ready: 593 assert.Equal(float64(1.0), resources.Value()) 594 assert.Zero(failures.Value()) 595 assert.Equal(MetricOpen, closed.Value()) 596 assert.NoError(s.Close()) 597 case <-time.After(time.Second): 598 assert.FailNow("Failed to spawn AcquireWait goroutine") 599 } 600 601 select { 602 case err := <-result: 603 assert.Equal(ErrClosed, err) 604 assert.Equal(float64(1.0), resources.Value()) 605 assert.Equal(float64(1.0), failures.Value()) 606 assert.Equal(MetricClosed, closed.Value()) 607 608 s.Release() 609 assert.Equal(float64(1.0), resources.Value()) 610 assert.Equal(float64(1.0), failures.Value()) 611 assert.Equal(MetricClosed, closed.Value()) 612 case <-time.After(time.Second): 613 assert.FailNow("AcquireWait blocked unexpectedly") 614 } 615 616 assert.Equal(ErrClosed, s.Close()) 617 assert.Equal(float64(1.0), resources.Value()) 618 assert.Equal(float64(1.0), failures.Value()) 619 assert.Equal(MetricClosed, closed.Value()) 620 621 select { 622 case <-s.Closed(): 623 // passing 624 default: 625 assert.Fail("The Closed channel was not signaled") 626 } 627 628 assert.Equal(ErrClosed, s.AcquireWait(timer)) 629 assert.Equal(float64(1.0), resources.Value()) 630 assert.Equal(float64(2.0), failures.Value()) 631 assert.Equal(MetricClosed, closed.Value()) 632 } 633 634 func testInstrumentedCloseableAcquireCtxSuccess(t *testing.T) { 635 var ( 636 assert = assert.New(t) 637 resources = generic.NewCounter("test") 638 failures = generic.NewCounter("test") 639 closed = generic.NewGauge("test") 640 s = InstrumentCloseable(CloseableMutex(), WithResources(resources), WithFailures(failures), WithClosed(closed)) 641 642 ready = make(chan struct{}) 643 result = make(chan error) 644 ctx, cancel = context.WithCancel(context.Background()) 645 ) 646 647 defer cancel() 648 assert.NotNil(s.Closed()) 649 assert.Equal(MetricOpen, closed.Value()) 650 651 go func() { 652 s.Acquire() 653 close(ready) 654 result <- s.AcquireCtx(ctx) 655 }() 656 657 select { 658 case <-ready: 659 assert.Equal(float64(1.0), resources.Value()) 660 assert.Zero(failures.Value()) 661 assert.Equal(MetricOpen, closed.Value()) 662 s.Release() 663 664 assert.Zero(resources.Value()) 665 assert.Zero(failures.Value()) 666 assert.Equal(MetricOpen, closed.Value()) 667 case <-time.After(time.Second): 668 assert.FailNow("Failed to spawn AcquireCtx goroutine") 669 } 670 671 select { 672 case err := <-result: 673 assert.NoError(err) 674 assert.Equal(float64(1.0), resources.Value()) 675 assert.Zero(failures.Value()) 676 assert.Equal(MetricOpen, closed.Value()) 677 678 s.Release() 679 assert.Zero(resources.Value()) 680 assert.Zero(failures.Value()) 681 assert.Equal(MetricOpen, closed.Value()) 682 case <-time.After(time.Second): 683 assert.FailNow("AcquireCtx blocked unexpectedly") 684 } 685 686 assert.NoError(s.Close()) 687 assert.Zero(resources.Value()) 688 assert.Zero(failures.Value()) 689 assert.Equal(MetricClosed, closed.Value()) 690 691 select { 692 case <-s.Closed(): 693 // passing 694 default: 695 assert.Fail("The Closed channel was not signaled") 696 } 697 698 assert.Equal(ErrClosed, s.AcquireCtx(ctx)) 699 assert.Zero(resources.Value()) 700 assert.Equal(float64(1.0), failures.Value()) 701 assert.Equal(MetricClosed, closed.Value()) 702 } 703 704 func testInstrumentedCloseableAcquireCtxCancel(t *testing.T) { 705 var ( 706 assert = assert.New(t) 707 resources = generic.NewCounter("test") 708 failures = generic.NewCounter("test") 709 closed = generic.NewGauge("test") 710 s = InstrumentCloseable(CloseableMutex(), WithResources(resources), WithFailures(failures), WithClosed(closed)) 711 712 ready = make(chan struct{}) 713 result = make(chan error) 714 ctx, cancel = context.WithCancel(context.Background()) 715 ) 716 717 defer cancel() 718 assert.NotNil(s.Closed()) 719 assert.Equal(MetricOpen, closed.Value()) 720 721 go func() { 722 s.Acquire() 723 close(ready) 724 result <- s.AcquireCtx(ctx) 725 }() 726 727 select { 728 case <-ready: 729 assert.Equal(float64(1.0), resources.Value()) 730 assert.Zero(failures.Value()) 731 assert.Equal(MetricOpen, closed.Value()) 732 cancel() 733 case <-time.After(time.Second): 734 assert.FailNow("Failed to spawn AcquireCtx goroutine") 735 } 736 737 select { 738 case err := <-result: 739 assert.Equal(ctx.Err(), err) 740 assert.Equal(float64(1.0), resources.Value()) 741 assert.Equal(float64(1.0), failures.Value()) 742 assert.Equal(MetricOpen, closed.Value()) 743 744 s.Release() 745 assert.Zero(resources.Value()) 746 assert.Equal(float64(1.0), failures.Value()) 747 assert.Equal(MetricOpen, closed.Value()) 748 case <-time.After(time.Second): 749 assert.FailNow("AcquireCtx blocked unexpectedly") 750 } 751 752 assert.NoError(s.Close()) 753 assert.Zero(resources.Value()) 754 assert.Equal(float64(1.0), failures.Value()) 755 assert.Equal(MetricClosed, closed.Value()) 756 757 select { 758 case <-s.Closed(): 759 // passing 760 default: 761 assert.Fail("The Closed channel was not signaled") 762 } 763 } 764 765 func testInstrumentedCloseableAcquireCtxClose(t *testing.T) { 766 var ( 767 assert = assert.New(t) 768 resources = generic.NewCounter("test") 769 failures = generic.NewCounter("test") 770 closed = generic.NewGauge("test") 771 s = InstrumentCloseable(CloseableMutex(), WithResources(resources), WithFailures(failures), WithClosed(closed)) 772 773 ready = make(chan struct{}) 774 result = make(chan error) 775 ctx, cancel = context.WithCancel(context.Background()) 776 ) 777 778 defer cancel() 779 assert.NotNil(s.Closed()) 780 assert.Equal(MetricOpen, closed.Value()) 781 782 go func() { 783 s.Acquire() 784 close(ready) 785 result <- s.AcquireCtx(ctx) 786 }() 787 788 select { 789 case <-ready: 790 assert.Equal(float64(1.0), resources.Value()) 791 assert.Zero(failures.Value()) 792 assert.Equal(MetricOpen, closed.Value()) 793 794 assert.NoError(s.Close()) 795 assert.Equal(float64(1.0), resources.Value()) 796 assert.Zero(failures.Value()) 797 assert.Equal(MetricClosed, closed.Value()) 798 case <-time.After(time.Second): 799 assert.FailNow("Failed to spawn AcquireCtx goroutine") 800 } 801 802 select { 803 case err := <-result: 804 assert.Equal(ErrClosed, err) 805 assert.Equal(float64(1.0), resources.Value()) 806 assert.Equal(float64(1.0), failures.Value()) 807 assert.Equal(MetricClosed, closed.Value()) 808 809 assert.Equal(ErrClosed, s.Release()) 810 assert.Equal(float64(1.0), resources.Value()) 811 assert.Equal(float64(1.0), failures.Value()) 812 assert.Equal(MetricClosed, closed.Value()) 813 case <-time.After(time.Second): 814 assert.FailNow("AcquireCtx blocked unexpectedly") 815 } 816 817 assert.Equal(ErrClosed, s.Close()) 818 assert.Equal(float64(1.0), resources.Value()) 819 assert.Equal(float64(1.0), failures.Value()) 820 assert.Equal(MetricClosed, closed.Value()) 821 822 select { 823 case <-s.Closed(): 824 // passing 825 default: 826 assert.Fail("The Closed channel was not signaled") 827 } 828 } 829 830 func TestInstrumentedCloseable(t *testing.T) { 831 t.Run("Acquire", testInstrumentedCloseableAcquire) 832 833 t.Run("TryAcquire", testInstrumentedCloseableTryAcquire) 834 835 t.Run("AcquireWait", func(t *testing.T) { 836 t.Run("Success", testInstrumentedCloseableAcquireWaitSuccess) 837 t.Run("Timeout", testInstrumentedCloseableAcquireWaitTimeout) 838 t.Run("Close", testInstrumentedCloseableAcquireWaitClose) 839 }) 840 841 t.Run("AcquireCtx", func(t *testing.T) { 842 t.Run("Success", testInstrumentedCloseableAcquireCtxSuccess) 843 t.Run("Cancel", testInstrumentedCloseableAcquireCtxCancel) 844 t.Run("Close", testInstrumentedCloseableAcquireCtxClose) 845 }) 846 }