use crate::core::store::FeoxStore;
use crate::error::FeoxError;
use bytes::Bytes;
use std::thread;
use std::time::Duration;
#[test]
fn test_insert_with_ttl() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
store.insert_with_ttl(b"key1", b"value1", 1).unwrap();
let value = store.get(b"key1").unwrap();
assert_eq!(value, b"value1");
thread::sleep(Duration::from_millis(1100));
let result = store.get(b"key1");
assert!(result.is_err());
}
#[test]
fn test_get_ttl() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
store.insert_with_ttl(b"key1", b"value1", 10).unwrap();
let ttl = store.get_ttl(b"key1").unwrap();
assert!(ttl.is_some());
let ttl_seconds = ttl.unwrap();
assert!(ttl_seconds > 8 && ttl_seconds <= 10);
store.insert(b"key2", b"value2").unwrap();
let ttl = store.get_ttl(b"key2").unwrap();
assert!(ttl.is_none());
}
#[test]
fn test_update_ttl() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
store.insert(b"key1", b"value1").unwrap();
store.update_ttl(b"key1", 5).unwrap();
let ttl = store.get_ttl(b"key1").unwrap();
assert!(ttl.is_some());
store.persist(b"key1").unwrap();
let ttl = store.get_ttl(b"key1").unwrap();
assert!(ttl.is_none());
}
#[test]
fn test_ttl_preserves_value() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
store
.insert_with_ttl(b"key1", b"original_value", 10)
.unwrap();
store.update_ttl(b"key1", 20).unwrap();
let value = store.get(b"key1").unwrap();
assert_eq!(value, b"original_value");
}
#[test]
fn test_expired_key_not_found() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
store.insert_with_ttl(b"ephemeral", b"data", 0).unwrap();
let result = store.get(b"ephemeral");
assert!(result.is_ok());
store.insert_with_ttl(b"ephemeral2", b"data", 1).unwrap();
assert!(store.get(b"ephemeral2").is_ok());
thread::sleep(Duration::from_secs(2));
let result = store.get(b"ephemeral2");
assert!(result.is_err());
}
#[test]
fn test_update_resets_ttl() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
store.insert_with_ttl(b"key1", b"value1", 10).unwrap();
store.insert_with_ttl(b"key1", b"value2", 20).unwrap();
let ttl = store.get_ttl(b"key1").unwrap().unwrap();
assert!(ttl > 15 && ttl <= 20);
let value = store.get(b"key1").unwrap();
assert_eq!(value, b"value2");
}
#[test]
fn test_regular_insert_removes_ttl() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
store.insert_with_ttl(b"key1", b"value1", 10).unwrap();
let ttl = store.get_ttl(b"key1").unwrap();
assert!(ttl.is_some());
store.insert(b"key1", b"value2").unwrap();
let ttl = store.get_ttl(b"key1").unwrap();
assert!(ttl.is_none());
let value = store.get(b"key1").unwrap();
assert_eq!(value, b"value2");
thread::sleep(Duration::from_millis(100));
assert!(store.get(b"key1").is_ok());
}
#[test]
fn test_ttl_operations_fail_when_disabled() {
let store = FeoxStore::new(None).unwrap();
assert!(matches!(
store.insert_with_ttl(b"key1", b"value1", 10),
Err(FeoxError::TtlNotEnabled)
));
assert!(matches!(
store.insert_with_ttl_and_timestamp(b"key2", b"value2", 10, None),
Err(FeoxError::TtlNotEnabled)
));
store.insert(b"key3", b"value3").unwrap();
assert!(matches!(
store.get_ttl(b"key3"),
Err(FeoxError::TtlNotEnabled)
));
assert!(matches!(
store.update_ttl(b"key3", 10),
Err(FeoxError::TtlNotEnabled)
));
assert!(matches!(
store.persist(b"key3"),
Err(FeoxError::TtlNotEnabled)
));
assert_eq!(store.get(b"key3").unwrap(), b"value3");
store.delete(b"key3").unwrap();
}
#[test]
fn test_ttl_with_builder_explicit_disable() {
let store = FeoxStore::builder().enable_ttl(false).build().unwrap();
assert!(matches!(
store.insert_with_ttl(b"key1", b"value1", 10),
Err(FeoxError::TtlNotEnabled)
));
}
#[test]
fn test_insert_bytes_with_ttl() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
let value = Bytes::from_static(b"value1");
store.insert_bytes_with_ttl(b"key1", value, 1).unwrap();
let retrieved = store.get_bytes(b"key1").unwrap();
assert_eq!(&retrieved[..], b"value1");
thread::sleep(Duration::from_millis(1100));
let result = store.get(b"key1");
assert!(result.is_err());
}
#[test]
fn test_insert_bytes_with_ttl_and_timestamp() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
let base_timestamp = store.get_timestamp_pub();
let value1 = Bytes::from(vec![1, 2, 3, 4]);
store
.insert_bytes_with_ttl_and_timestamp(b"key1", value1, 10, Some(base_timestamp))
.unwrap();
let value2 = Bytes::from(vec![5, 6, 7, 8]);
let result = store.insert_bytes_with_ttl_and_timestamp(
b"key1",
value2.clone(),
10,
Some(base_timestamp - 1000),
);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), FeoxError::OlderTimestamp));
store
.insert_bytes_with_ttl_and_timestamp(b"key1", value2, 10, Some(base_timestamp + 1000))
.unwrap();
let retrieved = store.get(b"key1").unwrap();
assert_eq!(retrieved.as_slice(), &[5, 6, 7, 8]);
}
#[test]
fn test_insert_bytes_ttl_not_enabled() {
let store = FeoxStore::builder().enable_ttl(false).build().unwrap();
let value = Bytes::from_static(b"value1");
let result = store.insert_bytes_with_ttl(b"key1", value, 10);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), FeoxError::TtlNotEnabled));
}
#[test]
fn test_insert_bytes_preserves_ttl() {
let store = FeoxStore::builder().enable_ttl(true).build().unwrap();
let value1 = Bytes::from_static(b"value1");
store.insert_bytes_with_ttl(b"key1", value1, 10).unwrap();
let ttl = store.get_ttl(b"key1").unwrap();
assert!(ttl.is_some());
let ttl_seconds = ttl.unwrap();
assert!(ttl_seconds > 8 && ttl_seconds <= 10);
let value2 = Bytes::from_static(b"value2");
store.insert_bytes(b"key1", value2).unwrap();
let ttl = store.get_ttl(b"key1").unwrap();
assert!(ttl.is_none());
}