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

Code before:
// configuration change is initiated to remove peer-2. This change commits
// successfully but only applies on peer-2 and peer-4.
//
// The expected result for leader transfer is:
//   - It will fail to peer-2 because it has been removed.
//   - It will fail to peer-3 because it has unapplied configuration change.
//   - It will succeed to peer-4 because it has already applied the
//     configuration change.
#[test]
fn test_when_applied_conf_change_on_transferee() {
    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.must_add_peer(region_id, new_peer(4, 4));

    cluster.must_put(b"k1", b"v1");

    fail::cfg("apply_on_conf_change_1_1", "pause").unwrap();
    fail::cfg("apply_on_conf_change_3_1", "pause").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));

    // Use async_put for insertion here to avoid timeout errors, as synchronize put
    // would hang due to the leader's apply process being paused.
    let _ = cluster.async_put(b"k2", b"v2").unwrap();

    pd_client.transfer_leader(region_id, new_peer(2, 2), vec![]);
    sleep_ms(300);
    assert_eq!(
        pd_client.check_region_leader(region_id, new_peer(2, 2)),
        false
    );

    pd_client.transfer_leader(region_id, new_peer(3, 3), vec![]);
    sleep_ms(300);
    assert_eq!(
        pd_client.check_region_leader(region_id, new_peer(3, 3)),
        false
    );

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

    // Verify the data completeness on the new leader.

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

Code after:
// successfully but only applies on peer-2 and peer-4.
//
// The expected result for leader transfer is:
//   - It will fail to peer-2 because it has been removed.
//   - It will fail to peer-3 because it has unapplied configuration change.
//   - It will succeed to peer-4 because it has already applied the
//     configuration change.
#[test]
fn test_when_applied_conf_change_on_transferee() {
    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.must_add_peer(region_id, new_peer(4, 4));

    cluster.must_put(b"k1", b"v1");

    fail::cfg("apply_on_conf_change_1_1", "pause").unwrap();
    fail::cfg("apply_on_conf_change_3_1", "pause").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));

    // Use async_put for insertion here to avoid timeout errors, as synchronize put
    // would hang due to the leader's apply process being paused.
    let _ = cluster.async_put(b"k2", b"v2").unwrap();

    pd_client.transfer_leader(region_id, new_peer(2, 2), vec![]);
    sleep_ms(300);
    assert_eq!(
        pd_client.check_region_leader(region_id, new_peer(2, 2)),
        false
    );

    pd_client.transfer_leader(region_id, new_peer(3, 3), vec![]);
    sleep_ms(300);
    assert_eq!(
        pd_client.check_region_leader(region_id, new_peer(3, 3)),
        false
    );

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

    // Verify the data completeness on the new leader.
    must_get_equal(&cluster.get_engine(4), b"k1", b"v1");