コード例 #1
0
ファイル: consensus_test.go プロジェクト: divtxt/raft
func testCM_SOLO_Follower_ElectsSelfOnElectionTimeout(
	t *testing.T,
	mcm *managedConsensusModule,
	mrs *testhelpers.MockRpcSender,
) {
	if mcm.pcm.GetServerState() != FOLLOWER {
		t.Fatal()
	}
	if mcm.pcm.RaftPersistentState.GetVotedFor() != "" {
		t.Fatal()
	}

	// Test that a tick before election timeout causes no state change.
	err := mcm.Tick()
	if err != nil {
		t.Fatal(err)
	}
	if mcm.pcm.RaftPersistentState.GetCurrentTerm() != testdata.CurrentTerm {
		t.Fatal()
	}
	if mcm.pcm.GetServerState() != FOLLOWER {
		t.Fatal()
	}

	var expectedNewTerm TermNo = testdata.CurrentTerm + 1

	timeout1 := mcm.pcm.ElectionTimeoutTracker.GetCurrentElectionTimeout()
	// Test that election timeout causes a new election
	mcm.tickTilElectionTimeout(t)
	if mcm.pcm.RaftPersistentState.GetCurrentTerm() != expectedNewTerm {
		t.Fatal(expectedNewTerm, mcm.pcm.RaftPersistentState.GetCurrentTerm())
	}
	// Single node should immediately elect itself as leader
	if mcm.pcm.GetServerState() != LEADER {
		t.Fatal()
	}
	// candidate has voted for itself
	if mcm.pcm.RaftPersistentState.GetVotedFor() != testdata.ThisServerId {
		t.Fatal()
	}
	// a new election timeout was chosen
	if mcm.pcm.ElectionTimeoutTracker.GetCurrentElectionTimeout() == timeout1 {
		t.Fatal()
	}
	// candidate state is fresh
	expectedCvs, err := consensus_state.NewCandidateVolatileState(mcm.pcm.ClusterInfo)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(mcm.pcm.CandidateVolatileState, expectedCvs) {
		t.Fatal()
	}

	// no RPCs issued
	mrs.CheckSentRpcs(t, make(map[ServerId]interface{}))
	mrs.ClearSentRpcs()
}
コード例 #2
0
ファイル: consensus_test.go プロジェクト: divtxt/raft
func testCM_FollowerOrCandidate_StartsElectionOnElectionTimeout_Part2(
	t *testing.T,
	mcm *managedConsensusModule,
	mrs *testhelpers.MockRpcSender,
	expectedNewTerm TermNo,
) {
	timeout1 := mcm.pcm.ElectionTimeoutTracker.GetCurrentElectionTimeout()
	// Test that election timeout causes a new election
	mcm.tickTilElectionTimeout(t)
	if mcm.pcm.RaftPersistentState.GetCurrentTerm() != expectedNewTerm {
		t.Fatal(expectedNewTerm, mcm.pcm.RaftPersistentState.GetCurrentTerm())
	}
	if mcm.pcm.GetServerState() != CANDIDATE {
		t.Fatal()
	}
	// candidate has voted for itself
	if mcm.pcm.RaftPersistentState.GetVotedFor() != testdata.ThisServerId {
		t.Fatal()
	}
	// a new election timeout was chosen
	// Playing the odds here :P
	if mcm.pcm.ElectionTimeoutTracker.GetCurrentElectionTimeout() == timeout1 {
		t.Fatal()
	}
	// candidate state is fresh
	expectedCvs, err := consensus_state.NewCandidateVolatileState(mcm.pcm.ClusterInfo)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(mcm.pcm.CandidateVolatileState, expectedCvs) {
		t.Fatal()
	}

	// candidate has issued RequestVote RPCs to all other servers.
	lastLogIndex, lastLogTerm, err := GetIndexAndTermOfLastEntry(mcm.pcm.LogRO)
	if err != nil {
		t.Fatal(err)
	}
	expectedRpc := &RpcRequestVote{expectedNewTerm, lastLogIndex, lastLogTerm}
	expectedRpcs := map[ServerId]interface{}{}
	err = mcm.pcm.ClusterInfo.ForEachPeer(func(serverId ServerId) error {
		expectedRpcs[serverId] = expectedRpc
		return nil
	})
	if err != nil {
		t.Fatal(err)
	}
	mrs.CheckSentRpcs(t, expectedRpcs)
	mrs.ClearSentRpcs()
}