11use crate :: common:: actions:: when;
22use crate :: common:: assertions:: then;
3- use crate :: common:: setup:: given_an_active_session;
3+ use crate :: common:: setup:: { COUNTERPARTY_COMP_ID , OUR_COMP_ID , given_an_active_session} ;
44use crate :: common:: test_messages:: { TestMessage , replace_field_value} ;
55use hotfix:: message:: { FixMessage , generate_message} ;
66use hotfix:: session:: Status ;
77use hotfix_message:: dict:: { FieldLocation , FixDatatype } ;
8+ use hotfix_message:: field_types:: Timestamp ;
89use hotfix_message:: fix44:: MSG_TYPE ;
9- use hotfix_message:: message:: Message ;
10+ use hotfix_message:: message:: { Config , Message } ;
1011use hotfix_message:: { HardCodedFixFieldDefinition , Part , fix44} ;
1112
1213/// Tests that when a counterparty sends a message containing an invalid/unrecognised field,
@@ -34,8 +35,6 @@ async fn test_garbled_message_with_invalid_target_comp_id_gets_ignored() {
3435
3536 // counterparty sends a message with invalid body length, which constitutes a garbled message
3637 let garbled_message = build_execution_report_with_incorrect_body_length (
37- "dummy-acceptor" ,
38- "dummy-initiator" ,
3938 mock_counterparty. next_target_sequence_number ( ) ,
4039 ) ;
4140 when ( & mut mock_counterparty)
@@ -59,6 +58,79 @@ async fn test_garbled_message_with_invalid_target_comp_id_gets_ignored() {
5958 then ( & mut mock_counterparty) . gets_disconnected ( ) . await ;
6059}
6160
61+ /// Tests that when a counterparty sends a message with an invalid BeginString,
62+ /// the session logs out and disconnects.
63+ #[ tokio:: test]
64+ async fn test_message_with_invalid_begin_string ( ) {
65+ let ( _session, mut mock_counterparty) = given_an_active_session ( ) . await ;
66+
67+ // a message with invalid BeginString is sent by the counterparty
68+ let invalid_message = build_execution_report_with_incorrect_begin_string (
69+ mock_counterparty. next_target_sequence_number ( ) ,
70+ ) ;
71+ when ( & mut mock_counterparty)
72+ . sends_raw_message ( invalid_message)
73+ . await ;
74+
75+ // then we log out and disconnect
76+ then ( & mut mock_counterparty)
77+ . receives ( |msg| assert_eq ! ( msg. header( ) . get:: <& str >( MSG_TYPE ) . unwrap( ) , "5" ) )
78+ . await ;
79+ then ( & mut mock_counterparty) . gets_disconnected ( ) . await ;
80+ }
81+
82+ /// Tests that when a counterparty sends a message with an invalid TargetCompId,
83+ /// the session sends a Reject (MsgType=3) and logs out and disconnects.
84+ #[ tokio:: test]
85+ async fn test_message_with_invalid_target_comp_id ( ) {
86+ let ( _session, mut mock_counterparty) = given_an_active_session ( ) . await ;
87+
88+ // a message with incorrect TargetCompId is sent by the counterparty
89+ let invalid_message = build_execution_report_with_comp_id (
90+ mock_counterparty. next_target_sequence_number ( ) ,
91+ COUNTERPARTY_COMP_ID ,
92+ "WRONG_COMP_ID" ,
93+ ) ;
94+ when ( & mut mock_counterparty)
95+ . sends_raw_message ( invalid_message)
96+ . await ;
97+
98+ // then we send a reject, log out and disconnect
99+ then ( & mut mock_counterparty)
100+ . receives ( |msg| assert_eq ! ( msg. header( ) . get:: <& str >( MSG_TYPE ) . unwrap( ) , "3" ) )
101+ . await ;
102+ then ( & mut mock_counterparty)
103+ . receives ( |msg| assert_eq ! ( msg. header( ) . get:: <& str >( MSG_TYPE ) . unwrap( ) , "5" ) )
104+ . await ;
105+ then ( & mut mock_counterparty) . gets_disconnected ( ) . await ;
106+ }
107+
108+ /// Tests that when a counterparty sends a message with an invalid SenderCompId,
109+ /// the session sends a Reject (MsgType=3) and logs out and disconnects.
110+ #[ tokio:: test]
111+ async fn test_message_with_invalid_sender_comp_id ( ) {
112+ let ( _session, mut mock_counterparty) = given_an_active_session ( ) . await ;
113+
114+ // a message with incorrect SenderCompId is sent by the counterparty
115+ let invalid_message = build_execution_report_with_comp_id (
116+ mock_counterparty. next_target_sequence_number ( ) ,
117+ "WRONG_COMP_ID" ,
118+ OUR_COMP_ID ,
119+ ) ;
120+ when ( & mut mock_counterparty)
121+ . sends_raw_message ( invalid_message)
122+ . await ;
123+
124+ // then we send a reject, log out and disconnect
125+ then ( & mut mock_counterparty)
126+ . receives ( |msg| assert_eq ! ( msg. header( ) . get:: <& str >( MSG_TYPE ) . unwrap( ) , "3" ) )
127+ . await ;
128+ then ( & mut mock_counterparty)
129+ . receives ( |msg| assert_eq ! ( msg. header( ) . get:: <& str >( MSG_TYPE ) . unwrap( ) , "5" ) )
130+ . await ;
131+ then ( & mut mock_counterparty) . gets_disconnected ( ) . await ;
132+ }
133+
62134/// A new order message with an extra, invalid field.
63135#[ derive( Clone , Debug ) ]
64136struct ExecutionReportWithInvalidField {
@@ -121,16 +193,45 @@ pub const CUSTOM_FIELD: &HardCodedFixFieldDefinition = &HardCodedFixFieldDefinit
121193 location : FieldLocation :: Body ,
122194} ;
123195
124- fn build_execution_report_with_incorrect_body_length (
125- sender_comp_id : & str ,
126- target_comp_id : & str ,
127- msg_seq_num : usize ,
128- ) -> Vec < u8 > {
196+ fn build_execution_report_with_incorrect_body_length ( msg_seq_num : usize ) -> Vec < u8 > {
129197 let report = TestMessage :: dummy_execution_report ( ) ;
130198 let mut raw_message =
131- generate_message ( sender_comp_id , target_comp_id , msg_seq_num, report) . unwrap ( ) ;
199+ generate_message ( COUNTERPARTY_COMP_ID , OUR_COMP_ID , msg_seq_num, report) . unwrap ( ) ;
132200
133201 replace_field_value ( & mut raw_message, 9 , b"999" ) ;
134202
135203 raw_message
136204}
205+
206+ fn build_execution_report_with_incorrect_begin_string ( msg_seq_num : usize ) -> Vec < u8 > {
207+ let report = TestMessage :: dummy_execution_report ( ) ;
208+
209+ // we expect BeginString FIX.4.4 but this message contains FIX.4.2
210+ let mut msg = Message :: new ( "FIX.4.2" , report. message_type ( ) ) ;
211+ msg. set ( fix44:: SENDER_COMP_ID , COUNTERPARTY_COMP_ID ) ;
212+ msg. set ( fix44:: TARGET_COMP_ID , OUR_COMP_ID ) ;
213+ msg. set ( fix44:: MSG_SEQ_NUM , msg_seq_num) ;
214+ msg. set ( fix44:: SENDING_TIME , Timestamp :: utc_now ( ) ) ;
215+
216+ report. write ( & mut msg) ;
217+
218+ msg. encode ( & Config :: default ( ) ) . unwrap ( )
219+ }
220+
221+ fn build_execution_report_with_comp_id (
222+ msg_seq_num : usize ,
223+ sender_comp_id : & str ,
224+ target_comp_id : & str ,
225+ ) -> Vec < u8 > {
226+ let report = TestMessage :: dummy_execution_report ( ) ;
227+
228+ let mut msg = Message :: new ( "FIX.4.4" , report. message_type ( ) ) ;
229+ msg. set ( fix44:: SENDER_COMP_ID , sender_comp_id) ;
230+ msg. set ( fix44:: TARGET_COMP_ID , target_comp_id) ;
231+ msg. set ( fix44:: MSG_SEQ_NUM , msg_seq_num) ;
232+ msg. set ( fix44:: SENDING_TIME , Timestamp :: utc_now ( ) ) ;
233+
234+ report. write ( & mut msg) ;
235+
236+ msg. encode ( & Config :: default ( ) ) . unwrap ( )
237+ }
0 commit comments