@@ -24,6 +24,7 @@ import (
24
24
"github.com/stretchr/testify/assert"
25
25
"github.com/stretchr/testify/require"
26
26
27
+ "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
27
28
clientv3 "go.etcd.io/etcd/client/v3"
28
29
"go.etcd.io/etcd/tests/v3/framework/e2e"
29
30
"go.etcd.io/etcd/tests/v3/framework/testutils"
@@ -164,3 +165,60 @@ func testLeaseRevokeIssue(t *testing.T, clusterSize int, connectToOneFollower bo
164
165
close (stopC )
165
166
<- doneC
166
167
}
168
+
169
+ func TestLeaseRevokeDuringRenew (t * testing.T ) {
170
+ e2e .BeforeTest (t )
171
+
172
+ ctx := t .Context ()
173
+
174
+ t .Log ("Starting a new etcd cluster" )
175
+ epc , err := e2e .NewEtcdProcessCluster (ctx , t ,
176
+ e2e .WithClusterSize (1 ),
177
+ e2e .WithGoFailEnabled (true ),
178
+ e2e .WithGoFailClientTimeout (40 * time .Second ),
179
+ )
180
+ require .NoError (t , err )
181
+ defer func () {
182
+ require .NoErrorf (t , epc .Close (), "error closing etcd processes" )
183
+ }()
184
+
185
+ eps := epc .Procs [0 ].EndpointsGRPC ()
186
+ t .Logf ("Creating two clients for lease operations: %v" , eps )
187
+ clientForRenew , err := clientv3 .New (clientv3.Config {Endpoints : eps , DialTimeout : 3 * time .Second })
188
+ require .NoError (t , err )
189
+ defer clientForRenew .Close ()
190
+
191
+ clientForRevoke , err := clientv3 .New (clientv3.Config {Endpoints : eps , DialTimeout : 3 * time .Second })
192
+ require .NoError (t , err )
193
+ defer clientForRevoke .Close ()
194
+
195
+ t .Log ("Creating a new lease" )
196
+ leaseRsp , err := clientForRenew .Grant (ctx , 60 )
197
+ require .NoError (t , err )
198
+
199
+ t .Log ("Activate the 'beforeCheckpointInLeaseRenew' failpoint" )
200
+ require .NoError (t , epc .Procs [0 ].Failpoints ().SetupHTTP (ctx , "beforeCheckpointInLeaseRenew" , `sleep("3s")` ))
201
+
202
+ t .Logf ("Starting a goroutine to keep alive the lease: %d" , leaseRsp .ID )
203
+ doneC := make (chan struct {})
204
+ startC := make (chan struct {}, 1 )
205
+ var renewError error
206
+ go func () {
207
+ defer close (doneC )
208
+ startC <- struct {}{}
209
+ _ , renewError = clientForRenew .KeepAliveOnce (ctx , leaseRsp .ID )
210
+ }()
211
+
212
+ t .Log ("Wait for the KeepAliveOnce goroutine to get started" )
213
+ <- startC
214
+ time .Sleep (200 * time .Millisecond )
215
+
216
+ t .Logf ("Revoke the lease: %d" , leaseRsp .ID )
217
+ _ , lerr := clientForRevoke .Revoke (ctx , leaseRsp .ID )
218
+ require .NoError (t , lerr )
219
+
220
+ t .Log ("Waiting for the keepAlive goroutine to exit" )
221
+ <- doneC
222
+
223
+ require .ErrorIs (t , rpctypes .ErrLeaseNotFound , renewError )
224
+ }
0 commit comments