use std::time::Duration;
use crate::bus::session::BusConfig;
use crate::bus::{
BusCloseReport, BusHandle, BusOwner, ExecutionId, RobotInstant, SourceLabel, StepToken,
};
use crate::identity::{ParticipantId, ParticipantIdError, TimelineId};
#[doc(hidden)]
#[derive(Clone, Debug)]
pub struct TestHarness {
pub(crate) participant_id: ParticipantId,
pub(crate) timeline: TimelineId,
pub(crate) config: Option<serde_json::Value>,
pub(crate) shutdown_grace: Duration,
pub(crate) query_reply_delay: Option<Duration>,
}
impl TestHarness {
pub fn new(participant_id: impl Into<String>) -> std::result::Result<Self, ParticipantIdError> {
Ok(Self {
participant_id: ParticipantId::new(participant_id)?,
timeline: TimelineId::mint(),
config: None,
shutdown_grace: crate::participant::launch::SHUTDOWN_GRACE,
query_reply_delay: None,
})
}
#[must_use]
pub fn with_timeline(mut self, timeline: TimelineId) -> Self {
self.timeline = timeline;
self
}
#[must_use]
pub fn with_config(mut self, config: serde_json::Value) -> Self {
self.config = Some(config);
self
}
#[doc(hidden)]
#[must_use]
pub fn with_query_reply_delay(mut self, delay: Duration) -> Self {
self.query_reply_delay = Some(delay);
self
}
}
pub struct TestBus {
owner: Option<BusOwner>,
handle: BusHandle,
execution: ExecutionId,
}
impl TestBus {
pub async fn for_participant(participant: &str) -> crate::Result<Self> {
let execution = ExecutionId::mint();
Self::open(
BusConfig::for_participant(execution, ParticipantId::new(participant)?, Vec::new()),
execution,
)
.await
}
pub async fn external(label: &str) -> crate::Result<Self> {
let execution = ExecutionId::mint();
Self::open(
BusConfig::for_external(execution, Some(SourceLabel::new(label)?), Vec::new()),
execution,
)
.await
}
async fn open(config: BusConfig, execution: ExecutionId) -> crate::Result<Self> {
let (owner, handle) = BusOwner::open(config).await?;
Ok(Self {
owner: Some(owner),
handle,
execution,
})
}
#[must_use]
pub fn handle(&self) -> &BusHandle {
&self.handle
}
#[must_use]
pub fn execution(&self) -> ExecutionId {
self.execution
}
pub async fn close(mut self) -> BusCloseReport {
match self.owner.take() {
Some(owner) => owner.close().await,
None => BusCloseReport::default(),
}
}
}
impl std::fmt::Debug for TestBus {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("TestBus")
.field("execution", &self.execution)
.finish_non_exhaustive()
}
}
#[must_use]
pub fn step_token(at: RobotInstant) -> StepToken {
StepToken::mint(at)
}