use crate::MessageStore;
#[async_trait::async_trait]
pub trait TestStoreFactory: Send + Sync {
async fn create_store(&self) -> Box<dyn MessageStore>;
fn is_persistent(&self) -> bool {
true
}
}
pub async fn test_new_store_initialization(factory: &dyn TestStoreFactory) {
let store = factory.create_store().await;
assert_eq!(store.next_sender_seq_number(), 1);
assert_eq!(store.next_target_seq_number(), 1);
}
pub async fn test_add_and_get_messages(factory: &dyn TestStoreFactory) {
let mut store = factory.create_store().await;
let message1 = b"test message 1";
let message2 = b"test message 2";
let message3 = b"test message 3";
store
.add(1, message1)
.await
.expect("Failed to add message 1");
store
.add(2, message2)
.await
.expect("Failed to add message 2");
store
.add(3, message3)
.await
.expect("Failed to add message 3");
let messages = store.get_slice(1, 3).await.expect("Failed to get messages");
assert_eq!(messages.len(), 3);
assert_eq!(messages[0], message1);
assert_eq!(messages[1], message2);
assert_eq!(messages[2], message3);
}
pub async fn test_get_slice_partial_range(factory: &dyn TestStoreFactory) {
let mut store = factory.create_store().await;
let message1 = b"message 1";
let message2 = b"message 2";
let message3 = b"message 3";
let message4 = b"message 4";
store
.add(1, message1)
.await
.expect("Failed to add message 1");
store
.add(2, message2)
.await
.expect("Failed to add message 2");
store
.add(3, message3)
.await
.expect("Failed to add message 3");
store
.add(4, message4)
.await
.expect("Failed to add message 4");
let messages = store.get_slice(2, 3).await.expect("Failed to get messages");
assert_eq!(messages.len(), 2);
assert_eq!(messages[0], message2);
assert_eq!(messages[1], message3);
}
pub async fn test_get_slice_empty_range(factory: &dyn TestStoreFactory) {
let store = factory.create_store().await;
let messages = store.get_slice(1, 3).await.expect("Failed to get messages");
assert_eq!(messages.len(), 0);
}
pub async fn test_increment_sender_seq_number(factory: &dyn TestStoreFactory) {
let mut store = factory.create_store().await;
assert_eq!(store.next_sender_seq_number(), 1);
store
.increment_sender_seq_number()
.await
.expect("Failed to increment sender seq number");
assert_eq!(store.next_sender_seq_number(), 2);
store
.increment_sender_seq_number()
.await
.expect("Failed to increment sender seq number");
assert_eq!(store.next_sender_seq_number(), 3);
}
pub async fn test_increment_target_seq_number(factory: &dyn TestStoreFactory) {
let mut store = factory.create_store().await;
assert_eq!(store.next_target_seq_number(), 1);
store
.increment_target_seq_number()
.await
.expect("Failed to increment target seq number");
assert_eq!(store.next_target_seq_number(), 2);
store
.increment_target_seq_number()
.await
.expect("Failed to increment target seq number");
assert_eq!(store.next_target_seq_number(), 3);
}
pub async fn test_set_target_seq_number(factory: &dyn TestStoreFactory) {
let mut store = factory.create_store().await;
assert_eq!(store.next_target_seq_number(), 1);
store
.set_target_seq_number(10)
.await
.expect("Failed to set target seq number");
assert_eq!(store.next_target_seq_number(), 11);
store
.set_target_seq_number(5)
.await
.expect("Failed to set target seq number");
assert_eq!(store.next_target_seq_number(), 6);
}
pub async fn test_reset_store(factory: &dyn TestStoreFactory) {
let mut store = factory.create_store().await;
store
.add(1, b"message 1")
.await
.expect("Failed to add message");
store
.add(2, b"message 2")
.await
.expect("Failed to add message");
store
.increment_sender_seq_number()
.await
.expect("Failed to increment sender seq number");
store
.increment_target_seq_number()
.await
.expect("Failed to increment target seq number");
assert_eq!(store.next_sender_seq_number(), 2);
assert_eq!(store.next_target_seq_number(), 2);
let messages_before_reset = store.get_slice(1, 2).await.expect("Failed to get messages");
assert_eq!(messages_before_reset.len(), 2);
store.reset().await.expect("Failed to reset store");
assert_eq!(store.next_sender_seq_number(), 1);
assert_eq!(store.next_target_seq_number(), 1);
let messages_after_reset = store.get_slice(1, 2).await.expect("Failed to get messages");
assert_eq!(messages_after_reset.len(), 0);
}
pub async fn test_persistence_across_store_instances(factory: &dyn TestStoreFactory) {
if !factory.is_persistent() {
return;
}
{
let mut store1 = factory.create_store().await;
store1
.add(1, b"persistent message")
.await
.expect("Failed to add message");
store1
.increment_sender_seq_number()
.await
.expect("Failed to increment sender seq number");
store1
.set_target_seq_number(5)
.await
.expect("Failed to set target seq number");
}
{
let store2 = factory.create_store().await;
assert_eq!(store2.next_sender_seq_number(), 2);
assert_eq!(store2.next_target_seq_number(), 6);
let messages = store2
.get_slice(1, 1)
.await
.expect("Failed to get messages");
assert_eq!(messages.len(), 1);
assert_eq!(messages[0], b"persistent message");
}
}
pub async fn test_get_slice_beyond_available_messages(factory: &dyn TestStoreFactory) {
let mut store = factory.create_store().await;
store
.add(1, b"only message")
.await
.expect("Failed to add message");
let messages = store
.get_slice(1, 10)
.await
.expect("Failed to get messages");
assert_eq!(messages.len(), 1);
assert_eq!(messages[0], b"only message");
}
pub async fn test_overwrite_existing_message(factory: &dyn TestStoreFactory) {
let mut store = factory.create_store().await;
store
.add(1, b"original message")
.await
.expect("Failed to add original message");
store
.add(1, b"updated message")
.await
.expect("Failed to add updated message");
let messages = store.get_slice(1, 1).await.expect("Failed to get messages");
assert_eq!(messages.len(), 1);
assert_eq!(messages[0], b"updated message");
}
pub async fn test_creation_time_is_set(factory: &dyn TestStoreFactory) {
use chrono::Utc;
let before = Utc::now();
let store = factory.create_store().await;
let after = Utc::now();
assert!(before <= store.creation_time());
assert!(store.creation_time() <= after);
}
pub async fn test_creation_time_is_preserved(factory: &dyn TestStoreFactory) {
if !factory.is_persistent() {
return;
}
let store = factory.create_store().await;
let creation_time1 = store.creation_time();
drop(store);
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
let store = factory.create_store().await;
let creation_time2 = store.creation_time();
assert_eq!(creation_time1, creation_time2);
}
pub async fn test_creation_time_gets_reset_correctly(factory: &dyn TestStoreFactory) {
use chrono::Utc;
let mut store = factory.create_store().await;
tokio::time::sleep(std::time::Duration::from_millis(2)).await;
let after_sleep = Utc::now();
tokio::time::sleep(std::time::Duration::from_millis(2)).await;
store.reset().await.expect("failed to reset store");
let reset_creation_time = store.creation_time();
assert!(reset_creation_time > after_sleep);
if !factory.is_persistent() {
return;
}
drop(store);
let store = factory.create_store().await;
assert_eq!(reset_creation_time, store.creation_time());
}
#[macro_export]
macro_rules! conformance_tests {
($mod_name:ident, $factory:expr) => {
mod $mod_name {
use super::*;
#[tokio::test]
async fn test_new_store_initialization() {
let factory = $factory;
$crate::test_utils::test_new_store_initialization(&factory).await;
}
#[tokio::test]
async fn test_add_and_get_messages() {
let factory = $factory;
$crate::test_utils::test_add_and_get_messages(&factory).await;
}
#[tokio::test]
async fn test_get_slice_partial_range() {
let factory = $factory;
$crate::test_utils::test_get_slice_partial_range(&factory).await;
}
#[tokio::test]
async fn test_get_slice_empty_range() {
let factory = $factory;
$crate::test_utils::test_get_slice_empty_range(&factory).await;
}
#[tokio::test]
async fn test_increment_sender_seq_number() {
let factory = $factory;
$crate::test_utils::test_increment_sender_seq_number(&factory).await;
}
#[tokio::test]
async fn test_increment_target_seq_number() {
let factory = $factory;
$crate::test_utils::test_increment_target_seq_number(&factory).await;
}
#[tokio::test]
async fn test_set_target_seq_number() {
let factory = $factory;
$crate::test_utils::test_set_target_seq_number(&factory).await;
}
#[tokio::test]
async fn test_reset_store() {
let factory = $factory;
$crate::test_utils::test_reset_store(&factory).await;
}
#[tokio::test]
async fn test_persistence_across_store_instances() {
let factory = $factory;
$crate::test_utils::test_persistence_across_store_instances(&factory).await;
}
#[tokio::test]
async fn test_get_slice_beyond_available_messages() {
let factory = $factory;
$crate::test_utils::test_get_slice_beyond_available_messages(&factory).await;
}
#[tokio::test]
async fn test_overwrite_existing_message() {
let factory = $factory;
$crate::test_utils::test_overwrite_existing_message(&factory).await;
}
#[tokio::test]
async fn test_creation_time_is_set() {
let factory = $factory;
$crate::test_utils::test_creation_time_is_set(&factory).await;
}
#[tokio::test]
async fn test_creation_time_is_preserved() {
let factory = $factory;
$crate::test_utils::test_creation_time_is_preserved(&factory).await;
}
#[tokio::test]
async fn test_creation_time_gets_reset_correctly() {
let factory = $factory;
$crate::test_utils::test_creation_time_gets_reset_correctly(&factory).await;
}
}
};
}