Repository: tikv/tikv
File: tests/failpoints/cases/test_transfer_leader.rs (Rust)

Code before:
    pd_client.transfer_leader(region_id, new_peer(3, 3), vec![]);
    pd_client.region_leader_must_be(region_id, new_peer(3, 3));
    let region = block_on(pd_client.get_region_by_id(region_id))
        .unwrap()
        .unwrap();
    assert_eq!(region.get_peers()[1].get_role(), PeerRole::Learner);
}

// This test verifies that a leader transfer is allowed when the transferee
// has been applied a conf change but the leader has not yet applied.
#[test]
fn test_when_applied_conf_change_on_transferee_pessimistic_lock() {
    let mut cluster = new_server_cluster(0, 4);
    let pd_client = cluster.pd_client.clone();
    pd_client.disable_default_operator();
    let region_id = cluster.run_conf_change();
    pd_client.must_add_peer(region_id, new_peer(2, 2));
    pd_client.must_add_peer(region_id, new_peer(3, 3));
    pd_client.region_leader_must_be(region_id, new_peer(1, 1));

    fail::cfg("apply_on_conf_change_1_1", "pause").unwrap();
    fail::cfg("propose_locks_before_transfer_leader", "return").unwrap();

    pd_client.remove_peer(region_id, new_peer(2, 2));
    sleep_ms(300);
    // Peer 2 is still exists since the leader hasn't applied the ConfChange
    // yet.
    pd_client.must_have_peer(region_id, new_peer(2, 2));

    pd_client.transfer_leader(region_id, new_peer(3, 3), vec![]);
    pd_client.region_leader_must_be(region_id, new_peer(3, 3));

    pd_client.must_none_peer(region_id, new_peer(2, 2));
}

// This test verifies that a leader transfer is allowed when the transferee
// has been applied a region split but the leader has not yet applied.
#[test]
fn test_when_applied_region_split_on_transferee_pessimistic_lock() {
    let mut cluster = new_server_cluster(0, 3);
    // To enable the transferee to quickly report the split region information.
    cluster.cfg.raft_store.pd_heartbeat_tick_interval = ReadableDuration::millis(50);
    let pd_client = cluster.pd_client.clone();
    pd_client.disable_default_operator();
    let region_id = cluster.run_conf_change();
    pd_client.must_add_peer(region_id, new_peer(2, 2));
    pd_client.must_add_peer(region_id, new_peer(3, 3));
    // Use peer_id 4 as the leader since we want to reuse the failpoint
    // apply_before_split_1_3.
    pd_client.transfer_leader(region_id, new_peer(3, 3), vec![]);
    pd_client.region_leader_must_be(region_id, new_peer(3, 3));

Review comment (suggestion):
```suggestion
    // Peer 2 still exists since the leader hasn't applied the ConfChange
```

Code after:
    pd_client.region_leader_must_be(region_id, new_peer(3, 3));
    let region = block_on(pd_client.get_region_by_id(region_id))
        .unwrap()
        .unwrap();
    assert_eq!(region.get_peers()[1].get_role(), PeerRole::Learner);
}

// This test verifies that a leader transfer is allowed when the transferee
// has applied a conf change but the leader has not yet applied.
#[test]
fn test_when_applied_conf_change_on_transferee_pessimistic_lock() {
    let mut cluster = new_server_cluster(0, 4);
    let pd_client = cluster.pd_client.clone();
    pd_client.disable_default_operator();
    let region_id = cluster.run_conf_change();
    pd_client.must_add_peer(region_id, new_peer(2, 2));
    pd_client.must_add_peer(region_id, new_peer(3, 3));
    pd_client.region_leader_must_be(region_id, new_peer(1, 1));

    fail::cfg("apply_on_conf_change_1_1", "pause").unwrap();
    fail::cfg("propose_locks_before_transfer_leader", "return").unwrap();

    pd_client.remove_peer(region_id, new_peer(2, 2));
    sleep_ms(300);
    // Peer 2 still exists since the leader hasn't applied the ConfChange
    // yet.
    pd_client.must_have_peer(region_id, new_peer(2, 2));

    pd_client.transfer_leader(region_id, new_peer(3, 3), vec![]);
    pd_client.region_leader_must_be(region_id, new_peer(3, 3));

    pd_client.must_none_peer(region_id, new_peer(2, 2));
}

// This test verifies that a leader transfer is allowed when the transferee
// has applied a region split but the leader has not yet applied.
#[test]
fn test_when_applied_region_split_on_transferee_pessimistic_lock() {
    let mut cluster = new_server_cluster(0, 3);
    // To enable the transferee to quickly report the split region information.
    cluster.cfg.raft_store.pd_heartbeat_tick_interval = ReadableDuration::millis(50);
    let pd_client = cluster.pd_client.clone();
    pd_client.disable_default_operator();
    let region_id = cluster.run_conf_change();
    pd_client.must_add_peer(region_id, new_peer(2, 2));
    pd_client.must_add_peer(region_id, new_peer(3, 3));
    // Use peer_id 4 as the leader since we want to reuse the failpoint
    // apply_before_split_1_3.
    pd_client.transfer_leader(region_id, new_peer(3, 3), vec![]);
    pd_client.region_leader_must_be(region_id, new_peer(3, 3));