(t *testing.T)
| 29 | ) |
| 30 | |
| 31 | func TestBasic(t *testing.T) { |
| 32 | t.Parallel() |
| 33 | |
| 34 | km := newKeyMutex() |
| 35 | ctx := context.Background() |
| 36 | |
| 37 | km.Lock(ctx, "c1") |
| 38 | km.Lock(ctx, "c2") |
| 39 | |
| 40 | assert.Equal(t, len(km.locks), 2) |
| 41 | assert.Equal(t, km.locks["c1"].ref, 1) |
| 42 | assert.Equal(t, km.locks["c2"].ref, 1) |
| 43 | |
| 44 | checkWaitFn := func(key string, num int) { |
| 45 | retries := 100 |
| 46 | waitLock := false |
| 47 | |
| 48 | for range retries { |
| 49 | // prevent from data-race |
| 50 | km.mu.Lock() |
| 51 | ref := km.locks[key].ref |
| 52 | km.mu.Unlock() |
| 53 | |
| 54 | if ref == num { |
| 55 | waitLock = true |
| 56 | break |
| 57 | } |
| 58 | time.Sleep(time.Duration(randutil.Int63n(100)) * time.Millisecond) |
| 59 | } |
| 60 | assert.Equal(t, waitLock, true) |
| 61 | } |
| 62 | |
| 63 | // should acquire successfully after release |
| 64 | { |
| 65 | waitCh := make(chan struct{}) |
| 66 | go func() { |
| 67 | defer close(waitCh) |
| 68 | |
| 69 | km.Lock(ctx, "c1") |
| 70 | }() |
| 71 | checkWaitFn("c1", 2) |
| 72 | |
| 73 | km.Unlock("c1") |
| 74 | |
| 75 | <-waitCh |
| 76 | assert.Equal(t, km.locks["c1"].ref, 1) |
| 77 | } |
| 78 | |
| 79 | // failed to acquire if context cancel |
| 80 | { |
| 81 | var errCh = make(chan error, 1) |
| 82 | |
| 83 | ctx, cancel := context.WithCancel(context.Background()) |
| 84 | go func() { |
| 85 | errCh <- km.Lock(ctx, "c1") |
| 86 | }() |
| 87 | |
| 88 | checkWaitFn("c1", 2) |
nothing calls this directly
no test coverage detected
searching dependent graphs…