ic_testkit/pic/
startup.rs1use std::panic::{AssertUnwindSafe, catch_unwind};
2
3use pocket_ic::{PocketIc, PocketIcBuilder};
4
5use super::transport;
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct PocketIcStartupError {
10 message: String,
11}
12
13pub trait PocketIcBuilderExt {
15 fn try_build(self) -> Result<PocketIc, PocketIcStartupError>;
21}
22
23impl PocketIcBuilderExt for PocketIcBuilder {
24 fn try_build(self) -> Result<PocketIc, PocketIcStartupError> {
25 catch_unwind(AssertUnwindSafe(|| self.build()))
26 .map_err(|payload| PocketIcStartupError::from_panic(payload.as_ref()))
27 }
28}
29
30impl PocketIcStartupError {
31 fn from_panic(payload: &(dyn std::any::Any + Send)) -> Self {
32 Self {
33 message: transport::panic_payload_to_string(payload),
34 }
35 }
36
37 #[must_use]
39 pub fn message(&self) -> &str {
40 &self.message
41 }
42}
43
44impl std::fmt::Display for PocketIcStartupError {
45 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(formatter, "PocketIC startup panicked: {}", self.message)
47 }
48}
49
50impl std::error::Error for PocketIcStartupError {}
51
52#[cfg(test)]
53mod tests {
54 use super::PocketIcStartupError;
55
56 #[test]
57 fn startup_error_preserves_string_panic_message() {
58 let error = PocketIcStartupError::from_panic(&"startup failed");
59
60 assert_eq!(error.message(), "startup failed");
61 assert_eq!(
62 error.to_string(),
63 "PocketIC startup panicked: startup failed"
64 );
65 }
66}