use super::super::{KeyPair, SeaError, SessionStorage};
use async_trait::async_trait;
use std::collections::HashMap;
use std::sync::Mutex;
pub struct InMemorySessionStorage {
data: Mutex<HashMap<String, KeyPair>>,
}
impl Default for InMemorySessionStorage {
fn default() -> Self {
Self::new()
}
}
impl InMemorySessionStorage {
pub fn new() -> Self {
Self {
data: Mutex::new(HashMap::new()),
}
}
}
#[async_trait]
impl SessionStorage for InMemorySessionStorage {
async fn save(&self, alias: &str, pair: &KeyPair) -> Result<(), SeaError> {
self.data
.lock()
.unwrap()
.insert(alias.to_string(), pair.clone());
Ok(())
}
async fn load(&self, alias: &str) -> Result<Option<KeyPair>, SeaError> {
Ok(self.data.lock().unwrap().get(alias).cloned())
}
async fn clear(&self, alias: &str) -> Result<(), SeaError> {
self.data.lock().unwrap().remove(alias);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
fn test_pair() -> KeyPair {
KeyPair {
pub_key: "test.pub".to_string(),
priv_key: "test.priv".to_string(),
epub_key: Some("test.epub".to_string()),
epriv_key: Some("test.epriv".to_string()),
}
}
#[tokio::test]
async fn test_save_load_roundtrip() {
let storage = InMemorySessionStorage::new();
let pair = test_pair();
storage.save("alice", &pair).await.unwrap();
let loaded = storage.load("alice").await.unwrap();
assert!(loaded.is_some());
let loaded = loaded.unwrap();
assert_eq!(loaded.pub_key, pair.pub_key);
assert_eq!(loaded.priv_key, pair.priv_key);
}
#[tokio::test]
async fn test_load_missing_returns_none() {
let storage = InMemorySessionStorage::new();
let loaded = storage.load("nobody").await.unwrap();
assert!(loaded.is_none());
}
#[tokio::test]
async fn test_clear_removes_entry() {
let storage = InMemorySessionStorage::new();
let pair = test_pair();
storage.save("bob", &pair).await.unwrap();
assert!(storage.load("bob").await.unwrap().is_some());
storage.clear("bob").await.unwrap();
assert!(storage.load("bob").await.unwrap().is_none());
}
#[tokio::test]
async fn test_default_is_empty() {
let storage = InMemorySessionStorage::default();
let loaded = storage.load("anyone").await.unwrap();
assert!(loaded.is_none());
}
#[tokio::test]
async fn test_overwrite_existing() {
let storage = InMemorySessionStorage::new();
let pair1 = test_pair();
let mut pair2 = test_pair();
pair2.pub_key = "other.pub".to_string();
storage.save("alice", &pair1).await.unwrap();
storage.save("alice", &pair2).await.unwrap();
let loaded = storage.load("alice").await.unwrap().unwrap();
assert_eq!(loaded.pub_key, "other.pub");
}
}