use mnesis::*;
use std::fmt;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
struct AId([u8; 8]);
impl AId {
fn new(id: u64) -> Self {
Self(id.to_be_bytes())
}
}
impl fmt::Display for AId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", u64::from_be_bytes(self.0))
}
}
impl AsRef<[u8]> for AId {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
#[derive(Debug, thiserror::Error)]
#[error("e")]
struct AError;
#[derive(Debug, Clone, DomainEvent)]
enum SingleEvent {
Only,
}
#[derive(Default, Debug, Clone)]
struct SingleState {
triggered: bool,
}
impl AggregateState for SingleState {
type Event = SingleEvent;
fn initial() -> Self {
Self::default()
}
fn apply(mut self, event: &SingleEvent) -> Self {
match event {
SingleEvent::Only => self.triggered = true,
}
self
}
}
#[mnesis::aggregate(state = SingleState, error = AError, id = AId)]
struct SingleAggregate;
#[test]
fn single_variant_event_enum() {
let mut agg = AggregateRoot::<SingleAggregate>::new(AId::new(1));
agg.replay(Version::INITIAL, &SingleEvent::Only).unwrap();
assert!(agg.state().triggered);
}
#[derive(Debug, Clone, DomainEvent)]
#[allow(
dead_code,
reason = "test-only event type — variants exist to stress-test macro variant arm generation"
)]
enum ManyEvent {
V1,
V2(u8),
V3(String),
V4 { x: i32 },
V5 { a: String, b: u64 },
V6,
V7(Vec<u8>),
V8,
V9,
V10,
}
#[test]
fn many_variant_event_names() {
assert_eq!(ManyEvent::V1.name(), "V1");
assert_eq!(ManyEvent::V2(0).name(), "V2");
assert_eq!(ManyEvent::V3(String::new()).name(), "V3");
assert_eq!(ManyEvent::V4 { x: 0 }.name(), "V4");
assert_eq!(
ManyEvent::V5 {
a: String::new(),
b: 0
}
.name(),
"V5"
);
assert_eq!(ManyEvent::V10.name(), "V10");
}
#[derive(Debug, Clone, DomainEvent)]
enum VeryLongEventNameThatShouldStillWorkCorrectlyWithTheMacro {
SomethingHappenedWithAnExtremelyDescriptiveNameThatGoesOnAndOn(String),
}
#[derive(Default, Debug, Clone)]
struct VeryLongStateNameThatShouldStillWorkCorrectlyWithTheMacro {
data: String,
}
impl AggregateState for VeryLongStateNameThatShouldStillWorkCorrectlyWithTheMacro {
type Event = VeryLongEventNameThatShouldStillWorkCorrectlyWithTheMacro;
fn initial() -> Self {
Self::default()
}
fn apply(mut self, event: &VeryLongEventNameThatShouldStillWorkCorrectlyWithTheMacro) -> Self {
match event {
VeryLongEventNameThatShouldStillWorkCorrectlyWithTheMacro::SomethingHappenedWithAnExtremelyDescriptiveNameThatGoesOnAndOn(s) => {
self.data = s.clone();
}
}
self
}
}
#[mnesis::aggregate(
state = VeryLongStateNameThatShouldStillWorkCorrectlyWithTheMacro,
error = AError,
id = AId
)]
struct VeryLongAggregateNameThatShouldStillWorkCorrectlyWithTheMacro;
#[test]
fn very_long_type_names() {
let mut agg =
AggregateRoot::<VeryLongAggregateNameThatShouldStillWorkCorrectlyWithTheMacro>::new(
AId::new(1),
);
agg.replay(
Version::INITIAL,
&VeryLongEventNameThatShouldStillWorkCorrectlyWithTheMacro::SomethingHappenedWithAnExtremelyDescriptiveNameThatGoesOnAndOn(
"hello".into(),
),
)
.unwrap();
assert_eq!(agg.state().data, "hello");
}
mod inner {
use super::*;
#[derive(Debug, Clone, DomainEvent)]
pub enum InnerEvent {
Ping,
}
#[derive(Default, Debug, Clone)]
pub struct InnerState {
pub pings: u32,
}
impl AggregateState for InnerState {
type Event = InnerEvent;
fn initial() -> Self {
Self::default()
}
fn apply(mut self, _: &InnerEvent) -> Self {
self.pings += 1;
self
}
}
#[derive(Debug, thiserror::Error)]
#[error("inner error")]
pub struct InnerError;
}
#[mnesis::aggregate(state = inner::InnerState, error = inner::InnerError, id = AId)]
struct PathTypeAggregate;
#[test]
fn aggregate_with_path_types() {
let mut agg = AggregateRoot::<PathTypeAggregate>::new(AId::new(1));
agg.replay(Version::INITIAL, &inner::InnerEvent::Ping)
.unwrap();
agg.replay(Version::new(2).unwrap(), &inner::InnerEvent::Ping)
.unwrap();
assert_eq!(agg.state().pings, 2);
}
#[derive(Debug, Clone, DomainEvent)]
#[allow(
dead_code,
reason = "test-only event type — fields exist to test mixed variant shape generation"
)]
enum MixedShapeEvent {
Unit,
Tuple(String, u64),
Struct { name: String, value: i32 },
NestedTuple(Vec<String>),
}
#[test]
fn mixed_shape_event_names() {
assert_eq!(MixedShapeEvent::Unit.name(), "Unit");
assert_eq!(MixedShapeEvent::Tuple("a".into(), 1).name(), "Tuple");
assert_eq!(
MixedShapeEvent::Struct {
name: "b".into(),
value: 2,
}
.name(),
"Struct"
);
assert_eq!(
MixedShapeEvent::NestedTuple(vec!["c".into()]).name(),
"NestedTuple"
);
}
#[mnesis::aggregate(state = SingleState, error = AError, id = AId)]
struct r#Type;
#[test]
fn raw_identifier_aggregate_name() {
let agg = AggregateRoot::<r#Type>::new(AId::new(1));
assert_eq!(agg.version(), None);
}