1use candid::{CandidType, Principal, utils::ArgumentEncoder};
2use pocket_ic::PocketIc;
3use serde::de::DeserializeOwned;
4
5use super::{
6 CandidCallError, CandidCallExt, CanisterInstallExt, InstallSpec,
7 StandaloneCanisterFixtureError, try_pic,
8};
9
10const DEFAULT_EXTRA_INSTALL_CYCLES: u128 = 0;
11
12pub struct StandaloneCanisterFixture {
17 pocket_ic: PocketIc,
18 canister_id: Principal,
19}
20
21impl StandaloneCanisterFixture {
22 #[must_use]
24 pub const fn pocket_ic(&self) -> &PocketIc {
25 &self.pocket_ic
26 }
27
28 #[must_use]
30 pub const fn canister_id(&self) -> Principal {
31 self.canister_id
32 }
33
34 #[must_use]
36 pub fn into_parts(self) -> (PocketIc, Principal) {
37 (self.pocket_ic, self.canister_id)
38 }
39
40 pub fn update_call<T, A>(&self, method: &str, args: A) -> Result<T, CandidCallError>
42 where
43 T: CandidType + DeserializeOwned,
44 A: ArgumentEncoder,
45 {
46 self.pocket_ic.update_candid(self.canister_id, method, args)
47 }
48
49 #[track_caller]
55 pub fn update_call_or_panic<T, A>(&self, method: &str, args: A) -> T
56 where
57 T: CandidType + DeserializeOwned,
58 A: ArgumentEncoder,
59 {
60 self.pocket_ic
61 .update_candid_or_panic(self.canister_id, method, args)
62 }
63
64 pub fn update_call_as<T, A>(
66 &self,
67 caller: Principal,
68 method: &str,
69 args: A,
70 ) -> Result<T, CandidCallError>
71 where
72 T: CandidType + DeserializeOwned,
73 A: ArgumentEncoder,
74 {
75 self.pocket_ic
76 .update_candid_as(self.canister_id, caller, method, args)
77 }
78
79 #[track_caller]
85 pub fn update_call_as_or_panic<T, A>(&self, caller: Principal, method: &str, args: A) -> T
86 where
87 T: CandidType + DeserializeOwned,
88 A: ArgumentEncoder,
89 {
90 self.pocket_ic
91 .update_candid_as_or_panic(self.canister_id, caller, method, args)
92 }
93
94 pub fn query_call<T, A>(&self, method: &str, args: A) -> Result<T, CandidCallError>
96 where
97 T: CandidType + DeserializeOwned,
98 A: ArgumentEncoder,
99 {
100 self.pocket_ic.query_candid(self.canister_id, method, args)
101 }
102
103 #[track_caller]
109 pub fn query_call_or_panic<T, A>(&self, method: &str, args: A) -> T
110 where
111 T: CandidType + DeserializeOwned,
112 A: ArgumentEncoder,
113 {
114 self.pocket_ic
115 .query_candid_or_panic(self.canister_id, method, args)
116 }
117
118 pub fn query_call_as<T, A>(
120 &self,
121 caller: Principal,
122 method: &str,
123 args: A,
124 ) -> Result<T, CandidCallError>
125 where
126 T: CandidType + DeserializeOwned,
127 A: ArgumentEncoder,
128 {
129 self.pocket_ic
130 .query_candid_as(self.canister_id, caller, method, args)
131 }
132
133 #[track_caller]
139 pub fn query_call_as_or_panic<T, A>(&self, caller: Principal, method: &str, args: A) -> T
140 where
141 T: CandidType + DeserializeOwned,
142 A: ArgumentEncoder,
143 {
144 self.pocket_ic
145 .query_candid_as_or_panic(self.canister_id, caller, method, args)
146 }
147}
148
149#[must_use]
152pub fn install_prebuilt_canister(wasm: Vec<u8>, init_bytes: Vec<u8>) -> StandaloneCanisterFixture {
153 try_install_prebuilt_canister(wasm, init_bytes)
154 .unwrap_or_else(|err| panic!("failed to install prebuilt canister fixture: {err}"))
155}
156
157pub fn try_install_prebuilt_canister(
160 wasm: Vec<u8>,
161 init_bytes: Vec<u8>,
162) -> Result<StandaloneCanisterFixture, StandaloneCanisterFixtureError> {
163 try_install_prebuilt_canister_from_spec(InstallSpec::new(
164 wasm,
165 init_bytes,
166 DEFAULT_EXTRA_INSTALL_CYCLES,
167 ))
168}
169
170#[must_use]
173pub fn install_prebuilt_canister_with_cycles(
174 wasm: Vec<u8>,
175 init_bytes: Vec<u8>,
176 install_cycles: u128,
177) -> StandaloneCanisterFixture {
178 try_install_prebuilt_canister_with_cycles(wasm, init_bytes, install_cycles)
179 .unwrap_or_else(|err| panic!("failed to install prebuilt canister fixture: {err}"))
180}
181
182pub fn try_install_prebuilt_canister_with_cycles(
185 wasm: Vec<u8>,
186 init_bytes: Vec<u8>,
187 install_cycles: u128,
188) -> Result<StandaloneCanisterFixture, StandaloneCanisterFixtureError> {
189 try_install_prebuilt_canister_from_spec(InstallSpec::new(wasm, init_bytes, install_cycles))
190}
191
192#[must_use]
195pub fn install_prebuilt_canister_from_spec(spec: InstallSpec) -> StandaloneCanisterFixture {
196 try_install_prebuilt_canister_from_spec(spec)
197 .unwrap_or_else(|err| panic!("failed to install prebuilt canister fixture: {err}"))
198}
199
200pub fn try_install_prebuilt_canister_from_spec(
203 spec: InstallSpec,
204) -> Result<StandaloneCanisterFixture, StandaloneCanisterFixtureError> {
205 let pocket_ic = try_pic().map_err(StandaloneCanisterFixtureError::Start)?;
206 let canister_id = pocket_ic
207 .try_create_and_install(spec)
208 .map_err(StandaloneCanisterFixtureError::Install)?;
209
210 Ok(StandaloneCanisterFixture {
211 pocket_ic,
212 canister_id,
213 })
214}