From 82f44ed0cc93938319c654779f78b8c73e2e491f Mon Sep 17 00:00:00 2001 From: lkoester Date: Tue, 24 Jan 2023 14:44:28 +0100 Subject: [PATCH] fixed tc insertion, added unit tests for releasing single tcs as well as inserting and releasing multiple tcs with same timestamp --- satrs-core/src/pus/scheduling.rs | 184 +++++++++++++++++++++++++++++-- 1 file changed, 176 insertions(+), 8 deletions(-) diff --git a/satrs-core/src/pus/scheduling.rs b/satrs-core/src/pus/scheduling.rs index d996600..b7deeeb 100644 --- a/satrs-core/src/pus/scheduling.rs +++ b/satrs-core/src/pus/scheduling.rs @@ -6,6 +6,7 @@ use std::collections::BTreeMap; use std::time::SystemTimeError; use std::vec; use std::vec::Vec; +use std::sync::{mpsc, Arc, RwLock}; #[derive(Debug)] pub struct PusScheduler { @@ -59,7 +60,7 @@ impl PusScheduler { } pub fn insert_tc(&mut self, time_stamp: UnixTimestamp, addr: StoreAddr) -> bool { - if time_stamp > self.current_time + self.time_margin { + if time_stamp < self.current_time + self.time_margin { return false; } match self.tc_map.entry(time_stamp) { @@ -97,10 +98,15 @@ impl PusScheduler { #[cfg(test)] mod tests { + use std::{println, vec}; + use std::sync::mpsc; + use std::sync::mpsc::{channel, Receiver, TryRecvError}; use crate::pool::StoreAddr; use crate::pus::scheduling::PusScheduler; use spacepackets::time::UnixTimestamp; use std::time::Duration; + use spacepackets::ecss::PacketTypeCodes::UnsignedInt; + use std::vec::Vec; #[test] fn basic() { @@ -115,20 +121,65 @@ mod tests { fn reset() { let mut scheduler = PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); - scheduler.insert_tc( - UnixTimestamp::new_only_seconds(200), + + let worked = scheduler.insert_tc( + UnixTimestamp::new_only_seconds(100), StoreAddr { pool_idx: 0, packet_idx: 1, }, ); - scheduler.insert_tc( + + assert!(worked); + + let worked = scheduler.insert_tc( UnixTimestamp::new_only_seconds(200), StoreAddr { pool_idx: 0, packet_idx: 2, }, ); + + assert!(worked); + + let worked = scheduler.insert_tc( + UnixTimestamp::new_only_seconds(300), + StoreAddr { + pool_idx: 0, + packet_idx: 2, + }, + ); + + assert!(worked); + + assert_eq!(scheduler.num_scheduled_telecommands(), 3); + assert!(scheduler.is_enabled()); + scheduler.reset(); + assert!(!scheduler.is_enabled()); + assert_eq!(scheduler.num_scheduled_telecommands(), 0); + } + + #[test] + fn insert_multi_with_same_time() { + let mut scheduler = + PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + + scheduler.insert_tc( + UnixTimestamp::new_only_seconds(100), + StoreAddr { + pool_idx: 0, + packet_idx: 1, + }, + ); + + let worked = scheduler.insert_tc( + UnixTimestamp::new_only_seconds(100), + StoreAddr { + pool_idx: 0, + packet_idx: 2, + }, + ); + scheduler.insert_tc( UnixTimestamp::new_only_seconds(300), StoreAddr { @@ -136,10 +187,127 @@ mod tests { packet_idx: 2, }, ); + assert_eq!(scheduler.num_scheduled_telecommands(), 3); - assert!(scheduler.is_enabled()); - scheduler.reset(); - assert!(!scheduler.is_enabled()); - assert_eq!(scheduler.num_scheduled_telecommands(), 0); + } + + + #[test] + fn time() { + let mut scheduler = + PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let time = UnixTimestamp::new(1,2).unwrap(); + scheduler.update_time(time); + assert_eq!(scheduler.current_time(), &time); + } + + #[test] + fn release_basic() { + let mut scheduler = + PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + + scheduler.insert_tc( + UnixTimestamp::new_only_seconds(100), + StoreAddr { + pool_idx: 0, + packet_idx: 1, + }, + ); + + scheduler.insert_tc( + UnixTimestamp::new_only_seconds(200), + StoreAddr { + pool_idx: 0, + packet_idx: 2, + }, + ); + + let mut i = 0; + let mut test_closure_1 = |boolvar: bool, store_addr: &StoreAddr| { + assert_eq!(boolvar, true); + assert_eq!(store_addr, &StoreAddr { + pool_idx: 0, + packet_idx: 1, + }); + i += 1; + }; + + // test 1: too early, no tcs + scheduler.update_time(UnixTimestamp::new_only_seconds(99)); + + scheduler.release_telecommands( &mut test_closure_1); + + // test 2: exact time stamp of tc, releases 1 tc + scheduler.update_time(UnixTimestamp::new_only_seconds(100)); + + scheduler.release_telecommands(&mut test_closure_1); + + // test 3, late timestamp, release 1 overdue tc + let mut test_closure_2 = |boolvar: bool, store_addr: &StoreAddr| { + assert_eq!(boolvar, true); + assert_eq!(store_addr, &StoreAddr { + pool_idx: 0, + packet_idx: 2, + }); + i += 1; + }; + + scheduler.update_time(UnixTimestamp::new_only_seconds(206)); + + scheduler.release_telecommands(&mut test_closure_2); + + //test 4: no tcs left + scheduler.release_telecommands(&mut test_closure_2); + + // check that 2 total tcs have been released + assert_eq!(i, 2); + } + + #[test] + fn release_multi_with_same_time() { + let mut scheduler = + PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + + scheduler.insert_tc( + UnixTimestamp::new_only_seconds(100), + StoreAddr { + pool_idx: 0, + packet_idx: 1, + }, + ); + + scheduler.insert_tc( + UnixTimestamp::new_only_seconds(100), + StoreAddr { + pool_idx: 0, + packet_idx: 1, + }, + ); + + let mut i = 0; + let mut test_closure = |boolvar: bool, store_addr: &StoreAddr| { + assert_eq!(boolvar, true); + assert_eq!(store_addr, &StoreAddr { + pool_idx: 0, + packet_idx: 1, + }); + i += 1; + }; + + // test 1: too early, no tcs + scheduler.update_time(UnixTimestamp::new_only_seconds(99)); + + scheduler.release_telecommands( &mut test_closure); + + // test 2: exact time stamp of tc, releases 2 tc + scheduler.update_time(UnixTimestamp::new_only_seconds(100)); + + scheduler.release_telecommands(&mut test_closure); + + //test 3: no tcs left + scheduler.release_telecommands(&mut test_closure); + + // check that 2 total tcs have been released + assert_eq!(i, 2); } }