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

     1  // Copyright 2017 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  	epb "github.com/coreos/etcd/etcdserver/api/v3election/v3electionpb"
    24  	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
    25  	"github.com/coreos/etcd/pkg/testutil"
    26  )
    27  
    28  // TestV3ElectionCampaign checks that Campaign will not give
    29  // simultaneous leadership to multiple campaigners.
    30  func TestV3ElectionCampaign(t *testing.T) {
    31  	defer testutil.AfterTest(t)
    32  	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
    33  	defer clus.Terminate(t)
    34  
    35  	lease1, err1 := toGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30})
    36  	if err1 != nil {
    37  		t.Fatal(err1)
    38  	}
    39  	lease2, err2 := toGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30})
    40  	if err2 != nil {
    41  		t.Fatal(err2)
    42  	}
    43  
    44  	lc := toGRPC(clus.Client(0)).Election
    45  	req1 := &epb.CampaignRequest{Name: []byte("foo"), Lease: lease1.ID, Value: []byte("abc")}
    46  	l1, lerr1 := lc.Campaign(context.TODO(), req1)
    47  	if lerr1 != nil {
    48  		t.Fatal(lerr1)
    49  	}
    50  
    51  	campaignc := make(chan struct{})
    52  	go func() {
    53  		defer close(campaignc)
    54  		req2 := &epb.CampaignRequest{Name: []byte("foo"), Lease: lease2.ID, Value: []byte("def")}
    55  		l2, lerr2 := lc.Campaign(context.TODO(), req2)
    56  		if lerr2 != nil {
    57  			t.Fatal(lerr2)
    58  		}
    59  		if l1.Header.Revision >= l2.Header.Revision {
    60  			t.Fatalf("expected l1 revision < l2 revision, got %d >= %d", l1.Header.Revision, l2.Header.Revision)
    61  		}
    62  	}()
    63  
    64  	select {
    65  	case <-time.After(200 * time.Millisecond):
    66  	case <-campaignc:
    67  		t.Fatalf("got leadership before resign")
    68  	}
    69  
    70  	if _, uerr := lc.Resign(context.TODO(), &epb.ResignRequest{Leader: l1.Leader}); uerr != nil {
    71  		t.Fatal(uerr)
    72  	}
    73  
    74  	select {
    75  	case <-time.After(200 * time.Millisecond):
    76  		t.Fatalf("campaigner unelected after resign")
    77  	case <-campaignc:
    78  	}
    79  
    80  	lval, lverr := lc.Leader(context.TODO(), &epb.LeaderRequest{Name: []byte("foo")})
    81  	if lverr != nil {
    82  		t.Fatal(lverr)
    83  	}
    84  
    85  	if string(lval.Kv.Value) != "def" {
    86  		t.Fatalf("got election value %q, expected %q", string(lval.Kv.Value), "def")
    87  	}
    88  }
    89  
    90  // TestV3ElectionObserve checks that an Observe stream receives
    91  // proclamations from different leaders uninterrupted.
    92  func TestV3ElectionObserve(t *testing.T) {
    93  	defer testutil.AfterTest(t)
    94  	clus := NewClusterV3(t, &ClusterConfig{Size: 1})
    95  	defer clus.Terminate(t)
    96  
    97  	lc := toGRPC(clus.Client(0)).Election
    98  
    99  	// observe leadership events
   100  	observec := make(chan struct{})
   101  	go func() {
   102  		defer close(observec)
   103  		s, err := lc.Observe(context.Background(), &epb.LeaderRequest{Name: []byte("foo")})
   104  		observec <- struct{}{}
   105  		if err != nil {
   106  			t.Fatal(err)
   107  		}
   108  		for i := 0; i < 10; i++ {
   109  			resp, rerr := s.Recv()
   110  			if rerr != nil {
   111  				t.Fatal(rerr)
   112  			}
   113  			respV := 0
   114  			fmt.Sscanf(string(resp.Kv.Value), "%d", &respV)
   115  			// leader transitions should not go backwards
   116  			if respV < i {
   117  				t.Fatalf(`got observe value %q, expected >= "%d"`, string(resp.Kv.Value), i)
   118  			}
   119  			i = respV
   120  		}
   121  	}()
   122  
   123  	select {
   124  	case <-observec:
   125  	case <-time.After(time.Second):
   126  		t.Fatalf("observe stream took too long to start")
   127  	}
   128  
   129  	lease1, err1 := toGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30})
   130  	if err1 != nil {
   131  		t.Fatal(err1)
   132  	}
   133  	c1, cerr1 := lc.Campaign(context.TODO(), &epb.CampaignRequest{Name: []byte("foo"), Lease: lease1.ID, Value: []byte("0")})
   134  	if cerr1 != nil {
   135  		t.Fatal(cerr1)
   136  	}
   137  
   138  	// overlap other leader so it waits on resign
   139  	leader2c := make(chan struct{})
   140  	go func() {
   141  		defer close(leader2c)
   142  
   143  		lease2, err2 := toGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30})
   144  		if err2 != nil {
   145  			t.Fatal(err2)
   146  		}
   147  		c2, cerr2 := lc.Campaign(context.TODO(), &epb.CampaignRequest{Name: []byte("foo"), Lease: lease2.ID, Value: []byte("5")})
   148  		if cerr2 != nil {
   149  			t.Fatal(cerr2)
   150  		}
   151  		for i := 6; i < 10; i++ {
   152  			v := []byte(fmt.Sprintf("%d", i))
   153  			req := &epb.ProclaimRequest{Leader: c2.Leader, Value: v}
   154  			if _, err := lc.Proclaim(context.TODO(), req); err != nil {
   155  				t.Fatal(err)
   156  			}
   157  		}
   158  	}()
   159  
   160  	for i := 1; i < 5; i++ {
   161  		v := []byte(fmt.Sprintf("%d", i))
   162  		req := &epb.ProclaimRequest{Leader: c1.Leader, Value: v}
   163  		if _, err := lc.Proclaim(context.TODO(), req); err != nil {
   164  			t.Fatal(err)
   165  		}
   166  	}
   167  	// start second leader
   168  	lc.Resign(context.TODO(), &epb.ResignRequest{Leader: c1.Leader})
   169  
   170  	select {
   171  	case <-observec:
   172  	case <-time.After(time.Second):
   173  		t.Fatalf("observe did not observe all events in time")
   174  	}
   175  
   176  	<-leader2c
   177  }