浏览代码

Merge pull request #5218 from heyitsanthony/fix-issue-3699

integration: wait for ReadyNotify in Issue3699 test
Anthony Romano 9 年之前
父节点
当前提交
11ec94b7e8
共有 3 个文件被更改,包括 22 次插入7 次删除
  1. 1 1
      integration/cluster.go
  2. 10 6
      integration/cluster_test.go
  3. 11 0
      rafthttp/transport.go

+ 1 - 1
integration/cluster.go

@@ -329,11 +329,11 @@ func (c *cluster) waitLeader(t *testing.T, membs []*member) int {
 			}
 			}
 			if lead != 0 && lead != m.s.Lead() {
 			if lead != 0 && lead != m.s.Lead() {
 				lead = 0
 				lead = 0
+				time.Sleep(10 * tickDuration)
 				break
 				break
 			}
 			}
 			lead = m.s.Lead()
 			lead = m.s.Lead()
 		}
 		}
-		time.Sleep(10 * tickDuration)
 	}
 	}
 
 
 	for i, m := range membs {
 	for i, m := range membs {

+ 10 - 6
integration/cluster_test.go

@@ -21,6 +21,7 @@ import (
 	"os"
 	"os"
 	"strconv"
 	"strconv"
 	"testing"
 	"testing"
+	"time"
 
 
 	"github.com/coreos/etcd/client"
 	"github.com/coreos/etcd/client"
 	"github.com/coreos/etcd/pkg/testutil"
 	"github.com/coreos/etcd/pkg/testutil"
@@ -301,7 +302,6 @@ func TestIssue3699(t *testing.T) {
 
 
 	// make node a unavailable
 	// make node a unavailable
 	c.Members[0].Stop(t)
 	c.Members[0].Stop(t)
-	<-c.Members[0].s.StopNotify()
 
 
 	// add node d
 	// add node d
 	c.AddMember(t)
 	c.AddMember(t)
@@ -317,11 +317,16 @@ func TestIssue3699(t *testing.T) {
 
 
 	// bring back node a
 	// bring back node a
 	// node a will remain useless as long as d is the leader.
 	// node a will remain useless as long as d is the leader.
-	err := c.Members[0].Restart(t)
+	if err := c.Members[0].Restart(t); err != nil {
+		t.Fatal(err)
+	}
 	select {
 	select {
+	// waiting for ReadyNotify can take several seconds
+	case <-time.After(10 * time.Second):
+		t.Fatalf("waited too long for ready notification")
 	case <-c.Members[0].s.StopNotify():
 	case <-c.Members[0].s.StopNotify():
 		t.Fatalf("should not be stopped")
 		t.Fatalf("should not be stopped")
-	default:
+	case <-c.Members[0].s.ReadyNotify():
 	}
 	}
 	// must waitLeader so goroutines don't leak on terminate
 	// must waitLeader so goroutines don't leak on terminate
 	c.waitLeader(t, c.Members)
 	c.waitLeader(t, c.Members)
@@ -330,11 +335,10 @@ func TestIssue3699(t *testing.T) {
 	cc := mustNewHTTPClient(t, []string{c.URL(0)}, c.cfg.ClientTLS)
 	cc := mustNewHTTPClient(t, []string{c.URL(0)}, c.cfg.ClientTLS)
 	kapi := client.NewKeysAPI(cc)
 	kapi := client.NewKeysAPI(cc)
 	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
 	ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
-	_, err = kapi.Set(ctx, "/foo", "bar", nil)
-	cancel()
-	if err != nil {
+	if _, err := kapi.Set(ctx, "/foo", "bar", nil); err != nil {
 		t.Fatalf("unexpected error on Set (%v)", err)
 		t.Fatalf("unexpected error on Set (%v)", err)
 	}
 	}
+	cancel()
 }
 }
 
 
 // clusterMustProgress ensures that cluster can make progress. It creates
 // clusterMustProgress ensures that cluster can make progress. It creates

+ 11 - 0
rafthttp/transport.go

@@ -202,11 +202,19 @@ func (t *Transport) Stop() {
 	if tr, ok := t.pipelineRt.(*http.Transport); ok {
 	if tr, ok := t.pipelineRt.(*http.Transport); ok {
 		tr.CloseIdleConnections()
 		tr.CloseIdleConnections()
 	}
 	}
+	t.peers = nil
+	t.remotes = nil
 }
 }
 
 
 func (t *Transport) AddRemote(id types.ID, us []string) {
 func (t *Transport) AddRemote(id types.ID, us []string) {
 	t.mu.Lock()
 	t.mu.Lock()
 	defer t.mu.Unlock()
 	defer t.mu.Unlock()
+	if t.remotes == nil {
+		// there's no clean way to shutdown the golang http server
+		// (see: https://github.com/golang/go/issues/4674) before
+		// stopping the transport; ignore any new connections.
+		return
+	}
 	if _, ok := t.peers[id]; ok {
 	if _, ok := t.peers[id]; ok {
 		return
 		return
 	}
 	}
@@ -223,6 +231,9 @@ func (t *Transport) AddRemote(id types.ID, us []string) {
 func (t *Transport) AddPeer(id types.ID, us []string) {
 func (t *Transport) AddPeer(id types.ID, us []string) {
 	t.mu.Lock()
 	t.mu.Lock()
 	defer t.mu.Unlock()
 	defer t.mu.Unlock()
+	if t.peers == nil {
+		panic("transport stopped")
+	}
 	if _, ok := t.peers[id]; ok {
 	if _, ok := t.peers[id]; ok {
 		return
 		return
 	}
 	}