# Tests that a follower with PreVote+CheckQuorum can forget the leader, allowing
# it to grant prevotes despite having heard from the leader recently.
#
# Also tests that forgetting the leader still won't grant prevotes to a
# replica that isn't up-to-date.
log-level none
----
ok

add-nodes 3 voters=(1,2,3) index=10 prevote=true checkquorum=true
----
ok

campaign 1
----
ok

stabilize
----
ok

log-level debug
----
ok

withdraw-support 3 1
----
  1 2 3
1 1 1 1
2 1 1 1
3 x 1 1

# If 3 attempts to campaign, 2 rejects it because it has a leader.
campaign 3
----
INFO 3 is starting a new election at term 1
INFO 3 became pre-candidate at term 1
INFO 3 [logterm: 1, index: 11] sent MsgPreVote request to 1 at term 1
INFO 3 [logterm: 1, index: 11] sent MsgPreVote request to 2 at term 1

stabilize 3
----
> 3 handling Ready
  Ready MustSync=true:
  State:StatePreCandidate
  HardState Term:1 Vote:1 Commit:11 Lead:0 LeadEpoch:0
  Messages:
  3->1 MsgPreVote Term:2 Log:1/11
  3->2 MsgPreVote Term:2 Log:1/11
  INFO 3 received MsgPreVoteResp from 3 at term 1
  INFO 3 has received 1 MsgPreVoteResp votes and 0 vote rejections

deliver-msgs 1 2
----
3->1 MsgPreVote Term:2 Log:1/11
INFO 1 [logterm: 1, index: 11, vote: 1] ignored MsgPreVote from 3 [logterm: 1, index: 11] at term 1: supporting fortified leader 1 at epoch 1
3->2 MsgPreVote Term:2 Log:1/11
INFO 2 [logterm: 1, index: 11, vote: 1] ignored MsgPreVote from 3 [logterm: 1, index: 11] at term 1: supporting fortified leader 1 at epoch 1

grant-support 3 1
----
  1 2 3
1 2 1 1
2 1 1 1
3 2 1 1

# Make 1 assert leadership over 3 again by sending MsgFortifyLeader.
tick-heartbeat 1
----
ok

stabilize
----
> 1 handling Ready
  Ready MustSync=true:
  HardState Term:1 Vote:1 Commit:11 Lead:1 LeadEpoch:2
  Messages:
  1->3 MsgFortifyLeader Term:1 Log:0/0
> 3 receiving messages
  1->3 MsgFortifyLeader Term:1 Log:0/0
  INFO 3 became follower at term 1
  DEBUG 3 reset election elapsed to 0
> 3 handling Ready
  Ready MustSync=true:
  State:StateFollower
  HardState Term:1 Vote:1 Commit:11 Lead:1 LeadEpoch:2
  Messages:
  3->1 MsgFortifyLeaderResp Term:1 Log:0/0 LeadEpoch:2
> 1 receiving messages
  3->1 MsgFortifyLeaderResp Term:1 Log:0/0 LeadEpoch:2

raft-state
----
1: StateLeader (Voter) Term:1 Lead:1 LeadEpoch:2
2: StateFollower (Voter) Term:1 Lead:1 LeadEpoch:1
3: StateFollower (Voter) Term:1 Lead:1 LeadEpoch:2

withdraw-support 3 1
----
  1 2 3
1 2 1 1
2 1 1 1
3 x 1 1

# ForgetLeader is ignored if the follower is supporting the leader's store
# liveness epoch.
forget-leader 2
----
INFO 2 [term 1] ignored MsgForgetLeader from 0 due to leader fortification

withdraw-support 2 1
----
  1 2 3
1 2 1 1
2 x 1 1
3 x 1 1

# If 2 forgets the leader, then 3 can obtain prevotes and hold an election
# despite 2 having heard from the leader recently.
forget-leader 2
----
INFO 2 forgetting leader 1 at term 1

raft-state
----
1: StateLeader (Voter) Term:1 Lead:1 LeadEpoch:2
2: StateFollower (Voter) Term:1 Lead:0 LeadEpoch:0
3: StateFollower (Voter) Term:1 Lead:1 LeadEpoch:2

campaign 3
----
INFO 3 is starting a new election at term 1
INFO 3 became pre-candidate at term 1
INFO 3 [logterm: 1, index: 11] sent MsgPreVote request to 1 at term 1
INFO 3 [logterm: 1, index: 11] sent MsgPreVote request to 2 at term 1

stabilize 3
----
> 3 handling Ready
  Ready MustSync=true:
  State:StatePreCandidate
  HardState Term:1 Vote:1 Commit:11 Lead:0 LeadEpoch:0
  Messages:
  3->1 MsgPreVote Term:2 Log:1/11
  3->2 MsgPreVote Term:2 Log:1/11
  INFO 3 received MsgPreVoteResp from 3 at term 1
  INFO 3 has received 1 MsgPreVoteResp votes and 0 vote rejections

stabilize 2
----
> 2 handling Ready
  Ready MustSync=true:
  HardState Term:1 Vote:1 Commit:11 Lead:0 LeadEpoch:0
> 2 receiving messages
  3->2 MsgPreVote Term:2 Log:1/11
  INFO 2 [logterm: 1, index: 11, vote: 1] cast MsgPreVote for 3 [logterm: 1, index: 11] at term 1
> 2 handling Ready
  Ready MustSync=false:
  Messages:
  2->3 MsgPreVoteResp Term:2 Log:0/0

stabilize 3
----
> 3 receiving messages
  2->3 MsgPreVoteResp Term:2 Log:0/0
  INFO 3 received MsgPreVoteResp from 2 at term 1
  INFO 3 has received 2 MsgPreVoteResp votes and 0 vote rejections
  INFO 3 became candidate at term 2
  INFO 3 [logterm: 1, index: 11] sent MsgVote request to 1 at term 2
  INFO 3 [logterm: 1, index: 11] sent MsgVote request to 2 at term 2
> 3 handling Ready
  Ready MustSync=true:
  State:StateCandidate
  HardState Term:2 Vote:3 Commit:11 Lead:0 LeadEpoch:0
  Messages:
  3->1 MsgVote Term:2 Log:1/11
  3->2 MsgVote Term:2 Log:1/11
  INFO 3 received MsgVoteResp from 3 at term 2
  INFO 3 has received 1 MsgVoteResp votes and 0 vote rejections

stabilize log-level=none
----
ok

raft-state
----
1: StateFollower (Voter) Term:2 Lead:3 LeadEpoch:1
2: StateFollower (Voter) Term:2 Lead:3 LeadEpoch:1
3: StateLeader (Voter) Term:2 Lead:3 LeadEpoch:1

# Test that forgetting the leader still won't grant prevotes if the candidate
# isn't up-to-date. We first replicate a proposal on 3 and 2.
propose 3 prop_1
----
ok

stabilize 3
----
> 3 handling Ready
  Ready MustSync=true:
  Entries:
  2/13 EntryNormal "prop_1"
  Messages:
  3->1 MsgApp Term:2 Log:2/12 Commit:12 Entries:[2/13 EntryNormal "prop_1"]
  3->2 MsgApp Term:2 Log:2/12 Commit:12 Entries:[2/13 EntryNormal "prop_1"]

stabilize 2
----
> 2 receiving messages
  3->2 MsgApp Term:2 Log:2/12 Commit:12 Entries:[2/13 EntryNormal "prop_1"]
> 2 handling Ready
  Ready MustSync=true:
  Entries:
  2/13 EntryNormal "prop_1"
  Messages:
  2->3 MsgAppResp Term:2 Log:0/13 Commit:12

withdraw-support 2 3
----
  1 2 3
1 2 1 1
2 x 1 x
3 x 1 1

forget-leader 2
----
INFO 2 forgetting leader 3 at term 2

# 1 is now behind on its log. It tries to campaign, but fails.
raft-log 1
----
1/11 EntryNormal ""
2/12 EntryNormal ""

withdraw-support 1 3
----
  1 2 3
1 2 1 x
2 x 1 x
3 x 1 1

# At this point we can't campaign because we are not supported by a quorum.
campaign 1
----
DEBUG 1 cannot campaign since it's not supported by a quorum in store liveness

grant-support 3 1
----
  1 2 3
1 3 1 x
2 x 1 x
3 3 1 1

campaign 1
----
INFO 1 is starting a new election at term 2
INFO 1 became pre-candidate at term 2
INFO 1 [logterm: 2, index: 12] sent MsgPreVote request to 2 at term 2
INFO 1 [logterm: 2, index: 12] sent MsgPreVote request to 3 at term 2

process-ready 1
----
Ready MustSync=true:
State:StatePreCandidate
HardState Term:2 Commit:12 Lead:0 LeadEpoch:0
Messages:
1->2 MsgPreVote Term:3 Log:2/12
1->3 MsgPreVote Term:3 Log:2/12
INFO 1 received MsgPreVoteResp from 1 at term 2
INFO 1 has received 1 MsgPreVoteResp votes and 0 vote rejections

stabilize 2
----
> 2 handling Ready
  Ready MustSync=true:
  HardState Term:2 Vote:3 Commit:12 Lead:0 LeadEpoch:0
> 2 receiving messages
  1->2 MsgPreVote Term:3 Log:2/12
  INFO 2 [logterm: 2, index: 13, vote: 3] rejected MsgPreVote from 1 [logterm: 2, index: 12] at term 2
> 2 handling Ready
  Ready MustSync=false:
  Messages:
  2->1 MsgPreVoteResp Term:2 Log:0/0 Rejected (Hint: 0)

stabilize log-level=none
----
ok

raft-state
----
1: StateFollower (Voter) Term:2 Lead:3 LeadEpoch:0
2: StateFollower (Voter) Term:2 Lead:3 LeadEpoch:0
3: StateLeader (Voter) Term:2 Lead:3 LeadEpoch:1
