@@ -22,10 +22,14 @@ import (
22
22
"testing"
23
23
"time"
24
24
25
+ "github.com/stretchr/testify/assert"
26
+ "github.com/stretchr/testify/require"
25
27
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
26
28
"go.etcd.io/etcd/api/v3/mvccpb"
27
29
"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
28
30
"go.etcd.io/etcd/client/pkg/v3/testutil"
31
+ clientv3 "go.etcd.io/etcd/client/v3"
32
+ gofail "go.etcd.io/gofail/runtime"
29
33
30
34
"google.golang.org/grpc/codes"
31
35
"google.golang.org/grpc/metadata"
@@ -1056,6 +1060,78 @@ func TestV3LeaseRecoverKeyWithMutipleLease(t *testing.T) {
1056
1060
}
1057
1061
}
1058
1062
1063
+ func TestV3LeaseTimeToLiveWithLeaderChanged (t * testing.T ) {
1064
+ t .Run ("normal" , func (subT * testing.T ) {
1065
+ testV3LeaseTimeToLiveWithLeaderChanged (subT , "beforeLookupWhenLeaseTimeToLive" )
1066
+ })
1067
+
1068
+ t .Run ("forward" , func (subT * testing.T ) {
1069
+ testV3LeaseTimeToLiveWithLeaderChanged (subT , "beforeLookupWhenForwardLeaseTimeToLive" )
1070
+ })
1071
+ }
1072
+
1073
+ func testV3LeaseTimeToLiveWithLeaderChanged (t * testing.T , fpName string ) {
1074
+ if len (gofail .List ()) == 0 {
1075
+ t .Skip ("please run 'make gofail-enable' before running the test" )
1076
+ }
1077
+
1078
+ BeforeTest (t )
1079
+
1080
+ clus := NewClusterV3 (t , & ClusterConfig {Size : 3 })
1081
+ defer clus .Terminate (t )
1082
+
1083
+ ctx , cancel := context .WithTimeout (context .Background (), 30 * time .Second )
1084
+ defer cancel ()
1085
+
1086
+ oldLeadIdx := clus .WaitLeader (t )
1087
+ followerIdx := (oldLeadIdx + 1 ) % 3
1088
+
1089
+ followerMemberID := clus .Members [followerIdx ].ID ()
1090
+
1091
+ oldLeadC := clus .Client (oldLeadIdx )
1092
+
1093
+ leaseResp , err := oldLeadC .Grant (ctx , 100 )
1094
+ require .NoError (t , err )
1095
+
1096
+ require .NoError (t , gofail .Enable (fpName , `sleep("3s")` ))
1097
+ t .Cleanup (func () {
1098
+ terr := gofail .Disable (fpName )
1099
+ if terr != nil && terr != gofail .ErrDisabled {
1100
+ t .Fatalf ("failed to disable %s: %v" , fpName , terr )
1101
+ }
1102
+ })
1103
+
1104
+ readyCh := make (chan struct {})
1105
+ errCh := make (chan error , 1 )
1106
+
1107
+ var targetC * clientv3.Client
1108
+ switch fpName {
1109
+ case "beforeLookupWhenLeaseTimeToLive" :
1110
+ targetC = oldLeadC
1111
+ case "beforeLookupWhenForwardLeaseTimeToLive" :
1112
+ targetC = clus .Client ((oldLeadIdx + 2 ) % 3 )
1113
+ default :
1114
+ t .Fatalf ("unsupported %s failpoint" , fpName )
1115
+ }
1116
+
1117
+ go func () {
1118
+ <- readyCh
1119
+ time .Sleep (1 * time .Second )
1120
+
1121
+ _ , merr := oldLeadC .MoveLeader (ctx , uint64 (followerMemberID ))
1122
+ assert .NoError (t , gofail .Disable (fpName ))
1123
+ errCh <- merr
1124
+ }()
1125
+
1126
+ close (readyCh )
1127
+
1128
+ ttlResp , err := targetC .TimeToLive (ctx , leaseResp .ID )
1129
+ require .NoError (t , err )
1130
+ require .GreaterOrEqual (t , int64 (100 ), ttlResp .TTL )
1131
+
1132
+ require .NoError (t , <- errCh )
1133
+ }
1134
+
1059
1135
// acquireLeaseAndKey creates a new lease and creates an attached key.
1060
1136
func acquireLeaseAndKey (clus * ClusterV3 , key string ) (int64 , error ) {
1061
1137
// create lease
0 commit comments