integration: improve TestTransferLeader

so that it can check leader transition
This commit is contained in:
Gyu-Ho Lee 2016-08-19 13:02:22 -07:00
parent 5e6d2a23b7
commit eaa5d9772f
2 changed files with 39 additions and 28 deletions

View File

@ -702,13 +702,13 @@ func (m *member) Stop(t *testing.T) {
plog.Printf("stopped %s (%s)", m.Name, m.grpcAddr) plog.Printf("stopped %s (%s)", m.Name, m.grpcAddr)
} }
// StopWithAutoLeaderTransfer stops the member with auto leader transfer. // checkLeaderTransition waits for leader transition, returning the new leader ID.
func (m *member) StopWithAutoLeaderTransfer(t *testing.T) { func checkLeaderTransition(t *testing.T, m *member, oldLead uint64) uint64 {
plog.Printf("stopping %s (%s)", m.Name, m.grpcAddr) interval := time.Duration(m.s.Cfg.TickMs) * time.Millisecond
m.s.TransferLeadership() for m.s.Lead() == 0 || (m.s.Lead() == oldLead) {
m.Close() time.Sleep(interval)
m.hss = nil }
plog.Printf("stopped %s (%s)", m.Name, m.grpcAddr) return m.s.Lead()
} }
// StopNotify unblocks when a member stop completes // StopNotify unblocks when a member stop completes

View File

@ -26,7 +26,6 @@ import (
"github.com/coreos/etcd/client" "github.com/coreos/etcd/client"
"github.com/coreos/etcd/etcdserver" "github.com/coreos/etcd/etcdserver"
"github.com/coreos/etcd/etcdserver/etcdserverpb"
"github.com/coreos/etcd/pkg/testutil" "github.com/coreos/etcd/pkg/testutil"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -470,29 +469,41 @@ func TestTransferLeader(t *testing.T) {
clus := NewClusterV3(t, &ClusterConfig{Size: 3}) clus := NewClusterV3(t, &ClusterConfig{Size: 3})
defer clus.Terminate(t) defer clus.Terminate(t)
leaderIdx := clus.WaitLeader(t)
err := clus.Members[leaderIdx].s.TransferLeadership()
if err != nil {
t.Fatal(err)
}
}
func TestTransferLeaderStopTrigger(t *testing.T) {
defer testutil.AfterTest(t)
clus := NewClusterV3(t, &ClusterConfig{Size: 3})
defer clus.Terminate(t)
oldLeadIdx := clus.WaitLeader(t) oldLeadIdx := clus.WaitLeader(t)
clus.Members[oldLeadIdx].StopWithAutoLeaderTransfer(t) oldLeadID := uint64(clus.Members[oldLeadIdx].s.ID())
// issue put to one of the other member // ensure followers go through leader transition while learship transfer
kvc := toGRPC(clus.Client((oldLeadIdx + 1) % 3)).KV idc := make(chan uint64)
sctx, scancel := context.WithTimeout(context.TODO(), clus.Members[oldLeadIdx].electionTimeout()) for i := range clus.Members {
_, err := kvc.Range(sctx, &etcdserverpb.RangeRequest{Key: []byte("foo")}) if oldLeadIdx != i {
scancel() go func(m *member) {
idc <- checkLeaderTransition(t, m, oldLeadID)
}(clus.Members[i])
}
}
err := clus.Members[oldLeadIdx].s.TransferLeadership()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// wait until leader transitions have happened
var newLeadIDs [2]uint64
for i := range newLeadIDs {
select {
case newLeadIDs[i] = <-idc:
case <-time.After(time.Second):
t.Fatal("timed out waiting for leader transition")
}
}
// remaining members must agree on the same leader
if newLeadIDs[0] != newLeadIDs[1] {
t.Fatalf("expected same new leader %d == %d", newLeadIDs[0], newLeadIDs[1])
}
// new leader must be different than the old leader
if oldLeadID == newLeadIDs[0] {
t.Fatalf("expected old leader %d != new leader %d", oldLeadID, newLeadIDs[0])
}
} }