use blvm_node::node::*;
use blvm_node::{OutPoint, Transaction, TransactionInput, TransactionOutput};
use std::net::SocketAddr;
use tempfile::TempDir;
mod common;
use blvm_protocol::ProtocolVersion;
use common::*;
use serial_test::serial;
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn test_node_creation() {
let temp_dir = TempDir::new().unwrap();
let network_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let rpc_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let node = Node::new(
temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
None, )
.unwrap();
let _protocol = node.protocol();
let _storage = node.storage();
let _network = node.network();
let _rpc = node.rpc();
}
#[tokio::test]
async fn test_sync_coordinator() {
let sync = sync::SyncCoordinator::new();
assert_eq!(sync.progress(), 0.0);
assert!(!sync.is_synced());
}
#[tokio::test]
async fn test_mempool_manager() {
let mut mempool = mempool::MempoolManager::new();
assert_eq!(mempool.size(), 0);
assert!(mempool.transaction_hashes().is_empty());
use blvm_protocol::Transaction;
let tx = Transaction {
version: 1,
inputs: blvm_protocol::tx_inputs![],
outputs: blvm_protocol::tx_outputs![],
lock_time: 0,
};
let result = mempool.add_transaction(tx).unwrap();
assert!(result); }
#[tokio::test]
async fn test_mining_coordinator() {
use std::sync::Arc;
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let mut miner = miner::MiningCoordinator::new(mempool, None);
assert!(!miner.is_mining_enabled());
let info = miner.get_mining_info();
assert!(!info.enabled);
assert_eq!(info.threads, 1);
assert!(!info.has_template);
miner.enable_mining();
assert!(miner.is_mining_enabled());
miner.disable_mining();
assert!(!miner.is_mining_enabled());
}
#[tokio::test]
async fn test_sync_state_transitions() {
let states = vec![
sync::SyncState::Initial,
sync::SyncState::Headers,
sync::SyncState::Blocks,
sync::SyncState::Synced,
sync::SyncState::Error("test error".to_string()),
];
for state in states {
match state {
sync::SyncState::Initial => assert!(true),
sync::SyncState::Headers => assert!(true),
sync::SyncState::Blocks => assert!(true),
sync::SyncState::Synced => assert!(true),
sync::SyncState::Error(_) => assert!(true),
}
}
}
#[tokio::test]
async fn test_mining_info() {
use std::sync::Arc;
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let miner = miner::MiningCoordinator::new(mempool, None);
let info = miner.get_mining_info();
assert!(!info.enabled);
assert_eq!(info.threads, 1);
assert!(!info.has_template);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn test_node_creation_with_different_protocols() {
let network_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let rpc_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let mainnet_temp_dir = TempDir::new().unwrap();
let mainnet_node = Node::new(
mainnet_temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
Some(blvm_protocol::ProtocolVersion::BitcoinV1),
)
.unwrap();
assert_eq!(
mainnet_node.protocol().get_protocol_version(),
blvm_protocol::ProtocolVersion::BitcoinV1
);
let testnet_temp_dir = TempDir::new().unwrap();
let testnet_node = Node::new(
testnet_temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
Some(blvm_protocol::ProtocolVersion::Testnet3),
)
.unwrap();
assert_eq!(
testnet_node.protocol().get_protocol_version(),
blvm_protocol::ProtocolVersion::Testnet3
);
let regtest_temp_dir = TempDir::new().unwrap();
let regtest_node = Node::new(
regtest_temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
None, )
.unwrap();
assert_eq!(
regtest_node.protocol().get_protocol_version(),
blvm_protocol::ProtocolVersion::Regtest
);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn test_node_component_initialization() {
let temp_dir = TempDir::new().unwrap();
let network_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let rpc_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let node = Node::new(
temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
None,
)
.unwrap();
let protocol = node.protocol();
assert!(protocol.supports_feature("fast_mining"));
let storage = node.storage();
let _ = storage.blocks().block_count().unwrap();
let network = node.network();
assert_eq!(network.peer_count(), 0);
let rpc = node.rpc();
let _blockchain = rpc.blockchain();
let _network = rpc.network();
let _mining = rpc.mining();
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn test_node_startup_shutdown() {
let temp_dir = TempDir::new().unwrap();
let network_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let rpc_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let node = Node::new(
temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
None,
)
.unwrap();
assert!(true); }
#[tokio::test]
async fn test_sync_coordinator_operations() {
let sync = sync::SyncCoordinator::new();
assert_eq!(sync.progress(), 0.0);
assert!(!sync.is_synced());
assert_eq!(sync.progress(), 0.0);
assert!(!sync.is_synced());
}
#[tokio::test]
async fn test_sync_coordinator_error_handling() {
let sync = sync::SyncCoordinator::new();
let _error_msg = "Connection failed".to_string();
assert!(!sync.is_synced());
}
#[tokio::test]
async fn test_sync_coordinator_peer_selection() {
let sync = sync::SyncCoordinator::new();
let peers = vec![
"peer1".to_string(),
"peer2".to_string(),
"peer3".to_string(),
];
let selected_peers = &peers;
assert!(!selected_peers.is_empty());
assert!(selected_peers.len() <= peers.len());
for peer in selected_peers {
assert!(peers.contains(peer));
}
}
#[tokio::test]
async fn test_sync_coordinator_stalled_detection() {
let sync = sync::SyncCoordinator::new();
assert_eq!(sync.progress(), 0.0);
assert!(!sync.is_synced());
}
#[tokio::test]
async fn test_mempool_manager_operations() {
let mut mempool = mempool::MempoolManager::new();
assert_eq!(mempool.size(), 0);
assert!(mempool.transaction_hashes().is_empty());
let tx1 = valid_transaction();
let tx2 = Transaction {
version: 2, inputs: blvm_protocol::tx_inputs![TransactionInput {
prevout: OutPoint {
hash: random_hash(),
index: 1,
},
script_sig: vec![0x42, 0x05], sequence: 0xfffffffe,
}],
outputs: blvm_protocol::tx_outputs![TransactionOutput {
value: 25_0000_0000, script_pubkey: p2pkh_script(random_hash20()).into(),
}],
lock_time: 1, };
let result1 = mempool.add_transaction(tx1).unwrap();
let result2 = mempool.add_transaction(tx2).unwrap();
assert!(result1);
assert!(result2);
assert_eq!(mempool.size(), 2);
let hashes = mempool.transaction_hashes();
assert_eq!(hashes.len(), 2);
}
#[tokio::test]
async fn test_mempool_manager_eviction() {
let mut mempool = mempool::MempoolManager::new();
for i in 0..100 {
let tx = TestTransactionBuilder::new()
.add_input(OutPoint {
hash: random_hash(),
index: 0,
})
.add_output(1000, p2pkh_script(random_hash20()))
.build();
mempool.add_transaction(tx).unwrap();
}
assert!(mempool.size() <= 100);
}
#[tokio::test]
async fn test_mempool_manager_fee_prioritization() {
let mut mempool = mempool::MempoolManager::new();
let high_fee_tx = TestTransactionBuilder::new()
.add_input(OutPoint {
hash: random_hash(),
index: 0,
})
.add_output(1000, p2pkh_script(random_hash20()))
.build();
let low_fee_tx = TestTransactionBuilder::new()
.add_input(OutPoint {
hash: random_hash(),
index: 0,
})
.add_output(1000, p2pkh_script(random_hash20()))
.build();
mempool.add_transaction(high_fee_tx).unwrap();
mempool.add_transaction(low_fee_tx).unwrap();
}
#[tokio::test]
async fn test_mempool_manager_conflict_detection() {
let mut mempool = mempool::MempoolManager::new();
let outpoint = OutPoint {
hash: random_hash(),
index: 0,
};
let tx1 = TestTransactionBuilder::new()
.add_input(outpoint.clone())
.add_output(1000, p2pkh_script(random_hash20()))
.build();
let tx2 = TestTransactionBuilder::new()
.add_input(outpoint)
.add_output(2000, p2pkh_script(random_hash20()))
.build();
mempool.add_transaction(tx1).unwrap();
let result = mempool.add_transaction(tx2).unwrap();
assert!(!result); }
#[tokio::test]
async fn test_mining_coordinator_operations() {
use std::sync::Arc;
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let mut miner = miner::MiningCoordinator::new(mempool, None);
assert!(!miner.is_mining_enabled());
let info = miner.get_mining_info();
assert!(!info.enabled);
assert_eq!(info.threads, 1);
assert!(!info.has_template);
miner.enable_mining();
assert!(miner.is_mining_enabled());
miner.disable_mining();
assert!(!miner.is_mining_enabled());
}
#[tokio::test]
async fn test_mining_coordinator_block_template() {
use std::sync::Arc;
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let miner = miner::MiningCoordinator::new(mempool, None);
}
#[tokio::test]
async fn test_mining_coordinator_transaction_selection() {
use std::sync::Arc;
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let miner = miner::MiningCoordinator::new(mempool, None);
let transactions = vec![
valid_transaction(),
valid_transaction(),
valid_transaction(),
];
}
#[tokio::test]
async fn test_mining_coordinator_fee_optimization() {
use std::sync::Arc;
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let miner = miner::MiningCoordinator::new(mempool, None);
let transactions = vec![
TestTransactionBuilder::new()
.add_input(OutPoint {
hash: random_hash(),
index: 0,
})
.add_output(1000, p2pkh_script(random_hash20()))
.build(),
TestTransactionBuilder::new()
.add_input(OutPoint {
hash: random_hash(),
index: 0,
})
.add_output(2000, p2pkh_script(random_hash20()))
.build(),
];
}
#[tokio::test]
async fn test_mining_coordinator_mining_state() {
use std::sync::Arc;
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let mut miner = miner::MiningCoordinator::new(mempool, None);
assert!(!miner.is_mining_enabled());
miner.enable_mining();
assert!(miner.is_mining_enabled());
}
#[tokio::test]
async fn test_sync_mempool_interaction() {
let sync = sync::SyncCoordinator::new();
let mut mempool = mempool::MempoolManager::new();
let tx = valid_transaction();
let result = mempool.add_transaction(tx).unwrap();
assert!(result);
}
#[tokio::test]
async fn test_mining_mempool_interaction() {
use std::sync::Arc;
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let mut miner = miner::MiningCoordinator::new(mempool, None);
let mut mempool = mempool::MempoolManager::new();
miner.enable_mining();
assert!(miner.is_mining_enabled());
let tx = valid_transaction();
mempool.add_transaction(tx).unwrap();
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn test_full_node_coordination() {
let temp_dir = TempDir::new().unwrap();
let network_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let rpc_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let node = Node::new(
temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
None,
)
.unwrap();
let protocol = node.protocol();
let storage = node.storage();
let network = node.network();
let rpc = node.rpc();
assert!(protocol.supports_feature("fast_mining"));
let _ = storage.blocks().block_count().unwrap();
assert_eq!(network.peer_count(), 0);
}
#[tokio::test]
async fn test_mempool_process_once() {
let mut mempool = mempool::MempoolManager::new();
let result = mempool.process_once().await;
assert!(result.is_ok());
assert_eq!(mempool.size(), 0);
}
#[tokio::test]
async fn test_mempool_processing_workflow() {
let mut mempool = mempool::MempoolManager::new();
let tx = valid_transaction();
let result = mempool.add_transaction(tx);
assert!(result.is_ok());
assert_eq!(mempool.size(), 1);
let result = mempool.process_once().await;
assert!(result.is_ok());
assert_eq!(mempool.size(), 1);
}
#[tokio::test]
async fn test_mempool_cleanup_workflow() {
let mut mempool = mempool::MempoolManager::new();
let tx1 = unique_transaction();
let tx2 = unique_transaction();
mempool.add_transaction(tx1).unwrap();
mempool.add_transaction(tx2).unwrap();
assert_eq!(mempool.size(), 2);
let result = mempool.process_once().await;
assert!(result.is_ok());
assert_eq!(mempool.size(), 2);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn test_node_run_once() {
let temp_dir = TempDir::new().unwrap();
let network_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let rpc_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let mut node = Node::new(
temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
Some(ProtocolVersion::Regtest),
)
.unwrap();
let result = node.run_once().await;
assert!(result.is_ok());
assert!(node.protocol().supports_feature("fast_mining"));
assert_eq!(node.network().peer_count(), 0);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn test_node_health_check() {
let temp_dir = TempDir::new().unwrap();
let network_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let rpc_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let node = Node::new(
temp_dir.path().to_str().unwrap(),
network_addr,
rpc_addr,
Some(ProtocolVersion::Regtest),
)
.unwrap();
let mut node = node;
let result = node.run_once().await;
assert!(result.is_ok());
}