1use candid::Principal;
4use pocket_ic::{
5 CanisterStatusResult, PocketIc, PocketIcBuilder, RejectResponse, common::rest::RawMessageId,
6};
7use std::time::Duration;
8
9mod baseline;
10mod calls;
11mod diagnostics;
12mod errors;
13mod lifecycle;
14mod process_lock;
15mod snapshot;
16mod standalone;
17mod startup;
18
19pub use baseline::{
20 CachedPicBaseline, CachedPicBaselineGuard, ControllerSnapshots,
21 restore_or_rebuild_cached_pic_baseline,
22};
23pub use errors::{PicCallError, PicInstallError, StandaloneCanisterFixtureError};
24pub use process_lock::{
25 PicSerialGuard, PicSerialGuardError, acquire_pic_serial_guard, try_acquire_pic_serial_guard,
26};
27pub use startup::PicStartError;
28
29pub use standalone::{
30 StandaloneCanisterFixture, install_prebuilt_canister, install_prebuilt_canister_with_cycles,
31 try_install_prebuilt_canister, try_install_prebuilt_canister_with_cycles,
32};
33
34#[must_use]
43pub fn pic() -> Pic {
44 try_pic().unwrap_or_else(|err| panic!("failed to start PocketIC: {err}"))
45}
46
47pub fn try_pic() -> Result<Pic, PicStartError> {
49 PicBuilder::new().with_application_subnet().try_build()
50}
51
52pub struct PicBuilder(PocketIcBuilder);
63
64#[expect(clippy::new_without_default)]
65impl PicBuilder {
66 #[must_use]
68 pub fn new() -> Self {
69 Self(PocketIcBuilder::new())
70 }
71
72 #[must_use]
74 pub fn with_application_subnet(mut self) -> Self {
75 self.0 = self.0.with_application_subnet();
76 self
77 }
78
79 #[must_use]
81 pub fn with_ii_subnet(mut self) -> Self {
82 self.0 = self.0.with_ii_subnet();
83 self
84 }
85
86 #[must_use]
88 pub fn with_nns_subnet(mut self) -> Self {
89 self.0 = self.0.with_nns_subnet();
90 self
91 }
92
93 #[must_use]
95 pub fn build(self) -> Pic {
96 self.try_build()
97 .unwrap_or_else(|err| panic!("failed to start PocketIC: {err}"))
98 }
99
100 pub fn try_build(self) -> Result<Pic, PicStartError> {
102 startup::try_build_pic(self.0)
103 }
104}
105pub struct Pic {
114 inner: PocketIc,
115}
116
117impl Pic {
118 pub fn tick(&self) {
120 self.inner.tick();
121 }
122
123 pub fn advance_time(&self, duration: Duration) {
125 self.inner.advance_time(duration);
126 }
127
128 #[must_use]
130 pub fn create_canister(&self) -> Principal {
131 self.inner.create_canister()
132 }
133
134 pub fn add_cycles(&self, canister_id: Principal, amount: u128) {
136 let _ = self.inner.add_cycles(canister_id, amount);
137 }
138
139 pub fn install_canister(
141 &self,
142 canister_id: Principal,
143 wasm_module: Vec<u8>,
144 arg: Vec<u8>,
145 sender: Option<Principal>,
146 ) {
147 self.inner
148 .install_canister(canister_id, wasm_module, arg, sender);
149 }
150
151 pub fn upgrade_canister(
153 &self,
154 canister_id: Principal,
155 wasm_module: Vec<u8>,
156 arg: Vec<u8>,
157 sender: Option<Principal>,
158 ) -> Result<(), RejectResponse> {
159 self.inner
160 .upgrade_canister(canister_id, wasm_module, arg, sender)
161 }
162
163 pub fn reinstall_canister(
165 &self,
166 canister_id: Principal,
167 wasm_module: Vec<u8>,
168 arg: Vec<u8>,
169 sender: Option<Principal>,
170 ) -> Result<(), RejectResponse> {
171 self.inner
172 .reinstall_canister(canister_id, wasm_module, arg, sender)
173 }
174
175 pub fn submit_call(
177 &self,
178 canister_id: Principal,
179 sender: Principal,
180 method: &str,
181 payload: Vec<u8>,
182 ) -> Result<RawMessageId, RejectResponse> {
183 self.inner.submit_call(canister_id, sender, method, payload)
184 }
185
186 pub fn await_call(&self, message_id: RawMessageId) -> Result<Vec<u8>, RejectResponse> {
188 self.inner.await_call(message_id)
189 }
190
191 pub fn canister_status(
193 &self,
194 canister_id: Principal,
195 sender: Option<Principal>,
196 ) -> Result<CanisterStatusResult, RejectResponse> {
197 self.inner.canister_status(canister_id, sender)
198 }
199
200 pub fn fetch_canister_logs(
202 &self,
203 canister_id: Principal,
204 sender: Principal,
205 ) -> Result<Vec<pocket_ic::CanisterLogRecord>, RejectResponse> {
206 self.inner.fetch_canister_logs(canister_id, sender)
207 }
208
209 #[must_use]
211 pub fn current_time_nanos(&self) -> u64 {
212 self.inner.get_time().as_nanos_since_unix_epoch()
213 }
214
215 pub fn restore_time_nanos(&self, nanos_since_epoch: u64) {
217 let restored = pocket_ic::Time::from_nanos_since_unix_epoch(nanos_since_epoch);
218 self.inner.set_time(restored);
219 self.inner.set_certified_time(restored);
220 }
221}