good coverage

This commit is contained in:
Robin Müller 2023-02-05 18:59:28 +01:00
parent 7d695fc15b
commit 745bbb745e
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
4 changed files with 156 additions and 80 deletions

View File

@ -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

View File

@ -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;

View File

@ -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<T: PowerSwitch>(&mut self, switch: &mut T) -> Result<(), <T as PowerSwitch>::Error> {
fn switch_on<T: PowerSwitch>(
&mut self,
switch: &mut T,
) -> Result<(), <T as PowerSwitch>::Error> {
switch.switch_on()
}
fn switch_off<T: PowerSwitch>(&mut self, switch: &mut T) -> Result<(), <T as PowerSwitch>::Error> {
fn switch_off<T: PowerSwitch>(
&mut self,
switch: &mut T,
) -> Result<(), <T as PowerSwitch>::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;
}
}

View File

@ -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 {
}
}
// <T: FnMut(&[u8]) -> (&dyn CcsdsTimeProvider)>
pub fn insert_wrapped_tc<TimeStamp: CcsdsTimeProvider + TimeReader>(
&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(&timestamp).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(&timestamp).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(&timestamp).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(&timestamp).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(&timestamp).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::<spacepackets::time::cds::TimeProvider>(&tc, &mut pool)
{
let addr = match scheduler.insert_wrapped_tc::<cds::TimeProvider>(&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::<spacepackets::time::cds::TimeProvider>(&tc, &mut pool);
let err = scheduler.insert_wrapped_tc::<cds::TimeProvider>(&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::<spacepackets::time::cds::TimeProvider>(&tc, &mut pool);
let err = scheduler.insert_wrapped_tc::<cds::TimeProvider>(&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::<cds::TimeProvider>(&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::<cds::TimeProvider>(&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::<cds::TimeProvider>(&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}"),
}
}
}