diff --git a/log_test.go b/log_test.go index 2711ff9c..1e40a9b5 100644 --- a/log_test.go +++ b/log_test.go @@ -24,26 +24,26 @@ import ( ) func TestFindConflict(t *testing.T) { - previousEnts := []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}, {Index: 3, Term: 3}} + previousEnts := index(1).terms(1, 2, 3) tests := []struct { ents []pb.Entry wconflict uint64 }{ // no conflict, empty ent - {[]pb.Entry{}, 0}, + {nil, 0}, // no conflict - {[]pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}, {Index: 3, Term: 3}}, 0}, - {[]pb.Entry{{Index: 2, Term: 2}, {Index: 3, Term: 3}}, 0}, - {[]pb.Entry{{Index: 3, Term: 3}}, 0}, + {index(1).terms(1, 2, 3), 0}, + {index(2).terms(2, 3), 0}, + {index(3).terms(3), 0}, // no conflict, but has new entries - {[]pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}, {Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 4}}, 4}, - {[]pb.Entry{{Index: 2, Term: 2}, {Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 4}}, 4}, - {[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 4}}, 4}, - {[]pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 4}}, 4}, + {index(1).terms(1, 2, 3, 4, 4), 4}, + {index(2).terms(2, 3, 4, 5), 4}, + {index(3).terms(3, 4, 4), 4}, + {index(4).terms(4, 4), 4}, // conflicts with existing entries - {[]pb.Entry{{Index: 1, Term: 4}, {Index: 2, Term: 4}}, 1}, - {[]pb.Entry{{Index: 2, Term: 1}, {Index: 3, Term: 4}, {Index: 4, Term: 4}}, 2}, - {[]pb.Entry{{Index: 3, Term: 1}, {Index: 4, Term: 2}, {Index: 5, Term: 4}, {Index: 6, Term: 4}}, 3}, + {index(1).terms(4, 4), 1}, + {index(2).terms(1, 4, 4), 2}, + {index(3).terms(1, 2, 4, 4), 3}, } for i, tt := range tests { @@ -56,13 +56,6 @@ func TestFindConflict(t *testing.T) { } func TestFindConflictByTerm(t *testing.T) { - ents := func(fromIndex uint64, terms []uint64) []pb.Entry { - e := make([]pb.Entry, 0, len(terms)) - for i, term := range terms { - e = append(e, pb.Entry{Term: term, Index: fromIndex + uint64(i)}) - } - return e - } for _, tt := range []struct { ents []pb.Entry // ents[0] contains the (index, term) of the snapshot index uint64 @@ -70,28 +63,28 @@ func TestFindConflictByTerm(t *testing.T) { want uint64 }{ // Log starts from index 1. - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 100, term: 2, want: 100}, // ErrUnavailable - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 5, term: 6, want: 5}, - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 5, term: 5, want: 5}, - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 5, term: 4, want: 2}, - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 5, term: 2, want: 2}, - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 5, term: 1, want: 0}, - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 1, term: 2, want: 1}, - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 1, term: 1, want: 0}, - {ents: ents(0, []uint64{0, 2, 2, 5, 5, 5}), index: 0, term: 0, want: 0}, + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 100, term: 2, want: 100}, // ErrUnavailable + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 5, term: 6, want: 5}, + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 5, term: 5, want: 5}, + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 5, term: 4, want: 2}, + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 5, term: 2, want: 2}, + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 5, term: 1, want: 0}, + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 1, term: 2, want: 1}, + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 1, term: 1, want: 0}, + {ents: index(0).terms(0, 2, 2, 5, 5, 5), index: 0, term: 0, want: 0}, // Log with compacted entries. - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 30, term: 3, want: 30}, // ErrUnavailable - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 14, term: 9, want: 14}, - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 14, term: 4, want: 14}, - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 14, term: 3, want: 12}, - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 14, term: 2, want: 9}, - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 11, term: 5, want: 11}, - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 10, term: 5, want: 10}, - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 10, term: 3, want: 10}, - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 10, term: 2, want: 9}, - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 9, term: 2, want: 9}, // ErrCompacted - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 4, term: 2, want: 4}, // ErrCompacted - {ents: ents(10, []uint64{3, 3, 3, 4, 4, 4}), index: 0, term: 0, want: 0}, // ErrCompacted + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 30, term: 3, want: 30}, // ErrUnavailable + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 14, term: 9, want: 14}, + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 14, term: 4, want: 14}, + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 14, term: 3, want: 12}, + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 14, term: 2, want: 9}, + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 11, term: 5, want: 11}, + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 10, term: 5, want: 10}, + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 10, term: 3, want: 10}, + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 10, term: 2, want: 9}, + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 9, term: 2, want: 9}, // ErrCompacted + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 4, term: 2, want: 4}, // ErrCompacted + {ents: index(10).terms(3, 3, 3, 4, 4, 4), index: 0, term: 0, want: 0}, // ErrCompacted } { t.Run("", func(t *testing.T) { st := NewMemoryStorage() @@ -113,7 +106,7 @@ func TestFindConflictByTerm(t *testing.T) { } func TestIsUpToDate(t *testing.T) { - previousEnts := []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}, {Index: 3, Term: 3}} + previousEnts := index(1).terms(1, 2, 3) raftLog := newLog(NewMemoryStorage(), raftLogger) raftLog.append(previousEnts...) tests := []struct { @@ -143,7 +136,7 @@ func TestIsUpToDate(t *testing.T) { } func TestAppend(t *testing.T) { - previousEnts := []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}} + previousEnts := index(1).terms(1, 2) tests := []struct { ents []pb.Entry windex uint64 @@ -151,29 +144,29 @@ func TestAppend(t *testing.T) { wunstable uint64 }{ { - []pb.Entry{}, + nil, 2, - []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}, + index(1).terms(1, 2), 3, }, { - []pb.Entry{{Index: 3, Term: 2}}, + index(3).terms(2), 3, - []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}, {Index: 3, Term: 2}}, + index(1).terms(1, 2, 2), 3, }, // conflicts with index 1 { - []pb.Entry{{Index: 1, Term: 2}}, + index(1).terms(2), 1, - []pb.Entry{{Index: 1, Term: 2}}, + index(1).terms(2), 1, }, // conflicts with index 2 { - []pb.Entry{{Index: 2, Term: 3}, {Index: 3, Term: 3}}, + index(2).terms(3, 3), 3, - []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 3}, {Index: 3, Term: 3}}, + index(1).terms(1, 3, 3), 2, }, } @@ -203,7 +196,7 @@ func TestAppend(t *testing.T) { // // return false func TestLogMaybeAppend(t *testing.T) { - previousEnts := []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}, {Index: 3, Term: 3}} + previousEnts := index(1).terms(1, 2, 3) lastindex := uint64(3) lastterm := uint64(3) commit := uint64(1) @@ -221,12 +214,12 @@ func TestLogMaybeAppend(t *testing.T) { }{ // not match: term is different { - lastterm - 1, lastindex, lastindex, []pb.Entry{{Index: lastindex + 1, Term: 4}}, + lastterm - 1, lastindex, lastindex, index(lastindex + 1).terms(4), 0, false, commit, false, }, // not match: index out of bound { - lastterm, lastindex + 1, lastindex, []pb.Entry{{Index: lastindex + 2, Term: 4}}, + lastterm, lastindex + 1, lastindex, index(lastindex + 2).terms(4), 0, false, commit, false, }, // match with the last existing entry @@ -251,36 +244,36 @@ func TestLogMaybeAppend(t *testing.T) { 0, true, commit, false, // commit do not decrease }, { - lastterm, lastindex, lastindex, []pb.Entry{{Index: lastindex + 1, Term: 4}}, + lastterm, lastindex, lastindex, index(lastindex + 1).terms(4), lastindex + 1, true, lastindex, false, }, { - lastterm, lastindex, lastindex + 1, []pb.Entry{{Index: lastindex + 1, Term: 4}}, + lastterm, lastindex, lastindex + 1, index(lastindex + 1).terms(4), lastindex + 1, true, lastindex + 1, false, }, { - lastterm, lastindex, lastindex + 2, []pb.Entry{{Index: lastindex + 1, Term: 4}}, + lastterm, lastindex, lastindex + 2, index(lastindex + 1).terms(4), lastindex + 1, true, lastindex + 1, false, // do not increase commit higher than lastnewi }, { - lastterm, lastindex, lastindex + 2, []pb.Entry{{Index: lastindex + 1, Term: 4}, {Index: lastindex + 2, Term: 4}}, + lastterm, lastindex, lastindex + 2, index(lastindex+1).terms(4, 4), lastindex + 2, true, lastindex + 2, false, }, // match with the entry in the middle { - lastterm - 1, lastindex - 1, lastindex, []pb.Entry{{Index: lastindex, Term: 4}}, + lastterm - 1, lastindex - 1, lastindex, index(lastindex).terms(4), lastindex, true, lastindex, false, }, { - lastterm - 2, lastindex - 2, lastindex, []pb.Entry{{Index: lastindex - 1, Term: 4}}, + lastterm - 2, lastindex - 2, lastindex, index(lastindex - 1).terms(4), lastindex - 1, true, lastindex - 1, false, }, { - lastterm - 3, lastindex - 3, lastindex, []pb.Entry{{Index: lastindex - 2, Term: 4}}, + lastterm - 3, lastindex - 3, lastindex, index(lastindex - 2).terms(4), lastindex - 2, true, lastindex - 2, true, // conflict with existing committed entry }, { - lastterm - 2, lastindex - 2, lastindex, []pb.Entry{{Index: lastindex - 1, Term: 4}, {Index: lastindex, Term: 4}}, + lastterm - 2, lastindex - 2, lastindex, index(lastindex-1).terms(4, 4), lastindex, true, lastindex, false, }, } @@ -312,25 +305,20 @@ func TestLogMaybeAppend(t *testing.T) { // TestCompactionSideEffects ensures that all the log related functionality works correctly after // a compaction. func TestCompactionSideEffects(t *testing.T) { - var i uint64 // Populate the log with 1000 entries; 750 in stable storage and 250 in unstable. lastIndex := uint64(1000) unstableIndex := uint64(750) lastTerm := lastIndex storage := NewMemoryStorage() - for i = 1; i <= unstableIndex; i++ { - storage.Append([]pb.Entry{{Term: i, Index: i}}) - } + require.NoError(t, storage.Append(index(1).termsIn(1, unstableIndex+1))) raftLog := newLog(storage, raftLogger) - for i = unstableIndex; i < lastIndex; i++ { - raftLog.append(pb.Entry{Term: i + 1, Index: i + 1}) - } + raftLog.append(index(unstableIndex+1).termsIn(unstableIndex+1, lastIndex+1)...) require.True(t, raftLog.maybeCommit(lastIndex, lastTerm)) raftLog.appliedTo(raftLog.committed, 0 /* size */) offset := uint64(500) - storage.Compact(offset) + require.NoError(t, storage.Compact(offset)) require.Equal(t, lastIndex, raftLog.lastIndex()) for j := offset; j <= raftLog.lastIndex(); j++ { @@ -358,11 +346,7 @@ func TestHasNextCommittedEnts(t *testing.T) { snap := pb.Snapshot{ Metadata: pb.SnapshotMetadata{Term: 1, Index: 3}, } - ents := []pb.Entry{ - {Term: 1, Index: 4}, - {Term: 1, Index: 5}, - {Term: 1, Index: 6}, - } + ents := index(4).terms(1, 1, 1) tests := []struct { applied uint64 applying uint64 @@ -416,11 +400,7 @@ func TestNextCommittedEnts(t *testing.T) { snap := pb.Snapshot{ Metadata: pb.SnapshotMetadata{Term: 1, Index: 3}, } - ents := []pb.Entry{ - {Term: 1, Index: 4}, - {Term: 1, Index: 5}, - {Term: 1, Index: 6}, - } + ents := index(4).terms(1, 1, 1) tests := []struct { applied uint64 applying uint64 @@ -475,11 +455,7 @@ func TestAcceptApplying(t *testing.T) { snap := pb.Snapshot{ Metadata: pb.SnapshotMetadata{Term: 1, Index: 3}, } - ents := []pb.Entry{ - {Term: 1, Index: 4}, - {Term: 1, Index: 5}, - {Term: 1, Index: 6}, - } + ents := index(4).terms(1, 1, 1) tests := []struct { index uint64 allowUnstable bool @@ -530,11 +506,7 @@ func TestAppliedTo(t *testing.T) { snap := pb.Snapshot{ Metadata: pb.SnapshotMetadata{Term: 1, Index: 3}, } - ents := []pb.Entry{ - {Term: 1, Index: 4}, - {Term: 1, Index: 5}, - {Term: 1, Index: 6}, - } + ents := index(4).terms(1, 1, 1) tests := []struct { index uint64 size entryEncodingSize @@ -580,7 +552,7 @@ func TestAppliedTo(t *testing.T) { // TestNextUnstableEnts ensures unstableEntries returns the unstable part of the // entries correctly. func TestNextUnstableEnts(t *testing.T) { - previousEnts := []pb.Entry{{Term: 1, Index: 1}, {Term: 2, Index: 2}} + previousEnts := index(1).terms(1, 2) tests := []struct { unstable uint64 wents []pb.Entry @@ -610,7 +582,7 @@ func TestNextUnstableEnts(t *testing.T) { } func TestCommitTo(t *testing.T) { - previousEnts := []pb.Entry{{Term: 1, Index: 1}, {Term: 2, Index: 2}, {Term: 3, Index: 3}} + previousEnts := index(1).terms(1, 2, 3) commit := uint64(2) tests := []struct { commit uint64 @@ -675,13 +647,13 @@ func TestStableToWithSnap(t *testing.T) { {snapi, snapt + 1, nil, snapi + 1}, {snapi - 1, snapt + 1, nil, snapi + 1}, - {snapi + 1, snapt, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 2}, - {snapi, snapt, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1}, - {snapi - 1, snapt, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1}, + {snapi + 1, snapt, index(snapi + 1).terms(snapt), snapi + 2}, + {snapi, snapt, index(snapi + 1).terms(snapt), snapi + 1}, + {snapi - 1, snapt, index(snapi + 1).terms(snapt), snapi + 1}, - {snapi + 1, snapt + 1, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1}, - {snapi, snapt + 1, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1}, - {snapi - 1, snapt + 1, []pb.Entry{{Index: snapi + 1, Term: snapt}}, snapi + 1}, + {snapi + 1, snapt + 1, index(snapi + 1).terms(snapt), snapi + 1}, + {snapi, snapt + 1, index(snapi + 1).terms(snapt), snapi + 1}, + {snapi - 1, snapt + 1, index(snapi + 1).terms(snapt), snapi + 1}, } for i, tt := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { @@ -692,7 +664,6 @@ func TestStableToWithSnap(t *testing.T) { raftLog.stableTo(tt.stablei, tt.stablet) require.Equal(t, tt.wunstable, raftLog.unstable.offset) }) - } } @@ -719,9 +690,7 @@ func TestCompaction(t *testing.T) { } }() storage := NewMemoryStorage() - for i := uint64(1); i <= tt.lastIndex; i++ { - storage.Append([]pb.Entry{{Index: i}}) - } + require.NoError(t, storage.Append(index(1).termsIn(1, tt.lastIndex+1))) raftLog := newLog(storage, raftLogger) raftLog.maybeCommit(tt.lastIndex, 0) @@ -734,7 +703,6 @@ func TestCompaction(t *testing.T) { } require.Equal(t, tt.wleft[j], len(raftLog.allEntries())) } - }) } } @@ -760,9 +728,7 @@ func TestIsOutOfBounds(t *testing.T) { storage := NewMemoryStorage() storage.ApplySnapshot(pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: offset}}) l := newLog(storage, raftLogger) - for i := uint64(1); i <= num; i++ { - l.append(pb.Entry{Index: i + offset}) - } + l.append(index(offset+1).termsIn(offset+1, offset+num+1)...) first := offset + 1 tests := []struct { @@ -834,9 +800,7 @@ func TestTerm(t *testing.T) { storage := NewMemoryStorage() storage.ApplySnapshot(pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: offset, Term: 1}}) l := newLog(storage, raftLogger) - for i := uint64(1); i < num; i++ { - l.append(pb.Entry{Index: offset + i, Term: i}) - } + l.append(index(offset+1).termsIn(1, num)...) for i, tt := range []struct { idx uint64 @@ -897,11 +861,7 @@ func TestSlice(t *testing.T) { halfe := pb.Entry{Index: half, Term: half} entries := func(from, to uint64) []pb.Entry { - res := make([]pb.Entry, 0, to-from) - for i := from; i < to; i++ { - res = append(res, pb.Entry{Index: i, Term: i}) - } - return res + return index(from).termsIn(from, to) } storage := NewMemoryStorage() @@ -986,11 +946,7 @@ func TestScan(t *testing.T) { last := offset + num half := offset + num/2 entries := func(from, to uint64) []pb.Entry { - res := make([]pb.Entry, 0, to-from) - for i := from; i < to; i++ { - res = append(res, pb.Entry{Index: i, Term: i}) - } - return res + return index(from).termsIn(from, to) } entrySize := entsSize(entries(half, half+1)) @@ -1044,3 +1000,31 @@ func mustTerm(term uint64, err error) uint64 { } return term } + +// index is a helper type for generating slices of pb.Entry. The value of index +// is the first entry index in the generated slices. +type index uint64 + +// terms generates a slice of entries at indices [index, index+len(terms)), with +// the given terms of each entry. Terms must be non-decreasing. +func (i index) terms(terms ...uint64) []pb.Entry { + index := uint64(i) + entries := make([]pb.Entry, 0, len(terms)) + for _, term := range terms { + entries = append(entries, pb.Entry{Term: term, Index: index}) + index++ + } + return entries +} + +// termsIn generates a slice of to-from entries, at consecutive indices starting +// from i, and consecutive terms in [from, to). +func (i index) termsIn(from, to uint64) []pb.Entry { + index := uint64(i) + entries := make([]pb.Entry, 0, to-from) + for term := from; term < to; term++ { + entries = append(entries, pb.Entry{Term: term, Index: index}) + index++ + } + return entries +} diff --git a/raft_test.go b/raft_test.go index e9d9657b..4f705e7b 100644 --- a/raft_test.go +++ b/raft_test.go @@ -1048,18 +1048,14 @@ func TestOldMessages(t *testing.T) { tt.send(pb.Message{From: 2, To: 2, Type: pb.MsgHup}) tt.send(pb.Message{From: 1, To: 1, Type: pb.MsgHup}) // pretend we're an old leader trying to make progress; this entry is expected to be ignored. - tt.send(pb.Message{From: 2, To: 1, Type: pb.MsgApp, Term: 2, Entries: []pb.Entry{{Index: 3, Term: 2}}}) + tt.send(pb.Message{From: 2, To: 1, Type: pb.MsgApp, Term: 2, Entries: index(3).terms(2)}) // commit a new entry tt.send(pb.Message{From: 1, To: 1, Type: pb.MsgProp, Entries: []pb.Entry{{Data: []byte("somedata")}}}) + ents := index(0).terms(0, 1, 2, 3, 3) + ents[4].Data = []byte("somedata") ilog := &raftLog{ - storage: &MemoryStorage{ - ents: []pb.Entry{ - {}, {Data: nil, Term: 1, Index: 1}, - {Data: nil, Term: 2, Index: 2}, {Data: nil, Term: 3, Index: 3}, - {Data: []byte("somedata"), Term: 3, Index: 4}, - }, - }, + storage: &MemoryStorage{ents: ents}, unstable: unstable{offset: 5}, committed: 4, } @@ -1183,24 +1179,24 @@ func TestCommit(t *testing.T) { w uint64 }{ // single - {[]uint64{1}, []pb.Entry{{Index: 1, Term: 1}}, 1, 1}, - {[]uint64{1}, []pb.Entry{{Index: 1, Term: 1}}, 2, 0}, - {[]uint64{2}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}, 2, 2}, - {[]uint64{1}, []pb.Entry{{Index: 1, Term: 2}}, 2, 1}, + {[]uint64{1}, index(1).terms(1), 1, 1}, + {[]uint64{1}, index(1).terms(1), 2, 0}, + {[]uint64{2}, index(1).terms(1, 2), 2, 2}, + {[]uint64{1}, index(1).terms(2), 2, 1}, // odd - {[]uint64{2, 1, 1}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}, 1, 1}, - {[]uint64{2, 1, 1}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 1}}, 2, 0}, - {[]uint64{2, 1, 2}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}, 2, 2}, - {[]uint64{2, 1, 2}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 1}}, 2, 0}, + {[]uint64{2, 1, 1}, index(1).terms(1, 2), 1, 1}, + {[]uint64{2, 1, 1}, index(1).terms(1, 1), 2, 0}, + {[]uint64{2, 1, 2}, index(1).terms(1, 2), 2, 2}, + {[]uint64{2, 1, 2}, index(1).terms(1, 1), 2, 0}, // even - {[]uint64{2, 1, 1, 1}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}, 1, 1}, - {[]uint64{2, 1, 1, 1}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 1}}, 2, 0}, - {[]uint64{2, 1, 1, 2}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}, 1, 1}, - {[]uint64{2, 1, 1, 2}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 1}}, 2, 0}, - {[]uint64{2, 1, 2, 2}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}, 2, 2}, - {[]uint64{2, 1, 2, 2}, []pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 1}}, 2, 0}, + {[]uint64{2, 1, 1, 1}, index(1).terms(1, 2), 1, 1}, + {[]uint64{2, 1, 1, 1}, index(1).terms(1, 1), 2, 0}, + {[]uint64{2, 1, 1, 2}, index(1).terms(1, 2), 1, 1}, + {[]uint64{2, 1, 1, 2}, index(1).terms(1, 1), 2, 0}, + {[]uint64{2, 1, 2, 2}, index(1).terms(1, 2), 2, 2}, + {[]uint64{2, 1, 2, 2}, index(1).terms(1, 1), 2, 0}, } for i, tt := range tests { @@ -1307,7 +1303,7 @@ func TestHandleMsgApp(t *testing.T) { for i, tt := range tests { storage := newTestMemoryStorage(withPeers(1)) - storage.Append([]pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}}) + require.NoError(t, storage.Append(index(1).terms(1, 2))) sm := newTestRaft(1, 10, 1, storage) sm.becomeFollower(2, None) @@ -1341,7 +1337,7 @@ func TestHandleHeartbeat(t *testing.T) { for i, tt := range tests { storage := newTestMemoryStorage(withPeers(1, 2)) - storage.Append([]pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}, {Index: 3, Term: 3}}) + require.NoError(t, storage.Append(index(1).terms(1, 2, 3))) sm := newTestRaft(1, 5, 1, storage) sm.becomeFollower(2, 2) sm.raftLog.commitTo(commit) @@ -1362,7 +1358,7 @@ func TestHandleHeartbeat(t *testing.T) { // TestHandleHeartbeatResp ensures that we re-send log entries when we get a heartbeat response. func TestHandleHeartbeatResp(t *testing.T) { storage := newTestMemoryStorage(withPeers(1, 2)) - storage.Append([]pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 2}, {Index: 3, Term: 3}}) + require.NoError(t, storage.Append(index(1).terms(1, 2, 3))) sm := newTestRaft(1, 5, 1, storage) sm.becomeCandidate() sm.becomeLeader() @@ -1558,13 +1554,6 @@ func testRecvMsgVote(t *testing.T, msgType pb.MessageType) { {StateCandidate, 3, 3, 1, true}, } - max := func(a, b uint64) uint64 { - if a > b { - return a - } - return b - } - for i, tt := range tests { sm := newTestRaft(1, 10, 1, newTestMemoryStorage(withPeers(1))) sm.state = tt.state @@ -1578,7 +1567,7 @@ func testRecvMsgVote(t *testing.T, msgType pb.MessageType) { } sm.Vote = tt.voteFor sm.raftLog = &raftLog{ - storage: &MemoryStorage{ents: []pb.Entry{{}, {Index: 1, Term: 2}, {Index: 2, Term: 2}}}, + storage: &MemoryStorage{ents: index(0).terms(0, 2, 2)}, unstable: unstable{offset: 3}, } @@ -2517,7 +2506,7 @@ func TestReadOnlyForNewLeader(t *testing.T) { peers := make([]stateMachine, 0) for _, c := range nodeConfigs { storage := newTestMemoryStorage(withPeers(1, 2, 3)) - storage.Append([]pb.Entry{{Index: 1, Term: 1}, {Index: 2, Term: 1}}) + require.NoError(t, storage.Append(index(1).terms(1, 1))) storage.SetHardState(pb.HardState{Term: 1, Commit: c.committed}) if c.compactIndex != 0 { storage.Compact(c.compactIndex) @@ -2618,7 +2607,7 @@ func TestLeaderAppResp(t *testing.T) { // thus the last log term must be 1 to be committed. sm := newTestRaft(1, 10, 1, newTestMemoryStorage(withPeers(1, 2, 3))) sm.raftLog = &raftLog{ - storage: &MemoryStorage{ents: []pb.Entry{{}, {Index: 1, Term: 1}, {Index: 2, Term: 1}}}, + storage: &MemoryStorage{ents: index(0).terms(0, 1, 1)}, unstable: unstable{offset: 3}, } sm.becomeCandidate() @@ -2732,7 +2721,7 @@ func TestRecvMsgBeat(t *testing.T) { for i, tt := range tests { sm := newTestRaft(1, 10, 1, newTestMemoryStorage(withPeers(1, 2, 3))) - sm.raftLog = &raftLog{storage: &MemoryStorage{ents: []pb.Entry{{}, {Index: 1, Term: 1}, {Index: 2, Term: 1}}}} + sm.raftLog = &raftLog{storage: &MemoryStorage{ents: index(0).terms(0, 1, 1)}} sm.Term = 1 sm.state = tt.state switch tt.state { @@ -2758,7 +2747,7 @@ func TestRecvMsgBeat(t *testing.T) { } func TestLeaderIncreaseNext(t *testing.T) { - previousEnts := []pb.Entry{{Term: 1, Index: 1}, {Term: 1, Index: 2}, {Term: 1, Index: 3}} + previousEnts := index(1).terms(1, 2, 3) tests := []struct { // progress state tracker.StateType @@ -2891,7 +2880,7 @@ func TestSendAppendForProgressSnapshot(t *testing.T) { } func TestRecvMsgUnreachable(t *testing.T) { - previousEnts := []pb.Entry{{Term: 1, Index: 1}, {Term: 1, Index: 2}, {Term: 1, Index: 3}} + previousEnts := index(1).terms(1, 2, 3) s := newTestMemoryStorage(withPeers(1, 2)) s.Append(previousEnts) r := newTestRaft(1, 10, 1, s) @@ -3126,7 +3115,7 @@ func TestLearnerReceiveSnapshot(t *testing.T) { } func TestRestoreIgnoreSnapshot(t *testing.T) { - previousEnts := []pb.Entry{{Term: 1, Index: 1}, {Term: 1, Index: 2}, {Term: 1, Index: 3}} + previousEnts := index(1).terms(1, 1, 1) commit := uint64(1) storage := newTestMemoryStorage(withPeers(1, 2)) sm := newTestRaft(1, 10, 1, storage) @@ -4512,28 +4501,8 @@ func TestFastLogRejection(t *testing.T) { // Firstly leader appends (type=MsgApp,index=7,logTerm=4, entries=...); // After rejected leader appends (type=MsgApp,index=3,logTerm=2). { - leaderLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 2, Index: 2}, - {Term: 2, Index: 3}, - {Term: 4, Index: 4}, - {Term: 4, Index: 5}, - {Term: 4, Index: 6}, - {Term: 4, Index: 7}, - }, - followerLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 2, Index: 2}, - {Term: 2, Index: 3}, - {Term: 3, Index: 4}, - {Term: 3, Index: 5}, - {Term: 3, Index: 6}, - {Term: 3, Index: 7}, - {Term: 3, Index: 8}, - {Term: 3, Index: 9}, - {Term: 3, Index: 10}, - {Term: 3, Index: 11}, - }, + leaderLog: index(1).terms(1, 2, 2, 4, 4, 4, 4), + followerLog: index(1).terms(1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3), rejectHintTerm: 3, rejectHintIndex: 7, nextAppendTerm: 2, @@ -4543,29 +4512,8 @@ func TestFastLogRejection(t *testing.T) { // Firstly leader appends (type=MsgApp,index=8,logTerm=5, entries=...); // After rejected leader appends (type=MsgApp,index=4,logTerm=3). { - leaderLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 2, Index: 2}, - {Term: 2, Index: 3}, - {Term: 3, Index: 4}, - {Term: 4, Index: 5}, - {Term: 4, Index: 6}, - {Term: 4, Index: 7}, - {Term: 5, Index: 8}, - }, - followerLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 2, Index: 2}, - {Term: 2, Index: 3}, - {Term: 3, Index: 4}, - {Term: 3, Index: 5}, - {Term: 3, Index: 6}, - {Term: 3, Index: 7}, - {Term: 3, Index: 8}, - {Term: 3, Index: 9}, - {Term: 3, Index: 10}, - {Term: 3, Index: 11}, - }, + leaderLog: index(1).terms(1, 2, 2, 3, 4, 4, 4, 5), + followerLog: index(1).terms(1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3), rejectHintTerm: 3, rejectHintIndex: 8, nextAppendTerm: 3, @@ -4575,18 +4523,8 @@ func TestFastLogRejection(t *testing.T) { // Firstly leader appends (type=MsgApp,index=4,logTerm=1, entries=...); // After rejected leader appends (type=MsgApp,index=1,logTerm=1). { - leaderLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 1, Index: 2}, - {Term: 1, Index: 3}, - {Term: 1, Index: 4}, - }, - followerLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 2, Index: 2}, - {Term: 2, Index: 3}, - {Term: 4, Index: 4}, - }, + leaderLog: index(1).terms(1, 1, 1, 1), + followerLog: index(1).terms(1, 2, 2, 4), rejectHintTerm: 1, rejectHintIndex: 1, nextAppendTerm: 1, @@ -4597,20 +4535,8 @@ func TestFastLogRejection(t *testing.T) { // Firstly leader appends (type=MsgApp,index=6,logTerm=1, entries=...); // After rejected leader appends (type=MsgApp,index=1,logTerm=1). { - leaderLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 1, Index: 2}, - {Term: 1, Index: 3}, - {Term: 1, Index: 4}, - {Term: 1, Index: 5}, - {Term: 1, Index: 6}, - }, - followerLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 2, Index: 2}, - {Term: 2, Index: 3}, - {Term: 4, Index: 4}, - }, + leaderLog: index(1).terms(1, 1, 1, 1, 1, 1), + followerLog: index(1).terms(1, 2, 2, 4), rejectHintTerm: 1, rejectHintIndex: 1, nextAppendTerm: 1, @@ -4621,20 +4547,8 @@ func TestFastLogRejection(t *testing.T) { // Firstly leader appends (type=MsgApp,index=4,logTerm=1, entries=...); // After rejected leader appends (type=MsgApp,index=1,logTerm=1). { - leaderLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 1, Index: 2}, - {Term: 1, Index: 3}, - {Term: 1, Index: 4}, - }, - followerLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 2, Index: 2}, - {Term: 2, Index: 3}, - {Term: 4, Index: 4}, - {Term: 4, Index: 5}, - {Term: 4, Index: 6}, - }, + leaderLog: index(1).terms(1, 1, 1, 1), + followerLog: index(1).terms(1, 2, 2, 4, 4, 4), rejectHintTerm: 1, rejectHintIndex: 1, nextAppendTerm: 1, @@ -4644,19 +4558,8 @@ func TestFastLogRejection(t *testing.T) { // Firstly leader appends (type=MsgApp,index=5,logTerm=5, entries=...); // After rejected leader appends (type=MsgApp,index=4,logTerm=4). { - leaderLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 1, Index: 2}, - {Term: 1, Index: 3}, - {Term: 4, Index: 4}, - {Term: 5, Index: 5}, - }, - followerLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 1, Index: 2}, - {Term: 1, Index: 3}, - {Term: 4, Index: 4}, - }, + leaderLog: index(1).terms(1, 1, 1, 4, 5), + followerLog: index(1).terms(1, 1, 1, 4), rejectHintTerm: 4, rejectHintIndex: 4, nextAppendTerm: 4, @@ -4664,25 +4567,8 @@ func TestFastLogRejection(t *testing.T) { }, // Test case from example comment in stepLeader (on leader). { - leaderLog: []pb.Entry{ - {Term: 2, Index: 1}, - {Term: 5, Index: 2}, - {Term: 5, Index: 3}, - {Term: 5, Index: 4}, - {Term: 5, Index: 5}, - {Term: 5, Index: 6}, - {Term: 5, Index: 7}, - {Term: 5, Index: 8}, - {Term: 5, Index: 9}, - }, - followerLog: []pb.Entry{ - {Term: 2, Index: 1}, - {Term: 4, Index: 2}, - {Term: 4, Index: 3}, - {Term: 4, Index: 4}, - {Term: 4, Index: 5}, - {Term: 4, Index: 6}, - }, + leaderLog: index(1).terms(2, 5, 5, 5, 5, 5, 5, 5, 5), + followerLog: index(1).terms(2, 4, 4, 4, 4, 4), rejectHintTerm: 4, rejectHintIndex: 6, nextAppendTerm: 2, @@ -4690,23 +4576,8 @@ func TestFastLogRejection(t *testing.T) { }, // Test case from example comment in handleAppendEntries (on follower). { - leaderLog: []pb.Entry{ - {Term: 2, Index: 1}, - {Term: 2, Index: 2}, - {Term: 2, Index: 3}, - {Term: 2, Index: 4}, - {Term: 2, Index: 5}, - }, - followerLog: []pb.Entry{ - {Term: 2, Index: 1}, - {Term: 4, Index: 2}, - {Term: 4, Index: 3}, - {Term: 4, Index: 4}, - {Term: 4, Index: 5}, - {Term: 4, Index: 6}, - {Term: 4, Index: 7}, - {Term: 4, Index: 8}, - }, + leaderLog: index(1).terms(2, 2, 2, 2, 2), + followerLog: index(1).terms(2, 4, 4, 4, 4, 4, 4, 4), rejectHintTerm: 2, rejectHintIndex: 1, nextAppendTerm: 2, @@ -4719,19 +4590,9 @@ func TestFastLogRejection(t *testing.T) { // MsgAppResp rejection will return same index=3, with logTerm=0. The leader // will rollback by one entry, and send MsgApp with index=2,logTerm=1. { - leaderLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 1, Index: 2}, - {Term: 3, Index: 3}, - }, - followerLog: []pb.Entry{ - {Term: 1, Index: 1}, - {Term: 1, Index: 2}, - {Term: 3, Index: 3}, - {Term: 3, Index: 4}, - {Term: 3, Index: 5}, // <- this entry and below are compacted - }, - followerCompact: 5, + leaderLog: index(1).terms(1, 1, 3), + followerLog: index(1).terms(1, 1, 3, 3, 3), + followerCompact: 5, // entries <= index 5 are compacted rejectHintTerm: 0, rejectHintIndex: 3, nextAppendTerm: 1,