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 benchmark;
10
11#[cfg(not(target_arch = "wasm32"))]
12pub mod artifacts;
13
14#[cfg(not(target_arch = "wasm32"))]
15pub mod pic;
16
17pub mod performance;
18use candid::Principal;
19
20///
21/// Account
22///
23
24#[derive(Clone, Debug, Eq, PartialEq)]
25pub struct Account {
26    pub owner: Principal,
27    pub subaccount: Option<[u8; 32]>,
28}
29
30///
31/// Deterministic dummy-value generator for tests.
32///
33/// Produces stable principals/accounts derived from a numeric seed, which makes
34/// tests reproducible without hardcoding raw byte arrays.
35///
36
37pub struct Fake;
38
39impl Fake {
40    ///
41    /// Deterministically derive an [`Account`] from `seed`.
42    ///
43    #[must_use]
44    pub fn account(seed: u32) -> Account {
45        let mut sub = [0u8; 32];
46        let bytes = seed.to_be_bytes();
47        sub[..4].copy_from_slice(&bytes);
48
49        Account {
50            owner: Self::principal(seed),
51            subaccount: Some(sub),
52        }
53    }
54
55    ///
56    /// Deterministically derive a [`Principal`] from `seed`.
57    ///
58    #[must_use]
59    pub fn principal(seed: u32) -> Principal {
60        let mut buf = [0u8; 29];
61        buf[..4].copy_from_slice(&seed.to_be_bytes());
62
63        Principal::from_slice(&buf)
64    }
65}
66
67///
68/// TESTS
69///
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn fake_account_is_deterministic_and_unique() {
77        let a1 = Fake::account(42);
78        let a2 = Fake::account(42);
79        let b = Fake::account(99);
80
81        // Deterministic: same seed => same account
82        assert_eq!(a1, a2, "Fake::account should be deterministic");
83
84        // Unique: different seeds => different account
85        assert_ne!(a1, b, "Fake::account should vary by seed");
86    }
87
88    #[test]
89    fn fake_principal_is_deterministic_and_unique() {
90        let p1 = Fake::principal(7);
91        let p2 = Fake::principal(7);
92        let q = Fake::principal(8);
93
94        assert_eq!(p1, p2, "Fake::principal should be deterministic");
95        assert_ne!(p1, q, "Fake::principal should differ for different seeds");
96
97        let bytes = p1.as_slice();
98        assert_eq!(bytes.len(), 29, "Principal must be 29 bytes");
99    }
100}