Browse Source

raft: add tests for raft.compact

Xiang Li 11 years ago
parent
commit
45e4a8643a
4 changed files with 50 additions and 9 deletions
  1. 1 2
      raft/node.go
  2. 1 1
      raft/node_test.go
  3. 5 6
      raft/raft.go
  4. 43 0
      raft/raft_test.go

+ 1 - 2
raft/node.go

@@ -24,8 +24,7 @@ type SoftState struct {
 }
 
 func (a *SoftState) equal(b *SoftState) bool {
-	nodeeq := reflect.DeepEqual(a.Nodes, b.Nodes)
-	return a.Lead == b.Lead && a.RaftState == b.RaftState && a.ShouldStop == b.ShouldStop && nodeeq
+	return reflect.DeepEqual(a, b)
 }
 
 // Ready encapsulates the entries and messages that are ready to read,

+ 1 - 1
raft/node_test.go

@@ -221,7 +221,7 @@ func TestNodeRestart(t *testing.T) {
 
 // TestCompacts ensures Node.Compact creates a correct raft snapshot and compacts
 // the raft log (call raft.compact)
-func TestCompact(t *testing.T) {
+func TestNodeCompact(t *testing.T) {
 	ctx := context.Background()
 	n := newNode()
 	r := newRaft(1, []int64{1}, 0, 0)

+ 5 - 6
raft/raft.go

@@ -153,7 +153,7 @@ func (r *raft) hasLeader() bool { return r.lead != None }
 func (r *raft) shouldStop() bool { return r.removed[r.id] }
 
 func (r *raft) softState() *SoftState {
-	return &SoftState{Lead: r.lead, Nodes: r.nodes(), RaftState: r.state, ShouldStop: r.shouldStop()}
+	return &SoftState{Lead: r.lead, RaftState: r.state, Nodes: r.nodes(), ShouldStop: r.shouldStop()}
 }
 
 func (r *raft) String() string {
@@ -515,13 +515,12 @@ func stepFollower(r *raft, m pb.Message) {
 	}
 }
 
-func (r *raft) compact(index int64, nodes []int64, d []byte) error {
+func (r *raft) compact(index int64, nodes []int64, d []byte) {
 	if index > r.raftLog.applied {
-		return fmt.Errorf("raft: compact index (%d) exceeds applied index (%d)", index, r.raftLog.applied)
+		panic(fmt.Sprintf("raft: compact index (%d) exceeds applied index (%d)", index, r.raftLog.applied))
 	}
-	r.raftLog.snap(d, r.raftLog.applied, r.raftLog.term(r.raftLog.applied), nodes)
-	r.raftLog.compact(r.raftLog.applied)
-	return nil
+	r.raftLog.snap(d, index, r.raftLog.term(index), nodes)
+	r.raftLog.compact(index)
 }
 
 // restore recovers the statemachine from a snapshot. It restores the log and the

+ 43 - 0
raft/raft_test.go

@@ -408,6 +408,49 @@ func TestProposalByProxy(t *testing.T) {
 	}
 }
 
+func TestCompact(t *testing.T) {
+	tests := []struct {
+		compacti int64
+		nodes    []int64
+		snapd    []byte
+		wpanic   bool
+	}{
+		{1, []int64{1, 2, 3}, []byte("some data"), false},
+		{2, []int64{1, 2, 3}, []byte("some data"), false},
+		{4, []int64{1, 2, 3}, []byte("some data"), true}, // compact out of range
+	}
+
+	for i, tt := range tests {
+		func() {
+			defer func() {
+				if r := recover(); r != nil {
+					if tt.wpanic != true {
+						t.Errorf("%d: panic = %v, want %v", i, false, true)
+					}
+				}
+			}()
+			sm := &raft{
+				state: StateLeader,
+				raftLog: &raftLog{
+					committed: 2,
+					applied:   2,
+					ents:      []pb.Entry{{}, {Term: 1}, {Term: 1}, {Term: 1}},
+				},
+			}
+			sm.compact(tt.compacti, tt.nodes, tt.snapd)
+			if sm.raftLog.offset != tt.compacti {
+				t.Errorf("%d: log.offset = %d, want %d", i, sm.raftLog.offset, tt.compacti)
+			}
+			if !reflect.DeepEqual(sm.raftLog.snapshot.Nodes, tt.nodes) {
+				t.Errorf("%d: snap.nodes = %v, want %v", i, sm.raftLog.snapshot.Nodes, tt.nodes)
+			}
+			if !reflect.DeepEqual(sm.raftLog.snapshot.Data, tt.snapd) {
+				t.Errorf("%d: snap.data = %v, want %v", i, sm.raftLog.snapshot.Data, tt.snapd)
+			}
+		}()
+	}
+}
+
 func TestCommit(t *testing.T) {
 	tests := []struct {
 		matches []int64