diff --git a/satrs/src/cfdp/source.rs b/satrs/src/cfdp/source.rs index b05bca9..84aea47 100644 --- a/satrs/src/cfdp/source.rs +++ b/satrs/src/cfdp/source.rs @@ -1,5 +1,4 @@ use core::{cell::RefCell, ops::ControlFlow, str::Utf8Error}; -use std::println; use spacepackets::{ cfdp::{ @@ -748,11 +747,14 @@ impl< #[cfg(test)] mod tests { - use std::path::PathBuf; + use std::{path::PathBuf, string::ToString}; use alloc::string::String; use spacepackets::{ - cfdp::{pdu::metadata::MetadataPduReader, ChecksumType, CrcFlag}, + cfdp::{ + pdu::{finished::FinishedPduCreator, metadata::MetadataPduReader}, + ChecksumType, CrcFlag, + }, util::UnsignedByteFieldU16, }; use tempfile::TempPath; @@ -790,8 +792,8 @@ mod tests { struct SourceHandlerTestbench { handler: TestSourceHandler, - // src_path: PathBuf, - // dest_path: PathBuf, + srcfile: Option, + destfile: Option, } impl SourceHandlerTestbench { @@ -816,9 +818,22 @@ mod tests { basic_remote_cfg_table(REMOTE_ID, crc_on_transmission_by_default), SeqCountProviderSimple::default(), ), + srcfile: None, + destfile: None, } } + fn put_request( + &mut self, + put_request: &impl ReadablePutRequest, + ) -> Result<(), PutRequestError> { + if self.srcfile.is_some() || self.destfile.is_some() { + self.srcfile = Some(put_request.source_file().unwrap().to_string()); + self.destfile = Some(put_request.dest_file().unwrap().to_string()); + } + self.handler.put_request(put_request) + } + fn all_fault_queues_empty(&self) -> bool { self.handler .local_cfg @@ -834,6 +849,33 @@ mod tests { fn get_next_sent_pdu(&self) -> Option { self.handler.pdu_sender.retrieve_next_pdu() } + + fn common_pdu_check_for_file_transfer(&self, pdu_header: &PduHeader, crc_flag: CrcFlag) { + assert_eq!( + pdu_header.seg_ctrl(), + SegmentationControl::NoRecordBoundaryPreservation + ); + assert_eq!( + pdu_header.seg_metadata_flag(), + SegmentMetadataFlag::NotPresent + ); + assert_eq!(pdu_header.common_pdu_conf().source_id(), LOCAL_ID.into()); + assert_eq!(pdu_header.common_pdu_conf().dest_id(), REMOTE_ID.into()); + assert_eq!(pdu_header.common_pdu_conf().crc_flag, crc_flag); + assert_eq!( + pdu_header.common_pdu_conf().trans_mode, + TransmissionMode::Unacknowledged + ); + assert_eq!( + pdu_header.common_pdu_conf().direction, + Direction::TowardsReceiver + ); + assert_eq!( + pdu_header.common_pdu_conf().file_flag, + LargeFileFlag::Normal + ); + assert_eq!(pdu_header.common_pdu_conf().transaction_seq_num.size(), 2); + } } #[test] @@ -848,31 +890,21 @@ mod tests { assert_eq!(tb.handler.step(), TransactionStep::Idle); } - #[test] - fn test_empty_file_transfer_not_acked_no_closure() { - let fault_handler = TestFaultHandler::default(); - let test_sender = TestCfdpSender::default(); - let mut tb = SourceHandlerTestbench::new(false, fault_handler, test_sender); - let (srcfile, destfile) = init_full_filepaths_textfile(); - let srcfile_str = String::from(srcfile.to_str().unwrap()); - let destfile_str = String::from(destfile.to_str().unwrap()); - let put_request = PutRequestOwned::new_regular_request( - REMOTE_ID.into(), - &srcfile_str, - &destfile_str, - Some(TransmissionMode::Unacknowledged), - Some(false), - ) - .expect("creating put request failed"); + fn common_no_acked_file_transfer( + tb: &mut SourceHandlerTestbench, + cfdp_user: &mut TestCfdpUser, + put_request: PutRequestOwned, + srcfile_str: String, + destfile_str: String, + ) -> PduHeader { tb.handler .put_request(&put_request) .expect("put_request call failed"); assert_eq!(tb.handler.state(), State::Busy); assert_eq!(tb.handler.step(), TransactionStep::Idle); - let mut cfdp_user = TestCfdpUser::new(0, srcfile_str.clone(), destfile_str.clone(), 0); let sent_packets = tb .handler - .state_machine(&mut cfdp_user, None) + .state_machine(cfdp_user, None) .expect("source handler FSM failure"); assert_eq!(sent_packets, 2); assert!(!tb.pdu_queue_empty()); @@ -885,6 +917,8 @@ mod tests { ); let metadata_pdu = MetadataPduReader::new(&next_pdu.raw_pdu).expect("invalid metadata PDU format"); + let pdu_header = metadata_pdu.pdu_header(); + tb.common_pdu_check_for_file_transfer(metadata_pdu.pdu_header(), CrcFlag::NoCrc); assert_eq!( metadata_pdu .src_file_name() @@ -906,7 +940,16 @@ mod tests { metadata_pdu.metadata_params().checksum_type, ChecksumType::Crc32 ); - assert!(!metadata_pdu.metadata_params().closure_requested); + let closure_requested = if let Some(closure_requested) = put_request.closure_requested { + assert_eq!( + metadata_pdu.metadata_params().closure_requested, + closure_requested + ); + closure_requested + } else { + assert!(metadata_pdu.metadata_params().closure_requested); + metadata_pdu.metadata_params().closure_requested + }; assert_eq!(metadata_pdu.options(), &[]); let next_pdu = tb.get_next_sent_pdu().unwrap(); @@ -916,33 +959,10 @@ mod tests { Some(FileDirectiveType::EofPdu) ); let eof_pdu = EofPdu::from_bytes(&next_pdu.raw_pdu).expect("invalid metadata PDU format"); + tb.common_pdu_check_for_file_transfer(eof_pdu.pdu_header(), CrcFlag::NoCrc); assert_eq!(eof_pdu.condition_code(), ConditionCode::NoError); assert_eq!(eof_pdu.file_size(), 0); assert_eq!(eof_pdu.file_checksum(), CRC_32.digest().finalize()); - assert_eq!( - eof_pdu.pdu_header().common_pdu_conf().source_id(), - LOCAL_ID.into() - ); - assert_eq!( - eof_pdu.pdu_header().common_pdu_conf().dest_id(), - REMOTE_ID.into() - ); - assert_eq!( - eof_pdu.pdu_header().common_pdu_conf().crc_flag, - CrcFlag::NoCrc - ); - assert_eq!( - eof_pdu.pdu_header().common_pdu_conf().direction, - Direction::TowardsReceiver - ); - assert_eq!( - eof_pdu.pdu_header().common_pdu_conf().file_flag, - LargeFileFlag::Normal - ); - assert_eq!( - eof_pdu.pdu_header().common_pdu_conf().trans_mode, - TransmissionMode::Unacknowledged - ); assert_eq!( eof_pdu .pdu_header() @@ -951,14 +971,76 @@ mod tests { .value_const(), 0 ); - assert_eq!( - eof_pdu - .pdu_header() - .common_pdu_conf() - .transaction_seq_num - .size(), - 2 + if !closure_requested { + assert_eq!(tb.handler.state(), State::Idle); + assert_eq!(tb.handler.step(), TransactionStep::Idle); + } else { + assert_eq!(tb.handler.state(), State::Busy); + assert_eq!(tb.handler.step(), TransactionStep::WaitingForFinished); + } + *pdu_header + } + + #[test] + fn test_empty_file_transfer_not_acked_no_closure() { + let fault_handler = TestFaultHandler::default(); + let test_sender = TestCfdpSender::default(); + let mut tb = SourceHandlerTestbench::new(false, fault_handler, test_sender); + let (srcfile, destfile) = init_full_filepaths_textfile(); + let srcfile_str = String::from(srcfile.to_str().unwrap()); + let destfile_str = String::from(destfile.to_str().unwrap()); + let put_request = PutRequestOwned::new_regular_request( + REMOTE_ID.into(), + &srcfile_str, + &destfile_str, + Some(TransmissionMode::Unacknowledged), + Some(false), + ) + .expect("creating put request failed"); + let mut cfdp_user = TestCfdpUser::new(0, srcfile_str.clone(), destfile_str.clone(), 0); + common_no_acked_file_transfer( + &mut tb, + &mut cfdp_user, + put_request, + srcfile_str, + destfile_str, ); + } + + #[test] + fn test_empty_file_transfer_not_acked_with_closure() { + let fault_handler = TestFaultHandler::default(); + let test_sender = TestCfdpSender::default(); + let mut tb = SourceHandlerTestbench::new(false, fault_handler, test_sender); + let (srcfile, destfile) = init_full_filepaths_textfile(); + let srcfile_str = String::from(srcfile.to_str().unwrap()); + let destfile_str = String::from(destfile.to_str().unwrap()); + let put_request = PutRequestOwned::new_regular_request( + REMOTE_ID.into(), + &srcfile_str, + &destfile_str, + Some(TransmissionMode::Unacknowledged), + Some(true), + ) + .expect("creating put request failed"); + let mut cfdp_user = TestCfdpUser::new(0, srcfile_str.clone(), destfile_str.clone(), 0); + let pdu_header = common_no_acked_file_transfer( + &mut tb, + &mut cfdp_user, + put_request, + srcfile_str, + destfile_str, + ); + let finished_pdu = FinishedPduCreator::new_default( + pdu_header, + DeliveryCode::Complete, + FileStatus::Retained, + ); + let finished_pdu_vec = finished_pdu.to_vec().unwrap(); + let packet_info = PacketInfo::new(&finished_pdu_vec).unwrap(); + tb.handler + .state_machine(&mut cfdp_user, Some(&packet_info)) + .unwrap(); assert_eq!(tb.handler.state(), State::Idle); assert_eq!(tb.handler.step(), TransactionStep::Idle); }