Skip to main content

cloud_sdk_testkit/
raw_fault.rs

1//! Deterministic delivery-phase fault injection for raw executors.
2
3use cloud_sdk::transport::{
4    AsyncRawHttpExecutor, AsyncResponseStaging, BlockingRawHttpExecutor, RawResponsePolicy,
5    ResponseCompletion, ResponseWriter, TransportFailure, TransportRequest,
6};
7
8/// Failure point injected by [`RawFaultExecutor`].
9#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
10pub enum RawFault {
11    /// Fail before any request bytes can be delivered.
12    NotSent,
13    /// Fail after delivery may have begun.
14    PossiblySent,
15    /// Fail after a response head has started.
16    ResponseStarted,
17    /// Exercise the mandatory unknown-to-possibly-sent mapping.
18    Unknown,
19}
20
21/// Payload-free deterministic raw fault.
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub struct RawFaultError;
24
25impl core::fmt::Display for RawFaultError {
26    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
27        formatter.write_str("injected raw transport fault")
28    }
29}
30
31impl core::error::Error for RawFaultError {}
32
33/// No-allocation executor that fails at one selected delivery phase.
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
35pub struct RawFaultExecutor {
36    fault: RawFault,
37}
38
39impl RawFaultExecutor {
40    /// Creates one deterministic fault injector.
41    #[must_use]
42    pub const fn new(fault: RawFault) -> Self {
43        Self { fault }
44    }
45
46    fn failure(self) -> TransportFailure<RawFaultError> {
47        match self.fault {
48            RawFault::NotSent => TransportFailure::not_sent(RawFaultError),
49            RawFault::PossiblySent => TransportFailure::possibly_sent(RawFaultError),
50            RawFault::ResponseStarted => TransportFailure::response_started(RawFaultError),
51            RawFault::Unknown => TransportFailure::unknown(RawFaultError),
52        }
53    }
54}
55
56impl BlockingRawHttpExecutor for RawFaultExecutor {
57    type Error = TransportFailure<RawFaultError>;
58
59    fn execute(
60        &self,
61        _request: TransportRequest<'_>,
62        _policy: RawResponsePolicy<'_>,
63        _response: &mut ResponseWriter<'_>,
64    ) -> Result<(), Self::Error> {
65        Err(self.failure())
66    }
67}
68
69impl AsyncRawHttpExecutor for RawFaultExecutor {
70    type Error = TransportFailure<RawFaultError>;
71
72    async fn execute<'executor, 'request, 'policy, 'writer, 'buffer>(
73        &'executor self,
74        _request: TransportRequest<'request>,
75        _policy: RawResponsePolicy<'policy>,
76        _response: AsyncResponseStaging<'writer, 'buffer>,
77    ) -> Result<ResponseCompletion, Self::Error>
78    where
79        'executor: 'writer,
80        'request: 'writer,
81        'policy: 'writer,
82        'buffer: 'writer,
83    {
84        Err(self.failure())
85    }
86}