good coverage
This commit is contained in:
parent
7d695fc15b
commit
745bbb745e
@ -56,7 +56,7 @@ optional = true
|
|||||||
# version = "0.5.2"
|
# version = "0.5.2"
|
||||||
# path = "../spacepackets"
|
# path = "../spacepackets"
|
||||||
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
||||||
rev = "7aa3432f167d3b5d888a4aa0606780188d74f567"
|
rev = "8cf6f72cf35df42cc7cde5dd45c77cfd56231dbd"
|
||||||
|
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
|
@ -30,10 +30,10 @@ pub mod params;
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
||||||
pub mod pool;
|
pub mod pool;
|
||||||
|
pub mod power;
|
||||||
pub mod pus;
|
pub mod pus;
|
||||||
pub mod res_code;
|
pub mod res_code;
|
||||||
pub mod seq_count;
|
pub mod seq_count;
|
||||||
pub mod tmtc;
|
pub mod tmtc;
|
||||||
pub mod power;
|
|
||||||
|
|
||||||
pub use spacepackets;
|
pub use spacepackets;
|
||||||
|
@ -21,7 +21,7 @@ pub enum SwitchState {
|
|||||||
Off = 0,
|
Off = 0,
|
||||||
On = 1,
|
On = 1,
|
||||||
Unknown = 2,
|
Unknown = 2,
|
||||||
Faulty = 3
|
Faulty = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SwitchId = u16;
|
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_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>;
|
||||||
fn send_switch_off_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()
|
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()
|
switch.switch_off()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,11 @@ use std::time::SystemTimeError;
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ScheduleError {
|
pub enum ScheduleError {
|
||||||
PusError(PusError),
|
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,
|
NestedScheduledTc,
|
||||||
StoreError(StoreError),
|
StoreError(StoreError),
|
||||||
TcDataEmpty,
|
TcDataEmpty,
|
||||||
@ -33,11 +37,10 @@ impl Display for ScheduleError {
|
|||||||
ScheduleError::PusError(e) => {
|
ScheduleError::PusError(e) => {
|
||||||
write!(f, "Pus Error: {}", e)
|
write!(f, "Pus Error: {}", e)
|
||||||
}
|
}
|
||||||
ScheduleError::TimeMarginTooShort(current_time, timestamp) => {
|
ScheduleError::ReleaseTimeInTimeMargin(current_time, margin, timestamp) => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Error: time margin too short, current time: {:?}, time stamp: {:?}",
|
"Error: time margin too short, current time: {current_time:?}, time margin: {margin:?}, release time: {timestamp:?}"
|
||||||
current_time, timestamp
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ScheduleError::NestedScheduledTc => {
|
ScheduleError::NestedScheduledTc => {
|
||||||
@ -186,8 +189,9 @@ impl PusScheduler {
|
|||||||
addr: StoreAddr,
|
addr: StoreAddr,
|
||||||
) -> Result<(), ScheduleError> {
|
) -> Result<(), ScheduleError> {
|
||||||
if time_stamp < self.current_time + self.time_margin {
|
if time_stamp < self.current_time + self.time_margin {
|
||||||
return Err(ScheduleError::TimeMarginTooShort(
|
return Err(ScheduleError::ReleaseTimeInTimeMargin(
|
||||||
self.current_time,
|
self.current_time,
|
||||||
|
self.time_margin,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -222,7 +226,6 @@ impl PusScheduler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// <T: FnMut(&[u8]) -> (&dyn CcsdsTimeProvider)>
|
|
||||||
pub fn insert_wrapped_tc<TimeStamp: CcsdsTimeProvider + TimeReader>(
|
pub fn insert_wrapped_tc<TimeStamp: CcsdsTimeProvider + TimeReader>(
|
||||||
&mut self,
|
&mut self,
|
||||||
pus_tc: &PusTc,
|
pus_tc: &PusTc,
|
||||||
@ -321,6 +324,62 @@ mod tests {
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use std::{println, vec};
|
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]
|
#[test]
|
||||||
fn basic() {
|
fn basic() {
|
||||||
let mut scheduler =
|
let mut scheduler =
|
||||||
@ -328,6 +387,8 @@ mod tests {
|
|||||||
assert!(scheduler.is_enabled());
|
assert!(scheduler.is_enabled());
|
||||||
scheduler.disable();
|
scheduler.disable();
|
||||||
assert!(!scheduler.is_enabled());
|
assert!(!scheduler.is_enabled());
|
||||||
|
scheduler.enable();
|
||||||
|
assert!(scheduler.is_enabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -616,68 +677,6 @@ mod tests {
|
|||||||
assert_eq!(i, 2);
|
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]
|
#[test]
|
||||||
fn insert_unwrapped_tc() {
|
fn insert_unwrapped_tc() {
|
||||||
let mut scheduler =
|
let mut scheduler =
|
||||||
@ -701,7 +700,7 @@ mod tests {
|
|||||||
|
|
||||||
scheduler.update_time(UnixTimestamp::new_only_seconds(101));
|
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 i = 0;
|
||||||
let mut test_closure = |boolvar: bool, store_addr: &StoreAddr| {
|
let mut test_closure = |boolvar: bool, store_addr: &StoreAddr| {
|
||||||
@ -730,9 +729,7 @@ mod tests {
|
|||||||
let mut buf: [u8; 32] = [0; 32];
|
let mut buf: [u8; 32] = [0; 32];
|
||||||
let tc = scheduled_tc(UnixTimestamp::new_only_seconds(100), &mut buf);
|
let tc = scheduled_tc(UnixTimestamp::new_only_seconds(100), &mut buf);
|
||||||
|
|
||||||
let addr = match scheduler
|
let addr = match scheduler.insert_wrapped_tc::<cds::TimeProvider>(&tc, &mut pool) {
|
||||||
.insert_wrapped_tc::<spacepackets::time::cds::TimeProvider>(&tc, &mut pool)
|
|
||||||
{
|
|
||||||
Ok(addr) => addr,
|
Ok(addr) => addr,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{}", e);
|
println!("{}", e);
|
||||||
@ -779,7 +776,7 @@ mod tests {
|
|||||||
let mut buf: [u8; 32] = [0; 32];
|
let mut buf: [u8; 32] = [0; 32];
|
||||||
let tc = wrong_tc_service(UnixTimestamp::new_only_seconds(100), &mut buf);
|
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());
|
assert!(err.is_err());
|
||||||
let err = err.unwrap_err();
|
let err = err.unwrap_err();
|
||||||
match err {
|
match err {
|
||||||
@ -800,7 +797,7 @@ mod tests {
|
|||||||
let mut buf: [u8; 32] = [0; 32];
|
let mut buf: [u8; 32] = [0; 32];
|
||||||
let tc = wrong_tc_subservice(UnixTimestamp::new_only_seconds(100), &mut buf);
|
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());
|
assert!(err.is_err());
|
||||||
let err = err.unwrap_err();
|
let err = err.unwrap_err();
|
||||||
match 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}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user