Browse Source

Merge pull request #1063 from coreos/node_run_test

raft: test node block proposal
Xiang Li 11 years ago
parent
commit
ff7f340bba
2 changed files with 82 additions and 1 deletions
  1. 1 1
      raft/node.go
  2. 81 0
      raft/node_test.go

+ 1 - 1
raft/node.go

@@ -34,7 +34,7 @@ type Ready struct {
 }
 
 func isStateEqual(a, b pb.State) bool {
-	return a.Term == b.Term && a.Vote == b.Vote && a.LastIndex == b.LastIndex
+	return a.Term == b.Term && a.Vote == b.Vote && a.Commit == b.Commit && a.LastIndex == b.LastIndex
 }
 
 func IsEmptyState(st pb.State) bool {

+ 81 - 0
raft/node_test.go

@@ -2,6 +2,7 @@ package raft
 
 import (
 	"reflect"
+	"runtime"
 	"testing"
 	"time"
 
@@ -81,6 +82,58 @@ func TestNodeStepUnblock(t *testing.T) {
 	}
 }
 
+// TestBlockProposal ensures that node will block proposal when it does not
+// know who is the current leader; node will accept proposal when it knows
+// who is the current leader.
+func TestBlockProposal(t *testing.T) {
+	n := newNode()
+	r := newRaft(1, []int64{1}, 10, 1)
+	go n.run(r)
+	defer n.Stop()
+
+	errc := make(chan error, 1)
+	go func() {
+		errc <- n.Propose(context.TODO(), []byte("somedata"))
+	}()
+
+	forceGosched()
+	select {
+	case err := <-errc:
+		t.Errorf("err = %v, want blocking", err)
+	default:
+	}
+
+	n.Campaign(context.TODO())
+	forceGosched()
+	select {
+	case err := <-errc:
+		if err != nil {
+			t.Errorf("err = %v, want %v", err, nil)
+		}
+	default:
+		t.Errorf("blocking proposal, want unblocking")
+	}
+}
+
+func TestReadyContainUpdates(t *testing.T) {
+	tests := []struct {
+		rd       Ready
+		wcontain bool
+	}{
+		{Ready{}, false},
+		{Ready{State: raftpb.State{Vote: 1}}, true},
+		{Ready{Entries: make([]raftpb.Entry, 1, 1)}, true},
+		{Ready{CommittedEntries: make([]raftpb.Entry, 1, 1)}, true},
+		{Ready{Messages: make([]raftpb.Message, 1, 1)}, true},
+	}
+
+	for i, tt := range tests {
+		if tt.rd.containsUpdates() != tt.wcontain {
+			t.Errorf("#%d: containUpdates = %v, want %v", i, tt.rd.containsUpdates(), tt.wcontain)
+		}
+	}
+}
+
 func TestNode(t *testing.T) {
 	ctx, cancel := context.WithCancel(context.Background())
 	defer cancel()
@@ -140,3 +193,31 @@ func TestNodeRestart(t *testing.T) {
 	default:
 	}
 }
+
+func TestIsStateEqual(t *testing.T) {
+	tests := []struct {
+		st raftpb.State
+		we bool
+	}{
+		{emptyState, true},
+		{raftpb.State{Vote: 1}, false},
+		{raftpb.State{Commit: 1}, false},
+		{raftpb.State{Term: 1}, false},
+		{raftpb.State{LastIndex: 1}, false},
+	}
+
+	for i, tt := range tests {
+		if isStateEqual(tt.st, emptyState) != tt.we {
+			t.Errorf("#%d, equal = %v, want %v", i, isStateEqual(tt.st, emptyState), tt.we)
+		}
+	}
+}
+
+// WARNING: This is a hack.
+// Remove this when we are able to block/check the status of the go-routines.
+func forceGosched() {
+	// possibility enough to sched upto 10 go routines.
+	for i := 0; i < 10000; i++ {
+		runtime.Gosched()
+	}
+}