-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdlm_test.go
133 lines (107 loc) · 2.87 KB
/
dlm_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package dlm
import (
"testing"
"time"
"github.com/stretchr/testify/require"
)
func RunDLMLockTest(t *testing.T, dlm DLM) {
// create a lock for a key
lockA, err := dlm.NewLock("dlm-lock-test", nil)
require.NoError(t, err)
// it should return the key
key := lockA.Key()
require.Equal(t, "dlm-lock-test", key)
// it should return the namespace
namespace := lockA.Namespace()
require.Equal(t, "test/", namespace)
// it should acquire the lock
err = lockA.Lock()
require.NoError(t, err)
// it should fail to acquire the lock twice
err = lockA.Lock()
require.Equal(t, ErrLockHeld, err)
// it should release the lock
err = lockA.Unlock()
require.NoError(t, err)
// it should fail to release the lock twice
err = lockA.Unlock()
require.Equal(t, ErrLockNotHeld, err)
// it should acquire the lock again
err = lockA.Lock()
require.NoError(t, err)
// create a second lock for the same key
lockB, err := dlm.NewLock("dlm-lock-test", nil)
require.NoError(t, err)
// it should block until the lock A is released
locked := make(chan bool)
go func(locked chan<- bool) {
err := lockB.Lock()
require.NoError(t, err)
locked <- true
}(locked)
select {
case <-locked:
require.Fail(t, "lock succeded on a key locked by another client")
case <-time.After(3 * time.Second):
err := lockA.Unlock()
require.NoError(t, err)
break
}
}
func RunDLMLockTTLTest(t *testing.T, dlm DLM) {
// create a lock for a key
lockA, err := dlm.NewLock("dlm-lock-ttl-test", &LockOptions{
TTL: 2 * time.Second,
})
require.NoError(t, err)
// it should acquire the lock
err = lockA.Lock()
require.NoError(t, err)
// create a second lock for the same key
lockB, err := dlm.NewLock("dlm-lock-ttl-test", &LockOptions{
RetryTime: 1 * time.Second,
})
require.NoError(t, err)
// it should lock after the TTL of the lock A has expired
locked := make(chan bool)
go func(locked chan<- bool) {
err := lockB.Lock()
require.NoError(t, err)
locked <- true
}(locked)
select {
case <-locked:
err := lockB.Unlock()
require.NoError(t, err)
case <-time.After(4 * time.Second):
require.Fail(t, "failed to expire lock")
}
}
func RunDLMLockWaitTimeTest(t *testing.T, dlm DLM) {
// create a lock for a key
lockA, err := dlm.NewLock("dlm-lock-wait-time-test", nil)
require.NoError(t, err)
// it should acquire the lock
err = lockA.Lock()
require.NoError(t, err)
// create a second lock for the same key
lockB, err := dlm.NewLock("dlm-lock-wait-time-test", &LockOptions{
WaitTime: 2 * time.Second,
})
require.NoError(t, err)
// it should fail after the wait time has ended
done := make(chan bool)
go func(done chan<- bool) {
err := lockB.Lock()
require.Equal(t, ErrCannotLock, err)
done <- true
}(done)
select {
case <-done:
err := lockA.Unlock()
require.NoError(t, err)
break
case <-time.After(3 * time.Second):
require.Fail(t, "failed to timeout during lock")
}
}