|
|
@@ -90,11 +90,6 @@ func TestIsUpToDate(t *testing.T) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// TestAppend ensures:
|
|
|
-// 1. If an existing entry conflicts with a new one (same index
|
|
|
-// but different terms), delete the existing entry and all that
|
|
|
-// follow it
|
|
|
-// 2.Append any new entries not already in the log
|
|
|
func TestAppend(t *testing.T) {
|
|
|
previousEnts := []pb.Entry{{Term: 1}, {Term: 2}}
|
|
|
previousUnstable := uint64(3)
|
|
|
@@ -154,6 +149,131 @@ func TestAppend(t *testing.T) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// TestLogMaybeAppend ensures:
|
|
|
+// If the given (index, term) matches with the existing log:
|
|
|
+// 1. If an existing entry conflicts with a new one (same index
|
|
|
+// but different terms), delete the existing entry and all that
|
|
|
+// follow it
|
|
|
+// 2.Append any new entries not already in the log
|
|
|
+// If the given (index, term) does not match with the existing log:
|
|
|
+// return false
|
|
|
+func TestLogMaybeAppend(t *testing.T) {
|
|
|
+ previousEnts := []pb.Entry{{Term: 1}, {Term: 2}, {Term: 3}}
|
|
|
+ lastindex := uint64(3)
|
|
|
+ lastterm := uint64(3)
|
|
|
+ commit := uint64(1)
|
|
|
+
|
|
|
+ tests := []struct {
|
|
|
+ logTerm uint64
|
|
|
+ index uint64
|
|
|
+ committed uint64
|
|
|
+ ents []pb.Entry
|
|
|
+
|
|
|
+ wlasti uint64
|
|
|
+ wappend bool
|
|
|
+ wcommit uint64
|
|
|
+ wpanic bool
|
|
|
+ }{
|
|
|
+ // not match: term is different
|
|
|
+ {
|
|
|
+ lastterm - 1, lastindex, lastindex, []pb.Entry{{Term: 4}},
|
|
|
+ 0, false, commit, false,
|
|
|
+ },
|
|
|
+ // not match: index out of bound
|
|
|
+ {
|
|
|
+ lastterm, lastindex + 1, lastindex, []pb.Entry{{Term: 4}},
|
|
|
+ 0, false, commit, false,
|
|
|
+ },
|
|
|
+ // match with the last existing entry
|
|
|
+ {
|
|
|
+ lastterm, lastindex, lastindex, nil,
|
|
|
+ lastindex, true, lastindex, false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm, lastindex, lastindex + 1, nil,
|
|
|
+ lastindex, true, lastindex, false, // do not increase commit higher than lastnewi
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm, lastindex, lastindex - 1, nil,
|
|
|
+ lastindex, true, lastindex - 1, false, // commit up to the commit in the message
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm, lastindex, 0, nil,
|
|
|
+ lastindex, true, commit, false, // commit do not decrease
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm - 3, lastindex - 3, lastindex, nil,
|
|
|
+ 1, true, commit, false, // commit do not decrease
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm, lastindex, lastindex, []pb.Entry{{Term: 4}},
|
|
|
+ lastindex + 1, true, lastindex, false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm, lastindex, lastindex + 1, []pb.Entry{{Term: 4}},
|
|
|
+ lastindex + 1, true, lastindex + 1, false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm, lastindex, lastindex + 2, []pb.Entry{{Term: 4}},
|
|
|
+ lastindex + 1, true, lastindex + 1, false, // do not increase commit higher than lastnewi
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm, lastindex, lastindex + 2, []pb.Entry{{Term: 4}, {Term: 4}},
|
|
|
+ lastindex + 2, true, lastindex + 2, false,
|
|
|
+ },
|
|
|
+ // match with the the entry in the middle
|
|
|
+ {
|
|
|
+ lastterm - 1, lastindex - 1, lastindex, []pb.Entry{{Term: 4}},
|
|
|
+ lastindex, true, lastindex, false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm - 2, lastindex - 2, lastindex, []pb.Entry{{Term: 4}},
|
|
|
+ lastindex - 1, true, lastindex - 1, false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm - 3, lastindex - 3, lastindex, []pb.Entry{{Term: 4}},
|
|
|
+ lastindex - 2, true, lastindex - 2, true, // conflict with existing committed entry
|
|
|
+ },
|
|
|
+ {
|
|
|
+ lastterm - 2, lastindex - 2, lastindex, []pb.Entry{{Term: 4}, {Term: 4}},
|
|
|
+ lastindex, true, lastindex, false,
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, tt := range tests {
|
|
|
+ raftLog := newLog()
|
|
|
+ raftLog.append(raftLog.lastIndex(), previousEnts...)
|
|
|
+ raftLog.committed = commit
|
|
|
+ func() {
|
|
|
+ defer func() {
|
|
|
+ if r := recover(); r != nil {
|
|
|
+ if tt.wpanic != true {
|
|
|
+ t.Errorf("%d: panic = %v, want %v", i, true, tt.wpanic)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ glasti, gappend := raftLog.maybeAppend(tt.index, tt.logTerm, tt.committed, tt.ents...)
|
|
|
+ gcommit := raftLog.committed
|
|
|
+
|
|
|
+ if glasti != tt.wlasti {
|
|
|
+ t.Errorf("#%d: lastindex = %d, want %d", i, glasti, tt.wlasti)
|
|
|
+ }
|
|
|
+ if gappend != tt.wappend {
|
|
|
+ t.Errorf("#%d: append = %v, want %v", i, gappend, tt.wappend)
|
|
|
+ }
|
|
|
+ if gcommit != tt.wcommit {
|
|
|
+ t.Errorf("#%d: committed = %d, want %d", i, gcommit, tt.wcommit)
|
|
|
+ }
|
|
|
+ if gappend {
|
|
|
+ gents := raftLog.slice(raftLog.lastIndex()-uint64(len(tt.ents))+1, raftLog.lastIndex()+1)
|
|
|
+ if !reflect.DeepEqual(tt.ents, gents) {
|
|
|
+ t.Errorf("%d: appended entries = %v, want %v", i, gents, tt.ents)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// TestCompactionSideEffects ensures that all the log related funcationality works correctly after
|
|
|
// a compaction.
|
|
|
func TestCompactionSideEffects(t *testing.T) {
|