use blvm_protocol::network::{NetworkAddress, NetworkMessage, VersionMessage};
use blvm_protocol::wire::{
calculate_checksum, deserialize_message, serialize_message, MAX_MESSAGE_PAYLOAD,
MESSAGE_HEADER_SIZE,
};
use std::io::Cursor;
#[test]
fn test_calculate_checksum_empty_payload() {
let empty: &[u8] = &[];
let checksum = calculate_checksum(empty);
assert_eq!(checksum.len(), 4);
let checksum2 = calculate_checksum(empty);
assert_eq!(checksum, checksum2);
}
#[test]
fn test_calculate_checksum_large_payload() {
let large_payload = vec![0u8; 1_000_000]; let checksum = calculate_checksum(&large_payload);
assert_eq!(checksum.len(), 4);
let checksum2 = calculate_checksum(&large_payload);
assert_eq!(checksum, checksum2);
}
#[test]
fn test_calculate_checksum_different_payloads() {
let payload1 = b"test1";
let payload2 = b"test2";
let checksum1 = calculate_checksum(payload1);
let checksum2 = calculate_checksum(payload2);
assert_ne!(checksum1, checksum2);
}
#[test]
fn test_serialize_message_max_payload() {
let magic = [0xf9, 0xbe, 0xb4, 0xd9];
let message = NetworkMessage::VerAck;
let result = serialize_message(&message, magic);
assert!(result.is_ok());
let serialized = result.unwrap();
assert!(serialized.len() >= MESSAGE_HEADER_SIZE);
}
#[test]
fn test_serialize_message_invalid_magic() {
let mainnet_magic = [0xf9, 0xbe, 0xb4, 0xd9];
let testnet_magic = [0x0b, 0x11, 0x09, 0x07];
let message = NetworkMessage::VerAck;
let result1 = serialize_message(&message, mainnet_magic);
let result2 = serialize_message(&message, testnet_magic);
assert!(result1.is_ok());
assert!(result2.is_ok());
let serialized1 = result1.unwrap();
let serialized2 = result2.unwrap();
assert_ne!(serialized1[..4], serialized2[..4]);
}
#[test]
fn test_deserialize_message_invalid_magic() {
let mainnet_magic = [0xf9, 0xbe, 0xb4, 0xd9];
let testnet_magic = [0x0b, 0x11, 0x09, 0x07];
let message = NetworkMessage::VerAck;
let serialized = serialize_message(&message, mainnet_magic).unwrap();
let mut cursor = Cursor::new(&serialized);
let result = deserialize_message(&mut cursor, testnet_magic);
assert!(result.is_err());
}
#[test]
fn test_deserialize_message_invalid_checksum() {
let magic = [0xf9, 0xbe, 0xb4, 0xd9];
let message = NetworkMessage::VerAck;
let mut serialized = serialize_message(&message, magic).unwrap();
serialized[20] ^= 0xFF;
let mut cursor = Cursor::new(&serialized);
let result = deserialize_message(&mut cursor, magic);
assert!(result.is_err());
}
#[test]
fn test_deserialize_message_short_header() {
let magic = [0xf9, 0xbe, 0xb4, 0xd9];
let short_data = vec![0u8; MESSAGE_HEADER_SIZE - 1];
let mut cursor = Cursor::new(&short_data);
let result = deserialize_message(&mut cursor, magic);
assert!(result.is_err());
}
#[test]
fn test_deserialize_message_invalid_command() {
let magic = [0xf9, 0xbe, 0xb4, 0xd9];
let mut header = vec![0u8; MESSAGE_HEADER_SIZE];
header[0..4].copy_from_slice(&magic);
let mut cmd = [0u8; 12];
cmd[..7].copy_from_slice(b"invalid");
cmd[7..].fill(0xff);
header[4..16].copy_from_slice(&cmd);
header[16..20].copy_from_slice(&0u32.to_le_bytes());
let empty_checksum = calculate_checksum(&[]);
header[20..24].copy_from_slice(&empty_checksum);
let mut cursor = Cursor::new(&header);
let result = deserialize_message(&mut cursor, magic);
assert!(result.is_err());
}
#[test]
fn test_deserialize_message_unknown_command() {
let magic = [0xf9, 0xbe, 0xb4, 0xd9];
let mut header = vec![0u8; MESSAGE_HEADER_SIZE];
header[0..4].copy_from_slice(&magic);
header[4..16].copy_from_slice(b"unknown\x00\x00\x00\x00\x00");
header[16..20].copy_from_slice(&0u32.to_le_bytes());
let empty_checksum = calculate_checksum(&[]);
header[20..24].copy_from_slice(&empty_checksum);
let mut cursor = Cursor::new(&header);
let result = deserialize_message(&mut cursor, magic);
assert!(result.is_err());
}
#[test]
fn test_deserialize_message_payload_too_large() {
let magic = [0xf9, 0xbe, 0xb4, 0xd9];
let mut header = vec![0u8; MESSAGE_HEADER_SIZE];
header[0..4].copy_from_slice(&magic);
let mut cmd = [0u8; 12];
cmd[..6].copy_from_slice(b"verack");
header[4..16].copy_from_slice(&cmd);
let too_large = (MAX_MESSAGE_PAYLOAD as u32) + 1;
header[16..20].copy_from_slice(&too_large.to_le_bytes());
let empty_checksum = calculate_checksum(&[]);
header[20..24].copy_from_slice(&empty_checksum);
let mut cursor = Cursor::new(&header);
let result = deserialize_message(&mut cursor, magic);
assert!(result.is_err());
}
#[test]
fn test_serialize_deserialize_roundtrip_verack() {
let magic = [0xf9, 0xbe, 0xb4, 0xd9];
let message = NetworkMessage::VerAck;
let serialized = serialize_message(&message, magic).unwrap();
let mut cursor = Cursor::new(&serialized);
let (deserialized, bytes_read) = deserialize_message(&mut cursor, magic).unwrap();
assert_eq!(deserialized, message);
assert_eq!(bytes_read, serialized.len());
}
#[test]
fn test_wire_format_constants() {
assert_eq!(MESSAGE_HEADER_SIZE, 24); assert_eq!(MAX_MESSAGE_PAYLOAD, 32 * 1024 * 1024); }
#[test]
fn test_command_encoding_edge_cases() {
let commands = vec![
"v", "version", "getheaders", "sendcmpct", ];
let magic = [0xf9, 0xbe, 0xb4, 0xd9];
for cmd in commands {
assert!(cmd.len() <= 12, "Command '{}' exceeds 12 bytes", cmd);
assert!(cmd.is_ascii(), "Command '{}' is not ASCII", cmd);
}
}