cloud-sdk-testkit 0.29.0

Provider-neutral mock transport and fixture boundary for cloud-sdk.
Documentation
use cloud_sdk::Method;
use cloud_sdk::transport::{
    AsyncExecutionError, BlockingRawHttpExecutor, DeliveryPhase, MediaType, RawResponsePolicy,
    RequestTarget, ResponseBuffer, ResponseMediaPolicy, TransportRequest, drive_async_raw,
};
use core::future::Future;
use core::task::{Context, Poll, Waker};

use crate::{RawFault, RawFaultExecutor};

fn policy() -> Option<RawResponsePolicy<'static>> {
    RawResponsePolicy::new(
        1,
        1,
        ResponseMediaPolicy::Optional(&[MediaType::JSON]),
        ResponseMediaPolicy::Optional(&[MediaType::JSON]),
        &[],
        0,
    )
    .ok()
}

#[test]
fn preserves_every_conservative_delivery_phase() {
    let Ok(target) = RequestTarget::new("/fault") else {
        unreachable!("testkit security fixture construction failed");
    };
    let Some(policy) = policy() else {
        unreachable!("testkit security fixture construction failed");
    };
    for (fault, expected) in [
        (RawFault::NotSent, DeliveryPhase::NotSent),
        (RawFault::PossiblySent, DeliveryPhase::PossiblySent),
        (RawFault::ResponseStarted, DeliveryPhase::ResponseStarted),
        (RawFault::Unknown, DeliveryPhase::PossiblySent),
    ] {
        let executor = RawFaultExecutor::new(fault);
        let mut body = [0xa5_u8; 1];
        let mut headers = [0xa5_u8; 32];
        let mut response = ResponseBuffer::new(&mut body, 1, &mut headers);
        let failure = BlockingRawHttpExecutor::execute(
            &executor,
            TransportRequest::new(Method::Get, target),
            policy,
            response.writer(),
        );
        assert!(matches!(failure, Err(error) if error.phase() == expected));
    }
}

#[test]
fn async_unknown_fault_is_immediately_possibly_sent() {
    let Ok(target) = RequestTarget::new("/fault") else {
        unreachable!("testkit security fixture construction failed");
    };
    let Some(policy) = policy() else {
        unreachable!("testkit security fixture construction failed");
    };
    let executor = RawFaultExecutor::new(RawFault::Unknown);
    let mut body = [0xa5_u8; 1];
    let mut headers = [0xa5_u8; 32];
    let mut response = ResponseBuffer::new(&mut body, 1, &mut headers);
    let future = drive_async_raw(
        &executor,
        TransportRequest::new(Method::Get, target),
        policy,
        response.writer(),
    );
    let mut future = core::pin::pin!(future);
    let waker = Waker::noop();
    let mut context = Context::from_waker(waker);
    assert!(matches!(
        Future::poll(future.as_mut(), &mut context),
        Poll::Ready(Err(AsyncExecutionError::Transport(error)))
            if error.phase() == DeliveryPhase::PossiblySent
    ));
}

#[test]
fn send_raw_executor_automatically_satisfies_local_async() {
    let Ok(target) = RequestTarget::new("/fault") else {
        unreachable!("testkit security fixture construction failed");
    };
    let Some(policy) = policy() else {
        unreachable!("testkit security fixture construction failed");
    };
    let executor = RawFaultExecutor::new(RawFault::NotSent);
    let mut body = [0xa5_u8; 1];
    let mut headers = [0xa5_u8; 32];
    let mut response = ResponseBuffer::new(&mut body, 1, &mut headers);
    let future = cloud_sdk::transport::drive_local_raw(
        &executor,
        TransportRequest::new(Method::Get, target),
        policy,
        response.writer(),
    );
    let mut future = core::pin::pin!(future);
    let mut context = Context::from_waker(Waker::noop());
    assert!(matches!(
        Future::poll(future.as_mut(), &mut context),
        Poll::Ready(Err(AsyncExecutionError::Transport(error)))
            if error.phase() == DeliveryPhase::NotSent
    ));
}