mod utils;
use eventsourcingdb::{EventCandidate, Precondition, TraceInfo};
use serde_json::json;
use utils::{
assert_event_match_eventcandidate, assert_events_match_eventcandidates,
create_numbered_eventcandidates, create_test_container, create_test_eventcandidate,
};
#[tokio::test]
async fn write_single_event() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event = create_test_eventcandidate("/test", json!({"value": 1}));
let result = client.write_events(vec![event.clone()], vec![]).await;
assert!(result.is_ok(), "Failed to write events: {result:?}");
let mut response = result.unwrap();
assert_eq!(response.len(), 1, "Expected one event in the response");
let response_event = response.pop().unwrap();
assert_event_match_eventcandidate(&response_event, &event, None, None);
}
#[tokio::test]
async fn write_multiple_events() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidates = create_numbered_eventcandidates(10);
let result = client.write_events(event_candidates.clone(), vec![]).await;
assert!(result.is_ok(), "Failed to write events: {result:?}");
let response = result.unwrap();
assert_events_match_eventcandidates(&response, &event_candidates);
}
#[tokio::test]
async fn write_event_with_is_pristine_condition_on_empty_subject() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidate = create_test_eventcandidate("/test/42", json!({"value": 1}));
let result = client
.write_events(
vec![event_candidate.clone()],
vec![Precondition::IsSubjectPristine {
subject: event_candidate.subject.clone(),
}],
)
.await;
assert!(result.is_ok(), "Failed to write events: {result:?}");
let mut response = result.unwrap();
assert_eq!(response.len(), 1, "Expected one event in the response");
let response_event = response.pop().unwrap();
assert_event_match_eventcandidate(&response_event, &event_candidate, None, None);
}
#[tokio::test]
async fn write_event_with_is_pristine_condition_on_non_empty_subject() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidate = create_test_eventcandidate("/test", json!({"value": 1}));
client
.write_events(vec![event_candidate.clone()], vec![])
.await
.expect("Failed to write initial event");
let result = client
.write_events(
vec![event_candidate.clone()],
vec![Precondition::IsSubjectPristine {
subject: event_candidate.subject.clone(),
}],
)
.await;
assert!(result.is_err(), "Expected an error, but got: {result:?}");
}
#[tokio::test]
async fn write_event_with_is_subject_populated_condition_on_empty_subject() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidate = create_test_eventcandidate("/test/42", json!({"value": 1}));
let result = client
.write_events(
vec![event_candidate.clone()],
vec![Precondition::IsSubjectPopulated {
subject: event_candidate.subject.clone(),
}],
)
.await;
assert!(result.is_err(), "Expected an error, but got: {result:?}");
}
#[tokio::test]
async fn write_event_with_is_subject_populated_condition_on_non_empty_subject() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let first_event = create_test_eventcandidate("/test", json!({"value": 1}));
let mut initial_response = client
.write_events(vec![first_event.clone()], vec![])
.await
.expect("Failed to write initial event");
let initial_event = initial_response
.pop()
.expect("Expected an event in the response for the initial write");
let expected_event_id = initial_event
.id()
.parse::<usize>()
.expect("Expected the event ID to be numeric")
+ 1;
let predecessor_hash = initial_event.hash().to_string();
let second_event = create_test_eventcandidate("/test", json!({"value": 2}));
let result = client
.write_events(
vec![second_event.clone()],
vec![Precondition::IsSubjectPopulated {
subject: second_event.subject.clone(),
}],
)
.await;
assert!(result.is_ok(), "Writing the event failed: {result:?}");
let mut response = result.unwrap();
let response_event = response.pop().expect("Expected an event in the response");
assert_event_match_eventcandidate(
&response_event,
&second_event,
Some(&predecessor_hash),
Some(expected_event_id),
);
}
#[tokio::test]
async fn write_events_with_is_pristine_condition_on_empty_subject() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidates = vec![
create_test_eventcandidate("/test/42", json!({"value": 1})),
create_test_eventcandidate("/test/42", json!({"value": 1})),
];
let result = client
.write_events(
event_candidates.clone(),
vec![Precondition::IsSubjectPristine {
subject: event_candidates[1].subject.clone(),
}],
)
.await;
assert!(result.is_ok(), "Failed to write events: {result:?}");
let response = result.unwrap();
assert_events_match_eventcandidates(&response, &event_candidates);
}
#[tokio::test]
async fn write_events_with_is_pristine_condition_on_non_empty_subject() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let fill_event_candidate = create_test_eventcandidate("/test", json!({"value": 1}));
client
.write_events(vec![fill_event_candidate.clone()], vec![])
.await
.expect("Failed to write initial event");
let event_candidates = vec![
create_test_eventcandidate("/test2", json!({"value": 1})),
fill_event_candidate.clone(),
];
let result = client
.write_events(
event_candidates,
vec![Precondition::IsSubjectPristine {
subject: fill_event_candidate.subject.clone(),
}],
)
.await;
assert!(result.is_err(), "Expected an error, but got: {result:?}");
}
#[tokio::test]
async fn write_event_with_is_subject_on_event_id_condition_on_empty_subject() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidate = create_test_eventcandidate("/test/42", json!({"value": 1}));
let result = client
.write_events(
vec![event_candidate.clone()],
vec![Precondition::IsSubjectOnEventId {
subject: event_candidate.subject.clone(),
event_id: "100".to_string(),
}],
)
.await;
assert!(result.is_err(), "Expected an error, but got: {result:?}");
}
#[tokio::test]
async fn write_event_with_is_subject_on_event_id_condition_on_non_empty_subject_correct_id() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidate = create_test_eventcandidate("/test", json!({"value": 1}));
let written = client
.write_events(vec![event_candidate.clone()], vec![])
.await
.expect("Failed to write initial event")
.pop()
.unwrap();
let result = client
.write_events(
vec![event_candidate.clone()],
vec![Precondition::IsSubjectOnEventId {
subject: event_candidate.subject.clone(),
event_id: written.id().to_string(),
}],
)
.await;
assert!(result.is_ok(), "Writing the event failed: {result:?}");
}
#[tokio::test]
async fn write_event_with_is_subject_on_event_id_condition_on_non_empty_subject_wrong_id() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidate = create_test_eventcandidate("/test", json!({"value": 1}));
client
.write_events(vec![event_candidate.clone()], vec![])
.await
.expect("Failed to write initial event")
.pop()
.unwrap();
let result = client
.write_events(
vec![event_candidate.clone()],
vec![Precondition::IsSubjectOnEventId {
subject: event_candidate.subject.clone(),
event_id: 100.to_string(),
}],
)
.await;
assert!(result.is_err(), "Expected an error, but got: {result:?}");
}
#[tokio::test]
async fn write_events_with_is_subject_on_event_id_condition_on_empty_subject() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidates = vec![
create_test_eventcandidate("/test/42", json!({"value": 1})),
create_test_eventcandidate("/test/42", json!({"value": 1})),
];
let result = client
.write_events(
event_candidates.clone(),
vec![Precondition::IsSubjectOnEventId {
subject: event_candidates[1].subject.clone(),
event_id: "100".to_string(),
}],
)
.await;
assert!(result.is_err(), "Expected an error, but got: {result:?}");
}
#[tokio::test]
async fn write_events_with_is_eventql_true_condition() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event_candidates = vec![
create_test_eventcandidate("/test/42", json!({"value": 1})),
create_test_eventcandidate("/test/42", json!({"value": 1})),
];
let result = client
.write_events(
event_candidates.clone(),
vec![Precondition::IsEventQLQueryTrue {
query: "FROM e IN events PROJECT INTO COUNT() == 0".to_string(),
}],
)
.await;
assert!(result.is_ok(), "Expected an ok, but got: {result:?}");
}
#[tokio::test]
async fn write_events_with_is_subject_on_event_id_condition_on_non_empty_subject_correct_id() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let fill_event_candidate = create_test_eventcandidate("/test", json!({"value": 1}));
let written = client
.write_events(vec![fill_event_candidate.clone()], vec![])
.await
.expect("Failed to write initial event")
.pop()
.unwrap();
let event_candidates = vec![
create_test_eventcandidate("/test2", json!({"value": 1})),
fill_event_candidate.clone(),
];
let result = client
.write_events(
event_candidates,
vec![Precondition::IsSubjectOnEventId {
subject: fill_event_candidate.subject.clone(),
event_id: written.id().to_string(),
}],
)
.await;
assert!(result.is_ok(), "Writing the events failed: {result:?}");
}
#[tokio::test]
async fn write_events_with_is_subject_on_event_id_condition_on_non_empty_subject_wrong_id() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let fill_event_candidate = create_test_eventcandidate("/test", json!({"value": 1}));
client
.write_events(vec![fill_event_candidate.clone()], vec![])
.await
.expect("Failed to write initial event")
.pop()
.unwrap();
let event_candidates = vec![
create_test_eventcandidate("/test2", json!({"value": 1})),
fill_event_candidate.clone(),
];
let result = client
.write_events(
event_candidates,
vec![Precondition::IsSubjectOnEventId {
subject: fill_event_candidate.subject.clone(),
event_id: 100.to_string(),
}],
)
.await;
assert!(result.is_err(), "Expected an error, but got: {result:?}");
}
#[tokio::test]
async fn write_single_event_with_traceparent() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event = EventCandidate::builder()
.source("https://www.eventsourcingdb.io".to_string())
.data(json!({"value": 1}))
.subject("/test".to_string())
.ty("io.eventsourcingdb.test".to_string())
.traceinfo(TraceInfo::Traceparent {
traceparent: "00-01234567012345670123456701234567-0123456701234567-00".to_string(),
})
.build();
let result = client.write_events(vec![event.clone()], vec![]).await;
assert!(result.is_ok(), "Failed to write events: {result:?}");
let mut response = result.unwrap();
assert_eq!(response.len(), 1, "Expected one event in the response");
let response_event = response.pop().unwrap();
assert_event_match_eventcandidate(&response_event, &event, None, None);
}
#[tokio::test]
async fn write_single_event_with_traceparent_and_state() {
let container = create_test_container().await;
let client = container.get_client().await.unwrap();
let event = EventCandidate::builder()
.source("https://www.eventsourcingdb.io".to_string())
.data(json!({"value": 1}))
.subject("/test".to_string())
.ty("io.eventsourcingdb.test".to_string())
.traceinfo(TraceInfo::WithState {
traceparent: "00-01234567012345670123456701234567-0123456701234567-00".to_string(),
tracestate: "state=12345".to_string(),
})
.build();
let result = client.write_events(vec![event.clone()], vec![]).await;
assert!(result.is_ok(), "Failed to write events: {result:?}");
let mut response = result.unwrap();
assert_eq!(response.len(), 1, "Expected one event in the response");
let response_event = response.pop().unwrap();
println!("Response event: {response_event:?}");
assert_event_match_eventcandidate(&response_event, &event, None, None);
}