diff --git a/wireframe_testing/src/helpers.rs b/wireframe_testing/src/helpers.rs index a42ba0bf..bf187469 100644 --- a/wireframe_testing/src/helpers.rs +++ b/wireframe_testing/src/helpers.rs @@ -33,6 +33,21 @@ impl TestSerializer for T where const DEFAULT_CAPACITY: usize = 4096; +/// Drive `app` with a single length-prefixed `frame` and return the bytes +/// produced by the server. +/// +/// The app runs on an in-memory duplex stream so tests need not open real +/// sockets. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_frame, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let bytes = drive_with_frame(app, vec![1, 2, 3]).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_frame( app: WireframeApp, frame: Vec, @@ -45,6 +60,19 @@ where drive_with_frame_with_capacity(app, frame, DEFAULT_CAPACITY).await } +/// Drive `app` with a single frame using a duplex buffer of `capacity` bytes. +/// +/// Adjusting the buffer size helps exercise edge cases such as small channels. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_frame_with_capacity, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let bytes = drive_with_frame_with_capacity(app, vec![0], 512).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_frame_with_capacity( app: WireframeApp, frame: Vec, @@ -58,6 +86,19 @@ where drive_with_frames_with_capacity(app, vec![frame], capacity).await } +/// Drive `app` with a sequence of frames using the default buffer size. +/// +/// Each frame is written to the duplex stream in order. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_frames, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let out = drive_with_frames(app, vec![vec![1], vec![2]]).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_frames( app: WireframeApp, frames: Vec>, @@ -70,6 +111,19 @@ where drive_with_frames_with_capacity(app, frames, DEFAULT_CAPACITY).await } +/// Drive `app` with multiple frames using a duplex buffer of `capacity` bytes. +/// +/// This variant exposes the buffer size for fine-grained control in tests. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_frames_with_capacity, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let out = drive_with_frames_with_capacity(app, vec![vec![1], vec![2]], 1024).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_frames_with_capacity( app: WireframeApp, frames: Vec>, @@ -102,6 +156,18 @@ where } } +/// Feed a single frame into a mutable `app`, allowing the instance to be reused +/// across calls. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_frame_mut, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let mut app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let bytes = drive_with_frame_mut(&mut app, vec![1]).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_frame_mut( app: &mut WireframeApp, frame: Vec, @@ -114,6 +180,17 @@ where drive_with_frame_with_capacity_mut(app, frame, DEFAULT_CAPACITY).await } +/// Feed a single frame into `app` using a duplex buffer of `capacity` bytes. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_frame_with_capacity_mut, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let mut app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let bytes = drive_with_frame_with_capacity_mut(&mut app, vec![1], 256).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_frame_with_capacity_mut( app: &mut WireframeApp, frame: Vec, @@ -127,6 +204,17 @@ where drive_with_frames_with_capacity_mut(app, vec![frame], capacity).await } +/// Feed multiple frames into a mutable `app`. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_frames_mut, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let mut app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let out = drive_with_frames_mut(&mut app, vec![vec![1], vec![2]]).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_frames_mut( app: &mut WireframeApp, frames: Vec>, @@ -139,6 +227,17 @@ where drive_with_frames_with_capacity_mut(app, frames, DEFAULT_CAPACITY).await } +/// Feed multiple frames into `app` with a duplex buffer of `capacity` bytes. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_frames_with_capacity_mut, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let mut app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let out = drive_with_frames_with_capacity_mut(&mut app, vec![vec![1], vec![2]], 64).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_frames_with_capacity_mut( app: &mut WireframeApp, frames: Vec>, @@ -167,6 +266,19 @@ where buf } +/// Encode `msg` using bincode, frame it and drive `app`. +/// +/// ```rust +/// # use wireframe_testing::{drive_with_bincode, processor}; +/// # use wireframe::app::WireframeApp; +/// #[derive(bincode::Encode)] +/// struct Ping(u8); +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let bytes = drive_with_bincode(app, Ping(1)).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn drive_with_bincode( app: WireframeApp, msg: M, @@ -194,6 +306,16 @@ where /// /// Returns any I/O errors encountered while interacting with the in-memory /// duplex stream. +/// +/// ```rust +/// # use wireframe_testing::{run_app_with_frame, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let out = run_app_with_frame(app, vec![1]).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn run_app_with_frame( app: WireframeApp, frame: Vec, @@ -215,6 +337,16 @@ where /// # Panics /// /// Panics if the spawned task running the application panics. +/// +/// ```rust +/// # use wireframe_testing::{run_app_with_frame_with_capacity, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let out = run_app_with_frame_with_capacity(app, vec![1], 128).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn run_app_with_frame_with_capacity( app: WireframeApp, frame: Vec, @@ -234,6 +366,16 @@ where /// /// Returns any I/O errors encountered while interacting with the in-memory /// duplex stream. +/// +/// ```rust +/// # use wireframe_testing::{run_app_with_frames, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let out = run_app_with_frames(app, vec![vec![1], vec![2]]).await?; +/// # Ok(()) +/// # } +/// ``` #[allow(dead_code)] pub async fn run_app_with_frames( app: WireframeApp, @@ -256,6 +398,16 @@ where /// # Panics /// /// Panics if the spawned task running the application panics. +/// +/// ```rust +/// # use wireframe_testing::{run_app_with_frames_with_capacity, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() -> tokio::io::Result<()> { +/// let app = WireframeApp::new().frame_processor(processor()).unwrap(); +/// let out = run_app_with_frames_with_capacity(app, vec![vec![1], vec![2]], 64).await?; +/// # Ok(()) +/// # } +/// ``` pub async fn run_app_with_frames_with_capacity( app: WireframeApp, frames: Vec>, @@ -291,6 +443,17 @@ where /// # Panics /// /// Panics if `handle_connection` fails. +/// +/// ```rust +/// # use wireframe_testing::{run_with_duplex_server, processor}; +/// # use wireframe::app::WireframeApp; +/// # async fn demo() { +/// let app = WireframeApp::new() +/// .frame_processor(processor()) +/// .unwrap(); +/// run_with_duplex_server(app).await; +/// } +/// ``` pub async fn run_with_duplex_server(app: WireframeApp) where S: TestSerializer,