#![cfg(all(
feature = "memory",
feature = "macros",
feature = "json",
feature = "testing"
))]
use std::num::ParseIntError;
use ruststream::memory::MemoryBroker;
use ruststream::prelude::*;
use ruststream::testing::TestApp;
use serde::{Deserialize, Serialize};
#[derive(Outgoing, Serialize, Deserialize)]
struct Ticket {
label: String,
}
#[subscriber("returns.plain")]
async fn settle_plain(ticket: &Ticket) -> HandlerOutcome {
let _ = &ticket.label;
HandlerOutcome::ack()
}
#[subscriber("returns.unit")]
async fn settle_unit(ticket: &Ticket) {
let _ = &ticket.label;
}
#[subscriber("returns.ok")]
async fn settle_ok(ticket: &Ticket) -> Result<(), HandlerOutcome> {
let _ = &ticket.label;
Ok(())
}
#[subscriber("returns.batch")]
async fn settle_batch(tickets: &[Ticket]) -> Result<(), HandlerOutcome> {
let _ = tickets.len();
Ok(())
}
#[subscriber("returns.parsed")]
async fn settle_parsed(ticket: &Ticket) -> Result<(), ParseIntError> {
let _: u32 = ticket.label.parse()?;
Ok(())
}
#[subscriber("returns.outcome")]
async fn settle_outcome(ticket: &Ticket) -> Result<HandlerOutcome, ParseIntError> {
let count: u32 = ticket.label.parse()?;
if count == 0 {
return Ok(HandlerOutcome::drop());
}
Ok(HandlerOutcome::ack())
}
fn ticket(label: &str) -> Ticket {
Ticket {
label: label.to_owned(),
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn every_settling_return_form_acks_a_finished_body() {
let app =
RustStream::new(AppInfo::new("returns", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include(settle_plain);
b.include(settle_unit);
b.include(settle_ok);
});
let tb = TestApp::start(app).await.expect("harness start");
for name in ["returns.plain", "returns.unit", "returns.ok"] {
tb.message(&ticket("7"))
.to(name)
.publish()
.await
.expect("inject");
tb.broker::<MemoryBroker>()
.subscriber(name)
.assert_called_once()
.settled(HandlerOutcome::ack());
}
tb.shutdown().await.expect("graceful shutdown");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn a_batch_body_settles_its_whole_batch() {
let app =
RustStream::new(AppInfo::new("returns", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include(settle_batch.batch(nonzero!(8)));
});
let tb = TestApp::start(app).await.expect("harness start");
for label in ["1", "2"] {
tb.message(&ticket(label))
.to("returns.batch")
.publish()
.await
.expect("inject");
}
tb.broker::<MemoryBroker>()
.subscriber("returns.batch")
.settled(HandlerOutcome::ack());
let seen = tb
.broker::<MemoryBroker>()
.subscriber("returns.batch")
.received_raw();
assert_eq!(seen.len(), 2, "both elements are recorded, batch or not");
tb.shutdown().await.expect("graceful shutdown");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn a_result_returning_body_settles_by_the_arm_it_takes() {
let app =
RustStream::new(AppInfo::new("returns", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include(settle_parsed);
b.include(settle_outcome);
});
let tb = TestApp::start(app).await.expect("harness start");
tb.message(&ticket("not a number"))
.to("returns.parsed")
.publish()
.await
.expect("inject");
tb.broker::<MemoryBroker>()
.subscriber("returns.parsed")
.assert_called_once()
.settled(HandlerOutcome::drop());
tb.message(&ticket("3"))
.to("returns.outcome")
.publish()
.await
.expect("inject");
tb.broker::<MemoryBroker>()
.subscriber("returns.outcome")
.assert_called_once()
.settled(HandlerOutcome::ack());
tb.message(&ticket("0"))
.to("returns.outcome")
.publish()
.await
.expect("inject");
tb.broker::<MemoryBroker>()
.subscriber("returns.outcome")
.assert_called(2)
.settled(HandlerOutcome::drop());
tb.shutdown().await.expect("graceful shutdown");
}