-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlease_test.go
131 lines (110 loc) · 3.51 KB
/
lease_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
package whatnot
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestLeaseCreationAndExpiration(t *testing.T) {
t.Run("Create a new lease", createNewLeaseOnPathElement)
t.Run("Test that Lease expires after set time", leaseExpiresAsExpected)
t.Run("Test that lease responds to context cancellation", leaseAcceptsCancelation)
t.Run("Test that element prefix can be locked and unlocked", lockPrefixThenUnlock)
}
func createNewLeaseOnPathElement(t *testing.T) {
t.Log("Creating a new lease on an existing Path Element")
gns := createTestNamespace(t)
err := gns.RegisterAbsolutePath(PathString("/testelement").ToAbsolutePath())
if !assert.Nil(t, err, "registering path returned error") {
t.Error(err.Error())
return
}
elem := gns.FetchAbsolutePath("/testelement")
lease, cancel := elem.LockWithLease(time.Second * 2)
if !assert.NotNil(t, lease, "creating lease returned nil") {
t.Error(err.Error())
return
}
t.Log("created one-second lease on test element")
cancel()
t.Log("cancelled one-second lease on test element")
}
func leaseExpiresAsExpected(t *testing.T) {
t.Log("Checking that lease expires at expected duration")
gns := createTestNamespace(t)
err := gns.RegisterAbsolutePath(PathString("/testelement").ToAbsolutePath())
if !assert.Nil(t, err, "registering path returned error") {
t.Error(err.Error())
return
}
elem := gns.FetchAbsolutePath("/testelement")
leaseFor := time.Second
ctx, cancel := elem.LockWithLease(leaseFor)
if !assert.Nil(t, err, "creating lease returned error") {
t.Error(err.Error())
return
}
defer cancel()
t.Log("created one-second lease on test element")
t.Log("measuring time for lease to expire")
start := time.Now()
<-ctx.Done()
t.Log("lease returned before time expired")
took := time.Now().Sub(start)
if !assert.Equal(t, leaseFor.Round(time.Second).Seconds(), took.Round(time.Second).Seconds(), "did not expire in expected time") {
t.Error("did not expire in expected time")
return
}
t.Logf("took %f seconds to expire", took.Seconds())
return
}
func leaseAcceptsCancelation(t *testing.T) {
t.Log("Creating a lease and then cancelling it prematurely")
gns := createTestNamespace(t)
err := gns.RegisterAbsolutePath(PathString("/testelement").ToAbsolutePath())
if !assert.Nil(t, err, "registering path returned error") {
t.Error(err.Error())
return
}
elem := gns.FetchAbsolutePath("/testelement")
leaseStart := time.Now()
leaseFor := time.Second * 5
ctx, cancel := elem.LockWithLease(leaseFor)
if !assert.Nil(t, err, "creating lease returned error") {
t.Error(err.Error())
return
}
go func() {
time.Sleep(time.Second)
t.Log("sending cancel")
cancel()
}()
<-ctx.Done()
t.Log("cancellation received")
t.Log(ctx.Err())
if leaseStart.Add(leaseFor).Before(time.Now()) {
t.Errorf("context did not cancel before lease expired")
}
}
func lockPrefixThenUnlock(t *testing.T) {
t.Log("Creating an element, locking it and all its children, then unlocking them")
gns := createTestNamespace(t)
err := gns.RegisterAbsolutePath(PathString("/testelement").ToAbsolutePath())
if !assert.Nil(t, err, "registering path returned error") {
t.Error(err.Error())
return
}
elem := gns.FetchAbsolutePath("/testelement")
elem.LockSubs()
t.Log("locked")
go func() {
time.Sleep(time.Second)
t.Log("doing recursive unlock")
elem.UnLockSubs()
t.Log("Unlocked")
}()
t.Log("acquiring additional lock, waiting for old one to release")
elem.Lock()
t.Log("old lock cancelled, new lock acquired")
elem.UnLock()
t.Log("lock released")
}