raft: add test for findConflict
parent
2b9cabcbcd
commit
90f26e4a56
10
raft/log.go
10
raft/log.go
|
@ -83,6 +83,16 @@ func (l *raftLog) append(after uint64, ents ...pb.Entry) uint64 {
|
||||||
return l.lastIndex()
|
return l.lastIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// findConflict finds the index of the conflict.
|
||||||
|
// It returns the the first pair of confilcting entries between the existing
|
||||||
|
// entries and the given entries, if there is any.
|
||||||
|
// If there is no conflicting entries, and the existing entries contains
|
||||||
|
// all the given entries, zero will be returned.
|
||||||
|
// If there is no conflicting entries, but the given entries contains new
|
||||||
|
// entries, the index of the first new entry will be returned.
|
||||||
|
// Conflicting entries has the same index but different term.
|
||||||
|
// The first given entry MUST have the index equal to from.
|
||||||
|
// The index of the given entries MUST be continously increasing.
|
||||||
func (l *raftLog) findConflict(from uint64, ents []pb.Entry) uint64 {
|
func (l *raftLog) findConflict(from uint64, ents []pb.Entry) uint64 {
|
||||||
for i, ne := range ents {
|
for i, ne := range ents {
|
||||||
if oe := l.at(from + uint64(i)); oe == nil || oe.Term != ne.Term {
|
if oe := l.at(from + uint64(i)); oe == nil || oe.Term != ne.Term {
|
||||||
|
|
|
@ -23,6 +23,42 @@ import (
|
||||||
pb "github.com/coreos/etcd/raft/raftpb"
|
pb "github.com/coreos/etcd/raft/raftpb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestFindConflict(t *testing.T) {
|
||||||
|
previousEnts := []pb.Entry{{Term: 1}, {Term: 2}, {Term: 3}}
|
||||||
|
tests := []struct {
|
||||||
|
from uint64
|
||||||
|
ents []pb.Entry
|
||||||
|
wconflict uint64
|
||||||
|
}{
|
||||||
|
// no conflict, empty ent
|
||||||
|
{1, []pb.Entry{}, 0},
|
||||||
|
{3, []pb.Entry{}, 0},
|
||||||
|
// no conflict
|
||||||
|
{1, []pb.Entry{{Term: 1}, {Term: 2}, {Term: 3}}, 0},
|
||||||
|
{2, []pb.Entry{{Term: 2}, {Term: 3}}, 0},
|
||||||
|
{3, []pb.Entry{{Term: 3}}, 0},
|
||||||
|
// no conflict, but has new entries
|
||||||
|
{1, []pb.Entry{{Term: 1}, {Term: 2}, {Term: 3}, {Term: 4}, {Term: 4}}, 4},
|
||||||
|
{2, []pb.Entry{{Term: 2}, {Term: 3}, {Term: 4}, {Term: 4}}, 4},
|
||||||
|
{3, []pb.Entry{{Term: 3}, {Term: 4}, {Term: 4}}, 4},
|
||||||
|
{4, []pb.Entry{{Term: 4}, {Term: 4}}, 4},
|
||||||
|
// conflicts with existing entries
|
||||||
|
{1, []pb.Entry{{Term: 4}, {Term: 4}}, 1},
|
||||||
|
{2, []pb.Entry{{Term: 1}, {Term: 4}, {Term: 4}}, 2},
|
||||||
|
{3, []pb.Entry{{Term: 1}, {Term: 2}, {Term: 4}, {Term: 4}}, 3},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tt := range tests {
|
||||||
|
raftLog := newLog()
|
||||||
|
raftLog.ents = append(raftLog.ents, previousEnts...)
|
||||||
|
|
||||||
|
gconflict := raftLog.findConflict(tt.from, tt.ents)
|
||||||
|
if gconflict != tt.wconflict {
|
||||||
|
t.Errorf("#%d: conflict = %d, want %d", i, gconflict, tt.wconflict)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestAppend ensures:
|
// TestAppend ensures:
|
||||||
// 1. If an existing entry conflicts with a new one (same index
|
// 1. If an existing entry conflicts with a new one (same index
|
||||||
// but different terms), delete the existing entry and all that
|
// but different terms), delete the existing entry and all that
|
||||||
|
|
Loading…
Reference in New Issue