use talk::storage::SessionStore;
use talk::types::AgentId;
use talk::{InMemorySessionStore, Session};
#[tokio::test]
async fn test_session_store_create_contract() {
let store = InMemorySessionStore::new();
let session = Session::new(AgentId::new());
let session_id = session.id;
let result = store.create(session.clone()).await;
assert!(
result.is_ok(),
"SessionStore::create should succeed for new session"
);
assert_eq!(
result.unwrap(),
session_id,
"SessionStore::create should return the session ID"
);
let duplicate_result = store.create(session).await;
assert!(
duplicate_result.is_err(),
"SessionStore::create should fail for duplicate session ID"
);
}
#[tokio::test]
async fn test_session_store_get_contract() {
let store = InMemorySessionStore::new();
let session = Session::new(AgentId::new());
let session_id = session.id;
let result = store.get(&session_id).await;
assert!(result.is_ok(), "SessionStore::get should not return error");
assert!(
result.unwrap().is_none(),
"SessionStore::get should return None for non-existent session"
);
store.create(session.clone()).await.unwrap();
let result = store.get(&session_id).await;
assert!(result.is_ok(), "SessionStore::get should not return error");
let retrieved = result.unwrap();
assert!(
retrieved.is_some(),
"SessionStore::get should return Some for existing session"
);
assert_eq!(
retrieved.unwrap().id,
session_id,
"SessionStore::get should return the correct session"
);
}
#[tokio::test]
async fn test_session_store_update_contract() {
let store = InMemorySessionStore::new();
let mut session = Session::new(AgentId::new());
let session_id = session.id;
let result = store.update(&session_id, session.clone()).await;
assert!(
result.is_err(),
"SessionStore::update should fail for non-existent session"
);
store.create(session.clone()).await.unwrap();
session.complete();
let result = store.update(&session_id, session.clone()).await;
assert!(
result.is_ok(),
"SessionStore::update should succeed for existing session"
);
let retrieved = store.get(&session_id).await.unwrap().unwrap();
assert_eq!(
retrieved.status,
talk::SessionStatus::Completed,
"SessionStore::update should persist changes"
);
}
#[tokio::test]
async fn test_session_store_delete_contract() {
let store = InMemorySessionStore::new();
let session = Session::new(AgentId::new());
let session_id = session.id;
let result = store.delete(&session_id).await;
assert!(
result.is_err(),
"SessionStore::delete should fail for non-existent session"
);
store.create(session).await.unwrap();
let result = store.delete(&session_id).await;
assert!(
result.is_ok(),
"SessionStore::delete should succeed for existing session"
);
let retrieved = store.get(&session_id).await.unwrap();
assert!(
retrieved.is_none(),
"SessionStore::delete should remove the session"
);
}
#[tokio::test]
async fn test_session_store_list_contract() {
let store = InMemorySessionStore::new();
let result = store.list().await;
assert!(result.is_ok(), "SessionStore::list should not return error");
assert_eq!(
result.unwrap().len(),
0,
"SessionStore::list should return empty vec for empty store"
);
let session1 = Session::new(AgentId::new());
let session2 = Session::new(AgentId::new());
let session3 = Session::new(AgentId::new());
let id1 = session1.id;
let id2 = session2.id;
let id3 = session3.id;
store.create(session1).await.unwrap();
store.create(session2).await.unwrap();
store.create(session3).await.unwrap();
let result = store.list().await;
assert!(result.is_ok(), "SessionStore::list should not return error");
let list = result.unwrap();
assert_eq!(
list.len(),
3,
"SessionStore::list should return all sessions"
);
assert!(list.contains(&id1), "SessionStore::list should include id1");
assert!(list.contains(&id2), "SessionStore::list should include id2");
assert!(list.contains(&id3), "SessionStore::list should include id3");
}
#[tokio::test]
async fn test_session_store_exists_contract() {
let store = InMemorySessionStore::new();
let session = Session::new(AgentId::new());
let session_id = session.id;
let result = store.exists(&session_id).await;
assert!(
result.is_ok(),
"SessionStore::exists should not return error"
);
assert_eq!(
result.unwrap(),
false,
"SessionStore::exists should return false for non-existent session"
);
store.create(session).await.unwrap();
let result = store.exists(&session_id).await;
assert!(
result.is_ok(),
"SessionStore::exists should not return error"
);
assert_eq!(
result.unwrap(),
true,
"SessionStore::exists should return true for existing session"
);
}
#[tokio::test]
async fn test_session_store_concurrent_operations_contract() {
let store = InMemorySessionStore::new();
let handles: Vec<_> = (0..20)
.map(|_| {
let store_clone = store.clone();
tokio::spawn(async move {
let session = Session::new(AgentId::new());
store_clone.create(session).await
})
})
.collect();
for handle in handles {
let result = handle.await.unwrap();
assert!(
result.is_ok(),
"Concurrent SessionStore::create operations should succeed"
);
}
let list = store.list().await.unwrap();
assert_eq!(list.len(), 20, "All concurrent creates should succeed");
let read_handles: Vec<_> = list
.iter()
.map(|id| {
let store_clone = store.clone();
let id_clone = *id;
tokio::spawn(async move { store_clone.get(&id_clone).await })
})
.collect();
for handle in read_handles {
let result = handle.await.unwrap();
assert!(
result.is_ok(),
"Concurrent SessionStore::get operations should succeed"
);
assert!(
result.unwrap().is_some(),
"Concurrent reads should retrieve existing sessions"
);
}
}
#[tokio::test]
async fn test_session_store_thread_safety_contract() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<InMemorySessionStore>();
}