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