From 745bbb745eae9ab85570c1722bc57a72b01fdbd2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 5 Feb 2023 18:59:28 +0100 Subject: [PATCH] good coverage --- satrs-core/Cargo.toml | 2 +- satrs-core/src/lib.rs | 2 +- satrs-core/src/power.rs | 14 +- satrs-core/src/pus/scheduling.rs | 218 ++++++++++++++++++++----------- 4 files changed, 156 insertions(+), 80 deletions(-) diff --git a/satrs-core/Cargo.toml b/satrs-core/Cargo.toml index 776995e..638e812 100644 --- a/satrs-core/Cargo.toml +++ b/satrs-core/Cargo.toml @@ -56,7 +56,7 @@ optional = true # version = "0.5.2" # path = "../spacepackets" git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git" -rev = "7aa3432f167d3b5d888a4aa0606780188d74f567" +rev = "8cf6f72cf35df42cc7cde5dd45c77cfd56231dbd" default-features = false diff --git a/satrs-core/src/lib.rs b/satrs-core/src/lib.rs index f4e0a9d..f8b3b31 100644 --- a/satrs-core/src/lib.rs +++ b/satrs-core/src/lib.rs @@ -30,10 +30,10 @@ pub mod params; #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub mod pool; +pub mod power; pub mod pus; pub mod res_code; pub mod seq_count; pub mod tmtc; -pub mod power; pub use spacepackets; diff --git a/satrs-core/src/power.rs b/satrs-core/src/power.rs index 0901acd..0875b87 100644 --- a/satrs-core/src/power.rs +++ b/satrs-core/src/power.rs @@ -21,7 +21,7 @@ pub enum SwitchState { Off = 0, On = 1, Unknown = 2, - Faulty = 3 + Faulty = 3, } pub type SwitchId = u16; @@ -33,10 +33,16 @@ pub trait PowerSwitcher { fn send_switch_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>; fn send_switch_off_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>; - fn switch_on(&mut self, switch: &mut T) -> Result<(), ::Error> { + fn switch_on( + &mut self, + switch: &mut T, + ) -> Result<(), ::Error> { switch.switch_on() } - fn switch_off(&mut self, switch: &mut T) -> Result<(), ::Error> { + fn switch_off( + &mut self, + switch: &mut T, + ) -> Result<(), ::Error> { switch.switch_off() } @@ -52,4 +58,4 @@ pub trait PowerSwitcher { /// This may take into account the time to send a command, wait for it to be executed, and /// see the switch changed. fn switch_delay_ms(&self) -> u32; -} \ No newline at end of file +} diff --git a/satrs-core/src/pus/scheduling.rs b/satrs-core/src/pus/scheduling.rs index a8ceeca..45bba51 100644 --- a/satrs-core/src/pus/scheduling.rs +++ b/satrs-core/src/pus/scheduling.rs @@ -18,7 +18,11 @@ use std::time::SystemTimeError; #[derive(Debug, Clone, PartialEq, Eq)] pub enum ScheduleError { PusError(PusError), - TimeMarginTooShort(UnixTimestamp, UnixTimestamp), + /// The release time is within the time-margin added on top of the current time. + /// The first parameter is the current time, the second one the time margin, and the third one + /// the release time. + ReleaseTimeInTimeMargin(UnixTimestamp, Duration, UnixTimestamp), + /// Nested time-tagged commands are not allowed. NestedScheduledTc, StoreError(StoreError), TcDataEmpty, @@ -33,11 +37,10 @@ impl Display for ScheduleError { ScheduleError::PusError(e) => { write!(f, "Pus Error: {}", e) } - ScheduleError::TimeMarginTooShort(current_time, timestamp) => { + ScheduleError::ReleaseTimeInTimeMargin(current_time, margin, timestamp) => { write!( f, - "Error: time margin too short, current time: {:?}, time stamp: {:?}", - current_time, timestamp + "Error: time margin too short, current time: {current_time:?}, time margin: {margin:?}, release time: {timestamp:?}" ) } ScheduleError::NestedScheduledTc => { @@ -186,8 +189,9 @@ impl PusScheduler { addr: StoreAddr, ) -> Result<(), ScheduleError> { if time_stamp < self.current_time + self.time_margin { - return Err(ScheduleError::TimeMarginTooShort( + return Err(ScheduleError::ReleaseTimeInTimeMargin( self.current_time, + self.time_margin, time_stamp, )); } @@ -222,7 +226,6 @@ impl PusScheduler { } } - // (&dyn CcsdsTimeProvider)> pub fn insert_wrapped_tc( &mut self, pus_tc: &PusTc, @@ -321,6 +324,62 @@ mod tests { #[allow(unused_imports)] use std::{println, vec}; + fn pus_tc_base(timestamp: UnixTimestamp, buf: &mut [u8]) -> (SpHeader, usize) { + let cds_time = cds::TimeProvider::from_unix_secs_with_u16_days(×tamp).unwrap(); + let len_time_stamp = cds_time.write_to_bytes(buf).unwrap(); + let len_packet = base_ping_tc_simple_ctor() + .write_to_bytes(&mut buf[len_time_stamp..]) + .unwrap(); + ( + SpHeader::tc_unseg(0x02, 0x34, len_packet as u16).unwrap(), + len_packet + len_time_stamp, + ) + } + + fn scheduled_tc(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTc { + let (mut sph, len_app_data) = pus_tc_base(timestamp, buf); + PusTc::new_simple(&mut sph, 11, 4, Some(&buf[..len_app_data]), true) + } + + fn wrong_tc_service(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTc { + let (mut sph, len_app_data) = pus_tc_base(timestamp, buf); + PusTc::new_simple(&mut sph, 12, 4, Some(&buf[..len_app_data]), true) + } + + fn wrong_tc_subservice(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTc { + let (mut sph, len_app_data) = pus_tc_base(timestamp, buf); + PusTc::new_simple(&mut sph, 11, 5, Some(&buf[..len_app_data]), true) + } + + fn double_wrapped_time_tagged_tc(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTc { + let cds_time = cds::TimeProvider::from_unix_secs_with_u16_days(×tamp).unwrap(); + let len_time_stamp = cds_time.write_to_bytes(buf).unwrap(); + let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); + // app data should not matter, double wrapped time-tagged commands should be rejected right + // away + let inner_time_tagged_tc = PusTc::new_simple(&mut sph, 11, 4, None, true); + let packet_len = inner_time_tagged_tc + .write_to_bytes(&mut buf[len_time_stamp..]) + .expect("writing inner time tagged tc failed"); + PusTc::new_simple( + &mut sph, + 11, + 4, + Some(&buf[..len_time_stamp + packet_len]), + true, + ) + } + + fn invalid_time_tagged_cmd() -> PusTc<'static> { + let mut sph = SpHeader::tc_unseg(0x02, 0x34, 1).unwrap(); + PusTc::new_simple(&mut sph, 11, 4, None, true) + } + + fn base_ping_tc_simple_ctor() -> PusTc<'static> { + let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); + PusTc::new_simple(&mut sph, 17, 1, None, true) + } + #[test] fn basic() { let mut scheduler = @@ -328,6 +387,8 @@ mod tests { assert!(scheduler.is_enabled()); scheduler.disable(); assert!(!scheduler.is_enabled()); + scheduler.enable(); + assert!(scheduler.is_enabled()); } #[test] @@ -616,68 +677,6 @@ mod tests { assert_eq!(i, 2); } - fn scheduled_tc(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTc { - let cds_time = cds::TimeProvider::from_unix_secs_with_u16_days(×tamp).unwrap(); - - let len_time_stamp = cds_time.write_to_bytes(buf).unwrap(); - - let len_packet = base_ping_tc_simple_ctor() - .write_to_bytes(&mut buf[len_time_stamp..]) - .unwrap(); - let mut sph = SpHeader::tc_unseg(0x02, 0x34, len_packet as u16).unwrap(); - - PusTc::new_simple( - &mut sph, - 11, - 4, - Some(&buf[..len_packet + len_time_stamp]), - true, - ) - } - - fn wrong_tc_service(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTc { - let cds_time = cds::TimeProvider::from_unix_secs_with_u16_days(×tamp).unwrap(); - - let len_time_stamp = cds_time.write_to_bytes(buf).unwrap(); - - let len_packet = base_ping_tc_simple_ctor() - .write_to_bytes(&mut buf[len_time_stamp..]) - .unwrap(); - let mut sph = SpHeader::tc_unseg(0x02, 0x34, len_packet as u16).unwrap(); - - PusTc::new_simple( - &mut sph, - 12, - 4, - Some(&buf[..len_packet + len_time_stamp]), - true, - ) - } - - fn wrong_tc_subservice(timestamp: UnixTimestamp, buf: &mut [u8]) -> PusTc { - let cds_time = cds::TimeProvider::from_unix_secs_with_u16_days(×tamp).unwrap(); - - let len_time_stamp = cds_time.write_to_bytes(buf).unwrap(); - - let len_packet = base_ping_tc_simple_ctor() - .write_to_bytes(&mut buf[len_time_stamp..]) - .unwrap(); - let mut sph = SpHeader::tc_unseg(0x02, 0x34, len_packet as u16).unwrap(); - - PusTc::new_simple( - &mut sph, - 11, - 5, - Some(&buf[..len_packet + len_time_stamp]), - true, - ) - } - - fn base_ping_tc_simple_ctor() -> PusTc<'static> { - let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); - PusTc::new_simple(&mut sph, 17, 1, None, true) - } - #[test] fn insert_unwrapped_tc() { let mut scheduler = @@ -701,7 +700,7 @@ mod tests { scheduler.update_time(UnixTimestamp::new_only_seconds(101)); - let mut addr_vec = vec::Vec::new(); + let mut addr_vec = Vec::new(); let mut i = 0; let mut test_closure = |boolvar: bool, store_addr: &StoreAddr| { @@ -730,9 +729,7 @@ mod tests { let mut buf: [u8; 32] = [0; 32]; let tc = scheduled_tc(UnixTimestamp::new_only_seconds(100), &mut buf); - let addr = match scheduler - .insert_wrapped_tc::(&tc, &mut pool) - { + let addr = match scheduler.insert_wrapped_tc::(&tc, &mut pool) { Ok(addr) => addr, Err(e) => { println!("{}", e); @@ -779,7 +776,7 @@ mod tests { let mut buf: [u8; 32] = [0; 32]; let tc = wrong_tc_service(UnixTimestamp::new_only_seconds(100), &mut buf); - let err = scheduler.insert_wrapped_tc::(&tc, &mut pool); + let err = scheduler.insert_wrapped_tc::(&tc, &mut pool); assert!(err.is_err()); let err = err.unwrap_err(); match err { @@ -800,7 +797,7 @@ mod tests { let mut buf: [u8; 32] = [0; 32]; let tc = wrong_tc_subservice(UnixTimestamp::new_only_seconds(100), &mut buf); - let err = scheduler.insert_wrapped_tc::(&tc, &mut pool); + let err = scheduler.insert_wrapped_tc::(&tc, &mut pool); assert!(err.is_err()); let err = err.unwrap_err(); match err { @@ -810,4 +807,77 @@ mod tests { } } } + + #[test] + fn insert_wrapped_tc_faulty_app_data() { + let mut scheduler = + PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)])); + let tc = invalid_time_tagged_cmd(); + let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); + assert!(insert_res.is_err()); + let err = insert_res.unwrap_err(); + match err { + ScheduleError::TcDataEmpty => {} + _ => panic!("unexpected error {err}"), + } + } + + #[test] + fn insert_doubly_wrapped_time_tagged_cmd() { + let mut scheduler = + PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)])); + let mut buf: [u8; 64] = [0; 64]; + let tc = double_wrapped_time_tagged_tc(UnixTimestamp::new_only_seconds(50), &mut buf); + let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); + assert!(insert_res.is_err()); + let err = insert_res.unwrap_err(); + match err { + ScheduleError::NestedScheduledTc => {} + _ => panic!("unexpected error {err}"), + } + } + + #[test] + fn test_ctor_from_current() { + let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5)) + .expect("creation from current time failed"); + let current_time = scheduler.current_time; + assert!(current_time.unix_seconds > 0); + } + + #[test] + fn test_update_from_current() { + let mut scheduler = + PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + assert_eq!(scheduler.current_time.unix_seconds, 0); + scheduler + .update_time_from_now() + .expect("updating scheduler time from now failed"); + assert!(scheduler.current_time.unix_seconds > 0); + } + + #[test] + fn release_time_within_time_margin() { + let mut scheduler = + PusScheduler::new(UnixTimestamp::new_only_seconds(0), Duration::from_secs(5)); + + let mut pool = LocalPool::new(PoolCfg::new(vec![(10, 32), (5, 64)])); + + let mut buf: [u8; 32] = [0; 32]; + + let tc = scheduled_tc(UnixTimestamp::new_only_seconds(4), &mut buf); + let insert_res = scheduler.insert_wrapped_tc::(&tc, &mut pool); + assert!(insert_res.is_err()); + let err = insert_res.unwrap_err(); + match err { + ScheduleError::ReleaseTimeInTimeMargin(curr_time, margin, release_time) => { + assert_eq!(curr_time, UnixTimestamp::new_only_seconds(0)); + assert_eq!(margin, Duration::from_secs(5)); + assert_eq!(release_time, UnixTimestamp::new_only_seconds(4)); + } + _ => panic!("unexepcted error {err}"), + } + } }