ic_testkit/pocket_ic/
error.rs1use reqwest::StatusCode;
4
5#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct Operation {
8 pub state_label: String,
9 pub op_id: String,
10}
11
12#[derive(Clone, Debug)]
14pub struct RequestContext {
15 pub url: String,
16 pub operation: Option<Operation>,
17 pub ingress: Option<crate::pocket_ic::common::rest::RawMessageId>,
19 pub may_have_executed: bool,
21 pub status: Option<StatusCode>,
22}
23
24#[derive(Debug, thiserror::Error)]
26pub enum ClientError {
27 #[error("PocketIC transport failed: {source}")]
28 Transport {
29 context: Box<RequestContext>,
30 #[source]
31 source: reqwest::Error,
32 },
33 #[error("PocketIC response body failed: {source}")]
34 Body {
35 context: Box<RequestContext>,
36 #[source]
37 source: reqwest::Error,
38 },
39 #[error("PocketIC response JSON failed: {source}")]
40 Json {
41 context: Box<RequestContext>,
42 #[source]
43 source: serde_json::Error,
44 },
45 #[error("PocketIC server returned {status}: {message}")]
46 Server {
47 context: Box<RequestContext>,
48 status: StatusCode,
49 message: String,
50 },
51 #[error("PocketIC request deadline expired")]
52 Timeout { context: Box<RequestContext> },
53 #[error("PocketIC response exceeds {limit} bytes")]
54 ResponseTooLarge {
55 context: Box<RequestContext>,
56 limit: usize,
57 },
58 #[error("canister rejected the call: {0:?}")]
59 Canister(crate::pocket_ic::RejectResponse),
60 #[error("Candid failed: {0}")]
61 Candid(#[from] candid::Error),
62 #[error("CBOR failed: {0}")]
63 Cbor(#[from] serde_cbor::Error),
64 #[error("I/O failed: {0}")]
65 Io(#[from] std::io::Error),
66 #[error("invalid PocketIC response: {0}")]
67 Protocol(String),
68}
69
70impl ClientError {
71 pub(crate) fn with_ingress(
72 mut self,
73 ingress: crate::pocket_ic::common::rest::RawMessageId,
74 ) -> Self {
75 match &mut self {
76 Self::Transport { context, .. }
77 | Self::Body { context, .. }
78 | Self::Json { context, .. }
79 | Self::Server { context, .. }
80 | Self::ResponseTooLarge { context, .. }
81 | Self::Timeout { context } => context.ingress = Some(ingress),
82 _ => {}
83 }
84 self
85 }
86
87 pub fn request_context(&self) -> Option<&RequestContext> {
88 match self {
89 Self::Transport { context, .. }
90 | Self::Body { context, .. }
91 | Self::Json { context, .. }
92 | Self::Server { context, .. }
93 | Self::ResponseTooLarge { context, .. }
94 | Self::Timeout { context } => Some(context),
95 _ => None,
96 }
97 }
98}
99
100impl From<crate::pocket_ic::RejectResponse> for ClientError {
101 fn from(value: crate::pocket_ic::RejectResponse) -> Self {
102 Self::Canister(value)
103 }
104}