use blvm_node::rpc::*;
use std::net::SocketAddr;
use tokio::time::{timeout, Duration};
mod common;
#[tokio::test]
async fn test_rpc_manager_creation() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let manager = RpcManager::new(addr);
let _blockchain = manager.blockchain();
let _network = manager.network();
let _mining = manager.mining();
}
#[tokio::test]
async fn test_blockchain_rpc() {
let blockchain = blockchain::BlockchainRpc::new();
let info = blockchain.get_blockchain_info().await.unwrap();
assert!(info.get("chain").is_some());
assert!(info.get("blocks").is_some());
let block_result = blockchain
.get_block("0000000000000000000000000000000000000000000000000000000000000000")
.await;
if let Ok(block) = block_result {
assert!(block.get("hash").is_some());
assert!(block.get("height").is_some());
} else {
assert!(block_result.is_err());
}
let hash = blockchain.get_block_hash(0).await.unwrap();
assert!(hash.is_string());
let tx = blockchain
.get_raw_transaction("0000000000000000000000000000000000000000000000000000000000000000")
.await
.unwrap();
assert!(tx.get("txid").is_some());
assert!(tx.get("version").is_some());
}
#[tokio::test]
async fn test_network_rpc() {
let network = network::NetworkRpc::new();
let info = network.get_network_info().await.unwrap();
assert!(info.get("version").is_some());
assert!(info.get("connections").is_some());
let peers = network.get_peer_info().await.unwrap();
assert!(peers.is_array());
}
#[tokio::test]
async fn test_mining_rpc() {
let mining = mining::MiningRpc::new();
let info = mining.get_mining_info().await.unwrap();
assert!(info.get("blocks").is_some());
assert!(info.get("difficulty").is_some());
let params = serde_json::json!([]);
let result = mining.get_block_template(¶ms).await;
assert!(true);
}
#[tokio::test]
async fn test_rpc_server_creation() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let server = server::RpcServer::new(addr);
assert!(true); }
#[tokio::test]
async fn test_rpc_request_processing() {
let request = r#"{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}"#;
let request_value: serde_json::Value = serde_json::from_str(request).unwrap();
let method = request_value.get("method").unwrap().as_str().unwrap();
let params = request_value.get("params").unwrap();
assert_eq!(method, "getblockchaininfo");
assert!(params.is_array());
}
#[tokio::test]
async fn test_rpc_error_handling() {
let invalid_json = r#"{"jsonrpc":"2.0","method":"invalid_method","params":[],"id":1}"#;
let request_value: serde_json::Value = serde_json::from_str(invalid_json).unwrap();
let method = request_value.get("method").unwrap().as_str().unwrap();
assert_eq!(method, "invalid_method");
}
#[tokio::test]
async fn test_rpc_server_initialization() {
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
let server = server::RpcServer::new(addr);
assert!(true);
assert!(true); }
#[tokio::test]
async fn test_rpc_request_parsing() {
let valid_request = r#"{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}"#;
let request_value: serde_json::Value = serde_json::from_str(valid_request).unwrap();
assert_eq!(
request_value.get("jsonrpc").unwrap().as_str().unwrap(),
"2.0"
);
assert_eq!(
request_value.get("method").unwrap().as_str().unwrap(),
"getblockchaininfo"
);
assert!(request_value.get("params").unwrap().is_array());
assert_eq!(request_value.get("id").unwrap().as_u64().unwrap(), 1);
}
#[tokio::test]
async fn test_rpc_response_formatting() {
let response = serde_json::json!({
"jsonrpc": "2.0",
"result": {
"chain": "main",
"blocks": 100,
"headers": 100
},
"id": 1
});
assert_eq!(response.get("jsonrpc").unwrap().as_str().unwrap(), "2.0");
assert!(response.get("result").unwrap().is_object());
assert_eq!(response.get("id").unwrap().as_u64().unwrap(), 1);
}
#[tokio::test]
async fn test_rpc_error_response_formatting() {
let error_response = serde_json::json!({
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found"
},
"id": 1
});
assert_eq!(
error_response.get("jsonrpc").unwrap().as_str().unwrap(),
"2.0"
);
assert!(error_response.get("error").unwrap().is_object());
assert_eq!(
error_response
.get("error")
.unwrap()
.get("code")
.unwrap()
.as_i64()
.unwrap(),
-32601
);
}
#[tokio::test]
async fn test_blockchain_rpc_getblockchaininfo() {
let blockchain = blockchain::BlockchainRpc::new();
let info = blockchain.get_blockchain_info().await.unwrap();
assert!(info.get("chain").is_some());
assert!(info.get("blocks").is_some());
assert!(info.get("headers").is_some());
assert!(info.get("bestblockhash").is_some());
assert!(info.get("difficulty").is_some());
assert!(info.get("mediantime").is_some());
assert!(info.get("verificationprogress").is_some());
assert!(info.get("initialblockdownload").is_some());
assert!(info.get("chainwork").is_some());
assert!(info.get("size_on_disk").is_some());
assert!(info.get("pruned").is_some());
}
#[tokio::test]
async fn test_blockchain_rpc_getblock() {
let blockchain = blockchain::BlockchainRpc::new();
let genesis_hash = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f";
let block_result = blockchain.get_block(genesis_hash).await;
if let Ok(block) = block_result {
assert!(block.get("hash").is_some());
assert!(block.get("height").is_some());
assert!(block.get("version").is_some());
assert!(block.get("time").is_some());
assert!(block.get("bits").is_some());
assert!(block.get("nonce").is_some());
assert!(block.get("tx").is_some());
} else {
assert!(block_result.is_err());
}
}
#[tokio::test]
async fn test_blockchain_rpc_getblockhash() {
let blockchain = blockchain::BlockchainRpc::new();
let hash = blockchain.get_block_hash(0).await.unwrap();
assert!(hash.is_string());
let result = blockchain.get_block_hash(999999).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_blockchain_rpc_getrawtransaction() {
let blockchain = blockchain::BlockchainRpc::new();
let tx_hash = "0000000000000000000000000000000000000000000000000000000000000000";
let tx = blockchain.get_raw_transaction(tx_hash).await.unwrap();
assert!(tx.get("txid").is_some());
assert!(tx.get("version").is_some());
assert!(tx.get("locktime").is_some());
assert!(tx.get("vin").is_some());
assert!(tx.get("vout").is_some());
}
#[tokio::test]
async fn test_blockchain_rpc_gettxout() {
let blockchain = blockchain::BlockchainRpc::new();
let tx_hash = "0000000000000000000000000000000000000000000000000000000000000000";
let vout = 0;
}
#[tokio::test]
async fn test_blockchain_rpc_gettxoutsetinfo() {
let blockchain = blockchain::BlockchainRpc::new();
}
#[tokio::test]
async fn test_network_rpc_getnetworkinfo() {
let network = network::NetworkRpc::new();
let info = network.get_network_info().await.unwrap();
assert!(info.get("version").is_some());
assert!(info.get("subversion").is_some());
assert!(info.get("protocolversion").is_some());
assert!(info.get("localservices").is_some());
assert!(info.get("localrelay").is_some());
assert!(info.get("timeoffset").is_some());
assert!(info.get("connections").is_some());
assert!(info.get("networkactive").is_some());
assert!(info.get("networks").is_some());
assert!(info.get("relayfee").is_some());
assert!(info.get("incrementalfee").is_some());
assert!(info.get("localaddresses").is_some());
assert!(info.get("warnings").is_some());
}
#[tokio::test]
async fn test_network_rpc_getpeerinfo() {
let network = network::NetworkRpc::new();
let peers = network.get_peer_info().await.unwrap();
assert!(peers.is_array());
if let Some(peer) = peers.as_array().unwrap().first() {
assert!(peer.get("id").is_some());
assert!(peer.get("addr").is_some());
assert!(peer.get("addrbind").is_some());
assert!(peer.get("services").is_some());
assert!(peer.get("relaytxes").is_some());
assert!(peer.get("lastsend").is_some());
assert!(peer.get("lastrecv").is_some());
assert!(peer.get("bytessent").is_some());
assert!(peer.get("bytesrecv").is_some());
assert!(peer.get("conntime").is_some());
assert!(peer.get("timeoffset").is_some());
assert!(peer.get("pingtime").is_some());
assert!(peer.get("minping").is_some());
assert!(peer.get("version").is_some());
assert!(peer.get("subver").is_some());
assert!(peer.get("inbound").is_some());
assert!(peer.get("addnode").is_some());
assert!(peer.get("startingheight").is_some());
assert!(peer.get("synced_headers").is_some());
assert!(peer.get("synced_blocks").is_some());
assert!(peer.get("inflight").is_some());
assert!(peer.get("whitelisted").is_some());
assert!(peer.get("permissions").is_some());
assert!(peer.get("minfeefilter").is_some());
assert!(peer.get("bytessent_per_msg").is_some());
assert!(peer.get("bytesrecv_per_msg").is_some());
}
}
#[tokio::test]
async fn test_network_rpc_getconnectioncount() {
let network = network::NetworkRpc::new();
}
#[tokio::test]
async fn test_network_rpc_getnettotals() {
let network = network::NetworkRpc::new();
}
#[tokio::test]
async fn test_mining_rpc_getmininginfo() {
let mining = mining::MiningRpc::new();
let info = mining.get_mining_info().await.unwrap();
assert!(info.get("blocks").is_some());
assert!(info.get("currentblockweight").is_some());
assert!(info.get("currentblocktx").is_some());
assert!(info.get("difficulty").is_some());
assert!(info.get("networkhashps").is_some());
assert!(info.get("pooledtx").is_some());
assert!(info.get("chain").is_some());
assert!(info.get("warnings").is_some());
}
#[tokio::test]
async fn test_mining_rpc_getblocktemplate() {
use blvm_node::storage::Storage;
use blvm_protocol::BlockHeader;
use std::sync::Arc;
use tempfile::TempDir;
let temp_dir = TempDir::new().unwrap();
let storage = Arc::new(Storage::new(temp_dir.path()).unwrap());
let mempool = Arc::new(blvm_node::node::mempool::MempoolManager::new());
let mining = mining::MiningRpc::with_dependencies(storage.clone(), mempool);
let genesis_header = BlockHeader {
version: 1,
prev_block_hash: [0u8; 32],
merkle_root: [0u8; 32],
timestamp: 1231006505,
bits: 0x1400ffff,
nonce: 2083236893,
};
storage.chain().initialize(&genesis_header).unwrap();
let params = serde_json::json!([]);
let result = mining.get_block_template(¶ms).await;
let template = match result {
Ok(t) => t,
Err(e) => {
if e.to_string().contains("Target too large")
|| e.to_string().contains("Insufficient headers")
{
return; }
panic!("Unexpected error: {e:?}");
}
};
assert!(template.get("version").is_some());
assert!(template.get("rules").is_some());
assert!(template.get("vbavailable").is_some());
assert!(template.get("vbrequired").is_some());
assert!(template.get("previousblockhash").is_some());
assert!(template.get("transactions").is_some());
assert!(template.get("coinbaseaux").is_some());
assert!(template.get("coinbasevalue").is_some());
assert!(template.get("longpollid").is_some());
assert!(template.get("target").is_some());
assert!(template.get("mintime").is_some());
assert!(template.get("mutable").is_some());
assert!(template.get("noncerange").is_some());
assert!(template.get("sigoplimit").is_some());
assert!(template.get("sizelimit").is_some());
assert!(template.get("weightlimit").is_some());
assert!(template.get("curtime").is_some());
assert!(template.get("bits").is_some());
assert!(template.get("height").is_some());
}
#[tokio::test]
async fn test_mining_rpc_submitblock() {
let mining = mining::MiningRpc::new();
let invalid_block = "0000000000000000000000000000000000000000000000000000000000000000";
}
#[tokio::test]
async fn test_mining_rpc_getblocktemplate_with_params() {
let mining = mining::MiningRpc::new();
let params = serde_json::json!({
"mode": "template",
"capabilities": ["coinbasetxn", "workid", "coinbase/append"],
"rules": ["segwit"]
});
}
#[tokio::test]
async fn test_rpc_invalid_json() {
let invalid_json = r#"{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1"#;
let result: Result<serde_json::Value, _> = serde_json::from_str(invalid_json);
assert!(result.is_err());
}
#[tokio::test]
async fn test_rpc_missing_method() {
let invalid_request = r#"{"jsonrpc":"2.0","params":[],"id":1}"#;
let request_value: serde_json::Value = serde_json::from_str(invalid_request).unwrap();
assert!(request_value.get("method").is_none());
}
#[tokio::test]
async fn test_rpc_invalid_params() {
let invalid_params = r#"{"jsonrpc":"2.0","method":"getblock","params":"invalid","id":1}"#;
let request_value: serde_json::Value = serde_json::from_str(invalid_params).unwrap();
let params = request_value.get("params").unwrap();
assert!(params.is_string());
}
#[tokio::test]
async fn test_rpc_timeout_handling() {
let result = timeout(Duration::from_millis(100), async {
tokio::time::sleep(Duration::from_millis(200)).await;
"timeout_test"
})
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_rpc_concurrent_requests() {
let blockchain = blockchain::BlockchainRpc::new();
let futures: Vec<_> = (0..10)
.map(|_| {
let blockchain = &blockchain;
async move { blockchain.get_blockchain_info().await }
})
.collect();
let results = futures::future::join_all(futures).await;
for result in results {
assert!(result.is_ok());
}
}