コード例 #1
0
ファイル: raft_test.go プロジェクト: divtxt/raft
func testConsensusModule_RpcReplyCallback_AndBecomeLeader(
	t *testing.T,
	cm *ConsensusModule,
	mrs *testhelpers.MockRpcSender,
) {
	// FIXME: multiple unsafe concurrent accesses

	// Sleep till election starts
	ett := cm.passiveConsensusModule.ElectionTimeoutTracker
	max_ticks := (ett.GetCurrentElectionTimeout().Nanoseconds() / testdata.TickerDuration.Nanoseconds()) + 2
	for i := int64(0); i < max_ticks; i++ {
		time.Sleep(testdata.TickerDuration)
		if cm.GetServerState() != FOLLOWER {
			break
		}
	}

	if cm.GetServerState() != CANDIDATE {
		t.Fatal()
	}

	// candidate has issued RequestVote RPCs to all other servers.
	lastLogIndex, lastLogTerm, err := consensus.GetIndexAndTermOfLastEntry(cm.passiveConsensusModule.LogRO)
	if err != nil {
		t.Fatal(err)
	}
	expectedRpc := &RpcRequestVote{testdata.CurrentTerm + 1, lastLogIndex, lastLogTerm}
	expectedRpcs := map[ServerId]interface{}{
		"s2": expectedRpc,
		"s3": expectedRpc,
		"s4": expectedRpc,
		"s5": expectedRpc,
	}
	mrs.CheckSentRpcs(t, expectedRpcs)

	// reply true for all votes
	serverTerm := cm.passiveConsensusModule.RaftPersistentState.GetCurrentTerm()
	if n := mrs.SendRVRepliesAndClearRpcs(&RpcRequestVoteReply{serverTerm, true}); n != 4 {
		t.Fatal(n)
	}

	time.Sleep(testdata.SleepToLetGoroutineRun)

	// server should now be a leader
	if cm.IsStopped() {
		t.Fatal()
	}
	if cm.GetServerState() != LEADER {
		t.Fatal()
	}

	// leader setup
	expectedRpc2 := &RpcAppendEntries{
		serverTerm,
		lastLogIndex,
		lastLogTerm,
		[]LogEntry{},
		cm.passiveConsensusModule.GetCommitIndex(),
	}
	expectedRpcs2 := map[ServerId]interface{}{
		"s2": expectedRpc2,
		"s3": expectedRpc2,
		"s4": expectedRpc2,
		"s5": expectedRpc2,
	}
	mrs.CheckSentRpcs(t, expectedRpcs2)

	// reply handling
	expectedMatchIndex := map[ServerId]LogIndex{"s2": 0, "s3": 0, "s4": 0, "s5": 0}
	if !reflect.DeepEqual(cm.passiveConsensusModule.LeaderVolatileState.MatchIndex, expectedMatchIndex) {
		t.Fatal()
	}

	if n := mrs.SendAERepliesAndClearRpcs(&RpcAppendEntriesReply{serverTerm, true}); n != 4 {
		t.Fatal(n)
	}

	time.Sleep(testdata.SleepToLetGoroutineRun)

	expectedMatchIndex = map[ServerId]LogIndex{
		"s2": lastLogIndex,
		"s3": lastLogIndex,
		"s4": lastLogIndex,
		"s5": lastLogIndex,
	}
	if !reflect.DeepEqual(cm.passiveConsensusModule.LeaderVolatileState.MatchIndex, expectedMatchIndex) {
		t.Fatal(cm.passiveConsensusModule.LeaderVolatileState.MatchIndex)
	}
}