use std::sync::Arc;
use futures::future::BoxFuture;
use rstest::fixture;
use wireframe::{
app::{Envelope, WireframeApp},
codec::examples::{HotlineFrame, HotlineFrameCodec},
serializer::{BincodeSerializer, Serializer},
};
pub use wireframe_testing::TestResult;
#[derive(Default)]
pub struct CodecTestHarnessWorld {
codec: Option<HotlineFrameCodec>,
app: Option<WireframeApp<BincodeSerializer, (), Envelope, HotlineFrameCodec>>,
response_payloads: Vec<Vec<u8>>,
response_frames: Vec<HotlineFrame>,
}
impl std::fmt::Debug for CodecTestHarnessWorld {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CodecTestHarnessWorld")
.field("codec", &self.codec)
.field("app", &self.app.as_ref().map(|_| ".."))
.field("response_payloads", &self.response_payloads.len())
.field("response_frames", &self.response_frames.len())
.finish()
}
}
#[rustfmt::skip]
#[fixture]
pub fn codec_test_harness_world() -> CodecTestHarnessWorld {
CodecTestHarnessWorld::default()
}
impl CodecTestHarnessWorld {
pub fn configure_app(&mut self, max_frame_length: usize) -> TestResult {
let codec = HotlineFrameCodec::new(max_frame_length);
let app = WireframeApp::<BincodeSerializer, (), Envelope>::new()?
.with_codec(codec.clone())
.route(
1,
Arc::new(|_: &Envelope| -> BoxFuture<'static, ()> { Box::pin(async {}) }),
)?;
self.codec = Some(codec);
self.app = Some(app);
Ok(())
}
pub async fn drive_payload(&mut self) -> TestResult {
let app = self.app.take().ok_or("app not configured")?;
let codec = self.codec.as_ref().ok_or("codec not configured")?;
let env = Envelope::new(1, Some(7), b"bdd-test".to_vec());
let serialized = BincodeSerializer.serialize(&env)?;
self.response_payloads =
wireframe_testing::drive_with_codec_payloads(app, codec, vec![serialized]).await?;
Ok(())
}
pub async fn drive_frames(&mut self) -> TestResult {
let app = self.app.take().ok_or("app not configured")?;
let codec = self.codec.as_ref().ok_or("codec not configured")?;
let env = Envelope::new(1, Some(7), b"bdd-frame-test".to_vec());
let serialized = BincodeSerializer.serialize(&env)?;
self.response_frames =
wireframe_testing::drive_with_codec_frames(app, codec, vec![serialized]).await?;
Ok(())
}
pub fn verify_payloads_non_empty(&self) -> TestResult {
if self.response_payloads.is_empty() {
return Err("expected non-empty response payloads".into());
}
Ok(())
}
pub fn verify_frames_have_transaction_ids(&self) -> TestResult {
if self.response_frames.is_empty() {
return Err("expected at least one response frame".into());
}
for frame in &self.response_frames {
if frame.transaction_id != 0 {
return Err(
format!("expected transaction_id 0, got {}", frame.transaction_id).into(),
);
}
}
Ok(())
}
}