use blvm_node::network::inventory::InventoryManager;
use blvm_node::network::peer::Peer;
use blvm_node::network::protocol::*;
use blvm_node::network::relay::RelayManager;
use blvm_node::network::*;
use std::net::SocketAddr;
use tokio::sync::mpsc;
mod common;
use blvm_node::network::inventory::{InventoryRequest, MSG_BLOCK, MSG_TX};
use blvm_node::network::protocol::InventoryVector;
use common::*;
#[tokio::test(flavor = "multi_thread")]
async fn test_network_manager_creation() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let manager = NetworkManager::new(addr);
assert_eq!(manager.peer_count(), 0);
assert!(manager.peer_addresses().is_empty());
}
#[tokio::test]
async fn test_peer_creation() {
let (tx, _rx) = mpsc::unbounded_channel();
let addr: SocketAddr = "127.0.0.1:8333".parse().unwrap();
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
let local_addr = listener.local_addr().unwrap();
let stream = tokio::net::TcpStream::connect(local_addr).await.unwrap();
let peer = Peer::new(stream, addr, tx);
assert_eq!(peer.address(), addr);
assert!(peer.is_connected());
}
#[tokio::test]
async fn test_peer_send_message() {
let (tx, _rx) = mpsc::unbounded_channel();
let addr: SocketAddr = "127.0.0.1:8333".parse().unwrap();
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
let local_addr = listener.local_addr().unwrap();
let stream = tokio::net::TcpStream::connect(local_addr).await.unwrap();
let peer = Peer::new(stream, addr, tx);
let test_message = b"test message".to_vec();
let result = peer.send_message(test_message).await;
assert!(result.is_ok(), "send_message should succeed");
}
#[tokio::test]
async fn test_inventory_manager() {
let mut inventory = InventoryManager::new();
assert_eq!(inventory.inventory_count(), 0);
assert_eq!(inventory.pending_request_count(), 0);
let hash = [1u8; 32];
let items = [blvm_node::network::protocol::InventoryVector { inv_type: 1, hash }];
inventory.add_inventory("peer1", &items[..]).unwrap();
assert_eq!(inventory.inventory_count(), 1);
assert!(inventory.has_inventory(&hash));
}
#[tokio::test]
async fn test_relay_manager() {
let mut relay = RelayManager::new();
let hash = [1u8; 32];
let stats = relay.get_stats();
assert_eq!(stats.relayed_blocks, 0);
assert_eq!(stats.relayed_transactions, 0);
assert!(relay.should_relay_block(&hash));
assert!(relay.should_relay_transaction(&hash));
relay.mark_block_relayed(hash);
relay.mark_transaction_relayed(hash);
let stats = relay.get_stats();
assert_eq!(stats.relayed_blocks, 1);
assert_eq!(stats.relayed_transactions, 1);
assert!(!relay.should_relay_block(&hash));
assert!(!relay.should_relay_transaction(&hash));
}
#[tokio::test]
async fn test_protocol_parser() {
use blvm_node::network::protocol::*;
let version_msg = VersionMessage {
version: 70015,
services: 1,
timestamp: 1234567890,
addr_recv: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
addr_from: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
nonce: 12345,
user_agent: "blvm-node/0.1.0".to_string(),
start_height: 0,
relay: true,
};
let message = ProtocolMessage::Version(version_msg);
let serialized = ProtocolParser::serialize_message(&message).unwrap();
assert!(serialized.len() >= 24); assert_eq!(&serialized[0..4], &BITCOIN_MAGIC_MAINNET); }
#[tokio::test]
async fn test_peer_state_transitions() {
let (tx, _rx) = mpsc::unbounded_channel();
let addr: SocketAddr = "127.0.0.1:8333".parse().unwrap();
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
let local_addr = listener.local_addr().unwrap();
let stream = tokio::net::TcpStream::connect(local_addr).await.unwrap();
let peer = Peer::new(stream, addr, tx);
assert!(peer.is_connected());
assert!(peer.is_connected());
assert_eq!(peer.address(), addr);
}
#[tokio::test]
async fn test_peer_address_handling() {
let (tx, _rx) = mpsc::unbounded_channel();
let addr_v4: SocketAddr = "192.168.1.1:8333".parse().unwrap();
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
let local_addr = listener.local_addr().unwrap();
let stream = tokio::net::TcpStream::connect(local_addr).await.unwrap();
let peer_v4 = Peer::new(stream, addr_v4, tx);
assert_eq!(peer_v4.address(), addr_v4);
let (tx2, _rx2) = mpsc::unbounded_channel();
let addr_v6: SocketAddr = "[::1]:8333".parse().unwrap();
let listener2 = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
let local_addr2 = listener2.local_addr().unwrap();
let stream2 = tokio::net::TcpStream::connect(local_addr2).await.unwrap();
let peer_v6 = Peer::new(stream2, addr_v6, tx2);
assert_eq!(peer_v6.address(), addr_v6);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_multiple_peer_tracking() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let manager = NetworkManager::new(addr);
let peer_addrs: Vec<SocketAddr> = vec![
"192.168.1.1:8333".parse().unwrap(),
"192.168.1.2:8333".parse().unwrap(),
"192.168.1.3:8333".parse().unwrap(),
];
assert_eq!(manager.peer_count(), 0);
assert!(manager.peer_addresses().is_empty());
}
#[tokio::test]
async fn test_message_serialization() {
let version_msg = VersionMessage {
version: 70015,
services: 1,
timestamp: 1234567890,
addr_recv: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
addr_from: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
nonce: 12345,
user_agent: "blvm-node/0.1.0".to_string(),
start_height: 0,
relay: true,
};
let message = ProtocolMessage::Version(version_msg);
let serialized = ProtocolParser::serialize_message(&message).unwrap();
assert_eq!(&serialized[0..4], &BITCOIN_MAGIC_MAINNET);
let command = &serialized[4..16];
assert_eq!(command, b"version\0\0\0\0\0");
}
#[tokio::test]
async fn test_message_deserialization() {
let version_msg = VersionMessage {
version: 70015,
services: 1,
timestamp: 1234567890,
addr_recv: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
addr_from: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
nonce: 12345,
user_agent: "blvm-node/0.1.0".to_string(),
start_height: 0,
relay: true,
};
let message = ProtocolMessage::Version(version_msg);
let serialized = ProtocolParser::serialize_message(&message).unwrap();
let deserialized = ProtocolParser::parse_message(&serialized).unwrap();
match deserialized {
ProtocolMessage::Version(deser_msg) => {
assert_eq!(deser_msg.version, 70015);
assert_eq!(deser_msg.services, 1);
assert_eq!(deser_msg.timestamp, 1234567890);
}
_ => panic!("Expected version message"),
}
}
#[tokio::test]
async fn test_checksum_validation() {
let version_msg = VersionMessage {
version: 70015,
services: 1,
timestamp: 1234567890,
addr_recv: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
addr_from: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
nonce: 12345,
user_agent: "blvm-node/0.1.0".to_string(),
start_height: 0,
relay: true,
};
let message = ProtocolMessage::Version(version_msg);
let serialized = ProtocolParser::serialize_message(&message).unwrap();
assert!(serialized.len() >= 24); assert_eq!(&serialized[0..4], &BITCOIN_MAGIC_MAINNET); }
#[tokio::test]
async fn test_malformed_message_handling() {
let mut invalid_data = vec![0u8; 24];
invalid_data[0..4].copy_from_slice(&0x12345678u32.to_le_bytes());
let result = ProtocolParser::parse_message(&invalid_data);
assert!(result.is_err());
let short_data = vec![0u8; 10];
let result = ProtocolParser::parse_message(&short_data);
assert!(result.is_err());
let mut invalid_cmd_data = vec![0u8; 24];
invalid_cmd_data[0..4].copy_from_slice(&BITCOIN_MAGIC_MAINNET); invalid_cmd_data[4..16].copy_from_slice(b"invalid\0\0\0\0\0");
let result = ProtocolParser::parse_message(&invalid_cmd_data);
assert!(result.is_err());
}
#[tokio::test]
async fn test_inventory_manager_operations() {
let mut inventory = InventoryManager::new();
let hash1 = random_hash();
let hash2 = random_hash();
let items1 = [blvm_node::network::protocol::InventoryVector {
inv_type: 1, hash: hash1,
}];
let items2 = [blvm_node::network::protocol::InventoryVector {
inv_type: 2, hash: hash2,
}];
inventory.add_inventory("peer1", &items1[..]).unwrap();
inventory.add_inventory("peer2", &items2[..]).unwrap();
assert_eq!(inventory.inventory_count(), 2);
assert!(inventory.has_inventory(&hash1));
assert!(inventory.has_inventory(&hash2));
}
#[tokio::test]
async fn test_inventory_peer_tracking() {
let mut inventory = InventoryManager::new();
let hash = random_hash();
let items = [blvm_node::network::protocol::InventoryVector { inv_type: 1, hash }];
inventory.add_inventory("peer1", &items[..]).unwrap();
inventory.add_inventory("peer2", &items[..]).unwrap();
}
#[tokio::test]
async fn test_inventory_request_handling() {
let mut inventory = InventoryManager::new();
let hash = random_hash();
let items = [blvm_node::network::protocol::InventoryVector { inv_type: 1, hash }];
inventory.add_inventory("peer1", &items[..]).unwrap();
let request = InventoryRequest {
inv_type: 1,
hash,
timestamp: 1234567890,
peer: "test_peer".to_string(),
};
}
#[tokio::test]
async fn test_relay_manager_operations() {
let mut relay = RelayManager::new();
let block_hash = random_hash();
let tx_hash = random_hash();
let stats = relay.get_stats();
assert_eq!(stats.relayed_blocks, 0);
assert_eq!(stats.relayed_transactions, 0);
assert!(relay.should_relay_block(&block_hash));
assert!(relay.should_relay_transaction(&tx_hash));
relay.mark_block_relayed(block_hash);
relay.mark_transaction_relayed(tx_hash);
let stats = relay.get_stats();
assert_eq!(stats.relayed_blocks, 1);
assert_eq!(stats.relayed_transactions, 1);
assert!(!relay.should_relay_block(&block_hash));
assert!(!relay.should_relay_transaction(&tx_hash));
}
#[tokio::test]
async fn test_relay_policy_enforcement() {
let mut relay = RelayManager::new();
let hash = random_hash();
assert!(relay.should_relay_block(&hash));
relay.mark_block_relayed(hash);
assert!(!relay.should_relay_block(&hash));
}
#[tokio::test]
async fn test_relay_peer_selection() {
let relay = RelayManager::new();
let hash = random_hash();
let peers = [
"peer1".to_string(),
"peer2".to_string(),
"peer3".to_string(),
];
}
#[tokio::test]
async fn test_inventory_request_data() {
let mut inventory = InventoryManager::new();
let hash = random_hash();
let peer = "peer1";
let get_data = inventory.request_data(hash, MSG_BLOCK, peer).unwrap();
assert_eq!(get_data.inventory.len(), 1);
assert_eq!(get_data.inventory[0].hash, hash);
assert_eq!(get_data.inventory[0].inv_type, MSG_BLOCK);
assert_eq!(inventory.pending_request_count(), 1);
}
#[tokio::test]
async fn test_inventory_mark_fulfilled() {
let mut inventory = InventoryManager::new();
let hash = random_hash();
let peer = "peer1";
let _get_data = inventory.request_data(hash, MSG_TX, peer).unwrap();
assert_eq!(inventory.pending_request_count(), 1);
inventory.mark_fulfilled(&hash);
assert_eq!(inventory.pending_request_count(), 0);
}
#[tokio::test]
async fn test_inventory_cleanup_old_requests() {
let mut inventory = InventoryManager::new();
let hash1 = random_hash();
let hash2 = random_hash();
let peer = "peer1";
let _get_data1 = inventory.request_data(hash1, MSG_BLOCK, peer).unwrap();
let _get_data2 = inventory.request_data(hash2, MSG_TX, peer).unwrap();
assert_eq!(inventory.pending_request_count(), 2);
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
inventory.cleanup_old_requests(0);
assert_eq!(inventory.pending_request_count(), 0);
}
#[tokio::test]
async fn test_inventory_get_peer_inventory() {
let mut inventory = InventoryManager::new();
let peer = "peer1";
let hash1 = random_hash();
let hash2 = random_hash();
let items = vec![
InventoryVector {
inv_type: MSG_BLOCK,
hash: hash1,
},
InventoryVector {
inv_type: MSG_TX,
hash: hash2,
},
];
inventory.add_inventory(peer, &items).unwrap();
let peer_inv = inventory.get_peer_inventory(peer);
assert!(peer_inv.is_some());
let peer_inv = peer_inv.unwrap();
assert_eq!(peer_inv.len(), 2);
assert!(peer_inv.contains(&hash1));
assert!(peer_inv.contains(&hash2));
}
#[tokio::test]
async fn test_inventory_remove_peer() {
let mut inventory = InventoryManager::new();
let peer = "peer1";
let hash = random_hash();
let items = vec![InventoryVector {
inv_type: MSG_BLOCK,
hash,
}];
inventory.add_inventory(peer, &items).unwrap();
assert!(inventory.get_peer_inventory(peer).is_some());
inventory.remove_peer(peer);
assert!(inventory.get_peer_inventory(peer).is_none());
}
#[tokio::test]
async fn test_inventory_pending_requests() {
let mut inventory = InventoryManager::new();
let hash1 = random_hash();
let hash2 = random_hash();
let peer = "peer1";
let _get_data1 = inventory.request_data(hash1, MSG_BLOCK, peer).unwrap();
let _get_data2 = inventory.request_data(hash2, MSG_TX, peer).unwrap();
let pending = inventory.get_pending_requests();
assert_eq!(pending.len(), 2);
let hashes: Vec<_> = pending.iter().map(|req| req.hash).collect();
assert!(hashes.contains(&hash1));
assert!(hashes.contains(&hash2));
}
#[tokio::test]
async fn test_inventory_integration_workflow() {
let mut inventory = InventoryManager::new();
let peer1 = "peer1";
let peer2 = "peer2";
let hash1 = random_hash();
let hash2 = random_hash();
let hash3 = random_hash();
let items1 = vec![InventoryVector {
inv_type: MSG_BLOCK,
hash: hash1,
}];
let items2 = vec![
InventoryVector {
inv_type: MSG_TX,
hash: hash2,
},
InventoryVector {
inv_type: MSG_BLOCK,
hash: hash3,
},
];
inventory.add_inventory(peer1, &items1).unwrap();
inventory.add_inventory(peer2, &items2).unwrap();
assert_eq!(inventory.inventory_count(), 3);
let get_data = inventory.request_data(hash1, MSG_BLOCK, peer1).unwrap();
assert_eq!(get_data.inventory.len(), 1);
assert_eq!(inventory.pending_request_count(), 1);
inventory.mark_fulfilled(&hash1);
assert_eq!(inventory.pending_request_count(), 0);
inventory.remove_peer(peer1);
assert!(inventory.get_peer_inventory(peer1).is_none());
assert!(inventory.get_peer_inventory(peer2).is_some());
assert_eq!(inventory.inventory_count(), 3);
}
#[tokio::test]
async fn test_protocol_message_parsing() {
use blvm_node::network::protocol::*;
let version_msg = VersionMessage {
version: 70015,
services: 1,
timestamp: 1234567890,
addr_recv: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
addr_from: NetworkAddress {
services: 1,
ip: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
port: 8333,
},
nonce: 12345,
user_agent: "/Satoshi:0.21.0/".to_string(),
start_height: 100,
relay: true,
};
let protocol_msg = ProtocolMessage::Version(version_msg.clone());
let json = serde_json::to_string(&protocol_msg).unwrap();
let deserialized: ProtocolMessage = serde_json::from_str(&json).unwrap();
match deserialized {
ProtocolMessage::Version(deser_version) => {
assert_eq!(deser_version.version, version_msg.version);
assert_eq!(deser_version.services, version_msg.services);
assert_eq!(deser_version.user_agent, version_msg.user_agent);
}
_ => panic!("Expected Version message"),
}
}
#[tokio::test]
async fn test_ping_pong_messages() {
use blvm_node::network::protocol::*;
let ping_msg = PingMessage { nonce: 12345 };
let pong_msg = PongMessage { nonce: 12345 };
let ping_protocol = ProtocolMessage::Ping(ping_msg.clone());
let pong_protocol = ProtocolMessage::Pong(pong_msg.clone());
let ping_json = serde_json::to_string(&ping_protocol).unwrap();
let pong_json = serde_json::to_string(&pong_protocol).unwrap();
let deser_ping: ProtocolMessage = serde_json::from_str(&ping_json).unwrap();
let deser_pong: ProtocolMessage = serde_json::from_str(&pong_json).unwrap();
match deser_ping {
ProtocolMessage::Ping(deser_ping) => assert_eq!(deser_ping.nonce, ping_msg.nonce),
_ => panic!("Expected Ping message"),
}
match deser_pong {
ProtocolMessage::Pong(deser_pong) => assert_eq!(deser_pong.nonce, pong_msg.nonce),
_ => panic!("Expected Pong message"),
}
}
#[tokio::test]
async fn test_getheaders_message() {
use blvm_node::network::protocol::*;
let hash1 = random_hash();
let hash2 = random_hash();
let stop_hash = random_hash();
let getheaders = GetHeadersMessage {
version: 70015,
block_locator_hashes: vec![hash1, hash2],
hash_stop: stop_hash,
};
let protocol_msg = ProtocolMessage::GetHeaders(getheaders.clone());
let json = serde_json::to_string(&protocol_msg).unwrap();
let deserialized: ProtocolMessage = serde_json::from_str(&json).unwrap();
match deserialized {
ProtocolMessage::GetHeaders(deser_getheaders) => {
assert_eq!(deser_getheaders.version, getheaders.version);
assert_eq!(
deser_getheaders.block_locator_hashes.len(),
getheaders.block_locator_hashes.len()
);
assert_eq!(deser_getheaders.hash_stop, getheaders.hash_stop);
}
_ => panic!("Expected GetHeaders message"),
}
}
#[tokio::test]
async fn test_headers_message() {
use blvm_node::network::protocol::*;
use blvm_protocol::BlockHeader;
let header1 = BlockHeader {
version: 1,
prev_block_hash: random_hash(),
merkle_root: random_hash(),
timestamp: 1234567890,
bits: 0x1d00ffff,
nonce: 12345,
};
let header2 = BlockHeader {
version: 1,
prev_block_hash: random_hash(),
merkle_root: random_hash(),
timestamp: 1234567891,
bits: 0x1d00ffff,
nonce: 12346,
};
let headers = HeadersMessage {
headers: vec![header1, header2],
};
let protocol_msg = ProtocolMessage::Headers(headers.clone());
let json = serde_json::to_string(&protocol_msg).unwrap();
let deserialized: ProtocolMessage = serde_json::from_str(&json).unwrap();
match deserialized {
ProtocolMessage::Headers(deser_headers) => {
assert_eq!(deser_headers.headers.len(), headers.headers.len());
assert_eq!(
deser_headers.headers[0].timestamp,
headers.headers[0].timestamp
);
}
_ => panic!("Expected Headers message"),
}
}
#[tokio::test]
async fn test_inv_message() {
use blvm_node::network::protocol::*;
let hash1 = random_hash();
let hash2 = random_hash();
let inv_items = vec![
InventoryVector {
inv_type: MSG_BLOCK,
hash: hash1,
},
InventoryVector {
inv_type: MSG_TX,
hash: hash2,
},
];
let inv_msg = InvMessage {
inventory: inv_items.clone(),
};
let protocol_msg = ProtocolMessage::Inv(inv_msg.clone());
let json = serde_json::to_string(&protocol_msg).unwrap();
let deserialized: ProtocolMessage = serde_json::from_str(&json).unwrap();
match deserialized {
ProtocolMessage::Inv(deser_inv) => {
assert_eq!(deser_inv.inventory.len(), inv_msg.inventory.len());
assert_eq!(
deser_inv.inventory[0].inv_type,
inv_msg.inventory[0].inv_type
);
assert_eq!(deser_inv.inventory[0].hash, inv_msg.inventory[0].hash);
}
_ => panic!("Expected Inv message"),
}
}
#[tokio::test]
async fn test_getdata_message() {
use blvm_node::network::protocol::*;
let hash1 = random_hash();
let hash2 = random_hash();
let getdata_items = vec![
InventoryVector {
inv_type: MSG_BLOCK,
hash: hash1,
},
InventoryVector {
inv_type: MSG_TX,
hash: hash2,
},
];
let getdata_msg = GetDataMessage {
inventory: getdata_items.clone(),
};
let protocol_msg = ProtocolMessage::GetData(getdata_msg.clone());
let json = serde_json::to_string(&protocol_msg).unwrap();
let deserialized: ProtocolMessage = serde_json::from_str(&json).unwrap();
match deserialized {
ProtocolMessage::GetData(deser_getdata) => {
assert_eq!(deser_getdata.inventory.len(), getdata_msg.inventory.len());
assert_eq!(
deser_getdata.inventory[0].inv_type,
getdata_msg.inventory[0].inv_type
);
}
_ => panic!("Expected GetData message"),
}
}
#[tokio::test(flavor = "multi_thread")]
async fn test_persistent_peers() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let manager = NetworkManager::new(addr);
let peer1: SocketAddr = "127.0.0.1:8333".parse().unwrap();
let peer2: SocketAddr = "127.0.0.1:8334".parse().unwrap();
manager.add_persistent_peer(peer1);
manager.add_persistent_peer(peer2);
let persistent = manager.get_persistent_peers_sync();
assert_eq!(persistent.len(), 2);
assert!(persistent.contains(&peer1));
assert!(persistent.contains(&peer2));
manager.remove_persistent_peer(peer1);
let persistent = manager.get_persistent_peers_sync();
assert_eq!(persistent.len(), 1);
assert!(!persistent.contains(&peer1));
assert!(persistent.contains(&peer2));
}
#[tokio::test(flavor = "multi_thread")]
async fn test_ban_list() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let manager = NetworkManager::new(addr);
let banned_peer: SocketAddr = "127.0.0.1:8333".parse().unwrap();
manager.ban_peer(banned_peer, 0);
assert!(manager.is_banned(banned_peer));
let banned = manager.get_banned_peers();
assert_eq!(banned.len(), 1);
assert_eq!(banned[0].0, banned_peer);
manager.unban_peer(banned_peer);
assert!(!manager.is_banned(banned_peer));
use std::time::{SystemTime, UNIX_EPOCH};
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
let unban_time = now + 3600; manager.ban_peer(banned_peer, unban_time);
assert!(manager.is_banned(banned_peer));
manager.clear_bans();
assert!(!manager.is_banned(banned_peer));
assert!(manager.get_banned_peers().is_empty());
}
#[tokio::test(flavor = "multi_thread")]
async fn test_network_stats() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let manager = NetworkManager::new(addr);
let (sent, received) = manager.get_network_stats_legacy();
assert_eq!(sent, 0);
assert_eq!(received, 0);
manager.track_bytes_sent(100).await;
manager.track_bytes_received(200).await;
let (sent, received) = manager.get_network_stats_legacy();
assert_eq!(sent, 100);
assert_eq!(received, 200);
manager.track_bytes_sent(50).await;
manager.track_bytes_received(75).await;
let (sent, received) = manager.get_network_stats_legacy();
assert_eq!(sent, 150);
assert_eq!(received, 275);
}
#[tokio::test]
async fn test_ping_all_peers() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let manager = NetworkManager::new(addr);
let result = manager.ping_all_peers().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_protocol_constants() {
use blvm_node::network::protocol::*;
assert_eq!(BITCOIN_MAGIC_MAINNET, [0xf9, 0xbe, 0xb4, 0xd9]);
assert_eq!(BITCOIN_MAGIC_TESTNET, [0x0b, 0x11, 0x09, 0x07]);
assert_eq!(BITCOIN_MAGIC_REGTEST, [0xfa, 0xbf, 0xb5, 0xda]);
assert_eq!(MAX_PROTOCOL_MESSAGE_LENGTH, 32 * 1024 * 1024);
assert!(ALLOWED_COMMANDS.contains(&"version"));
assert!(ALLOWED_COMMANDS.contains(&"verack"));
assert!(ALLOWED_COMMANDS.contains(&"ping"));
assert!(ALLOWED_COMMANDS.contains(&"pong"));
assert!(ALLOWED_COMMANDS.contains(&"block"));
assert!(ALLOWED_COMMANDS.contains(&"tx"));
assert!(ALLOWED_COMMANDS.contains(&"inv"));
assert!(ALLOWED_COMMANDS.contains(&"getdata"));
}