use blvm_node::rpc::server::RpcServer;
use serde_json::{json, Value};
fn create_test_server() -> RpcServer {
RpcServer::new("127.0.0.1:0".parse().unwrap())
}
#[tokio::test]
async fn test_rpc_batch_empty_array() {
let server = create_test_server();
let batch: Vec<Value> = vec![];
let batch_json = serde_json::to_string(&batch).unwrap();
let result = process_batch_request(&server, &batch_json).await;
assert!(result.is_ok());
let response: Vec<Value> = serde_json::from_str(&result.unwrap()).unwrap();
assert!(response.is_empty());
}
#[tokio::test]
async fn test_rpc_batch_single_request() {
let server = create_test_server();
let batch = vec![json!({
"jsonrpc": "2.0",
"method": "getblockcount",
"id": 1
})];
let batch_json = serde_json::to_string(&batch).unwrap();
let result = process_batch_request(&server, &batch_json).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_rpc_batch_mixed_valid_invalid() {
let server = create_test_server();
let batch = vec![
json!({
"jsonrpc": "2.0",
"method": "getblockcount",
"id": 1
}),
json!({
"jsonrpc": "2.0",
"method": "nonexistent",
"id": 2
}),
json!({
"jsonrpc": "2.0",
"invalid": "request",
"id": 3
}),
];
let batch_json = serde_json::to_string(&batch).unwrap();
let result = process_batch_request(&server, &batch_json).await;
assert!(result.is_ok());
let response: Vec<Value> = serde_json::from_str(&result.unwrap()).unwrap();
assert_eq!(response.len(), 3); }
#[tokio::test]
async fn test_rpc_batch_duplicate_ids() {
let server = create_test_server();
let batch = vec![
json!({
"jsonrpc": "2.0",
"method": "getblockcount",
"id": 1
}),
json!({
"jsonrpc": "2.0",
"method": "getblockcount",
"id": 1
}),
];
let batch_json = serde_json::to_string(&batch).unwrap();
let result = process_batch_request(&server, &batch_json).await;
assert!(result.is_ok());
let response: Vec<Value> = serde_json::from_str(&result.unwrap()).unwrap();
assert_eq!(response.len(), 2);
}
#[tokio::test]
async fn test_rpc_batch_missing_ids() {
let server = create_test_server();
let batch = vec![
json!({
"jsonrpc": "2.0",
"method": "getblockcount"
}),
json!({
"jsonrpc": "2.0",
"method": "getblockcount",
"id": 1
}),
];
let batch_json = serde_json::to_string(&batch).unwrap();
let result = process_batch_request(&server, &batch_json).await;
assert!(result.is_ok());
let response: Vec<Value> = serde_json::from_str(&result.unwrap()).unwrap();
assert_eq!(response.len(), 1);
}
#[tokio::test]
async fn test_rpc_batch_large_batch() {
let server = create_test_server();
let mut batch = Vec::new();
for i in 0..100 {
batch.push(json!({
"jsonrpc": "2.0",
"method": "getblockcount",
"id": i
}));
}
let batch_json = serde_json::to_string(&batch).unwrap();
let result = process_batch_request(&server, &batch_json).await;
assert!(result.is_ok());
let response: Vec<Value> = serde_json::from_str(&result.unwrap()).unwrap();
assert_eq!(response.len(), 100);
}
#[tokio::test]
async fn test_rpc_batch_invalid_json() {
let server = create_test_server();
let invalid_json = "[{ invalid json }]";
let result = process_batch_request(&server, invalid_json).await;
assert!(result.is_ok() || result.is_err()); }
#[tokio::test]
async fn test_rpc_batch_malformed_requests() {
let server = create_test_server();
let batch = vec![
json!({}), json!({"jsonrpc": "1.0"}), json!({"method": "test"}), ];
let batch_json = serde_json::to_string(&batch).unwrap();
let result = process_batch_request(&server, &batch_json).await;
assert!(result.is_ok());
let response: Vec<Value> = serde_json::from_str(&result.unwrap()).unwrap();
assert_eq!(response.len(), 3);
}
async fn process_batch_request(_server: &RpcServer, body: &str) -> Result<String, String> {
let value: Value = serde_json::from_str(body).map_err(|e| e.to_string())?;
if let Value::Array(requests) = value {
let mut responses = Vec::new();
for request in requests {
let id = request.get("id").cloned();
let has_jsonrpc = request.get("jsonrpc").and_then(|v| v.as_str()) == Some("2.0");
if !has_jsonrpc || request.get("method").is_none() {
responses.push(json!({
"jsonrpc": "2.0",
"error": {
"code": -32600,
"message": "Invalid Request"
},
"id": id
}));
} else if let Some(id) = id {
responses.push(json!({
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found"
},
"id": id
}));
}
}
Ok(serde_json::to_string(&responses).unwrap())
} else {
Ok(
r#"{"jsonrpc":"2.0","error":{"code":-32601,"message":"Method not found"},"id":null}"#
.to_string(),
)
}
}