#![cfg(feature = "mongodb")]
use truefix_store::{MessageStore, MongoStore, MongoStoreConfig};
async fn exercise_full_contract(uri: &str, unique_suffix: &str) {
let config = MongoStoreConfig {
sessions_collection: format!("t_sessions_{unique_suffix}"),
messages_collection: format!("t_messages_{unique_suffix}"),
session_id: "s1".to_owned(),
..MongoStoreConfig::new(uri)
};
let store = MongoStore::connect_with_config(config).await.unwrap();
assert_eq!(store.next_sender_seq().await.unwrap(), 1);
assert_eq!(store.next_target_seq().await.unwrap(), 1);
store.set_next_sender_seq(11).await.unwrap();
store.set_next_target_seq(22).await.unwrap();
assert_eq!(store.next_sender_seq().await.unwrap(), 11);
assert_eq!(store.next_target_seq().await.unwrap(), 22);
store.save(1, b"first").await.unwrap();
store.save(2, b"second").await.unwrap();
store.save(2, b"second-updated").await.unwrap(); let range = store.get(1, 2).await.unwrap();
assert_eq!(
range,
vec![(1, b"first".to_vec()), (2, b"second-updated".to_vec())]
);
store.reset().await.unwrap();
assert_eq!(store.next_sender_seq().await.unwrap(), 1);
assert_eq!(store.next_target_seq().await.unwrap(), 1);
assert!(store.get(1, 2).await.unwrap().is_empty());
}
async fn exercise_session_isolation(uri: &str, unique_suffix: &str) {
let cfg = |session_id: &str| MongoStoreConfig {
sessions_collection: format!("iso_sessions_{unique_suffix}"),
messages_collection: format!("iso_messages_{unique_suffix}"),
session_id: session_id.to_owned(),
..MongoStoreConfig::new(uri)
};
let a = MongoStore::connect_with_config(cfg("A")).await.unwrap();
let b = MongoStore::connect_with_config(cfg("B")).await.unwrap();
a.set_next_sender_seq(100).await.unwrap();
a.save(1, b"a-only").await.unwrap();
assert_eq!(b.next_sender_seq().await.unwrap(), 1); assert!(b.get(1, 1).await.unwrap().is_empty());
assert_eq!(a.get(1, 1).await.unwrap(), vec![(1, b"a-only".to_vec())]);
}
async fn exercise_creation_time(uri: &str, unique_suffix: &str) {
let config = MongoStoreConfig {
sessions_collection: format!("ct_sessions_{unique_suffix}"),
messages_collection: format!("ct_messages_{unique_suffix}"),
session_id: "s1".to_owned(),
..MongoStoreConfig::new(uri)
};
let store = MongoStore::connect_with_config(config).await.unwrap();
let created = store.creation_time().await.unwrap();
assert!(created.is_some(), "expected a recorded creation time");
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
store.reset().await.unwrap();
let after_reset = store.creation_time().await.unwrap();
assert!(
after_reset.unwrap().unix_timestamp() > created.unwrap().unix_timestamp(),
"reset() should advance the recorded creation time"
);
}
#[tokio::test]
async fn mongo_creation_time_if_available() {
let Ok(uri) = std::env::var("DATABASE_URL_MONGO") else {
eprintln!("skipping: DATABASE_URL_MONGO not set");
return;
};
exercise_creation_time(&uri, "mongo3").await;
}
#[tokio::test]
async fn mongo_full_contract_if_available() {
let Ok(uri) = std::env::var("DATABASE_URL_MONGO") else {
eprintln!("skipping: DATABASE_URL_MONGO not set");
return;
};
exercise_full_contract(&uri, "mongo1").await;
}
#[tokio::test]
async fn mongo_session_isolation_if_available() {
let Ok(uri) = std::env::var("DATABASE_URL_MONGO") else {
eprintln!("skipping: DATABASE_URL_MONGO not set");
return;
};
exercise_session_isolation(&uri, "mongo2").await;
}