ic-testkit 0.64.1

PocketIC-oriented test utilities for IC canister tests
Documentation
use super::*;
use ic_host_artifacts::wasm::validate;

const LIMITS: RawReplyLimits = RawReplyLimits {
    methods: 3,
    reply_bytes: 70_000,
    method_name_bytes: 100,
};

#[test]
fn validates_stateful_slots_and_opaque_page_spanning_replies() {
    let large = vec![0xff; 65_537];
    let methods = [
        RawReplyMethod {
            name: "read\"\\é",
            mode: ReplyMode::Update,
            reply: &large,
        },
        RawReplyMethod {
            name: "read\"\\é",
            mode: ReplyMode::Update,
            reply: b"second\0",
        },
        RawReplyMethod {
            name: "other",
            mode: ReplyMode::Update,
            reply: &[],
        },
    ];
    let wasm = module(
        &methods,
        LIMITS,
        "https://ic-testkit.invalid/test/",
        50_000_000_000,
        100_000,
    )
    .unwrap();
    validate(&wasm, 100_000).unwrap();
    assert!(wasm.windows(large.len()).any(|bytes| bytes == large));
    validate(&module(&[], LIMITS, "unused", 0, 10_000).unwrap(), 10_000).unwrap();
}

#[test]
fn refuses_catalog_and_compiled_output_limits() {
    let method = RawReplyMethod {
        name: "read",
        mode: ReplyMode::Update,
        reply: b"raw",
    };
    for limits in [
        RawReplyLimits {
            methods: 0,
            ..LIMITS
        },
        RawReplyLimits {
            reply_bytes: 2,
            ..LIMITS
        },
        RawReplyLimits {
            method_name_bytes: 3,
            ..LIMITS
        },
    ] {
        assert!(matches!(
            module(&[method], limits, "unused", 0, 10_000),
            Err(HeldReplyError::Catalog(RawReplyError::Budget { .. }))
        ));
    }
    assert!(matches!(
        module(
            &[RawReplyMethod {
                mode: ReplyMode::Query,
                ..method
            }],
            LIMITS,
            "unused",
            0,
            10_000
        ),
        Err(HeldReplyError::Query { slot: 0 })
    ));
    for name in ["", "bad\0", "bad\n"] {
        assert!(matches!(
            module(
                &[RawReplyMethod { name, ..method }],
                LIMITS,
                "unused",
                0,
                10_000
            ),
            Err(HeldReplyError::Catalog(RawReplyError::InvalidName {
                index: 0
            }))
        ));
    }
    assert!(matches!(
        module(&[method], LIMITS, "unused", 0, 1),
        Err(HeldReplyError::Compile(CompileError::ModuleLimit { .. }))
    ));
    let mut offset = usize::MAX;
    assert!(segment(&mut String::new(), &mut offset, b"x").is_err());
}