Skip to content

Commit 21737c6

Browse files
committed
Add test case for resend request without begin sequence number
1 parent 2c72537 commit 21737c6

3 files changed

Lines changed: 38 additions & 0 deletions

File tree

crates/hotfix/src/session.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ impl<A: Application<M>, M: FixMessage, S: MessageStore> Session<A, M, S> {
370370
Err(_) => {
371371
let reject = Reject::new(
372372
message
373+
.header()
373374
.get(fix44::MSG_SEQ_NUM)
374375
.map_err(|_| anyhow!("failed to get seq number"))?,
375376
)
@@ -392,6 +393,7 @@ impl<A: Application<M>, M: FixMessage, S: MessageStore> Session<A, M, S> {
392393
Err(_) => {
393394
let reject = Reject::new(
394395
message
396+
.header()
395397
.get(fix44::MSG_SEQ_NUM)
396398
.map_err(|_| anyhow!("failed to get seq number"))?,
397399
)

crates/hotfix/tests/common/test_messages.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,16 @@ pub fn replace_field_value(raw_message: &mut Vec<u8>, tag: u32, new_value: &[u8]
373373
}
374374
}
375375
}
376+
377+
/// Builds a resend request message without the required BeginSeqNo field.
378+
pub fn build_resend_request_without_begin_seq_no(msg_seq_num: u64) -> Vec<u8> {
379+
let mut msg = Message::new("FIX.4.4", "2"); // MsgType 2 = ResendRequest
380+
msg.set(fix44::SENDER_COMP_ID, COUNTERPARTY_COMP_ID);
381+
msg.set(fix44::TARGET_COMP_ID, OUR_COMP_ID);
382+
msg.set(fix44::MSG_SEQ_NUM, msg_seq_num);
383+
msg.set(fix44::SENDING_TIME, Timestamp::utc_now());
384+
// Intentionally omit BeginSeqNo (tag 7)
385+
msg.set(fix44::END_SEQ_NO, 2);
386+
387+
msg.encode(&Config::default()).unwrap()
388+
}

crates/hotfix/tests/session_test_cases/resend_tests.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::common::assertions::{assert_msg_type, then};
33
use crate::common::setup::given_an_active_session;
44
use crate::common::test_messages::{
55
TestMessage, build_execution_report_with_incorrect_body_length,
6+
build_resend_request_without_begin_seq_no,
67
};
78
use hotfix::message::FixMessage;
89
use hotfix::session::Status;
@@ -142,3 +143,25 @@ async fn test_resent_message_previously_received_is_ignored() {
142143
when(&session).requests_disconnect().await;
143144
then(&mut counterparty).gets_disconnected().await;
144145
}
146+
147+
/// Tests that when a counterparty sends a resend request without the required BeginSeqNo field,
148+
/// the session rejects the malformed message.
149+
#[tokio::test]
150+
async fn test_resend_request_without_begin_seq_no_is_rejected() {
151+
let (session, mut counterparty) = given_an_active_session().await;
152+
153+
// build a resend request message missing the required BeginSeqNo (tag 7)
154+
let seq_num = counterparty.next_target_sequence_number();
155+
let invalid_resend_request = build_resend_request_without_begin_seq_no(seq_num);
156+
when(&mut counterparty)
157+
.sends_raw_message(invalid_resend_request)
158+
.await;
159+
160+
// the session should reject this invalid resend request
161+
then(&mut counterparty)
162+
.receives(|msg| assert_msg_type(msg, MsgType::Reject))
163+
.await;
164+
165+
when(&session).requests_disconnect().await;
166+
then(&mut counterparty).gets_disconnected().await;
167+
}

0 commit comments

Comments
 (0)