use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Duration;
use minitimer::MiniTimer;
use minitimer::task::TaskBuilder;
mod common;
use common::CounterTask;
#[tokio::test]
async fn test_hour_level_task() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_once_by_seconds(3665)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
tokio::time::sleep(Duration::from_secs(10)).await;
let count = counter.load(Ordering::SeqCst);
assert_eq!(
count, 0,
"Hour-level task should NOT execute within 10 seconds, executed {} times",
count
);
}
#[tokio::test]
async fn test_day_level_task() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_once_by_seconds(90000)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
tokio::time::sleep(Duration::from_secs(10)).await;
let count = counter.load(Ordering::SeqCst);
assert_eq!(
count, 0,
"Day-level task should NOT execute within 10 seconds, executed {} times",
count
);
}
#[tokio::test]
async fn test_minute_level_repeated_task() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_repeated_by_seconds(60)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
for _ in 0..131 {
timer.tick().await;
}
let count = counter.load(Ordering::SeqCst);
assert!(
count >= 1,
"Minute-level repeated task should execute at least once in 131 ticks, executed {} times",
count
);
}
#[tokio::test]
async fn test_hour_level_repeated_task() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_repeated_by_seconds(3600)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
for _ in 0..10 {
timer.tick().await;
}
let count = counter.load(Ordering::SeqCst);
assert_eq!(
count, 0,
"Hour-level repeated task should NOT execute within 10 ticks, executed {} times",
count
);
}
#[tokio::test]
async fn test_minute_to_second_cascade() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_once_by_seconds(65)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
for _ in 0..70 {
timer.tick().await;
tokio::time::sleep(Duration::from_millis(50)).await;
}
let count = counter.load(Ordering::SeqCst);
assert!(
count >= 1,
"Task at 65s should execute after cascade from minute to second wheel, executed {} times",
count
);
}
#[tokio::test]
async fn test_hour_level_task_not_execute_early() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_once_by_seconds(3665)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
for _ in 0..100 {
timer.tick().await;
}
let count = counter.load(Ordering::SeqCst);
assert_eq!(
count, 0,
"Hour-level task should NOT execute within 100 ticks, executed {} times",
count
);
}
#[tokio::test]
async fn test_hour_to_minute_to_second_cascade_complete() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_once_by_seconds(65)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
assert!(timer.contains_task(1), "Task should exist");
for _ in 0..70 {
timer.tick().await;
tokio::time::sleep(Duration::from_millis(10)).await;
}
let count = counter.load(Ordering::SeqCst);
assert!(
count >= 1,
"Task should execute after cascade from minute to second wheel, executed {} times",
count
);
}
#[tokio::test]
async fn test_multi_wheel_tasks() {
let counter_second = Arc::new(AtomicU64::new(0));
let counter_minute = Arc::new(AtomicU64::new(0));
let counter_hour = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task_second = TaskBuilder::new(1)
.with_frequency_once_by_seconds(2)
.spawn_async(CounterTask::new(counter_second.clone()))
.unwrap();
let task_minute = TaskBuilder::new(2)
.with_frequency_once_by_seconds(65)
.spawn_async(CounterTask::new(counter_minute.clone()))
.unwrap();
let task_hour = TaskBuilder::new(3)
.with_frequency_once_by_seconds(3665)
.spawn_async(CounterTask::new(counter_hour.clone()))
.unwrap();
timer.add_task(task_second).unwrap();
timer.add_task(task_minute).unwrap();
timer.add_task(task_hour).unwrap();
for _ in 0..70 {
timer.tick().await;
}
let second_count = counter_second.load(Ordering::SeqCst);
let _minute_count = counter_minute.load(Ordering::SeqCst);
let hour_count = counter_hour.load(Ordering::SeqCst);
assert!(
second_count >= 1,
"Second-level task should execute, executed {} times",
second_count
);
assert_eq!(
hour_count, 0,
"Hour-level task should NOT execute within 70 ticks, executed {} times",
hour_count
);
}
#[tokio::test]
async fn test_task_placed_in_minute_wheel() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_once_by_seconds(120)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
let status = timer.task_status(1);
assert!(status.is_some(), "Task should have a status");
for _ in 0..130 {
timer.tick().await;
}
let count = counter.load(Ordering::SeqCst);
assert!(
count >= 1,
"Task should execute after 120 ticks, executed {} times",
count
);
}
#[tokio::test]
async fn test_task_placed_in_hour_wheel() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_once_by_seconds(7200)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
tokio::time::sleep(Duration::from_secs(5)).await;
let count = counter.load(Ordering::SeqCst);
assert_eq!(
count, 0,
"Task should NOT execute within 5 seconds (scheduled for 7200s), executed {} times",
count
);
}
#[tokio::test]
async fn test_repeated_task_spanning_wheels() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_repeated_by_seconds(90)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
for _ in 0..200 {
timer.tick().await;
}
let count = counter.load(Ordering::SeqCst);
assert!(
count >= 1,
"Repeated task at 90s interval should execute at least once in 200 ticks, executed {} times",
count
);
}
#[tokio::test]
async fn test_tick_method_works() {
let counter = Arc::new(AtomicU64::new(0));
let timer = MiniTimer::new();
let task = TaskBuilder::new(1)
.with_frequency_once_by_seconds(2)
.spawn_async(CounterTask::new(counter.clone()))
.unwrap();
timer.add_task(task).unwrap();
println!("Task count: {}", timer.task_count());
println!("Pending tasks: {:?}", timer.get_pending_tasks());
for i in 0..10 {
timer.tick().await;
tokio::time::sleep(Duration::from_millis(50)).await;
let c = counter.load(Ordering::SeqCst);
println!("After tick {}: counter = {}", i, c);
}
let count = counter.load(Ordering::SeqCst);
assert!(
count >= 1,
"Task should execute after 5 ticks, executed {} times",
count
);
}