test(gateway): add edge-case idempotency store tests
Add five new idempotency store tests covering: different-key acceptance, max_keys clamping to minimum of 1, rapid duplicate rejection, TTL-based key expiry and re-acceptance, and eviction preserving newest entries. Addresses audit finding on weak gateway idempotency test coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
bec1dc7b8c
commit
867a7a5cbd
2 changed files with 52 additions and 2 deletions
|
|
@ -3373,14 +3373,16 @@ async fn sync_directory(path: &Path) -> Result<()> {
|
|||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn sync_directory(_path: &Path) -> Result<()> {
|
||||
async fn sync_directory(_path: &Path) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::{fs::Permissions, os::unix::fs::PermissionsExt, path::PathBuf};
|
||||
#[cfg(unix)]
|
||||
use std::{fs::Permissions, os::unix::fs::PermissionsExt};
|
||||
use std::path::PathBuf;
|
||||
use tokio::sync::{Mutex, MutexGuard};
|
||||
use tokio::test;
|
||||
use tokio_stream::wrappers::ReadDirStream;
|
||||
|
|
|
|||
|
|
@ -2089,4 +2089,52 @@ mod tests {
|
|||
&signature_header
|
||||
));
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════
|
||||
// IdempotencyStore Edge-Case Tests
|
||||
// ══════════════════════════════════════════════════════════
|
||||
|
||||
#[test]
|
||||
fn idempotency_store_allows_different_keys() {
|
||||
let store = IdempotencyStore::new(Duration::from_secs(60), 100);
|
||||
assert!(store.record_if_new("key-a"));
|
||||
assert!(store.record_if_new("key-b"));
|
||||
assert!(store.record_if_new("key-c"));
|
||||
assert!(store.record_if_new("key-d"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn idempotency_store_max_keys_clamped_to_one() {
|
||||
let store = IdempotencyStore::new(Duration::from_secs(60), 0);
|
||||
assert!(store.record_if_new("only-key"));
|
||||
assert!(!store.record_if_new("only-key"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn idempotency_store_rapid_duplicate_rejected() {
|
||||
let store = IdempotencyStore::new(Duration::from_secs(300), 100);
|
||||
assert!(store.record_if_new("rapid"));
|
||||
assert!(!store.record_if_new("rapid"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn idempotency_store_accepts_after_ttl_expires() {
|
||||
let store = IdempotencyStore::new(Duration::from_millis(1), 100);
|
||||
assert!(store.record_if_new("ttl-key"));
|
||||
std::thread::sleep(Duration::from_millis(10));
|
||||
assert!(store.record_if_new("ttl-key"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn idempotency_store_eviction_preserves_newest() {
|
||||
let store = IdempotencyStore::new(Duration::from_secs(300), 1);
|
||||
assert!(store.record_if_new("old-key"));
|
||||
std::thread::sleep(Duration::from_millis(2));
|
||||
assert!(store.record_if_new("new-key"));
|
||||
|
||||
let keys = store.keys.lock();
|
||||
assert_eq!(keys.len(), 1);
|
||||
assert!(!keys.contains_key("old-key"));
|
||||
assert!(keys.contains_key("new-key"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue