Merge remote-tracking branch 'origin/main' into python-interop-example
All checks were successful
Rust/cfdp/pipeline/head This commit looks good

This commit is contained in:
Robin Müller 2024-08-28 09:57:28 +02:00
commit e7d6663022
2 changed files with 117 additions and 9 deletions

View File

@ -561,6 +561,10 @@ impl<
) { ) {
Ok(checksum_success) => { Ok(checksum_success) => {
file_delivery_complete = checksum_success; file_delivery_complete = checksum_success;
if !checksum_success {
self.tparams.tstate.delivery_code = DeliveryCode::Incomplete;
self.tparams.tstate.condition_code = ConditionCode::FileChecksumFailure;
}
} }
Err(e) => match e { Err(e) => match e {
FilestoreError::ChecksumTypeNotImplemented(_) => { FilestoreError::ChecksumTypeNotImplemented(_) => {
@ -850,7 +854,7 @@ impl<
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::{borrow::BorrowMut, cell::Cell, sync::atomic::AtomicBool}; use core::{cell::Cell, sync::atomic::AtomicBool};
#[allow(unused_imports)] #[allow(unused_imports)]
use std::println; use std::println;
use std::{fs, string::String}; use std::{fs, string::String};
@ -860,11 +864,7 @@ mod tests {
use spacepackets::{ use spacepackets::{
cfdp::{ cfdp::{
lv::Lv, lv::Lv,
pdu::{ pdu::{finished::FinishedPduReader, metadata::MetadataPduCreator, WritablePduPacket},
finished::{self, FinishedPduReader},
metadata::MetadataPduCreator,
WritablePduPacket,
},
ChecksumType, TransmissionMode, ChecksumType, TransmissionMode,
}, },
util::{UbfU16, UnsignedByteFieldU16}, util::{UbfU16, UnsignedByteFieldU16},
@ -1526,6 +1526,9 @@ mod tests {
let transaction_id = tb.handler.transaction_id().unwrap(); let transaction_id = tb.handler.transaction_id().unwrap();
let mut fault_hook = tb.handler.local_cfg.user_fault_hook().borrow_mut(); let mut fault_hook = tb.handler.local_cfg.user_fault_hook().borrow_mut();
assert!(fault_hook.notice_of_suspension_queue.is_empty()); assert!(fault_hook.notice_of_suspension_queue.is_empty());
// The file checksum failure is ignored by default and check limit handling is now
// performed.
let ignored_queue = &mut fault_hook.ignored_queue; let ignored_queue = &mut fault_hook.ignored_queue;
assert_eq!(ignored_queue.len(), 1); assert_eq!(ignored_queue.len(), 1);
let cancelled = ignored_queue.pop_front().unwrap(); let cancelled = ignored_queue.pop_front().unwrap();
@ -1552,6 +1555,7 @@ mod tests {
.expect("fsm error"); .expect("fsm error");
tb.state_check(State::Idle, TransactionStep::Idle); tb.state_check(State::Idle, TransactionStep::Idle);
// Transaction is cancelled because the check limit is reached.
let mut fault_hook = tb.handler.local_cfg.user_fault_hook().borrow_mut(); let mut fault_hook = tb.handler.local_cfg.user_fault_hook().borrow_mut();
let cancelled_queue = &mut fault_hook.notice_of_cancellation_queue; let cancelled_queue = &mut fault_hook.notice_of_cancellation_queue;
assert_eq!(cancelled_queue.len(), 1); assert_eq!(cancelled_queue.len(), 1);
@ -1575,6 +1579,12 @@ mod tests {
ConditionCode::CheckLimitReached ConditionCode::CheckLimitReached
); );
assert_eq!(finished_pdu.delivery_code(), DeliveryCode::Incomplete); assert_eq!(finished_pdu.delivery_code(), DeliveryCode::Incomplete);
assert!(finished_pdu.fault_location().is_some());
assert_eq!(
*finished_pdu.fault_location().unwrap().entity_id(),
REMOTE_ID.into()
);
assert_eq!(finished_pdu.fs_responses_raw(), &[]);
assert!(tb.handler.pdu_sender.queue_empty()); assert!(tb.handler.pdu_sender.queue_empty());
tb.expected_full_data = faulty_file_data.to_vec(); tb.expected_full_data = faulty_file_data.to_vec();
} }

View File

@ -724,6 +724,7 @@ impl PduProvider for DummyPduProvider {
pub struct PacketInfo<'raw_packet> { pub struct PacketInfo<'raw_packet> {
pdu_type: PduType, pdu_type: PduType,
file_directive_type: Option<FileDirectiveType>, file_directive_type: Option<FileDirectiveType>,
packet_len: usize,
raw_packet: &'raw_packet [u8], raw_packet: &'raw_packet [u8],
} }
@ -782,6 +783,7 @@ impl<'raw> PacketInfo<'raw> {
return Ok(Self { return Ok(Self {
pdu_type: pdu_header.pdu_type(), pdu_type: pdu_header.pdu_type(),
file_directive_type: None, file_directive_type: None,
packet_len: pdu_header.pdu_len(),
raw_packet, raw_packet,
}); });
} }
@ -801,12 +803,13 @@ impl<'raw> PacketInfo<'raw> {
Ok(Self { Ok(Self {
pdu_type: pdu_header.pdu_type(), pdu_type: pdu_header.pdu_type(),
file_directive_type: Some(directive), file_directive_type: Some(directive),
packet_len: pdu_header.pdu_len(),
raw_packet, raw_packet,
}) })
} }
pub fn raw_packet(&self) -> &[u8] { pub fn raw_packet(&self) -> &[u8] {
self.raw_packet &self.raw_packet[0..self.packet_len]
} }
} }
@ -1195,6 +1198,10 @@ pub(crate) mod tests {
packet_info.file_directive_type().unwrap(), packet_info.file_directive_type().unwrap(),
FileDirectiveType::MetadataPdu FileDirectiveType::MetadataPdu
); );
assert_eq!(
packet_info.raw_packet(),
&buf[0..metadata_pdu.len_written()]
);
assert_eq!( assert_eq!(
packet_info.packet_target().unwrap(), packet_info.packet_target().unwrap(),
PacketTarget::DestEntity PacketTarget::DestEntity
@ -1210,6 +1217,10 @@ pub(crate) mod tests {
.write_to_bytes(&mut buf) .write_to_bytes(&mut buf)
.expect("writing file data PDU failed"); .expect("writing file data PDU failed");
let packet_info = PacketInfo::new(&buf).expect("creating packet info failed"); let packet_info = PacketInfo::new(&buf).expect("creating packet info failed");
assert_eq!(
packet_info.raw_packet(),
&buf[0..file_data_pdu.len_written()]
);
assert_eq!(packet_info.pdu_type(), PduType::FileData); assert_eq!(packet_info.pdu_type(), PduType::FileData);
assert!(packet_info.file_directive_type().is_none()); assert!(packet_info.file_directive_type().is_none());
assert_eq!( assert_eq!(
@ -1229,6 +1240,7 @@ pub(crate) mod tests {
let packet_info = PacketInfo::new(&buf).expect("creating packet info failed"); let packet_info = PacketInfo::new(&buf).expect("creating packet info failed");
assert_eq!(packet_info.pdu_type(), PduType::FileDirective); assert_eq!(packet_info.pdu_type(), PduType::FileDirective);
assert!(packet_info.file_directive_type().is_some()); assert!(packet_info.file_directive_type().is_some());
assert_eq!(packet_info.raw_packet(), &buf[0..eof_pdu.len_written()]);
assert_eq!( assert_eq!(
packet_info.file_directive_type().unwrap(), packet_info.file_directive_type().unwrap(),
FileDirectiveType::EofPdu FileDirectiveType::EofPdu
@ -1292,10 +1304,13 @@ pub(crate) mod tests {
assert!(!remote_entity_cfg.remove_config(REMOTE_ID.value())); assert!(!remote_entity_cfg.remove_config(REMOTE_ID.value()));
let remote_entity_retrieved = remote_entity_cfg.get(REMOTE_ID.value()).unwrap(); let remote_entity_retrieved = remote_entity_cfg.get(REMOTE_ID.value()).unwrap();
assert_eq!(remote_entity_retrieved.entity_id, REMOTE_ID.into()); assert_eq!(remote_entity_retrieved.entity_id, REMOTE_ID.into());
// Does not exist.
assert!(remote_entity_cfg.get(LOCAL_ID.value()).is_none());
assert!(remote_entity_cfg.get_mut(LOCAL_ID.value()).is_none());
} }
#[test] #[test]
fn test_remote_cfg_provider_vector() { fn test_remote_cfg_provider_std() {
let remote_entity_cfg = RemoteEntityConfig::new_with_default_values( let remote_entity_cfg = RemoteEntityConfig::new_with_default_values(
REMOTE_ID.into(), REMOTE_ID.into(),
1024, 1024,
@ -1304,7 +1319,7 @@ pub(crate) mod tests {
TransmissionMode::Unacknowledged, TransmissionMode::Unacknowledged,
ChecksumType::Crc32, ChecksumType::Crc32,
); );
let mut remote_cfg_provider = VecRemoteEntityConfigProvider::default(); let mut remote_cfg_provider = StdRemoteEntityConfigProvider::default();
assert!(remote_cfg_provider.0.is_empty()); assert!(remote_cfg_provider.0.is_empty());
remote_cfg_provider.add_config(&remote_entity_cfg); remote_cfg_provider.add_config(&remote_entity_cfg);
assert_eq!(remote_cfg_provider.0.len(), 1); assert_eq!(remote_cfg_provider.0.len(), 1);
@ -1326,6 +1341,44 @@ pub(crate) mod tests {
assert_eq!(remote_cfg_provider.0.len(), 1); assert_eq!(remote_cfg_provider.0.len(), 1);
let cfg_1_mut = remote_cfg_provider.get_mut(LOCAL_ID.value()).unwrap(); let cfg_1_mut = remote_cfg_provider.get_mut(LOCAL_ID.value()).unwrap();
cfg_1_mut.default_crc_type = ChecksumType::Crc32C; cfg_1_mut.default_crc_type = ChecksumType::Crc32C;
assert!(!remote_cfg_provider.remove_config(REMOTE_ID.value()));
assert!(remote_cfg_provider.get_mut(REMOTE_ID.value()).is_none());
}
#[test]
fn test_remote_cfg_provider_vector() {
let mut remote_cfg_provider = VecRemoteEntityConfigProvider::default();
let remote_entity_cfg = RemoteEntityConfig::new_with_default_values(
REMOTE_ID.into(),
1024,
true,
false,
TransmissionMode::Unacknowledged,
ChecksumType::Crc32,
);
assert!(remote_cfg_provider.0.is_empty());
remote_cfg_provider.add_config(&remote_entity_cfg);
assert_eq!(remote_cfg_provider.0.len(), 1);
let remote_entity_cfg_2 = RemoteEntityConfig::new_with_default_values(
LOCAL_ID.into(),
1024,
true,
false,
TransmissionMode::Unacknowledged,
ChecksumType::Crc32,
);
let cfg_0 = remote_cfg_provider.get(REMOTE_ID.value()).unwrap();
assert_eq!(cfg_0.entity_id, REMOTE_ID.into());
remote_cfg_provider.add_config(&remote_entity_cfg_2);
assert_eq!(remote_cfg_provider.0.len(), 2);
let cfg_1 = remote_cfg_provider.get(LOCAL_ID.value()).unwrap();
assert_eq!(cfg_1.entity_id, LOCAL_ID.into());
assert!(remote_cfg_provider.remove_config(REMOTE_ID.value()));
assert_eq!(remote_cfg_provider.0.len(), 1);
let cfg_1_mut = remote_cfg_provider.get_mut(LOCAL_ID.value()).unwrap();
cfg_1_mut.default_crc_type = ChecksumType::Crc32C;
assert!(!remote_cfg_provider.remove_config(REMOTE_ID.value()));
assert!(remote_cfg_provider.get_mut(REMOTE_ID.value()).is_none());
} }
#[test] #[test]
@ -1352,4 +1405,49 @@ pub(crate) mod tests {
Ok(PacketTarget::SourceEntity) Ok(PacketTarget::SourceEntity)
); );
} }
#[test]
fn test_fault_handler_checksum_error_ignored_by_default() {
let fault_handler = FaultHandler::new(TestFaultHandler::default());
assert_eq!(
fault_handler.get_fault_handler(ConditionCode::FileChecksumFailure),
FaultHandlerCode::IgnoreError
);
}
#[test]
fn test_fault_handler_unsupported_checksum_ignored_by_default() {
let fault_handler = FaultHandler::new(TestFaultHandler::default());
assert_eq!(
fault_handler.get_fault_handler(ConditionCode::UnsupportedChecksumType),
FaultHandlerCode::IgnoreError
);
}
#[test]
fn test_fault_handler_basic() {
let mut fault_handler = FaultHandler::new(TestFaultHandler::default());
assert_eq!(
fault_handler.get_fault_handler(ConditionCode::FileChecksumFailure),
FaultHandlerCode::IgnoreError
);
fault_handler.set_fault_handler(
ConditionCode::FileChecksumFailure,
FaultHandlerCode::NoticeOfCancellation,
);
assert_eq!(
fault_handler.get_fault_handler(ConditionCode::FileChecksumFailure),
FaultHandlerCode::NoticeOfCancellation
);
}
#[test]
fn transaction_id_hashable_usable_as_map_key() {
let mut map = HashMap::new();
let transaction_id_0 = TransactionId::new(
UnsignedByteFieldU8::new(1).into(),
UnsignedByteFieldU8::new(2).into(),
);
map.insert(transaction_id_0, 5_u32);
}
} }