Skip to main content

ic_testkit/pic/
baseline.rs

1use super::{
2    CanisterSnapshotTarget, ControllerSnapshotError, ControllerSnapshots, PocketIcInstance,
3    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    /// Success means the complete captured set was restored.
45    pub fn restore(&self, funding: SnapshotRestoreFunding) -> Result<(), ControllerSnapshotError> {
46        self.instance
47            .instance
48            .restore_snapshots(&self.snapshots, funding)
49    }
50
51    /// Borrow the owned PocketIC instance behind this cached baseline.
52    #[must_use]
53    pub const fn pocket_ic(&self) -> &PocketIc {
54        &self.instance.instance
55    }
56
57    /// Return the number of canisters captured by this baseline.
58    #[must_use]
59    pub fn snapshot_count(&self) -> usize {
60        self.snapshots.len()
61    }
62
63    /// Iterate over captured canister ids in deterministic principal order.
64    pub fn snapshot_canister_ids(&self) -> impl Iterator<Item = Principal> + '_ {
65        self.snapshots.canister_ids()
66    }
67
68    /// Borrow the captured metadata associated with this cached baseline.
69    #[must_use]
70    pub const fn metadata(&self) -> &T {
71        &self.metadata
72    }
73
74    /// Mutably borrow the captured metadata associated with this cached baseline.
75    #[must_use]
76    pub const fn metadata_mut(&mut self) -> &mut T {
77        &mut self.metadata
78    }
79}