use truefix_core::{Field, Message, decode};
fn base_message() -> Message {
let mut m = Message::new();
m.header.set(Field::string(8, "FIX.4.4"));
m.header.set(Field::string(35, "n")); m.header.set(Field::int(34, 1));
m.header.set(Field::string(49, "CLIENT"));
m.header.set(Field::string(56, "SERVER"));
m
}
#[test]
fn a_length_field_followed_by_a_non_matching_tag_fails_to_decode() {
let mut m = base_message();
m.body.set(Field::int(95, 5));
m.body.set(Field::string(99, "hello-does-not-matter"));
let bytes = m.encode();
let result = decode(&bytes);
assert!(
result.is_err(),
"a length field not immediately followed by its documented data-tag partner must fail \
decoding, not silently consume bytes from the wrong field -- got {result:?}"
);
}
#[test]
fn a_length_that_spans_an_embedded_soh_and_a_whole_following_field_does_not_silently_swallow_it() {
let mut m = base_message();
let swallowed = b"ab\x01100=cd".to_vec(); assert_eq!(swallowed.len(), 9);
m.body.set(Field::int(95, 9)); m.body.set(Field::new(99, swallowed)); let bytes = m.encode();
let result = decode(&bytes);
assert!(
result.is_err(),
"a length field must only apply to its documented data-tag partner (96 for 95), never to \
an unrelated tag (99 here) -- letting it apply regardless silently swallows an embedded \
SOH and an entire following field (tag 100) into tag 99's value with no error at all, \
got {result:?}"
);
}
#[test]
fn a_length_field_followed_by_its_matching_data_tag_decodes_normally() {
let mut m = base_message();
m.body.set(Field::int(95, 5));
m.body.set(Field::string(96, "hello")); let bytes = m.encode();
let decoded = decode(&bytes).expect("a correctly-paired length/data field must decode");
assert_eq!(
decoded.body.get(96).and_then(|f| f.as_str().ok()),
Some("hello")
);
}
#[test]
fn a_non_numeric_length_field_value_fails_to_decode() {
let mut m = base_message();
m.body.set(Field::string(95, "abc")); m.body.set(Field::string(96, "hello"));
let bytes = m.encode();
let result = decode(&bytes);
assert!(
result.is_err(),
"a non-numeric data-length field value must fail decoding, not silently skip setting the \
pending length (letting the following data field be misparsed as plain text) -- got \
{result:?}"
);
}