use std::thread::sleep;
use std::time::Duration;
use std::time::SystemTime;
use bytes::Bytes;
use d_engine_core::Lease;
use crate::storage::lease::DefaultLease;
fn default_config() -> d_engine_core::config::LeaseConfig {
d_engine_core::config::LeaseConfig {
enabled: true,
interval_ms: 1000,
max_cleanup_duration_ms: 1,
}
}
#[test]
fn test_register_and_is_expired() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 1);
assert!(!lease.is_expired(b"key1"));
sleep(Duration::from_secs(2));
assert!(lease.is_expired(b"key1"));
}
#[test]
fn test_unregister() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 10);
assert_eq!(lease.len(), 1);
lease.unregister(b"key1");
assert_eq!(lease.len(), 0);
assert!(!lease.is_expired(b"key1"));
}
#[test]
fn test_unregister_nonexistent_key() {
let lease = DefaultLease::new(default_config());
lease.unregister(b"nonexistent");
assert_eq!(lease.len(), 0);
}
#[test]
fn test_get_expired_keys() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 1);
lease.register(Bytes::from("key2"), 1);
sleep(Duration::from_secs(2));
let expired = lease.get_expired_keys(SystemTime::now());
assert_eq!(expired.len(), 2);
assert_eq!(lease.len(), 0);
}
#[test]
fn test_is_empty() {
let lease = DefaultLease::new(default_config());
assert!(lease.is_empty());
lease.register(Bytes::from("key1"), 10);
assert!(!lease.is_empty());
lease.unregister(b"key1");
assert!(lease.is_empty());
}
#[test]
fn test_has_lease_keys() {
let lease = DefaultLease::new(default_config());
assert!(!lease.has_lease_keys());
lease.register(Bytes::from("key1"), 10);
assert!(lease.has_lease_keys());
lease.unregister(b"key1");
assert!(lease.has_lease_keys()); }
#[test]
fn test_may_have_expired_keys_false_when_no_keys() {
let lease = DefaultLease::new(default_config());
assert!(!lease.may_have_expired_keys(SystemTime::now()));
}
#[test]
fn test_may_have_expired_keys_false_when_all_valid() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 3600);
lease.register(Bytes::from("key2"), 7200);
assert!(!lease.may_have_expired_keys(SystemTime::now()));
}
#[test]
fn test_may_have_expired_keys_true_when_has_expired() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 1);
sleep(Duration::from_secs(2));
assert!(lease.may_have_expired_keys(SystemTime::now()));
}
#[test]
fn test_get_expiration() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 3600);
let expiration = lease.get_expiration(b"key1");
assert!(expiration.is_some());
assert!(expiration.unwrap() > SystemTime::now());
}
#[test]
fn test_get_expiration_not_found() {
let lease = DefaultLease::new(default_config());
let expiration = lease.get_expiration(b"nonexistent");
assert!(expiration.is_none());
}
#[test]
fn test_register_updates_existing_key() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 10);
assert_eq!(lease.len(), 1);
let first_expiry = lease.get_expiration(b"key1").unwrap();
sleep(Duration::from_millis(100));
lease.register(Bytes::from("key1"), 20);
let second_expiry = lease.get_expiration(b"key1").unwrap();
assert!(second_expiry > first_expiry);
assert_eq!(lease.len(), 1); }
#[test]
fn test_multiple_keys_same_expiration() {
let lease = DefaultLease::new(default_config());
let ttl = 5u64;
lease.register(Bytes::from("key1"), ttl);
lease.register(Bytes::from("key2"), ttl);
lease.register(Bytes::from("key3"), ttl);
assert_eq!(lease.len(), 3);
sleep(Duration::from_secs(ttl + 1));
let expired = lease.get_expired_keys(SystemTime::now());
assert_eq!(expired.len(), 3);
assert_eq!(lease.len(), 0);
}
#[test]
fn test_mixed_expired_and_valid_keys() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("expire_soon"), 1);
lease.register(Bytes::from("expire_later"), 3600);
sleep(Duration::from_secs(2));
let expired = lease.get_expired_keys(SystemTime::now());
assert_eq!(expired.len(), 1);
assert_eq!(expired[0], Bytes::from("expire_soon"));
assert_eq!(lease.len(), 1);
assert!(!lease.is_expired(b"expire_later"));
}
#[test]
fn test_snapshot_roundtrip() {
let config = default_config();
let lease1 = DefaultLease::new(config.clone());
lease1.register(Bytes::from("key1"), 3600);
lease1.register(Bytes::from("key2"), 7200);
let snapshot = lease1.to_snapshot();
let lease2 = DefaultLease::from_snapshot(&snapshot, config);
assert_eq!(lease2.len(), 2);
assert!(!lease2.is_expired(b"key1"));
assert!(!lease2.is_expired(b"key2"));
}
#[test]
fn test_snapshot_roundtrip_filters_expired_keys() {
let config = default_config();
let lease1 = DefaultLease::new(config.clone());
lease1.register(Bytes::from("valid_key"), 3600);
lease1.register(Bytes::from("expired_key"), 1);
sleep(Duration::from_secs(2));
let snapshot = lease1.to_snapshot();
let lease2 = DefaultLease::from_snapshot(&snapshot, config);
assert_eq!(lease2.len(), 1);
assert!(!lease2.is_expired(b"valid_key"));
}
#[test]
fn test_from_snapshot_with_invalid_data() {
let config = default_config();
let lease = DefaultLease::from_snapshot(&[0xFF, 0xFE], config);
assert_eq!(lease.len(), 0);
assert!(!lease.has_lease_keys());
}
#[test]
fn test_reload() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 3600);
let snapshot = lease.to_snapshot();
lease.register(Bytes::from("key2"), 100);
assert_eq!(lease.len(), 2);
lease.reload(&snapshot).unwrap();
assert_eq!(lease.len(), 1);
assert!(!lease.is_expired(b"key1"));
assert!(!lease.is_expired(b"key2"));
}
#[test]
fn test_reload_invalid_data() {
let lease = DefaultLease::new(default_config());
lease.register(Bytes::from("key1"), 3600);
assert_eq!(lease.len(), 1);
let result = lease.reload(&[0xFF, 0xFE, 0xFD]);
assert!(result.is_err());
assert_eq!(lease.len(), 1);
assert!(!lease.is_expired(b"key1"));
}
#[test]
fn test_reload_clears_apply_counter() {
let config = d_engine_core::config::LeaseConfig {
enabled: true,
interval_ms: 1000,
max_cleanup_duration_ms: 1,
};
let lease = DefaultLease::new(config.clone());
lease.register(Bytes::from("key1"), 3600);
let _ = lease.on_apply();
let _ = lease.on_apply();
let _ = lease.on_apply();
let snapshot = lease.to_snapshot();
lease.reload(&snapshot).unwrap();
let result = lease.on_apply();
assert!(result.is_empty());
}
#[test]
fn test_on_apply_piggyback_removed() {
let config = default_config();
let lease = DefaultLease::new(config);
lease.register(Bytes::from("key1"), 1);
sleep(Duration::from_secs(2));
let result = lease.on_apply();
assert!(result.is_empty());
assert_eq!(lease.len(), 1);
}
#[test]
fn test_enabled_config() {
let config = d_engine_core::config::LeaseConfig {
enabled: true,
interval_ms: 5000,
max_cleanup_duration_ms: 1,
};
let lease = DefaultLease::new(config);
assert!(lease.config().enabled);
assert_eq!(lease.config().interval_ms, 5000);
}