#![cfg_attr(test, allow(clippy::unwrap_used, reason = "test scope"))]
use super::global::GlobalPool;
use super::slab::SlabAllocator;
use super::stack::LockFreeStack;
use super::wrapper::TaskWrapper;
use crate::{Priority, TaskId};
#[test]
fn test_lock_free_stack() {
let stack = LockFreeStack::new();
assert_eq!(stack.push(1), Ok(()));
assert_eq!(stack.push(2), Ok(()));
assert_eq!(stack.push(3), Ok(()));
assert_eq!(stack.len(), 3);
assert_eq!(stack.pop(), Some(3));
assert_eq!(stack.pop(), Some(2));
assert_eq!(stack.pop(), Some(1));
assert_eq!(stack.pop(), None);
assert_eq!(stack.len(), 0);
}
#[test]
fn test_lock_free_stack_capacity() {
let stack = LockFreeStack::<i32>::new();
assert_eq!(stack.capacity(), super::stack::DEFAULT_STACK_CAPACITY);
let small = LockFreeStack::with_capacity(2);
assert_eq!(small.capacity(), 2);
assert_eq!(small.push(10), Ok(()));
assert_eq!(small.push(20), Ok(()));
assert_eq!(small.push(30), Err(30)); assert_eq!(small.len(), 2);
assert_eq!(small.pop(), Some(20));
assert_eq!(small.push(40), Ok(()));
assert_eq!(small.pop(), Some(40));
assert_eq!(small.pop(), Some(10));
assert_eq!(small.pop(), None);
let empty = LockFreeStack::with_capacity(0);
assert_eq!(empty.push(1), Err(1));
assert_eq!(empty.pop(), None);
}
#[test]
fn test_slab_allocator() {
let slab = SlabAllocator::new(10);
let idx1 = slab.insert("hello").unwrap();
let idx2 = slab.insert("world").unwrap();
assert_eq!(unsafe { slab.get(idx1) }, Some(&"hello"));
assert_eq!(unsafe { slab.get(idx2) }, Some(&"world"));
assert_eq!(slab.len(), 2);
assert_eq!(slab.remove(idx1), Some("hello"));
assert_eq!(slab.len(), 1);
assert_eq!(unsafe { slab.get(idx1) }, None);
let idx3 = slab.insert("reused").unwrap();
assert_eq!(idx3, idx1); }
#[test]
fn test_task_wrapper() {
let mut wrapper = TaskWrapper::<String>::new();
wrapper.init("test".to_string(), TaskId(1), Priority::High);
assert_eq!(wrapper.task_id(), Some(TaskId(1)));
assert_eq!(wrapper.priority(), Priority::High);
assert_eq!(wrapper.take(), Some("test".to_string()));
wrapper.reset();
assert_eq!(wrapper.task_id(), None);
assert_eq!(wrapper.reset_count(), 1);
}
#[test]
fn test_global_pool() {
let pool = GlobalPool::new(10);
pool.put(vec![1, 2, 3]);
pool.put(vec![4, 5, 6]);
let obj1 = pool.get();
assert!(obj1.is_empty() || obj1 == vec![4, 5, 6]);
let obj2 = pool.get();
assert!(obj2.is_empty() || obj2 == vec![1, 2, 3]);
}
#[test]
fn test_global_pool_max_size_wired_through() {
let pool = GlobalPool::new(1);
pool.put(vec![1]);
pool.put(vec![2]);
assert_eq!(pool.get(), vec![1]);
assert_eq!(pool.get(), Vec::<i32>::new()); }
#[test]
fn test_concurrent_stack() {
use std::sync::Arc;
use std::thread;
let stack = Arc::new(LockFreeStack::new());
let mut handles = vec![];
for i in 0..4 {
let stack = stack.clone();
handles.push(thread::spawn(move || {
for j in 0..100 {
stack
.push(i * 100 + j)
.expect("invariant: 400 pushes fit the default 1024-slot capacity");
}
}));
}
for handle in handles {
handle.join().unwrap();
}
assert_eq!(stack.len(), 400);
let mut count = 0;
while stack.pop().is_some() {
count += 1;
}
assert_eq!(count, 400);
}