ic-backup 0.62.0

Host-side snapshot backup and same-release recovery for Internet Computer canisters
Documentation
//! Count admission precedes extent allocation for both download and upload callers.
use super::*;
use crate::model::ic_snapshot_metadata::IcSnapshotMetadataRequest;
use crate::tests::support::ic_snapshot_metadata::values;
use ic_platform::candid::contract;

#[test]
fn exact_allowance_invalid_chunks_and_extreme_nat64_are_admitted_before_allocation() {
    let request =
        IcSnapshotMetadataRequest::new("renrk-eyaaa-aaaaa-aaada-cai", &[0, 255, 17]).unwrap();
    let mut values = values("data-source");
    values.wasm_chunk_store.clear();
    values.wasm_module_size = 8;
    values.wasm_memory_size = 0;
    values.stable_memory_size = 0;
    let metadata =
        IcSnapshotMetadataReply::decode(&request, &contract::encode_one(&values).unwrap()).unwrap();
    assert_eq!(planned_extents(&metadata, 4, 2).unwrap().len(), 2);
    assert!(matches!(
        planned_extents(&metadata, 4, 1),
        Err(SnapshotDataPlanningError::InsufficientAllowance {
            required: 2,
            original: 1
        })
    ));
    for chunk in [0, 1024 * 1024 + 1, u64::MAX] {
        assert!(matches!(
            planned_extents(&metadata, chunk, 2),
            Err(SnapshotDataPlanningError::InvalidChunkSize)
        ));
    }
    values.wasm_module_size = u64::MAX;
    values.wasm_memory_size = u64::MAX;
    let metadata =
        IcSnapshotMetadataReply::decode(&request, &contract::encode_one(values).unwrap()).unwrap();
    assert!(matches!(
        planned_extents(&metadata, 1, 2),
        Err(SnapshotDataPlanningError::CountOverflow)
    ));
    assert!(matches!(
        planned_extents(&metadata, 1024 * 1024, 2),
        Err(SnapshotDataPlanningError::InsufficientAllowance { .. })
    ));
}

#[test]
fn empty_regions_need_no_placeholder_but_known_empty_chunks_require_one_extent() {
    let request =
        IcSnapshotMetadataRequest::new("renrk-eyaaa-aaaaa-aaada-cai", &[0, 255, 17]).unwrap();
    let mut values = values("data-source");
    values.wasm_module_size = 0;
    values.wasm_memory_size = 0;
    values.stable_memory_size = 0;
    values.wasm_chunk_store.clear();
    let metadata =
        IcSnapshotMetadataReply::decode(&request, &contract::encode_one(&values).unwrap()).unwrap();
    assert!(
        planned_extents(&metadata, 1024 * 1024, 0)
            .unwrap()
            .is_empty()
    );
    let hash = <sha2::Sha256 as sha2::Digest>::digest(b"").to_vec();
    values
        .wasm_chunk_store
        .push(ic_platform::management_canister_types::ChunkHash { hash: hash.clone() });
    let metadata =
        IcSnapshotMetadataReply::decode(&request, &contract::encode_one(values).unwrap()).unwrap();
    let extents = planned_extents(&metadata, 1024 * 1024, 1).unwrap();
    assert!(
        matches!(extents.as_slice(), [SnapshotDataKind::WasmChunk { hash: actual }] if actual == &hash)
    );
    assert!(matches!(
        planned_extents(&metadata, 1024 * 1024, 0),
        Err(SnapshotDataPlanningError::InsufficientAllowance {
            required: 1,
            original: 0
        })
    ));
}