use rustyasn::{Config, Decoder, Encoder, EncodingRule};
use rustyfix::Dictionary;
use std::sync::Arc;
#[test]
fn test_basic_encoding_decoding() -> Result<(), Box<dyn std::error::Error>> {
let dict = Arc::new(
Dictionary::fix44().expect("Failed to load FIX 4.4 dictionary for integration test"),
);
let encoding_rules = [EncodingRule::BER, EncodingRule::DER, EncodingRule::OER];
for rule in encoding_rules {
let config = Config::new(rule);
let encoder = Encoder::new(config.clone(), dict.clone());
let decoder = Decoder::new(config, dict.clone());
let mut handle = encoder.start_message("D", "SENDER", "TARGET", 1);
handle
.add_string(11, "CL001") .add_string(55, "EUR/USD") .add_int(54, 1) .add_uint(38, 1_000_000);
let encoded = handle.encode().map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Encoding should succeed but failed: {e}"))
})?;
let decoded = decoder.decode(&encoded).map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Decoding should succeed but failed: {e}"))
})?;
assert_eq!(decoded.msg_type(), "D");
assert_eq!(decoded.sender_comp_id(), "SENDER");
assert_eq!(decoded.target_comp_id(), "TARGET");
assert_eq!(decoded.msg_seq_num(), 1);
assert_eq!(decoded.get_string(11), Some("CL001".to_string()));
assert_eq!(decoded.get_string(55), Some("EUR/USD".to_string()));
let parsed_int = decoded.get_int(54).map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Should parse int but failed: {e}"))
})?;
assert_eq!(parsed_int, Some(1));
let parsed_uint = decoded.get_uint(38).map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Should parse uint but failed: {e}"))
})?;
assert_eq!(parsed_uint, Some(1_000_000));
}
Ok(())
}
#[test]
fn test_streaming_decoder() -> Result<(), Box<dyn std::error::Error>> {
let dict = Arc::new(
Dictionary::fix44().expect("Failed to load FIX 4.4 dictionary for integration test"),
);
let config = Config::new(EncodingRule::DER);
let encoder = Encoder::new(config.clone(), dict.clone());
let mut decoder = rustyasn::DecoderStreaming::new(config, dict.clone());
let mut messages = Vec::new();
for i in 1..=3 {
let mut handle = encoder.start_message(
"0", "SENDER", "TARGET", i,
);
if i == 2 {
handle.add_string(112, "TEST123"); }
let encoded = handle.encode().map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Encoding should succeed but failed: {e}"))
})?;
messages.push(encoded);
}
for (i, msg_data) in messages.iter().enumerate() {
let mid = msg_data.len() / 2;
decoder.feed(&msg_data[..mid]);
let first_decode = decoder.decode_next().map_err(|e| {
Box::<dyn std::error::Error>::from(format!("First decode_next() failed: {e}"))
})?;
assert!(first_decode.is_none());
decoder.feed(&msg_data[mid..]);
let decoded = decoder
.decode_next()
.map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Second decode_next() failed: {e}"))
})?
.ok_or_else(|| {
Box::<dyn std::error::Error>::from("Should have a message but got None")
})?;
assert_eq!(decoded.msg_type(), "0");
assert_eq!(decoded.msg_seq_num(), (i + 1) as u64);
if i == 1 {
assert_eq!(decoded.get_string(112), Some("TEST123".to_string()));
}
}
let final_decode = decoder.decode_next().map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Final decode_next() failed: {e}"))
})?;
assert!(final_decode.is_none());
Ok(())
}
#[test]
fn test_message_size_limits() {
let dict = Arc::new(
Dictionary::fix44().expect("Failed to load FIX 4.4 dictionary for integration test"),
);
let mut config = Config::new(EncodingRule::BER);
config.max_message_size = 100;
let encoder = Encoder::new(config.clone(), dict.clone());
let _decoder = Decoder::new(config, dict.clone());
let mut handle = encoder.start_message("D", "SENDER", "TARGET", 1);
for i in 0..50 {
handle.add_string(1000 + i, format!("Field value {i}"));
}
let result = handle.encode();
assert!(result.is_err());
}
#[test]
fn test_field_types() -> Result<(), Box<dyn std::error::Error>> {
let dict = Arc::new(
Dictionary::fix44().expect("Failed to load FIX 4.4 dictionary for integration test"),
);
let config = Config::new(EncodingRule::DER);
let encoder = Encoder::new(config.clone(), dict.clone());
let decoder = Decoder::new(config, dict.clone());
let mut handle = encoder.start_message(
"8", "EXCHANGE", "CLIENT", 42,
);
handle
.add_bool(114, true) .add_string(95, "test_data") .add_int(31, -100) .add_uint(14, 500_000);
let encoded = handle
.encode()
.map_err(|e| format!("Encoding should succeed but failed: {e}"))?;
let decoded = decoder
.decode(&encoded)
.map_err(|e| format!("Decoding should succeed but failed: {e}"))?;
assert_eq!(decoded.get_bool(114), Some(true));
assert_eq!(decoded.get_string(95), Some("test_data".to_string()));
let parsed_int = decoded.get_int(31).map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Should parse int but failed: {e}"))
})?;
assert_eq!(parsed_int, Some(-100));
let parsed_uint = decoded.get_uint(14).map_err(|e| {
Box::<dyn std::error::Error>::from(format!("Should parse uint but failed: {e}"))
})?;
assert_eq!(parsed_uint, Some(500_000));
Ok(())
}
#[test]
fn test_encoding_rule_performance_profiles() {
let _dict = Arc::new(
Dictionary::fix44().expect("Failed to load FIX 4.4 dictionary for integration test"),
);
let low_latency = Config::low_latency();
assert_eq!(low_latency.encoding_rule, EncodingRule::OER);
assert!(!low_latency.validate_checksums);
let high_reliability = Config::high_reliability();
assert_eq!(high_reliability.encoding_rule, EncodingRule::DER);
assert!(high_reliability.validate_checksums);
}