103 lines
3.4 KiB
Rust
103 lines
3.4 KiB
Rust
//! Integration tests for the `object_pool` module.
|
|||
|
|
|
||
|
|
use sarasacw_omrf::object_pool::{ObjectPool, INVALID_TOKEN};
|
||
|
|
|
||
|
|
/// Coverage: the `INVALID_TOKEN` constant is `0`, the value the counter never produces.
|
||
|
|
#[test]
|
||
|
|
fn invalid_token_is_zero() {
|
||
|
|
assert_eq!(INVALID_TOKEN, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Coverage: `allocate` returns distinct, non-zero tokens across successive calls.
|
||
|
|
#[test]
|
||
|
|
fn allocate_yields_distinct_nonzero_tokens() {
|
||
|
|
let pool: ObjectPool<i32> = ObjectPool::new();
|
||
|
|
let t1 = pool.allocate(10);
|
||
|
|
let t2 = pool.allocate(20);
|
||
|
|
let t3 = pool.allocate(30);
|
||
|
|
assert_ne!(t1, 0);
|
||
|
|
assert_ne!(t2, 0);
|
||
|
|
assert_ne!(t3, 0);
|
||
|
|
assert_ne!(t1, t2);
|
||
|
|
assert_ne!(t2, t3);
|
||
|
|
assert_ne!(t1, t3);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Coverage: the guard-style `get` reads and `get_mut` writes an entry, with changes observable
|
||
|
|
/// by a subsequent `get`.
|
||
|
|
#[test]
|
||
|
|
fn get_and_get_mut_round_trip() {
|
||
|
|
let pool: ObjectPool<i32> = ObjectPool::new();
|
||
|
|
let t = pool.allocate(7);
|
||
|
|
assert_eq!(*pool.get(t).unwrap(), 7);
|
||
|
|
*pool.get_mut(t).unwrap() = 99;
|
||
|
|
assert_eq!(*pool.get(t).unwrap(), 99);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Coverage: the deadlock-safe closure-based `get_with`/`get_mut_with` read and write an entry.
|
||
|
|
#[test]
|
||
|
|
fn get_with_and_get_mut_with_round_trip() {
|
||
|
|
let pool: ObjectPool<i32> = ObjectPool::new();
|
||
|
|
let t = pool.allocate(1);
|
||
|
|
assert_eq!(pool.get_with(t, |v| *v).unwrap(), 1);
|
||
|
|
pool.get_mut_with(t, |v| *v = 42).unwrap();
|
||
|
|
assert_eq!(pool.get_with(t, |v| *v).unwrap(), 42);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Coverage: `pop` returns the owned value and invalidates the token for any further access.
|
||
|
|
#[test]
|
||
|
|
fn pop_returns_owned_value_and_invalidates_token() {
|
||
|
|
let pool: ObjectPool<String> = ObjectPool::new();
|
||
|
|
let t = pool.allocate("hello".to_string());
|
||
|
|
let owned = pool.pop(t).unwrap();
|
||
|
|
assert_eq!(owned, "hello");
|
||
|
|
assert!(pool.get(t).is_err());
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Coverage: `free` removes the entry; subsequent `get`/`get_mut` on the same token fail.
|
||
|
|
#[test]
|
||
|
|
fn free_invalidates_token() {
|
||
|
|
let pool: ObjectPool<i32> = ObjectPool::new();
|
||
|
|
let t = pool.allocate(5);
|
||
|
|
pool.free(t).unwrap();
|
||
|
|
assert!(pool.get(t).is_err());
|
||
|
|
assert!(pool.get_mut(t).is_err());
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Coverage: every access/mutation/removal method rejects `INVALID_TOKEN` (and any absent token).
|
||
|
|
#[test]
|
||
|
|
fn invalid_token_errors_on_all_methods() {
|
||
|
|
let pool: ObjectPool<i32> = ObjectPool::new();
|
||
|
|
let bad = INVALID_TOKEN;
|
||
|
|
assert!(pool.get(bad).is_err());
|
||
|
|
assert!(pool.get_mut(bad).is_err());
|
||
|
|
assert!(pool.get_with(bad, |_| ()).is_err());
|
||
|
|
assert!(pool.get_mut_with(bad, |_| ()).is_err());
|
||
|
|
assert!(pool.free(bad).is_err());
|
||
|
|
assert!(pool.pop(bad).is_err());
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Coverage: `clear` empties the pool; all previously-issued tokens become invalid.
|
||
|
|
#[test]
|
||
|
|
fn clear_removes_all_objects() {
|
||
|
|
let pool: ObjectPool<i32> = ObjectPool::new();
|
||
|
|
let t1 = pool.allocate(1);
|
||
|
|
let t2 = pool.allocate(2);
|
||
|
|
pool.clear();
|
||
|
|
assert!(pool.get(t1).is_err());
|
||
|
|
assert!(pool.get(t2).is_err());
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Coverage: two distinct tokens can be mutated independently via sequential closure access, which
|
||
|
|
/// never holds two guards at once (the deadlock-safe pattern).
|
||
|
|
#[test]
|
||
|
|
fn two_tokens_modified_independently_via_closure() {
|
||
|
|
let pool: ObjectPool<i32> = ObjectPool::new();
|
||
|
|
let t1 = pool.allocate(0);
|
||
|
|
let t2 = pool.allocate(0);
|
||
|
|
pool.get_mut_with(t1, |v| *v = 11).unwrap();
|
||
|
|
pool.get_mut_with(t2, |v| *v = 22).unwrap();
|
||
|
|
assert_eq!(pool.get_with(t1, |v| *v).unwrap(), 11);
|
||
|
|
assert_eq!(pool.get_with(t2, |v| *v).unwrap(), 22);
|
||
|
|
}
|