use nautilus_core::{UUID4, UnixNanos};
use crate::{
events::OrderPendingUpdate,
identifiers::{AccountId, ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId},
stubs::{TestDefault, test_uuid},
};
#[derive(Debug, Clone, bon::Builder)]
#[builder(finish_fn = into_spec)]
pub struct OrderPendingUpdateSpec {
#[builder(default = TraderId::test_default())]
pub trader_id: TraderId,
#[builder(default = StrategyId::test_default())]
pub strategy_id: StrategyId,
#[builder(default = InstrumentId::test_default())]
pub instrument_id: InstrumentId,
#[builder(default = ClientOrderId::test_default())]
pub client_order_id: ClientOrderId,
#[builder(default = AccountId::test_default())]
pub account_id: AccountId,
#[builder(default = test_uuid())]
pub event_id: UUID4,
#[builder(default = UnixNanos::default())]
pub ts_event: UnixNanos,
#[builder(default = UnixNanos::default())]
pub ts_init: UnixNanos,
#[builder(default = false)]
pub reconciliation: bool,
pub venue_order_id: Option<VenueOrderId>,
}
impl<S: order_pending_update_spec_builder::IsComplete> OrderPendingUpdateSpecBuilder<S> {
#[must_use]
pub fn build(self) -> OrderPendingUpdate {
let spec = self.into_spec();
OrderPendingUpdate::new(
spec.trader_id,
spec.strategy_id,
spec.instrument_id,
spec.client_order_id,
spec.account_id,
spec.event_id,
spec.ts_event,
spec.ts_init,
spec.reconciliation,
spec.venue_order_id,
)
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
use crate::stubs::reset_test_uuid_rng;
#[rstest]
fn defaults_are_sensible() {
let event = OrderPendingUpdateSpec::builder().build();
assert_eq!(event.trader_id, TraderId::test_default());
assert_eq!(event.strategy_id, StrategyId::test_default());
assert_eq!(event.instrument_id, InstrumentId::test_default());
assert_eq!(event.client_order_id, ClientOrderId::test_default());
assert_eq!(event.account_id, AccountId::test_default());
assert_eq!(event.ts_event, UnixNanos::default());
assert_eq!(event.ts_init, UnixNanos::default());
assert_eq!(event.reconciliation, 0);
assert_eq!(event.venue_order_id, None);
}
#[rstest]
fn overrides_apply_through_constructor() {
let event = OrderPendingUpdateSpec::builder()
.venue_order_id(VenueOrderId::from("V-1"))
.reconciliation(true)
.build();
assert_eq!(event.venue_order_id, Some(VenueOrderId::from("V-1")));
assert_eq!(event.reconciliation, 1);
assert_eq!(event.trader_id, TraderId::test_default());
}
#[rstest]
fn event_ids_are_unique_within_a_run() {
reset_test_uuid_rng();
let a = OrderPendingUpdateSpec::builder().build();
let b = OrderPendingUpdateSpec::builder().build();
let c = OrderPendingUpdateSpec::builder().build();
assert_ne!(a.event_id, b.event_id);
assert_ne!(b.event_id, c.event_id);
assert_ne!(a.event_id, c.event_id);
}
#[rstest]
fn event_id_sequence_is_reproducible() {
reset_test_uuid_rng();
let first_run: Vec<_> = (0..3)
.map(|_| OrderPendingUpdateSpec::builder().build().event_id)
.collect();
reset_test_uuid_rng();
let second_run: Vec<_> = (0..3)
.map(|_| OrderPendingUpdateSpec::builder().build().event_id)
.collect();
assert_eq!(first_run, second_run);
}
}