github.com/lfch/etcd-io/tests/v3@v3.0.0-20221004140520-eac99acd3e9d/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 pb "github.com/lfch/etcd-io/api/v3/etcdserverpb" 24 epb "github.com/lfch/etcd-io/server/v3/etcdserver/api/v3election/v3electionpb" 25 "github.com/lfch/etcd-io/tests/v3/framework/integration" 26 ) 27 28 // TestV3ElectionCampaign checks that Campaign will not give 29 // simultaneous leadership to multiple campaigners. 30 func TestV3ElectionCampaign(t *testing.T) { 31 integration.BeforeTest(t) 32 clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) 33 defer clus.Terminate(t) 34 35 lease1, err1 := integration.ToGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30}) 36 if err1 != nil { 37 t.Fatal(err1) 38 } 39 lease2, err2 := integration.ToGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30}) 40 if err2 != nil { 41 t.Fatal(err2) 42 } 43 44 lc := integration.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.Error(lerr2) 58 } 59 if l1.Header.Revision >= l2.Header.Revision { 60 t.Errorf("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 integration.BeforeTest(t) 94 clus := integration.NewCluster(t, &integration.ClusterConfig{Size: 1}) 95 defer clus.Terminate(t) 96 97 lc := integration.ToGRPC(clus.Client(0)).Election 98 99 // observe leadership events 100 observec := make(chan struct{}, 1) 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.Error(err) 107 } 108 for i := 0; i < 10; i++ { 109 resp, rerr := s.Recv() 110 if rerr != nil { 111 t.Error(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.Errorf(`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 := integration.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 := integration.ToGRPC(clus.RandClient()).Lease.LeaseGrant(context.TODO(), &pb.LeaseGrantRequest{TTL: 30}) 144 if err2 != nil { 145 t.Error(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.Error(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.Error(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 }