go.etcd.io/etcd@v3.3.27+incompatible/integration/v3_lease_test.go (about)

     1  // Copyright 2016 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package integration
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
    24  	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
    25  	"github.com/coreos/etcd/mvcc/mvccpb"
    26  	"github.com/coreos/etcd/pkg/testutil"
    27  
    28  	"google.golang.org/grpc/metadata"
    29  )
    30  
    31  // TestV3LeasePrmote ensures the newly elected leader can promote itself
    32  // to the primary lessor, refresh the leases and start to manage leases.
    33  // TODO: use customized clock to make this test go faster?
    34  func TestV3LeasePrmote(t *testing.T) {
    35  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
    36  	defer clus.Terminate(t)
    37  
    38  	// create lease
    39  	lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 3})
    40  	ttl := time.Duration(lresp.TTL) * time.Second
    41  	afterGrant := time.Now()
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	if lresp.Error != "" {
    46  		t.Fatal(lresp.Error)
    47  	}
    48  
    49  	// wait until the lease is going to expire.
    50  	time.Sleep(time.Until(afterGrant.Add(ttl - time.Second)))
    51  
    52  	// kill the current leader, all leases should be refreshed.
    53  	toStop := clus.waitLeader(t, clus.Members)
    54  	beforeStop := time.Now()
    55  	clus.Members[toStop].Stop(t)
    56  
    57  	var toWait []*member
    58  	for i, m := range clus.Members {
    59  		if i != toStop {
    60  			toWait = append(toWait, m)
    61  		}
    62  	}
    63  	clus.waitLeader(t, toWait)
    64  	clus.Members[toStop].Restart(t)
    65  	clus.waitLeader(t, clus.Members)
    66  	afterReelect := time.Now()
    67  
    68  	// ensure lease is refreshed by waiting for a "long" time.
    69  	// it was going to expire anyway.
    70  	time.Sleep(time.Until(beforeStop.Add(ttl - time.Second)))
    71  
    72  	if !leaseExist(t, clus, lresp.ID) {
    73  		t.Error("unexpected lease not exists")
    74  	}
    75  
    76  	// wait until the renewed lease is expected to expire.
    77  	time.Sleep(time.Until(afterReelect.Add(ttl)))
    78  
    79  	// wait for up to 10 seconds for lease to expire.
    80  	expiredCondition := func() (bool, error) {
    81  		return !leaseExist(t, clus, lresp.ID), nil
    82  	}
    83  	expired, err := testutil.Poll(100*time.Millisecond, 10*time.Second, expiredCondition)
    84  	if err != nil {
    85  		t.Error(err)
    86  	}
    87  
    88  	if !expired {
    89  		t.Error("unexpected lease exists")
    90  	}
    91  }
    92  
    93  // TestV3LeaseRevoke ensures a key is deleted once its lease is revoked.
    94  func TestV3LeaseRevoke(t *testing.T) {
    95  	defer testutil.AfterTest(t)
    96  	testLeaseRemoveLeasedKey(t, func(clus *ClusterV3, leaseID int64) error {
    97  		lc := toGRPC(clus.RandClient()).Lease
    98  		_, err := lc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseID})
    99  		return err
   100  	})
   101  }
   102  
   103  // TestV3LeaseGrantById ensures leases may be created by a given id.
   104  func TestV3LeaseGrantByID(t *testing.T) {
   105  	defer testutil.AfterTest(t)
   106  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
   107  	defer clus.Terminate(t)
   108  
   109  	// create fixed lease
   110  	lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant(
   111  		context.TODO(),
   112  		&pb.LeaseGrantRequest{ID: 1, TTL: 1})
   113  	if err != nil {
   114  		t.Errorf("could not create lease 1 (%v)", err)
   115  	}
   116  	if lresp.ID != 1 {
   117  		t.Errorf("got id %v, wanted id %v", lresp.ID, 1)
   118  	}
   119  
   120  	// create duplicate fixed lease
   121  	_, err = toGRPC(clus.RandClient()).Lease.LeaseGrant(
   122  		context.TODO(),
   123  		&pb.LeaseGrantRequest{ID: 1, TTL: 1})
   124  	if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseExist) {
   125  		t.Error(err)
   126  	}
   127  
   128  	// create fresh fixed lease
   129  	lresp, err = toGRPC(clus.RandClient()).Lease.LeaseGrant(
   130  		context.TODO(),
   131  		&pb.LeaseGrantRequest{ID: 2, TTL: 1})
   132  	if err != nil {
   133  		t.Errorf("could not create lease 2 (%v)", err)
   134  	}
   135  	if lresp.ID != 2 {
   136  		t.Errorf("got id %v, wanted id %v", lresp.ID, 2)
   137  	}
   138  }
   139  
   140  // TestV3LeaseExpire ensures a key is deleted once a key expires.
   141  func TestV3LeaseExpire(t *testing.T) {
   142  	defer testutil.AfterTest(t)
   143  	testLeaseRemoveLeasedKey(t, func(clus *ClusterV3, leaseID int64) error {
   144  		// let lease lapse; wait for deleted key
   145  
   146  		ctx, cancel := context.WithCancel(context.Background())
   147  		defer cancel()
   148  		wStream, err := toGRPC(clus.RandClient()).Watch.Watch(ctx)
   149  		if err != nil {
   150  			return err
   151  		}
   152  
   153  		wreq := &pb.WatchRequest{RequestUnion: &pb.WatchRequest_CreateRequest{
   154  			CreateRequest: &pb.WatchCreateRequest{
   155  				Key: []byte("foo"), StartRevision: 1}}}
   156  		if err := wStream.Send(wreq); err != nil {
   157  			return err
   158  		}
   159  		if _, err := wStream.Recv(); err != nil {
   160  			// the 'created' message
   161  			return err
   162  		}
   163  		if _, err := wStream.Recv(); err != nil {
   164  			// the 'put' message
   165  			return err
   166  		}
   167  
   168  		errc := make(chan error, 1)
   169  		go func() {
   170  			resp, err := wStream.Recv()
   171  			switch {
   172  			case err != nil:
   173  				errc <- err
   174  			case len(resp.Events) != 1:
   175  				fallthrough
   176  			case resp.Events[0].Type != mvccpb.DELETE:
   177  				errc <- fmt.Errorf("expected key delete, got %v", resp)
   178  			default:
   179  				errc <- nil
   180  			}
   181  		}()
   182  
   183  		select {
   184  		case <-time.After(15 * time.Second):
   185  			return fmt.Errorf("lease expiration too slow")
   186  		case err := <-errc:
   187  			return err
   188  		}
   189  	})
   190  }
   191  
   192  // TestV3LeaseKeepAlive ensures keepalive keeps the lease alive.
   193  func TestV3LeaseKeepAlive(t *testing.T) {
   194  	defer testutil.AfterTest(t)
   195  	testLeaseRemoveLeasedKey(t, func(clus *ClusterV3, leaseID int64) error {
   196  		lc := toGRPC(clus.RandClient()).Lease
   197  		lreq := &pb.LeaseKeepAliveRequest{ID: leaseID}
   198  		ctx, cancel := context.WithCancel(context.Background())
   199  		defer cancel()
   200  		lac, err := lc.LeaseKeepAlive(ctx)
   201  		if err != nil {
   202  			return err
   203  		}
   204  		defer lac.CloseSend()
   205  
   206  		// renew long enough so lease would've expired otherwise
   207  		for i := 0; i < 3; i++ {
   208  			if err = lac.Send(lreq); err != nil {
   209  				return err
   210  			}
   211  			lresp, rxerr := lac.Recv()
   212  			if rxerr != nil {
   213  				return rxerr
   214  			}
   215  			if lresp.ID != leaseID {
   216  				return fmt.Errorf("expected lease ID %v, got %v", leaseID, lresp.ID)
   217  			}
   218  			time.Sleep(time.Duration(lresp.TTL/2) * time.Second)
   219  		}
   220  		_, err = lc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseID})
   221  		return err
   222  	})
   223  }
   224  
   225  // TestV3LeaseExists creates a lease on a random client and confirms it exists in the cluster.
   226  func TestV3LeaseExists(t *testing.T) {
   227  	defer testutil.AfterTest(t)
   228  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
   229  	defer clus.Terminate(t)
   230  
   231  	// create lease
   232  	ctx0, cancel0 := context.WithCancel(context.Background())
   233  	defer cancel0()
   234  	lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant(
   235  		ctx0,
   236  		&pb.LeaseGrantRequest{TTL: 30})
   237  	if err != nil {
   238  		t.Fatal(err)
   239  	}
   240  	if lresp.Error != "" {
   241  		t.Fatal(lresp.Error)
   242  	}
   243  
   244  	if !leaseExist(t, clus, lresp.ID) {
   245  		t.Error("unexpected lease not exists")
   246  	}
   247  }
   248  
   249  // TestV3LeaseLeases creates leases and confirms list RPC fetches created ones.
   250  func TestV3LeaseLeases(t *testing.T) {
   251  	defer testutil.AfterTest(t)
   252  	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
   253  	defer clus.Terminate(t)
   254  
   255  	ctx0, cancel0 := context.WithCancel(context.Background())
   256  	defer cancel0()
   257  
   258  	// create leases
   259  	ids := []int64{}
   260  	for i := 0; i < 5; i++ {
   261  		lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant(
   262  			ctx0,
   263  			&pb.LeaseGrantRequest{TTL: 30})
   264  		if err != nil {
   265  			t.Fatal(err)
   266  		}
   267  		if lresp.Error != "" {
   268  			t.Fatal(lresp.Error)
   269  		}
   270  		ids = append(ids, lresp.ID)
   271  	}
   272  
   273  	lresp, err := toGRPC(clus.RandClient()).Lease.LeaseLeases(
   274  		context.Background(),
   275  		&pb.LeaseLeasesRequest{})
   276  	if err != nil {
   277  		t.Fatal(err)
   278  	}
   279  	for i := range lresp.Leases {
   280  		if lresp.Leases[i].ID != ids[i] {
   281  			t.Fatalf("#%d: lease ID expected %d, got %d", i, ids[i], lresp.Leases[i].ID)
   282  		}
   283  	}
   284  }
   285  
   286  // TestV3LeaseRenewStress keeps creating lease and renewing it immediately to ensure the renewal goes through.
   287  // it was oberserved that the immediate lease renewal after granting a lease from follower resulted lease not found.
   288  // related issue https://github.com/coreos/etcd/issues/6978
   289  func TestV3LeaseRenewStress(t *testing.T) {
   290  	testLeaseStress(t, stressLeaseRenew)
   291  }
   292  
   293  // TestV3LeaseTimeToLiveStress keeps creating lease and retrieving it immediately to ensure the lease can be retrieved.
   294  // it was oberserved that the immediate lease retrieval after granting a lease from follower resulted lease not found.
   295  // related issue https://github.com/coreos/etcd/issues/6978
   296  func TestV3LeaseTimeToLiveStress(t *testing.T) {
   297  	testLeaseStress(t, stressLeaseTimeToLive)
   298  }
   299  
   300  func testLeaseStress(t *testing.T, stresser func(context.Context, pb.LeaseClient) error) {
   301  	defer testutil.AfterTest(t)
   302  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
   303  	defer clus.Terminate(t)
   304  
   305  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   306  	defer cancel()
   307  	errc := make(chan error)
   308  
   309  	for i := 0; i < 30; i++ {
   310  		for j := 0; j < 3; j++ {
   311  			go func(i int) { errc <- stresser(ctx, toGRPC(clus.Client(i)).Lease) }(j)
   312  		}
   313  	}
   314  
   315  	for i := 0; i < 90; i++ {
   316  		if err := <-errc; err != nil {
   317  			t.Fatal(err)
   318  		}
   319  	}
   320  }
   321  
   322  func stressLeaseRenew(tctx context.Context, lc pb.LeaseClient) (reterr error) {
   323  	defer func() {
   324  		if tctx.Err() != nil {
   325  			reterr = nil
   326  		}
   327  	}()
   328  	lac, err := lc.LeaseKeepAlive(tctx)
   329  	if err != nil {
   330  		return err
   331  	}
   332  	for tctx.Err() == nil {
   333  		resp, gerr := lc.LeaseGrant(tctx, &pb.LeaseGrantRequest{TTL: 60})
   334  		if gerr != nil {
   335  			continue
   336  		}
   337  		err = lac.Send(&pb.LeaseKeepAliveRequest{ID: resp.ID})
   338  		if err != nil {
   339  			continue
   340  		}
   341  		rresp, rxerr := lac.Recv()
   342  		if rxerr != nil {
   343  			continue
   344  		}
   345  		if rresp.TTL == 0 {
   346  			return fmt.Errorf("TTL shouldn't be 0 so soon")
   347  		}
   348  	}
   349  	return nil
   350  }
   351  
   352  func stressLeaseTimeToLive(tctx context.Context, lc pb.LeaseClient) (reterr error) {
   353  	defer func() {
   354  		if tctx.Err() != nil {
   355  			reterr = nil
   356  		}
   357  	}()
   358  	for tctx.Err() == nil {
   359  		resp, gerr := lc.LeaseGrant(tctx, &pb.LeaseGrantRequest{TTL: 60})
   360  		if gerr != nil {
   361  			continue
   362  		}
   363  		_, kerr := lc.LeaseTimeToLive(tctx, &pb.LeaseTimeToLiveRequest{ID: resp.ID})
   364  		if rpctypes.Error(kerr) == rpctypes.ErrLeaseNotFound {
   365  			return kerr
   366  		}
   367  	}
   368  	return nil
   369  }
   370  
   371  func TestV3PutOnNonExistLease(t *testing.T) {
   372  	defer testutil.AfterTest(t)
   373  	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
   374  	defer clus.Terminate(t)
   375  
   376  	ctx, cancel := context.WithCancel(context.Background())
   377  	defer cancel()
   378  
   379  	badLeaseID := int64(0x12345678)
   380  	putr := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: badLeaseID}
   381  	_, err := toGRPC(clus.RandClient()).KV.Put(ctx, putr)
   382  	if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseNotFound) {
   383  		t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCLeaseNotFound)
   384  	}
   385  }
   386  
   387  // TestV3GetNonExistLease ensures client retrieving nonexistent lease on a follower doesn't result node panic
   388  // related issue https://github.com/coreos/etcd/issues/6537
   389  func TestV3GetNonExistLease(t *testing.T) {
   390  	defer testutil.AfterTest(t)
   391  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
   392  	defer clus.Terminate(t)
   393  
   394  	ctx, cancel := context.WithCancel(context.Background())
   395  	defer cancel()
   396  	lc := toGRPC(clus.RandClient()).Lease
   397  	lresp, err := lc.LeaseGrant(ctx, &pb.LeaseGrantRequest{TTL: 10})
   398  	if err != nil {
   399  		t.Errorf("failed to create lease %v", err)
   400  	}
   401  	_, err = lc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID})
   402  	if err != nil {
   403  		t.Fatal(err)
   404  	}
   405  
   406  	leaseTTLr := &pb.LeaseTimeToLiveRequest{
   407  		ID:   lresp.ID,
   408  		Keys: true,
   409  	}
   410  
   411  	for _, client := range clus.clients {
   412  		// quorum-read to ensure revoke completes before TimeToLive
   413  		if _, err := toGRPC(client).KV.Range(ctx, &pb.RangeRequest{Key: []byte("_")}); err != nil {
   414  			t.Fatal(err)
   415  		}
   416  		resp, err := toGRPC(client).Lease.LeaseTimeToLive(ctx, leaseTTLr)
   417  		if err != nil {
   418  			t.Fatalf("expected non nil error, but go %v", err)
   419  		}
   420  		if resp.TTL != -1 {
   421  			t.Fatalf("expected TTL to be -1, but got %v", resp.TTL)
   422  		}
   423  	}
   424  }
   425  
   426  // TestV3LeaseSwitch tests a key can be switched from one lease to another.
   427  func TestV3LeaseSwitch(t *testing.T) {
   428  	defer testutil.AfterTest(t)
   429  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
   430  	defer clus.Terminate(t)
   431  
   432  	key := "foo"
   433  
   434  	// create lease
   435  	ctx, cancel := context.WithCancel(context.Background())
   436  	defer cancel()
   437  	lresp1, err1 := toGRPC(clus.RandClient()).Lease.LeaseGrant(ctx, &pb.LeaseGrantRequest{TTL: 30})
   438  	if err1 != nil {
   439  		t.Fatal(err1)
   440  	}
   441  	lresp2, err2 := toGRPC(clus.RandClient()).Lease.LeaseGrant(ctx, &pb.LeaseGrantRequest{TTL: 30})
   442  	if err2 != nil {
   443  		t.Fatal(err2)
   444  	}
   445  
   446  	// attach key on lease1 then switch it to lease2
   447  	put1 := &pb.PutRequest{Key: []byte(key), Lease: lresp1.ID}
   448  	_, err := toGRPC(clus.RandClient()).KV.Put(ctx, put1)
   449  	if err != nil {
   450  		t.Fatal(err)
   451  	}
   452  	put2 := &pb.PutRequest{Key: []byte(key), Lease: lresp2.ID}
   453  	_, err = toGRPC(clus.RandClient()).KV.Put(ctx, put2)
   454  	if err != nil {
   455  		t.Fatal(err)
   456  	}
   457  
   458  	// revoke lease1 should not remove key
   459  	_, err = toGRPC(clus.RandClient()).Lease.LeaseRevoke(ctx, &pb.LeaseRevokeRequest{ID: lresp1.ID})
   460  	if err != nil {
   461  		t.Fatal(err)
   462  	}
   463  	rreq := &pb.RangeRequest{Key: []byte("foo")}
   464  	rresp, err := toGRPC(clus.RandClient()).KV.Range(context.TODO(), rreq)
   465  	if err != nil {
   466  		t.Fatal(err)
   467  	}
   468  	if len(rresp.Kvs) != 1 {
   469  		t.Fatalf("unexpect removal of key")
   470  	}
   471  
   472  	// revoke lease2 should remove key
   473  	_, err = toGRPC(clus.RandClient()).Lease.LeaseRevoke(ctx, &pb.LeaseRevokeRequest{ID: lresp2.ID})
   474  	if err != nil {
   475  		t.Fatal(err)
   476  	}
   477  	rresp, err = toGRPC(clus.RandClient()).KV.Range(context.TODO(), rreq)
   478  	if err != nil {
   479  		t.Fatal(err)
   480  	}
   481  	if len(rresp.Kvs) != 0 {
   482  		t.Fatalf("lease removed but key remains")
   483  	}
   484  }
   485  
   486  // TestV3LeaseFailover ensures the old leader drops lease keepalive requests within
   487  // election timeout after it loses its quorum. And the new leader extends the TTL of
   488  // the lease to at least TTL + election timeout.
   489  func TestV3LeaseFailover(t *testing.T) {
   490  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
   491  	defer clus.Terminate(t)
   492  
   493  	toIsolate := clus.waitLeader(t, clus.Members)
   494  
   495  	lc := toGRPC(clus.Client(toIsolate)).Lease
   496  
   497  	// create lease
   498  	lresp, err := lc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 5})
   499  	if err != nil {
   500  		t.Fatal(err)
   501  	}
   502  	if lresp.Error != "" {
   503  		t.Fatal(lresp.Error)
   504  	}
   505  
   506  	// isolate the current leader with its followers.
   507  	clus.Members[toIsolate].Pause()
   508  
   509  	lreq := &pb.LeaseKeepAliveRequest{ID: lresp.ID}
   510  
   511  	md := metadata.Pairs(rpctypes.MetadataRequireLeaderKey, rpctypes.MetadataHasLeader)
   512  	mctx := metadata.NewOutgoingContext(context.Background(), md)
   513  	ctx, cancel := context.WithCancel(mctx)
   514  	lac, err := lc.LeaseKeepAlive(ctx)
   515  	if err != nil {
   516  		t.Fatal(err)
   517  	}
   518  	defer func() {
   519  		lac.CloseSend()
   520  		cancel()
   521  	}()
   522  
   523  	// send keep alive to old leader until the old leader starts
   524  	// to drop lease request.
   525  	var expectedExp time.Time
   526  	for {
   527  		if err = lac.Send(lreq); err != nil {
   528  			break
   529  		}
   530  		lkresp, rxerr := lac.Recv()
   531  		if rxerr != nil {
   532  			break
   533  		}
   534  		expectedExp = time.Now().Add(time.Duration(lkresp.TTL) * time.Second)
   535  		time.Sleep(time.Duration(lkresp.TTL/2) * time.Second)
   536  	}
   537  
   538  	clus.Members[toIsolate].Resume()
   539  	clus.waitLeader(t, clus.Members)
   540  
   541  	// lease should not expire at the last received expire deadline.
   542  	time.Sleep(time.Until(expectedExp) - 500*time.Millisecond)
   543  
   544  	if !leaseExist(t, clus, lresp.ID) {
   545  		t.Error("unexpected lease not exists")
   546  	}
   547  }
   548  
   549  // TestV3LeaseRequireLeader ensures that a Recv will get a leader
   550  // loss error if there is no leader.
   551  func TestV3LeaseRequireLeader(t *testing.T) {
   552  	defer testutil.AfterTest(t)
   553  
   554  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
   555  	defer clus.Terminate(t)
   556  
   557  	lc := toGRPC(clus.Client(0)).Lease
   558  	clus.Members[1].Stop(t)
   559  	clus.Members[2].Stop(t)
   560  
   561  	md := metadata.Pairs(rpctypes.MetadataRequireLeaderKey, rpctypes.MetadataHasLeader)
   562  	mctx := metadata.NewOutgoingContext(context.Background(), md)
   563  	ctx, cancel := context.WithCancel(mctx)
   564  	defer cancel()
   565  	lac, err := lc.LeaseKeepAlive(ctx)
   566  	if err != nil {
   567  		t.Fatal(err)
   568  	}
   569  
   570  	donec := make(chan struct{})
   571  	go func() {
   572  		defer close(donec)
   573  		resp, err := lac.Recv()
   574  		if err == nil {
   575  			t.Fatalf("got response %+v, expected error", resp)
   576  		}
   577  		if rpctypes.ErrorDesc(err) != rpctypes.ErrNoLeader.Error() {
   578  			t.Errorf("err = %v, want %v", err, rpctypes.ErrNoLeader)
   579  		}
   580  	}()
   581  	select {
   582  	case <-time.After(5 * time.Second):
   583  		t.Fatal("did not receive leader loss error (in 5-sec)")
   584  	case <-donec:
   585  	}
   586  }
   587  
   588  const fiveMinTTL int64 = 300
   589  
   590  // TestV3LeaseRecoverAndRevoke ensures that revoking a lease after restart deletes the attached key.
   591  func TestV3LeaseRecoverAndRevoke(t *testing.T) {
   592  	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
   593  	defer clus.Terminate(t)
   594  
   595  	kvc := toGRPC(clus.Client(0)).KV
   596  	lsc := toGRPC(clus.Client(0)).Lease
   597  
   598  	lresp, err := lsc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: fiveMinTTL})
   599  	if err != nil {
   600  		t.Fatal(err)
   601  	}
   602  	if lresp.Error != "" {
   603  		t.Fatal(lresp.Error)
   604  	}
   605  	_, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID})
   606  	if err != nil {
   607  		t.Fatal(err)
   608  	}
   609  
   610  	// restart server and ensure lease still exists
   611  	clus.Members[0].Stop(t)
   612  	clus.Members[0].Restart(t)
   613  	clus.waitLeader(t, clus.Members)
   614  
   615  	// overwrite old client with newly dialed connection
   616  	// otherwise, error with "grpc: RPC failed fast due to transport failure"
   617  	nc, err := NewClientV3(clus.Members[0])
   618  	if err != nil {
   619  		t.Fatal(err)
   620  	}
   621  	kvc = toGRPC(nc).KV
   622  	lsc = toGRPC(nc).Lease
   623  	defer nc.Close()
   624  
   625  	// revoke should delete the key
   626  	_, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID})
   627  	if err != nil {
   628  		t.Fatal(err)
   629  	}
   630  	rresp, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")})
   631  	if err != nil {
   632  		t.Fatal(err)
   633  	}
   634  	if len(rresp.Kvs) != 0 {
   635  		t.Fatalf("lease removed but key remains")
   636  	}
   637  }
   638  
   639  // TestV3LeaseRevokeAndRecover ensures that revoked key stays deleted after restart.
   640  func TestV3LeaseRevokeAndRecover(t *testing.T) {
   641  	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
   642  	defer clus.Terminate(t)
   643  
   644  	kvc := toGRPC(clus.Client(0)).KV
   645  	lsc := toGRPC(clus.Client(0)).Lease
   646  
   647  	lresp, err := lsc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: fiveMinTTL})
   648  	if err != nil {
   649  		t.Fatal(err)
   650  	}
   651  	if lresp.Error != "" {
   652  		t.Fatal(lresp.Error)
   653  	}
   654  	_, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID})
   655  	if err != nil {
   656  		t.Fatal(err)
   657  	}
   658  
   659  	// revoke should delete the key
   660  	_, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID})
   661  	if err != nil {
   662  		t.Fatal(err)
   663  	}
   664  
   665  	// restart server and ensure revoked key doesn't exist
   666  	clus.Members[0].Stop(t)
   667  	clus.Members[0].Restart(t)
   668  	clus.waitLeader(t, clus.Members)
   669  
   670  	// overwrite old client with newly dialed connection
   671  	// otherwise, error with "grpc: RPC failed fast due to transport failure"
   672  	nc, err := NewClientV3(clus.Members[0])
   673  	if err != nil {
   674  		t.Fatal(err)
   675  	}
   676  	kvc = toGRPC(nc).KV
   677  	defer nc.Close()
   678  
   679  	rresp, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")})
   680  	if err != nil {
   681  		t.Fatal(err)
   682  	}
   683  	if len(rresp.Kvs) != 0 {
   684  		t.Fatalf("lease removed but key remains")
   685  	}
   686  }
   687  
   688  // TestV3LeaseRecoverKeyWithDetachedLease ensures that revoking a detached lease after restart
   689  // does not delete the key.
   690  func TestV3LeaseRecoverKeyWithDetachedLease(t *testing.T) {
   691  	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
   692  	defer clus.Terminate(t)
   693  
   694  	kvc := toGRPC(clus.Client(0)).KV
   695  	lsc := toGRPC(clus.Client(0)).Lease
   696  
   697  	lresp, err := lsc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: fiveMinTTL})
   698  	if err != nil {
   699  		t.Fatal(err)
   700  	}
   701  	if lresp.Error != "" {
   702  		t.Fatal(lresp.Error)
   703  	}
   704  	_, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID})
   705  	if err != nil {
   706  		t.Fatal(err)
   707  	}
   708  
   709  	// overwrite lease with none
   710  	_, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar")})
   711  	if err != nil {
   712  		t.Fatal(err)
   713  	}
   714  
   715  	// restart server and ensure lease still exists
   716  	clus.Members[0].Stop(t)
   717  	clus.Members[0].Restart(t)
   718  	clus.waitLeader(t, clus.Members)
   719  
   720  	// overwrite old client with newly dialed connection
   721  	// otherwise, error with "grpc: RPC failed fast due to transport failure"
   722  	nc, err := NewClientV3(clus.Members[0])
   723  	if err != nil {
   724  		t.Fatal(err)
   725  	}
   726  	kvc = toGRPC(nc).KV
   727  	lsc = toGRPC(nc).Lease
   728  	defer nc.Close()
   729  
   730  	// revoke the detached lease
   731  	_, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: lresp.ID})
   732  	if err != nil {
   733  		t.Fatal(err)
   734  	}
   735  	rresp, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")})
   736  	if err != nil {
   737  		t.Fatal(err)
   738  	}
   739  	if len(rresp.Kvs) != 1 {
   740  		t.Fatalf("only detached lease removed, key should remain")
   741  	}
   742  }
   743  
   744  func TestV3LeaseRecoverKeyWithMutipleLease(t *testing.T) {
   745  	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
   746  	defer clus.Terminate(t)
   747  
   748  	kvc := toGRPC(clus.Client(0)).KV
   749  	lsc := toGRPC(clus.Client(0)).Lease
   750  
   751  	var leaseIDs []int64
   752  	for i := 0; i < 2; i++ {
   753  		lresp, err := lsc.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: fiveMinTTL})
   754  		if err != nil {
   755  			t.Fatal(err)
   756  		}
   757  		if lresp.Error != "" {
   758  			t.Fatal(lresp.Error)
   759  		}
   760  		leaseIDs = append(leaseIDs, lresp.ID)
   761  
   762  		_, err = kvc.Put(context.TODO(), &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: lresp.ID})
   763  		if err != nil {
   764  			t.Fatal(err)
   765  		}
   766  	}
   767  
   768  	// restart server and ensure lease still exists
   769  	clus.Members[0].Stop(t)
   770  	clus.Members[0].Restart(t)
   771  	clus.waitLeader(t, clus.Members)
   772  	for i, leaseID := range leaseIDs {
   773  		if !leaseExist(t, clus, leaseID) {
   774  			t.Errorf("#%d: unexpected lease not exists", i)
   775  		}
   776  	}
   777  
   778  	// overwrite old client with newly dialed connection
   779  	// otherwise, error with "grpc: RPC failed fast due to transport failure"
   780  	nc, err := NewClientV3(clus.Members[0])
   781  	if err != nil {
   782  		t.Fatal(err)
   783  	}
   784  	kvc = toGRPC(nc).KV
   785  	lsc = toGRPC(nc).Lease
   786  	defer nc.Close()
   787  
   788  	// revoke the old lease
   789  	_, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseIDs[0]})
   790  	if err != nil {
   791  		t.Fatal(err)
   792  	}
   793  	// key should still exist
   794  	rresp, err := kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")})
   795  	if err != nil {
   796  		t.Fatal(err)
   797  	}
   798  	if len(rresp.Kvs) != 1 {
   799  		t.Fatalf("only detached lease removed, key should remain")
   800  	}
   801  
   802  	// revoke the latest lease
   803  	_, err = lsc.LeaseRevoke(context.TODO(), &pb.LeaseRevokeRequest{ID: leaseIDs[1]})
   804  	if err != nil {
   805  		t.Fatal(err)
   806  	}
   807  	rresp, err = kvc.Range(context.TODO(), &pb.RangeRequest{Key: []byte("foo")})
   808  	if err != nil {
   809  		t.Fatal(err)
   810  	}
   811  	if len(rresp.Kvs) != 0 {
   812  		t.Fatalf("lease removed but key remains")
   813  	}
   814  }
   815  
   816  // acquireLeaseAndKey creates a new lease and creates an attached key.
   817  func acquireLeaseAndKey(clus *ClusterV3, key string) (int64, error) {
   818  	// create lease
   819  	lresp, err := toGRPC(clus.RandClient()).Lease.LeaseGrant(
   820  		context.TODO(),
   821  		&pb.LeaseGrantRequest{TTL: 1})
   822  	if err != nil {
   823  		return 0, err
   824  	}
   825  	if lresp.Error != "" {
   826  		return 0, fmt.Errorf(lresp.Error)
   827  	}
   828  	// attach to key
   829  	put := &pb.PutRequest{Key: []byte(key), Lease: lresp.ID}
   830  	if _, err := toGRPC(clus.RandClient()).KV.Put(context.TODO(), put); err != nil {
   831  		return 0, err
   832  	}
   833  	return lresp.ID, nil
   834  }
   835  
   836  // testLeaseRemoveLeasedKey performs some action while holding a lease with an
   837  // attached key "foo", then confirms the key is gone.
   838  func testLeaseRemoveLeasedKey(t *testing.T, act func(*ClusterV3, int64) error) {
   839  	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
   840  	defer clus.Terminate(t)
   841  
   842  	leaseID, err := acquireLeaseAndKey(clus, "foo")
   843  	if err != nil {
   844  		t.Fatal(err)
   845  	}
   846  
   847  	if err = act(clus, leaseID); err != nil {
   848  		t.Fatal(err)
   849  	}
   850  
   851  	// confirm no key
   852  	rreq := &pb.RangeRequest{Key: []byte("foo")}
   853  	rresp, err := toGRPC(clus.RandClient()).KV.Range(context.TODO(), rreq)
   854  	if err != nil {
   855  		t.Fatal(err)
   856  	}
   857  	if len(rresp.Kvs) != 0 {
   858  		t.Fatalf("lease removed but key remains")
   859  	}
   860  }
   861  
   862  func leaseExist(t *testing.T, clus *ClusterV3, leaseID int64) bool {
   863  	l := toGRPC(clus.RandClient()).Lease
   864  
   865  	_, err := l.LeaseGrant(context.Background(), &pb.LeaseGrantRequest{ID: leaseID, TTL: 5})
   866  	if err == nil {
   867  		_, err = l.LeaseRevoke(context.Background(), &pb.LeaseRevokeRequest{ID: leaseID})
   868  		if err != nil {
   869  			t.Fatalf("failed to check lease %v", err)
   870  		}
   871  		return false
   872  	}
   873  
   874  	if eqErrGRPC(err, rpctypes.ErrGRPCLeaseExist) {
   875  		return true
   876  	}
   877  	t.Fatalf("unexpecter error %v", err)
   878  
   879  	return true
   880  }