this is the last test

This commit is contained in:
Robin Mueller
2025-09-24 19:37:13 +02:00
parent de3e5c52cb
commit 646ecfe54d
2 changed files with 337 additions and 13 deletions

View File

@@ -1286,8 +1286,11 @@ impl<
)?;
sent_packets += 1;
} else {
sent_packets += self
.write_multi_packet_nak_sequence(max_segment_reqs, acked_params.metadata_missing)?;
sent_packets += self.write_multi_packet_nak_sequence(
segments_to_send,
max_segment_reqs,
acked_params.metadata_missing,
)?;
}
Ok(sent_packets)
@@ -1296,6 +1299,7 @@ impl<
#[cold]
fn write_multi_packet_nak_sequence(
&mut self,
mut segments_to_send: usize,
max_segments: usize,
first_segment_metadata: bool,
) -> Result<u32, DestError> {
@@ -1310,7 +1314,6 @@ impl<
let mut segment_index = 0;
let mut buf_index = 0;
let mut remaining = max_segments;
let mut current_start_of_scope = 0;
let mut current_end_of_scope = 0;
let mut seg_buf = nak_pdu_creator.segment_request_buffer_mut();
@@ -1338,13 +1341,13 @@ impl<
&self.pdu_and_cksum_buffer.borrow()[..written_len],
)?;
sent_packets += 1;
remaining = remaining.saturating_sub(max_segments);
segments_to_send = segments_to_send.saturating_sub(max_segments);
// new PDU with the same capacity
nak_pdu_creator = NakPduCreatorWithReservedSeqReqsBuf::new(
self.pdu_and_cksum_buffer.get_mut(),
pdu_header,
core::cmp::min(remaining, max_segments),
core::cmp::min(segments_to_send, max_segments),
)
.unwrap();
seg_buf = nak_pdu_creator.segment_request_buffer_mut();
@@ -1383,6 +1386,7 @@ impl<
FileDirectiveType::NakPdu,
&self.pdu_and_cksum_buffer.borrow()[..written_len],
)?;
sent_packets += 1;
}
Ok(sent_packets)
}
@@ -2425,6 +2429,37 @@ mod tests {
tb.check_completion_indication_success(&mut test_user);
}
#[test]
fn test_empty_file_transfer_invalid_remote_id() {
let fault_handler = TestFaultHandler::default();
let mut tb = DestHandlerTestbench::new_with_fixed_paths(
fault_handler,
TransmissionMode::Unacknowledged,
false,
);
let mut test_user = tb.test_user_from_cached_paths(0);
let mut conf = tb.pdu_conf;
// Just swap them..
conf.set_source_and_dest_id(REMOTE_ID, LOCAL_ID).unwrap();
let pdu_header = PduHeader::new_for_file_directive(conf, 0);
let metadata_pdu = create_metadata_pdu(
&pdu_header,
tb.src_path.as_path(),
tb.dest_path.as_path(),
0,
false,
);
let packet_info = create_packet_info(&metadata_pdu, &mut tb.buf);
if let Err(DestError::NoRemoteConfigFound(id)) =
tb.handler.state_machine(&mut test_user, Some(&packet_info))
{
assert_eq!(id, REMOTE_ID.into());
} else {
panic!("expected no remote config found error");
}
tb.check_dest_file = false;
}
#[test]
fn test_empty_file_transfer_acked() {
let fault_handler = TestFaultHandler::default();
@@ -3763,4 +3798,288 @@ mod tests {
assert_eq!(cancellation.progress(), 0);
}
}
#[test]
fn test_multi_segment_nak() {
let file_data_str = "Hello Wooorld!";
let file_data = file_data_str.as_bytes();
let file_size = file_data.len() as u64;
let fault_handler = TestFaultHandler::default();
let mut tb = DestHandlerTestbench::new_with_fixed_paths(
fault_handler,
TransmissionMode::Acknowledged,
false,
);
// Disable this, we only want to check the deferred procedure.
tb.remote_cfg_mut().immediate_nak_mode = false;
let mut user = tb.test_user_from_cached_paths(file_size);
let transfer_info = tb
.generic_transfer_init(&mut user, file_size)
.expect("transfer init failed");
tb.state_check(State::Busy, TransactionStep::ReceivingFileDataPdus);
assert_eq!(
tb.generic_file_data_insert(&mut user, 2, &file_data[2..4])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 6, &file_data[6..8])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 10, &file_data[10..])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_eof_no_error(&mut user, file_data.to_vec())
.expect("EOF no error insertion failed"),
2
);
assert_eq!(tb.pdu_queue_len(), 2);
tb.check_eof_ack_pdu(ConditionCode::NoError);
assert_eq!(tb.pdu_queue_len(), 1);
let pdu = tb.get_next_pdu().unwrap();
assert_eq!(pdu.pdu_type, PduType::FileDirective);
assert_eq!(pdu.file_directive_type.unwrap(), FileDirectiveType::NakPdu);
let nak_pdu = NakPduReader::new(&pdu.raw_pdu).unwrap();
assert_eq!(nak_pdu.start_of_scope(), 0);
assert_eq!(nak_pdu.end_of_scope(), file_size);
let seg_reqs: Vec<(u64, u64)> = nak_pdu.get_segment_requests_iterator().unwrap().collect();
assert_eq!(seg_reqs.len(), 3);
assert_eq!(seg_reqs[0], (0, 2));
assert_eq!(seg_reqs[1], (4, 6));
assert_eq!(seg_reqs[2], (8, 10));
// We simulate the reply by re-inserting the missing file segment.
tb.generic_file_data_insert(&mut user, 0, &file_data[0..2])
.expect("file data insertion failed");
tb.generic_file_data_insert(&mut user, 4, &file_data[4..6])
.expect("file data insertion failed");
tb.generic_file_data_insert(&mut user, 8, &file_data[8..10])
.expect("file data insertion failed");
tb.check_completion_indication_success(&mut user);
assert_eq!(tb.pdu_queue_len(), 1);
tb.check_finished_pdu_success();
tb.acknowledge_finished_pdu(&mut user, &transfer_info);
}
#[test]
fn test_multi_packet_nak_sequence_large_file_flag() {
let file_data = [0_u8; 64];
let file_size = file_data.len() as u64;
let fault_handler = TestFaultHandler::default();
let mut tb = DestHandlerTestbench::new_with_fixed_paths(
fault_handler,
TransmissionMode::Acknowledged,
false,
);
// Disable this, we only want to check the deferred procedure.
tb.remote_cfg_mut().immediate_nak_mode = false;
let max_packet_len = 80;
tb.remote_cfg_mut().max_packet_len = max_packet_len;
tb.set_large_file_flag(LargeFileFlag::Large);
let mut user = tb.test_user_from_cached_paths(file_size);
let transfer_info = tb
.generic_transfer_init(&mut user, file_size)
.expect("transfer init failed");
tb.state_check(State::Busy, TransactionStep::ReceivingFileDataPdus);
assert_eq!(
NakPduCreatorWithReservedSeqReqsBuf::calculate_max_segment_requests(
max_packet_len,
&PduHeader::new_for_file_directive(tb.pdu_conf, 0),
)
.unwrap(),
3
);
let missing_segs_0: &[(u64, u64)] = &[(0, 2), (4, 6), (8, 10)];
let missing_segs_1: &[(u64, u64)] = &[(12, 14)];
assert_eq!(
tb.generic_file_data_insert(&mut user, 2, &file_data[2..4])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 6, &file_data[6..8])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 10, &file_data[10..12])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 14, &file_data[14..file_size as usize])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_eof_no_error(&mut user, file_data.to_vec())
.expect("EOF no error insertion failed"),
3
);
assert_eq!(tb.pdu_queue_len(), 3);
tb.check_eof_ack_pdu(ConditionCode::NoError);
let pdu = tb.get_next_pdu().unwrap();
assert_eq!(pdu.pdu_type, PduType::FileDirective);
assert_eq!(pdu.file_directive_type.unwrap(), FileDirectiveType::NakPdu);
let nak_pdu = NakPduReader::new(&pdu.raw_pdu).unwrap();
assert_eq!(nak_pdu.start_of_scope(), 0);
assert_eq!(nak_pdu.end_of_scope(), 10);
let seg_reqs: Vec<(u64, u64)> = nak_pdu.get_segment_requests_iterator().unwrap().collect();
assert_eq!(seg_reqs, missing_segs_0);
let pdu = tb.get_next_pdu().unwrap();
assert_eq!(pdu.pdu_type, PduType::FileDirective);
assert_eq!(pdu.file_directive_type.unwrap(), FileDirectiveType::NakPdu);
let nak_pdu = NakPduReader::new(&pdu.raw_pdu).unwrap();
assert_eq!(nak_pdu.start_of_scope(), 10);
assert_eq!(nak_pdu.end_of_scope(), file_size);
let seg_reqs: Vec<(u64, u64)> = nak_pdu.get_segment_requests_iterator().unwrap().collect();
assert_eq!(seg_reqs, missing_segs_1);
for missing_seg in missing_segs_0 {
assert_eq!(
tb.generic_file_data_insert(
&mut user,
missing_seg.0,
&file_data[missing_seg.0 as usize..missing_seg.1 as usize]
)
.expect("file data insertion failed"),
0
);
}
for missing_seg in missing_segs_1 {
assert_eq!(
tb.generic_file_data_insert(
&mut user,
missing_seg.0,
&file_data[missing_seg.0 as usize..missing_seg.1 as usize]
)
.expect("file data insertion failed"),
1
);
}
tb.check_completion_indication_success(&mut user);
assert_eq!(tb.pdu_queue_len(), 1);
tb.check_finished_pdu_success();
tb.acknowledge_finished_pdu(&mut user, &transfer_info);
}
#[test]
fn test_multi_packet_nak_sequence_normal_file_flag() {
let file_data = [0_u8; 64];
let file_size = file_data.len() as u64;
let fault_handler = TestFaultHandler::default();
let mut tb = DestHandlerTestbench::new_with_fixed_paths(
fault_handler,
TransmissionMode::Acknowledged,
false,
);
// Disable this, we only want to check the deferred procedure.
tb.remote_cfg_mut().immediate_nak_mode = false;
let max_packet_len = 50;
tb.remote_cfg_mut().max_packet_len = max_packet_len;
let mut user = tb.test_user_from_cached_paths(file_size);
let transfer_info = tb
.generic_transfer_init(&mut user, file_size)
.expect("transfer init failed");
tb.state_check(State::Busy, TransactionStep::ReceivingFileDataPdus);
assert_eq!(
NakPduCreatorWithReservedSeqReqsBuf::calculate_max_segment_requests(
max_packet_len,
&PduHeader::new_for_file_directive(tb.pdu_conf, 0),
)
.unwrap(),
4
);
let missing_segs_0: &[(u64, u64)] = &[(0, 2), (4, 6), (8, 10), (12, 14)];
let missing_segs_1: &[(u64, u64)] = &[(16, 18)];
assert_eq!(
tb.generic_file_data_insert(&mut user, 2, &file_data[2..4])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 6, &file_data[6..8])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 10, &file_data[10..12])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 14, &file_data[14..16])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_file_data_insert(&mut user, 18, &file_data[18..file_size as usize])
.expect("file data insertion failed"),
0
);
assert_eq!(
tb.generic_eof_no_error(&mut user, file_data.to_vec())
.expect("EOF no error insertion failed"),
3
);
assert_eq!(tb.pdu_queue_len(), 3);
tb.check_eof_ack_pdu(ConditionCode::NoError);
let pdu = tb.get_next_pdu().unwrap();
assert_eq!(pdu.pdu_type, PduType::FileDirective);
assert_eq!(pdu.file_directive_type.unwrap(), FileDirectiveType::NakPdu);
let nak_pdu = NakPduReader::new(&pdu.raw_pdu).unwrap();
assert_eq!(nak_pdu.start_of_scope(), 0);
assert_eq!(nak_pdu.end_of_scope(), 14);
let seg_reqs: Vec<(u64, u64)> = nak_pdu.get_segment_requests_iterator().unwrap().collect();
assert_eq!(seg_reqs, missing_segs_0);
let pdu = tb.get_next_pdu().unwrap();
assert_eq!(pdu.pdu_type, PduType::FileDirective);
assert_eq!(pdu.file_directive_type.unwrap(), FileDirectiveType::NakPdu);
let nak_pdu = NakPduReader::new(&pdu.raw_pdu).unwrap();
assert_eq!(nak_pdu.start_of_scope(), 14);
assert_eq!(nak_pdu.end_of_scope(), file_size);
let seg_reqs: Vec<(u64, u64)> = nak_pdu.get_segment_requests_iterator().unwrap().collect();
assert_eq!(seg_reqs, missing_segs_1);
for missing_seg in missing_segs_0 {
assert_eq!(
tb.generic_file_data_insert(
&mut user,
missing_seg.0,
&file_data[missing_seg.0 as usize..missing_seg.1 as usize]
)
.expect("file data insertion failed"),
0
);
}
for missing_seg in missing_segs_1 {
assert_eq!(
tb.generic_file_data_insert(
&mut user,
missing_seg.0,
&file_data[missing_seg.0 as usize..missing_seg.1 as usize]
)
.expect("file data insertion failed"),
1
);
}
tb.check_completion_indication_success(&mut user);
assert_eq!(tb.pdu_queue_len(), 1);
tb.check_finished_pdu_success();
tb.acknowledge_finished_pdu(&mut user, &transfer_info);
}
}

View File

@@ -138,7 +138,7 @@ impl CfdpUser for ExampleCfdpUser {
}
}
fn end_to_end_test(with_closure: bool) {
fn end_to_end_test(transmission_mode: TransmissionMode, with_closure: bool) {
// Simplified event handling using atomic signals.
let stop_signal_source = Arc::new(AtomicBool::new(false));
let stop_signal_dest = stop_signal_source.clone();
@@ -173,7 +173,7 @@ fn end_to_end_test(with_closure: bool) {
1024,
with_closure,
false,
spacepackets::cfdp::TransmissionMode::Unacknowledged,
transmission_mode,
ChecksumType::Crc32,
);
let seq_count_provider = AtomicU16::default();
@@ -199,7 +199,7 @@ fn end_to_end_test(with_closure: bool) {
1024,
true,
false,
spacepackets::cfdp::TransmissionMode::Unacknowledged,
transmission_mode,
ChecksumType::Crc32,
);
let mut dest_handler = DestinationHandler::new(
@@ -217,7 +217,7 @@ fn end_to_end_test(with_closure: bool) {
REMOTE_ID.into(),
srcfile.to_str().expect("invaid path string"),
destfile.to_str().expect("invaid path string"),
Some(TransmissionMode::Unacknowledged),
Some(transmission_mode),
Some(with_closure),
)
.expect("put request creation failed");
@@ -326,11 +326,16 @@ fn end_to_end_test(with_closure: bool) {
}
#[test]
fn end_to_end_test_no_closure() {
end_to_end_test(false);
fn end_to_end_unacknowledged_no_closure() {
end_to_end_test(TransmissionMode::Unacknowledged, false);
}
#[test]
fn end_to_end_test_with_closure() {
end_to_end_test(true);
fn end_to_end_unacknowledged_with_closure() {
end_to_end_test(TransmissionMode::Unacknowledged, true);
}
#[test]
fn end_to_end_acknowledged() {
end_to_end_test(TransmissionMode::Acknowledged, true);
}