Skip to content

Commit

Permalink
test should_not_leak_checkpoint_when_state_sync_into_existing_snapsho…
Browse files Browse the repository at this point in the history
…t_height
  • Loading branch information
ShuoWangNSL committed Sep 24, 2024
1 parent 01494af commit 54e5937
Showing 1 changed file with 118 additions and 0 deletions.
118 changes: 118 additions & 0 deletions rs/state_manager/tests/state_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3713,6 +3713,124 @@ fn can_handle_state_sync_and_commit_race_condition() {
})
}

#[test]
fn should_not_leak_checkpoint_when_state_sync_into_existing_snapshot_height() {
state_manager_test_with_state_sync(|src_metrics, src_state_manager, src_state_sync| {
let (_height, mut state) = src_state_manager.take_tip();
insert_dummy_canister(&mut state, canister_test_id(100));

src_state_manager.commit_and_certify(
state.clone(),
height(1),
CertificationScope::Full,
None,
);

let (_height, state) = src_state_manager.take_tip();
src_state_manager.commit_and_certify(state, height(2), CertificationScope::Full, None);

let hash_2 = wait_for_checkpoint(&*src_state_manager, height(2));

let (_height, state) = src_state_manager.take_tip();
src_state_manager.commit_and_certify(state, height(3), CertificationScope::Full, None);

wait_for_checkpoint(&*src_state_manager, height(3));

certify_height(&*src_state_manager, height(1));
certify_height(&*src_state_manager, height(2));

let id = StateSyncArtifactId {
height: height(2),
hash: hash_2.get(),
};

let msg = src_state_sync
.get(&id)
.expect("failed to get state sync messages");

assert_error_counters(src_metrics);

state_manager_test_with_state_sync(|dst_metrics, dst_state_manager, dst_state_sync| {
let (tip_height, state) = dst_state_manager.take_tip();
assert_eq!(tip_height, height(0));
dst_state_manager.commit_and_certify(state, height(1), CertificationScope::Full, None);
certify_height(&*dst_state_manager, height(1));

// The state sync is started before the state manager has the state at height 2.
let mut chunkable =
set_fetch_state_and_start_start_sync(&dst_state_manager, &dst_state_sync, &id);

// Start the state sync when the state manager is below height 2.
// Omit one chunk and corrupt some files in the state sync scratchpad before adding the final chunk.
let omit: HashSet<ChunkId> =
maplit::hashset! {ChunkId::new(FILE_GROUP_CHUNK_ID_OFFSET)};
let completion = pipe_partial_state_sync(&msg, &mut *chunkable, &omit, false);
assert_matches!(completion, Ok(false), "Unexpectedly completed state sync");

let (_height, state) = dst_state_manager.take_tip();
dst_state_manager.commit_and_certify(state, height(2), CertificationScope::Full, None);
certify_height(&*dst_state_manager, height(2));

let (_height, state) = dst_state_manager.take_tip();
dst_state_manager.commit_and_certify(state, height(3), CertificationScope::Full, None);
dst_state_manager.flush_tip_channel();

dst_state_manager.remove_states_below(height(3));

assert_eq!(dst_state_manager.checkpoint_heights(), vec![height(3)]);

assert_eq!(
dst_state_manager.list_state_heights(CERT_CERTIFIED),
vec![height(2)]
);

// Continue to perform the state sync at height 2 after the state manager reaches height 3.
pipe_state_sync(msg, chunkable);

// State sync adds back checkpoint @2 into the state manager.
assert_eq!(
dst_state_manager.checkpoint_heights(),
vec![height(2), height(3)]
);

// There should not exist duplicate entries for snapshot height 2.
assert_eq!(
dst_state_manager.list_state_heights(CERT_CERTIFIED),
vec![height(2)]
);

assert_eq!(
dst_state_manager.list_state_heights(CERT_ANY),
vec![height(2), height(3)]
);

let (_height, state) = dst_state_manager.take_tip();
dst_state_manager.commit_and_certify(
state,
height(4),
CertificationScope::Metadata,
None,
);
certify_height(&*dst_state_manager, height(3));
certify_height(&*dst_state_manager, height(4));

let (tip_height, _state) = dst_state_manager.take_tip();
assert_eq!(tip_height, height(4));
assert_eq!(dst_state_manager.latest_state_height(), height(4));
// checkpoint @2 should be removable.
dst_state_manager.flush_tip_channel();
dst_state_manager.remove_states_below(height(4));
assert_eq!(dst_state_manager.checkpoint_heights(), vec![height(3)]);
// Snapshots below 4 should be removable.
assert_eq!(
dst_state_manager.list_state_heights(CERT_ANY),
vec![height(4)]
);
assert_error_counters(dst_metrics);
})
})
}

#[test]
fn can_commit_below_state_sync() {
state_manager_test_with_state_sync(|src_metrics, src_state_manager, src_state_sync| {
Expand Down

0 comments on commit 54e5937

Please sign in to comment.