Skip to main content

ic_testkit/
lib.rs

1//! Reusable PocketIC-oriented test utilities for IC canister tests.
2//!
3//! This crate is intended for host-side test environments (for example via
4//! PocketIC) and provides generic helpers such as stable dummy principals,
5//! PocketIC wrappers, standalone canister fixtures, generic prebuilt wasm
6//! install helpers, retry helpers for PocketIC install throttling, and cached
7//! baseline primitives.
8
9pub mod artifacts;
10pub mod pic;
11use candid::Principal;
12
13///
14/// Account
15///
16
17#[derive(Clone, Debug, Eq, PartialEq)]
18pub struct Account {
19    pub owner: Principal,
20    pub subaccount: Option<[u8; 32]>,
21}
22
23///
24/// Deterministic dummy-value generator for tests.
25///
26/// Produces stable principals/accounts derived from a numeric seed, which makes
27/// tests reproducible without hardcoding raw byte arrays.
28///
29
30pub struct Fake;
31
32impl Fake {
33    ///
34    /// Deterministically derive an [`Account`] from `seed`.
35    ///
36    #[must_use]
37    pub fn account(seed: u32) -> Account {
38        let mut sub = [0u8; 32];
39        let bytes = seed.to_be_bytes();
40        sub[..4].copy_from_slice(&bytes);
41
42        Account {
43            owner: Self::principal(seed),
44            subaccount: Some(sub),
45        }
46    }
47
48    ///
49    /// Deterministically derive a [`Principal`] from `seed`.
50    ///
51    #[must_use]
52    pub fn principal(seed: u32) -> Principal {
53        let mut buf = [0u8; 29];
54        buf[..4].copy_from_slice(&seed.to_be_bytes());
55
56        Principal::from_slice(&buf)
57    }
58}
59
60///
61/// TESTS
62///
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn fake_account_is_deterministic_and_unique() {
70        let a1 = Fake::account(42);
71        let a2 = Fake::account(42);
72        let b = Fake::account(99);
73
74        // Deterministic: same seed => same account
75        assert_eq!(a1, a2, "Fake::account should be deterministic");
76
77        // Unique: different seeds => different account
78        assert_ne!(a1, b, "Fake::account should vary by seed");
79    }
80
81    #[test]
82    fn fake_principal_is_deterministic_and_unique() {
83        let p1 = Fake::principal(7);
84        let p2 = Fake::principal(7);
85        let q = Fake::principal(8);
86
87        assert_eq!(p1, p2, "Fake::principal should be deterministic");
88        assert_ne!(p1, q, "Fake::principal should differ for different seeds");
89
90        let bytes = p1.as_slice();
91        assert_eq!(bytes.len(), 29, "Principal must be 29 bytes");
92    }
93}