(t *testing.T)
| 652 | } |
| 653 | |
| 654 | func TestMutex(t *testing.T) { |
| 655 | a, ctx := test.New(t) |
| 656 | |
| 657 | ttl := (1 << 10) * test.Delay |
| 658 | ctx, cancel := context.WithTimeout(ctx, 5*time.Second+ttl) |
| 659 | defer cancel() |
| 660 | |
| 661 | cl, flush := test.NewRedis(ctx, "redis_test") |
| 662 | defer flush() |
| 663 | defer cl.Close() |
| 664 | |
| 665 | key := cl.Key("test1") |
| 666 | |
| 667 | err := LockMutex(ctx, cl, key, "test-id-1", ttl) |
| 668 | if !a.So(err, should.BeNil) { |
| 669 | t.Fatalf("Failed to lock mutex: %s", err) |
| 670 | } |
| 671 | |
| 672 | lockTTL, err := cl.PTTL(ctx, LockKey(key)).Result() |
| 673 | if !a.So(err, should.BeNil) { |
| 674 | t.FailNow() |
| 675 | } |
| 676 | a.So(lockTTL, should.BeGreaterThan, 0) |
| 677 | a.So(lockTTL, should.BeLessThanOrEqualTo, ttl) |
| 678 | |
| 679 | blockErrCh := make(chan error, 1) |
| 680 | go func() { |
| 681 | blockErrCh <- LockMutex(ctx, cl, key, "test-id-2", ttl) |
| 682 | }() |
| 683 | |
| 684 | timeoutErrCh := make(chan error, 1) |
| 685 | go func() { |
| 686 | ctx, cancel := context.WithTimeout(ctx, (1<<8)*test.Delay) |
| 687 | defer cancel() |
| 688 | timeoutErrCh <- LockMutex(ctx, cl, key, "test-id-3", ttl) |
| 689 | }() |
| 690 | |
| 691 | select { |
| 692 | case <-ctx.Done(): |
| 693 | t.Fatalf("Timed out while waiting for LockMutex with a deadline to return") |
| 694 | case err := <-timeoutErrCh: |
| 695 | if !a.So(errors.IsDeadlineExceeded(err) || errors.IsUnavailable(err), should.BeTrue) { |
| 696 | t.Fatal(err) |
| 697 | } |
| 698 | } |
| 699 | select { |
| 700 | case err := <-blockErrCh: |
| 701 | t.Fatalf("LockMutex returned before previous caller unlocked: %s", err) |
| 702 | default: |
| 703 | } |
| 704 | |
| 705 | err = UnlockMutex(ctx, cl, key, "test-id-1", ttl) |
| 706 | if !a.So(err, should.BeNil) { |
| 707 | t.Fatalf("Failed to unlock mutex: %s", err) |
| 708 | } |
| 709 | |
| 710 | select { |
| 711 | case <-ctx.Done(): |
nothing calls this directly
no test coverage detected