#[cfg(feature = "rest-api")]
mod tests {
use blvm_node::rpc::blockchain::BlockchainRpc;
use blvm_node::rpc::mempool::MempoolRpc;
use blvm_node::rpc::mining::MiningRpc;
use blvm_node::rpc::network::NetworkRpc;
use blvm_node::rpc::rawtx::RawTxRpc;
use blvm_node::rpc::rest::types::ApiResponse;
use blvm_node::rpc::rest::{
addresses, blocks, chain, fees, mempool as rest_mempool, mining, network as rest_network,
node, transactions,
};
use blvm_node::storage::Storage;
use serde_json::Value;
use std::sync::Arc;
use tempfile::TempDir;
fn create_test_blockchain_rpc() -> Arc<BlockchainRpc> {
let temp_dir = TempDir::new().unwrap();
let storage = Arc::new(Storage::new(temp_dir.path()).unwrap());
Arc::new(BlockchainRpc::with_dependencies(storage))
}
fn create_test_mempool_rpc() -> Arc<MempoolRpc> {
Arc::new(MempoolRpc::new())
}
fn create_test_network_rpc() -> Arc<NetworkRpc> {
Arc::new(NetworkRpc::new())
}
fn create_test_mining_rpc() -> Arc<MiningRpc> {
Arc::new(MiningRpc::new())
}
fn create_test_rawtx_rpc() -> Arc<RawTxRpc> {
Arc::new(RawTxRpc::new())
}
#[tokio::test]
async fn test_chain_tip_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_chain_tip(&blockchain).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_chain_height_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_chain_height(&blockchain).await;
assert!(result.is_ok());
let height: Value = result.unwrap();
assert!(height.is_number() || height.is_null());
}
#[tokio::test]
async fn test_chain_info_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_chain_info(&blockchain).await;
assert!(result.is_ok());
let info: Value = result.unwrap();
assert!(info.is_object() || info.is_null());
}
#[tokio::test]
async fn test_blocks_get_by_hash() {
let blockchain = create_test_blockchain_rpc();
let hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f";
let result = blocks::get_block_by_hash(&blockchain, hash).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_blocks_get_by_height() {
let blockchain = create_test_blockchain_rpc();
let result = blocks::get_block_by_height(&blockchain, 0).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_blocks_get_transactions() {
let blockchain = create_test_blockchain_rpc();
let hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f";
let result = blocks::get_block_transactions(&blockchain, hash).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_transactions_get_details() {
let rawtx = create_test_rawtx_rpc();
let txid = "0000000000000000000000000000000000000000000000000000000000000000";
let result = transactions::get_transaction(&rawtx, txid).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_transactions_get_confirmations() {
let rawtx = create_test_rawtx_rpc();
let txid = "0000000000000000000000000000000000000000000000000000000000000000";
let result = transactions::get_transaction_confirmations(&rawtx, txid).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_transactions_submit() {
let rawtx = create_test_rawtx_rpc();
let invalid_hex = "invalid";
let result = transactions::submit_transaction(&rawtx, invalid_hex).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_addresses_get_balance() {
let blockchain = create_test_blockchain_rpc();
let address = "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa";
let result = addresses::get_address_balance(&blockchain, address).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_addresses_get_transactions() {
let blockchain = create_test_blockchain_rpc();
let address = "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa";
let result = addresses::get_address_transactions(&blockchain, address).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_addresses_get_utxos() {
let blockchain = create_test_blockchain_rpc();
let address = "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa";
let result = addresses::get_address_utxos(&blockchain, address).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_mempool_get_all() {
let mempool = create_test_mempool_rpc();
let result = rest_mempool::get_mempool(&mempool, false).await;
assert!(result.is_ok());
let txs: Value = result.unwrap();
assert!(txs.is_array());
}
#[tokio::test]
async fn test_mempool_get_transaction() {
let mempool = create_test_mempool_rpc();
let txid = "0000000000000000000000000000000000000000000000000000000000000000";
let result = rest_mempool::get_mempool_transaction(&mempool, txid).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_mempool_get_stats() {
let mempool = create_test_mempool_rpc();
let result = rest_mempool::get_mempool_stats(&mempool).await;
assert!(result.is_ok());
let stats: Value = result.unwrap();
assert!(stats.is_object());
}
#[tokio::test]
async fn test_network_get_info() {
let network = create_test_network_rpc();
let result = rest_network::get_network_info(&network).await;
assert!(result.is_ok());
let info: Value = result.unwrap();
assert!(info.is_object());
}
#[tokio::test]
async fn test_network_get_peers() {
let network = create_test_network_rpc();
let result = rest_network::get_network_peers(&network).await;
assert!(result.is_ok());
let peers: Value = result.unwrap();
assert!(peers.is_array());
}
#[tokio::test]
async fn test_fees_estimate() {
let mining = create_test_mining_rpc();
let result = fees::get_fee_estimate(&mining, Some(6)).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_fees_estimate_default() {
let mining = create_test_mining_rpc();
let result = fees::get_fee_estimate(&mining, None).await;
assert!(result.is_ok() || result.is_err());
}
#[test]
fn test_api_response_structure() {
let data = serde_json::json!({"test": "data"});
let response = ApiResponse::success(data.clone(), None);
assert_eq!(response.data, data);
assert_eq!(response.meta.version, "1.0");
assert!(response.meta.timestamp.parse::<u64>().is_ok());
}
#[test]
fn test_api_response_with_links() {
use std::collections::HashMap;
let data = serde_json::json!({});
let mut links = HashMap::new();
links.insert("self".to_string(), "/api/v1/test".to_string());
let response = ApiResponse::success(data, None).with_links(links.clone());
assert_eq!(response.links, Some(links));
}
#[test]
fn test_api_response_with_request_id() {
let data = serde_json::json!({});
let request_id = Some("test-request-id".to_string());
let response = ApiResponse::success(data, request_id.clone());
assert_eq!(response.meta.request_id, request_id);
}
#[tokio::test]
async fn test_transactions_test_endpoint() {
let rawtx = create_test_rawtx_rpc();
let tx_hex = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020602ffffffff0100f2052a010000004341041b0e8c2567c12536aa13357b79a073dc4443acf83e08e2c1252d0efcb9a4ba20b4e93f883d634390d26ed65f763194ea3273f11a6718b3615b4d94e82801b0eac00000000";
let result = transactions::test_transaction(&rawtx, tx_hex).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_transactions_decode_endpoint() {
let rawtx = create_test_rawtx_rpc();
let tx_hex = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020602ffffffff0100f2052a010000004341041b0e8c2567c12536aa13357b79a073dc4443acf83e08e2c1252d0efcb9a4ba20b4e93f883d634390d26ed65f763194ea3273f11a6718b3615b4d94e82801b0eac00000000";
let result = transactions::decode_transaction(&rawtx, tx_hex).await;
assert!(result.is_ok(), "Should decode transaction");
let decoded = result.unwrap();
assert!(
decoded.is_object(),
"Decoded transaction should be an object"
);
}
#[tokio::test]
async fn test_transactions_create_endpoint() {
let rawtx = create_test_rawtx_rpc();
let inputs = serde_json::json!([
{
"txid": "0000000000000000000000000000000000000000000000000000000000000000",
"vout": 0
}
]);
let outputs = serde_json::json!({
"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4": 0.001
});
let result =
transactions::create_transaction(&rawtx, inputs, outputs, None, None, None).await;
assert!(result.is_ok(), "Should create transaction");
let tx_hex = result.unwrap();
assert!(tx_hex.is_string(), "Result should be hex string");
}
#[tokio::test]
async fn test_chain_difficulty_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_chain_difficulty(&blockchain).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_chain_utxo_set_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_utxo_set_info(&blockchain).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_chain_tips_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_chain_tips(&blockchain).await;
assert!(result.is_ok());
let tips = result.unwrap();
assert!(tips.is_array(), "Chain tips should be an array");
}
#[tokio::test]
async fn test_chain_tx_stats_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_chain_tx_stats(&blockchain, Some(144)).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_chain_prune_info_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_prune_info(&blockchain).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_chain_index_info_endpoint() {
let blockchain = create_test_blockchain_rpc();
let result = chain::get_index_info(&blockchain, None).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_blocks_header_endpoint() {
let blockchain = create_test_blockchain_rpc();
let hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f";
let result = blocks::get_block_header(&blockchain, hash, true).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_blocks_stats_endpoint() {
let blockchain = create_test_blockchain_rpc();
let hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f";
let result = blocks::get_block_stats(&blockchain, hash).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_blocks_filter_endpoint() {
let blockchain = create_test_blockchain_rpc();
let hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f";
let result = blocks::get_block_filter(&blockchain, hash, None).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_mempool_ancestors_endpoint() {
let mempool = create_test_mempool_rpc();
let txid = "0000000000000000000000000000000000000000000000000000000000000000";
let result = rest_mempool::get_mempool_ancestors(&mempool, txid, false).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_mempool_descendants_endpoint() {
let mempool = create_test_mempool_rpc();
let txid = "0000000000000000000000000000000000000000000000000000000000000000";
let result = rest_mempool::get_mempool_descendants(&mempool, txid, false).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_mempool_save_endpoint() {
let mempool = create_test_mempool_rpc();
let result = rest_mempool::save_mempool(&mempool).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_network_connection_count_endpoint() {
let network = create_test_network_rpc();
let result = rest_network::get_connection_count(&network).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_network_totals_endpoint() {
let network = create_test_network_rpc();
let result = rest_network::get_net_totals(&network).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_network_node_addresses_endpoint() {
let network = create_test_network_rpc();
let result = rest_network::get_node_addresses(&network, Some(10)).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_network_list_banned_endpoint() {
let network = create_test_network_rpc();
let result = rest_network::list_banned(&network).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_mining_info_endpoint() {
let mining = create_test_mining_rpc();
let result = mining::get_mining_info(&mining).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_mining_block_template_endpoint() {
let mining = create_test_mining_rpc();
let result = mining::get_block_template(&mining, None, None).await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_node_uptime_endpoint() {
use blvm_node::rpc::control::ControlRpc;
let control = ControlRpc::new();
let result = node::get_uptime(&control).await;
assert!(result.is_ok());
let uptime = result.unwrap();
assert!(uptime.is_number(), "Uptime should be a number");
}
#[tokio::test]
async fn test_node_memory_endpoint() {
use blvm_node::rpc::control::ControlRpc;
let control = ControlRpc::new();
let result = node::get_memory_info(&control, Some("stats")).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_node_rpc_info_endpoint() {
use blvm_node::rpc::control::ControlRpc;
let control = ControlRpc::new();
let result = node::get_rpc_info(&control).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_node_help_endpoint() {
use blvm_node::rpc::control::ControlRpc;
let control = ControlRpc::new();
let result = node::get_help(&control, None).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_node_logging_endpoint() {
use blvm_node::rpc::control::ControlRpc;
let control = ControlRpc::new();
let result = node::get_logging(&control).await;
assert!(result.is_ok());
}
}