Skip to main content

canic_testkit/
lib.rs

1//! Public PocketIC-oriented test utilities for projects that use Canic.
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 non-root canister fixtures, retry helpers for
6//! PocketIC install throttling, and cached baseline primitives.
7
8pub mod artifacts;
9pub mod pic;
10use canic::cdk::types::{Account, Principal};
11
12///
13/// Deterministic dummy-value generator for tests.
14///
15/// Produces stable principals/accounts derived from a numeric seed, which makes
16/// tests reproducible without hardcoding raw byte arrays.
17///
18
19pub struct Fake;
20
21impl Fake {
22    ///
23    /// Deterministically derive an [`Account`] from `seed`.
24    ///
25    #[must_use]
26    pub fn account(seed: u32) -> Account {
27        let mut sub = [0u8; 32];
28        let bytes = seed.to_be_bytes();
29        sub[..4].copy_from_slice(&bytes);
30
31        Account {
32            owner: Self::principal(seed),
33            subaccount: Some(sub),
34        }
35    }
36
37    ///
38    /// Deterministically derive a [`Principal`] from `seed`.
39    ///
40    #[must_use]
41    pub fn principal(seed: u32) -> Principal {
42        let mut buf = [0u8; 29];
43        buf[..4].copy_from_slice(&seed.to_be_bytes());
44
45        Principal::from_slice(&buf)
46    }
47}
48
49///
50/// TESTS
51///
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn fake_account_is_deterministic_and_unique() {
59        let a1 = Fake::account(42);
60        let a2 = Fake::account(42);
61        let b = Fake::account(99);
62
63        // Deterministic: same seed => same account
64        assert_eq!(a1, a2, "Fake::account should be deterministic");
65
66        // Unique: different seeds => different account
67        assert_ne!(a1, b, "Fake::account should vary by seed");
68    }
69
70    #[test]
71    fn fake_principal_is_deterministic_and_unique() {
72        let p1 = Fake::principal(7);
73        let p2 = Fake::principal(7);
74        let q = Fake::principal(8);
75
76        assert_eq!(p1, p2, "Fake::principal should be deterministic");
77        assert_ne!(p1, q, "Fake::principal should differ for different seeds");
78
79        let bytes = p1.as_slice();
80        assert_eq!(bytes.len(), 29, "Principal must be 29 bytes");
81    }
82}