ic-testkit 0.76.0

PocketIC-oriented test utilities for IC canister tests
Documentation
//! Release-bound `PocketIC` server policy, independent of client download defaults.

/// The server selected by this Testkit release's explicit provisioning CLI.
pub const POCKET_IC_SERVER_VERSION: &str = "16.1.0";

const SUPPORTED_MAJOR: u64 = 16;

/// Human-readable stable server range accepted by [`supports_pocket_ic_server`].
/// Provisioning's exact reviewed artifact version is selected independently.
#[must_use]
pub fn pocket_ic_server_requirement() -> String {
    format!(
        "pocket-ic-server >={SUPPORTED_MAJOR}.0.0,<{}.0.0 (stable)",
        SUPPORTED_MAJOR + 1
    )
}

/// Whether a successful server version probe satisfies Testkit's protocol policy.
///
/// Stable 16.x servers are supported, matching the selected `PocketIC` client's
/// `>=16.0.0,<17.0.0` protocol range. Provisioning selects one exact reviewed
/// artifact separately; this predicate does not authenticate executable bytes.
#[must_use]
pub fn supports_pocket_ic_server(output: &[u8]) -> bool {
    let Ok(text) = std::str::from_utf8(output) else {
        return false;
    };
    let Some(version) = text.trim().strip_prefix("pocket-ic-server ") else {
        return false;
    };
    let mut components = version.split('.');
    for index in 0..3 {
        let Some(part) = components.next() else {
            return false;
        };
        if part.is_empty()
            || (part.len() > 1 && part.starts_with('0'))
            || !part.bytes().all(|byte| byte.is_ascii_digit())
        {
            return false;
        }
        let Ok(value) = part.parse::<u64>() else {
            return false;
        };
        if index == 0 && value != SUPPORTED_MAJOR {
            return false;
        }
    }
    components.next().is_none()
}

#[cfg(test)]
mod tests {
    #[test]
    fn protocol_admission_is_independent_of_download_selection() {
        for version in ["16.0.0", "16.0.1", "16.1.0", "16.2.3"] {
            assert!(super::supports_pocket_ic_server(
                format!("pocket-ic-server {version}\n").as_bytes()
            ));
        }
        for output in [
            "pocket-ic-server 15.0.0",
            "pocket-ic-server 17.0.0",
            "pocket-ic-server 16.0",
            "pocket-ic-server 16.1.0.0",
            "pocket-ic-server 16.01.0",
            "pocket-ic-server 16.1.00",
            "pocket-ic-server 16.1.0-extra",
            "pocket-ic-server 16.18446744073709551616.0",
            "other 16.1.0",
        ] {
            assert!(!super::supports_pocket_ic_server(output.as_bytes()));
        }
        assert!(!super::supports_pocket_ic_server(b"\xff"));
    }
}