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)]
12pub struct PocketIcStartupError {
13 message: String,
14}
15
16pub trait PocketIcBuilderExt {
20 fn try_build(self) -> Result<PocketIc, PocketIcStartupError>;
27}
28
29impl PocketIcBuilderExt for PocketIcBuilder {
30 fn try_build(self) -> Result<PocketIc, PocketIcStartupError> {
31 catch_unwind(AssertUnwindSafe(|| self.build()))
32 .map_err(|payload| PocketIcStartupError::from_panic(payload.as_ref()))
33 }
34}
35
36impl PocketIcStartupError {
37 fn from_panic(payload: &(dyn std::any::Any + Send)) -> Self {
38 Self {
39 message: transport::panic_payload_to_string(payload),
40 }
41 }
42
43 #[must_use]
45 pub fn message(&self) -> &str {
46 &self.message
47 }
48}
49
50impl std::fmt::Display for PocketIcStartupError {
51 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(formatter, "PocketIC startup panicked: {}", self.message)
53 }
54}
55
56impl std::error::Error for PocketIcStartupError {}
57
58#[cfg(test)]
59mod tests {
60 use super::PocketIcStartupError;
61
62 #[test]
63 fn startup_error_preserves_string_panic_message() {
64 let error = PocketIcStartupError::from_panic(&"startup failed");
65
66 assert_eq!(error.message(), "startup failed");
67 assert_eq!(
68 error.to_string(),
69 "PocketIC startup panicked: startup failed"
70 );
71 }
72}