use fints::{decode_message, format_decoded, VerbosityLevel};
use proptest::prelude::*;
#[test]
fn test_parse_empty_message() {
let msg = decode_message(b"").unwrap();
assert!(
msg.segments.is_empty(),
"Empty bytes should produce empty segments"
);
}
#[test]
fn test_parse_single_empty_deg() {
let data = b"TEST:1:1+'";
let msg = decode_message(data).unwrap();
assert_eq!(msg.segments.len(), 1);
assert_eq!(msg.segments[0].segment_type, "TEST");
let deg0 = &msg.segments[0].degs[0];
assert!(
deg0.is_empty() || deg0.iter().all(|s| s.is_empty()),
"First data DEG should be empty, got: {:?}",
deg0
);
}
#[test]
fn test_parse_nested_escapes() {
let data = b"TEST:1:1+A??B'";
let msg = decode_message(data).unwrap();
assert_eq!(msg.segments.len(), 1);
let val = &msg.segments[0].degs[0][0];
assert_eq!(val, "A?B", "Double escape should produce single '?'");
}
#[test]
fn test_parse_iso8859_chars() {
let mut data = b"TEST:1:1+".to_vec();
data.extend_from_slice(&[0xC4u8, 0xD6u8, 0xDCu8]); data.push(b'\'');
let msg = decode_message(&data).unwrap();
let text = &msg.segments[0].degs[0][0];
assert!(
text.contains('\u{00C4}') || text.contains("Ä"),
"Should contain Ä, got: {:?}",
text
);
assert!(
text.contains('\u{00D6}') || text.contains("Ö"),
"Should contain Ö, got: {:?}",
text
);
assert!(
text.contains('\u{00DC}') || text.contains("Ü"),
"Should contain Ü, got: {:?}",
text
);
}
#[test]
fn test_parse_binary_zero_length() {
let data = b"TEST:1:1+@0@'";
let msg = decode_message(data).unwrap();
assert_eq!(msg.segments.len(), 1);
let val = &msg.segments[0].degs[0][0];
assert!(
val.contains("BINARY") || val.is_empty(),
"Zero-length binary should decode to a BINARY display or empty, got: {:?}",
val
);
}
#[test]
fn test_parse_multiple_empty_des() {
let data = b"TEST:1:1+A:::B'";
let msg = decode_message(data).unwrap();
assert_eq!(msg.segments.len(), 1);
let deg0 = &msg.segments[0].degs[0];
assert_eq!(
deg0.len(),
4,
"Expected 4 DEs in 'A:::B', got {}",
deg0.len()
);
assert_eq!(deg0[0], "A");
assert_eq!(deg0[1], "");
assert_eq!(deg0[2], "");
assert_eq!(deg0[3], "B");
}
#[test]
fn test_serialize_empty_message() {
let msg = decode_message(b"").unwrap();
assert_eq!(msg.segments.len(), 0);
assert_eq!(msg.raw_bytes, 0);
let formatted = format_decoded(&msg, VerbosityLevel::Minimal);
assert!(formatted.contains("0 bytes"));
}
#[test]
fn test_round_trip_complex() {
let input = b"TEST:1:1+Hello?+World+last'";
let msg = decode_message(input).unwrap();
assert_eq!(msg.segments.len(), 1);
assert_eq!(msg.segments[0].segment_type, "TEST");
assert_eq!(msg.segments[0].degs[0][0], "Hello+World");
assert_eq!(msg.segments[0].degs[1][0], "last");
}
#[test]
fn test_round_trip_all_separator_types() {
let input = b"HNSHK:2:4+PIN:1+999+one:two:three'";
let msg = decode_message(input).unwrap();
assert_eq!(msg.segments.len(), 1);
assert_eq!(msg.segments[0].segment_type, "HNSHK");
assert_eq!(msg.segments[0].segment_number, 2);
assert_eq!(msg.segments[0].degs[0][0], "PIN");
assert_eq!(msg.segments[0].degs[0][1], "1");
assert_eq!(msg.segments[0].degs[1][0], "999");
assert_eq!(msg.segments[0].degs[2][0], "one");
assert_eq!(msg.segments[0].degs[2][1], "two");
assert_eq!(msg.segments[0].degs[2][2], "three");
}
#[test]
fn test_parse_message_with_newlines() {
let data = b"HNHBS:5:1+2'\r\nHNHBK:1:3+000000000075+300+0'";
let msg = decode_message(data).unwrap();
assert_eq!(msg.segments.len(), 2);
assert_eq!(msg.segments[0].segment_type, "HNHBS");
assert_eq!(msg.segments[1].segment_type, "HNHBK");
}
proptest! {
#[test]
fn test_round_trip_arbitrary_text(s in "[a-zA-Z0-9 .,/!#%^&*()-]{0,50}") {
let segment = format!("TEST:1:1+{}'", s);
let msg = decode_message(segment.as_bytes()).unwrap();
prop_assert_eq!(msg.segments.len(), 1);
if !s.is_empty() {
prop_assert_eq!(&msg.segments[0].degs[0][0], &s);
}
}
#[test]
fn test_round_trip_multiple_segments(
a in "[a-zA-Z0-9]{1,10}",
b in "[a-zA-Z0-9]{1,10}"
) {
let segment = format!("SEG1:1:1+{}'\r\nSEG2:2:1+{}'", a, b);
let msg = decode_message(segment.as_bytes()).unwrap();
prop_assert_eq!(msg.segments.len(), 2);
prop_assert_eq!(&msg.segments[0].degs[0][0], &a);
prop_assert_eq!(&msg.segments[1].degs[0][0], &b);
}
}