Skip to main content

ic_testkit/pic/
baseline.rs

1use super::{
2    CanisterRestoreReceipt, CanisterSnapshotTarget, ControllerSnapshotError, ControllerSnapshots,
3    PocketIcInstance, PocketIcSnapshotExt, SnapshotRestoreFunding,
4};
5use candid::Principal;
6use pocket_ic::PocketIc;
7
8/// One owned PocketIC instance/server record with snapshots and caller metadata.
9///
10/// The value contains no synchronization. A [`super::PocketIcBaselineRecipe`]
11/// can own it as its fixture in a [`super::CachedPocketIcBaselinePool`].
12pub struct CachedPocketIcBaseline<T> {
13    instance: PocketIcInstance<PocketIc>,
14    snapshots: ControllerSnapshots,
15    metadata: T,
16}
17
18impl<T> CachedPocketIcBaseline<T> {
19    /// Capture a cached baseline with an explicit sender for every canister.
20    ///
21    /// Empty inputs are rejected before capture. Capture is ordered and transactional as documented by
22    /// [`PocketIcSnapshotExt::capture_snapshots`]. No sender fallback is performed.
23    pub fn capture<I>(
24        instance: PocketIcInstance<PocketIc>,
25        targets: I,
26        metadata: T,
27    ) -> Result<Self, ControllerSnapshotError>
28    where
29        I: IntoIterator<Item = CanisterSnapshotTarget>,
30    {
31        let mut targets = targets.into_iter().peekable();
32        if targets.peek().is_none() {
33            return Err(ControllerSnapshotError::EmptyCanisterSet);
34        }
35        let snapshots = instance.instance.capture_snapshots(targets)?;
36        Ok(Self {
37            instance,
38            snapshots,
39            metadata,
40        })
41    }
42
43    /// Restore with exactly the captured senders and selected cycle funding.
44    /// The receipt describes the complete successful restore and selected funding.
45    pub fn restore(
46        &self,
47        funding: SnapshotRestoreFunding,
48    ) -> Result<CanisterRestoreReceipt, ControllerSnapshotError> {
49        self.instance
50            .instance
51            .restore_snapshots(&self.snapshots, funding)?;
52        Ok(CanisterRestoreReceipt::from_restore(
53            &self.snapshots,
54            funding,
55        ))
56    }
57
58    /// Borrow the owned PocketIC instance behind this cached baseline.
59    #[must_use]
60    pub const fn pocket_ic(&self) -> &PocketIc {
61        &self.instance.instance
62    }
63
64    /// Return the number of canisters captured by this baseline.
65    #[must_use]
66    pub fn snapshot_count(&self) -> usize {
67        self.snapshots.len()
68    }
69
70    /// Iterate over captured canister ids in deterministic principal order.
71    pub fn snapshot_canister_ids(&self) -> impl Iterator<Item = Principal> + '_ {
72        self.snapshots.canister_ids()
73    }
74
75    /// Borrow the captured metadata associated with this cached baseline.
76    #[must_use]
77    pub const fn metadata(&self) -> &T {
78        &self.metadata
79    }
80
81    /// Mutably borrow the captured metadata associated with this cached baseline.
82    #[must_use]
83    pub const fn metadata_mut(&mut self) -> &mut T {
84        &mut self.metadata
85    }
86}