use std::time::Duration; use chrono::{DateTime, Utc}; use tokio::join; use shiny_common::clock::StaticClock; use shiny_common::pointer_utils::ToArc; use shiny_jobs::job_trigger::cron_trigger::CronTrigger; use shiny_jobs::job_trigger::interval_trigger::IntervalTrigger; use shiny_jobs::job_trigger::JobTrigger; #[tokio::test] async fn test_every_100ms_job() { let scheduler = IntervalTrigger::new(Duration::from_millis(10)); let mut counter = 0; tokio::select! { _ = async { loop { scheduler.next().await; counter+=1; } } => {} _ = tokio::time::sleep(Duration::from_millis(100)) => {} } assert!(counter >= 7 && counter <= 10, "counter = {counter}") } #[tokio::test] async fn test_cron_jobs() { join!( // minute assert_launch_at("33 * * * *", "2023-12-30T11:33:00+03:00"), assert_launch_at("*/20 * * * *", "2023-12-30T11:00:00+03:00"), assert_launch_at("0/20 * * * *", "2023-12-30T11:20:00+03:00"), assert_launch_at("0/20 * * * *", "2023-12-30T11:40:00+03:00"), assert_not_launch_at("0/20 * * * *", "2023-12-30T11:30:00+03:00"), assert_launch_at("11-33/10 * * * *", "2023-12-30T11:31:00+03:00"), assert_not_launch_at("11-33/10 * * * *", "2023-12-30T11:00:00+03:00"), // hour assert_launch_at("0 11 * * *", "2023-12-30T11:00:00+00:00"), assert_launch_at("0 */3 * * *", "2023-12-30T00:00:00+00:00"), assert_launch_at("0 0/3 * * *", "2023-12-30T03:00:00+00:00"), assert_launch_at("0 0/3 * * *", "2023-12-30T12:00:00+00:00"), assert_not_launch_at("0 0/3 * * *", "2023-12-30T11:00:00+00:00"), assert_launch_at("0 11-18/2 * * *", "2023-12-30T15:00:00+00:00"), assert_not_launch_at("0 11-18/2 * * *", "2023-12-30T12:00:00+00:00"), // day assert_launch_at("0 0 11 * *", "2023-12-11T00:00:00+00:00"), assert_launch_at("0 0 */3 * *", "2023-12-04T00:00:00+00:00"), assert_launch_at("0 0 1/3 * *", "2023-12-04T00:00:00+00:00"), assert_launch_at("0 0 1/3 * *", "2023-12-13T00:00:00+00:00"), assert_not_launch_at("0 0 1/3 * *", "2023-12-11T00:00:00+00:00"), assert_launch_at("0 0 11-18/2 * *", "2023-12-13T00:00:00+00:00"), assert_not_launch_at("0 0 11-18/2 * *", "2023-12-12T00:00:00+00:00"), // month assert_launch_at("0 0 1 11 *", "2023-11-01T00:00:00+00:00"), assert_launch_at("0 0 1 NOV *", "2023-11-01T00:00:00+00:00"), assert_launch_at("0 0 1 */3 *", "2023-04-01T00:00:00+00:00"), assert_launch_at("0 0 1 1/3 *", "2023-07-01T00:00:00+00:00"), assert_launch_at("0 0 1 1/3 *", "2023-10-01T00:00:00+00:00"), assert_not_launch_at("0 0 1 1/3 *", "2023-12-01T00:00:00+00:00"), assert_launch_at("0 0 1 3-11/2 *", "2023-05-01T00:00:00+00:00"), assert_not_launch_at("0 0 1 3-11/2 *", "2023-04-01T00:00:00+00:00"), ); } async fn assert_launch_at(schedule: &'static str, at: &'static str) { let at: DateTime = DateTime::parse_from_rfc3339(at).expect("function should be called with valid time").into(); let clock = StaticClock(at - Duration::from_millis(10)); let trigger = CronTrigger::new(schedule, clock.arc()).unwrap(); tokio::select! { _ = trigger.next() => {} _ = tokio::time::sleep(Duration::from_millis(20)) => { panic!("unexpected result for schedule: {schedule} at {at}") } } } async fn assert_not_launch_at(schedule: &'static str, at: &'static str) { let at: DateTime = DateTime::parse_from_rfc3339(at).expect("function should be called with valid time").into(); let clock = StaticClock(at - Duration::from_millis(10)); let trigger = CronTrigger::new(schedule, clock.arc()).unwrap(); tokio::select! { _ = trigger.next() => { panic!("unexpected result for schedule: {schedule} at {at}") } _ = tokio::time::sleep(Duration::from_millis(20)) => { } } }