/// Integration tests for the scheduled tasks (cron) system. /// Run with: cargo test --test test_scheduler use serde_json::json; /// Verify that Schedule types (de)serialize correctly. #[tokio::test] async fn test_scheduler_types_roundtrip() { use picobot::scheduler::Schedule; let s1 = Schedule::Every { every_ms: 3600000 }; let json = serde_json::to_string(&s1).unwrap(); let s2: Schedule = serde_json::from_str(&json).unwrap(); match s2 { Schedule::Every { every_ms } => assert_eq!(every_ms, 3600000), _ => panic!("expected Every"), } let s1 = Schedule::At { at: 1000000 }; let json = serde_json::to_string(&s1).unwrap(); let s2: Schedule = serde_json::from_str(&json).unwrap(); match s2 { Schedule::At { at } => assert_eq!(at, 1000000), _ => panic!("expected At"), } let s1 = Schedule::Cron { expr: "0 0 9 * * *".into(), tz: None, }; let json = serde_json::to_string(&s1).unwrap(); let s2: Schedule = serde_json::from_str(&json).unwrap(); match s2 { Schedule::Cron { expr, tz } => { assert_eq!(expr, "0 0 9 * * *"); assert!(tz.is_none()); } _ => panic!("expected Cron"), } } /// Verify that next_run_for_schedule produces valid future timestamps. #[test] fn test_next_run_always_future() { use picobot::scheduler::{next_run_for_schedule, Schedule}; let now = 1700000000000_i64; let schedules = vec![ Schedule::Every { every_ms: 60000 }, Schedule::Cron { expr: "0 0 9 * * *".into(), tz: None, }, ]; for s in &schedules { let next = next_run_for_schedule(s, now); assert!(next.is_some(), "expected next run for {:?}", s); assert!(next.unwrap() > now, "next run should be after now for {:?}", s); } }