use bytes::Bytes;
use flume::Receiver;
use jsonrpc_core::{ErrorCode, Failure, Id, Version};
use mcp_stdio_wrapper::logger::init_logger;
use mcp_stdio_wrapper::streamer_error::{mcp_error, rpc_error};
use serde::de::Error;
use serde_json::{Value, json};
struct TestCase {
input_json: String,
error_message: &'static str,
expected_output: Value,
}
#[tokio::test]
/// test id parsing
/// # Errors
/// returns error when test fails
/// # Panics
/// code panics when test fails
async fn test_error() -> Result<(), Box<dyn std::error::Error>> {
init_logger(Some("debug"), None);
let (tx, rx) = flume::unbounded();
let worker: usize = 1;
let test_cases = vec![
TestCase {
input_json: json!({"jsonrpc":"2.0","id":1,"method":"tools/list"}).to_string(),
error_message: "error1",
expected_output: json!({
"jsonrpc":"2.0",
"error":{"code":ErrorCode::InternalError,"message":"error1"},
"id":1
}),
},
TestCase {
input_json: json!({"jsonrpc":"2.0","id":"id_2","method":"tools/list"}).to_string(),
error_message: "error2",
expected_output: json!({
"jsonrpc":"2.0",
"error":{"code":ErrorCode::InternalError,"message":"error2"},
"id":"id_2"
}),
},
TestCase {
input_json: String::new(),
error_message: "error3",
expected_output: json!({
"jsonrpc":"2.0",
"error":{"code":ErrorCode::InternalError,"message":"error3"},
"id":null
}),
},
];
// Run tests in a loop
for case in test_cases {
mcp_error(&worker, case.input_json.as_bytes(), case.error_message, &tx).await;
verify(&rx, &case.expected_output).await;
}
Ok(())
}
async fn verify(rx: &Receiver<Bytes>, expected: &Value) {
let msg = rx.recv_async().await.expect("receiving error");
let msg_str = String::from_utf8_lossy(&msg);
let actual = serde_json::from_str::<Value>(&msg_str).expect("deserializing error");
println!("{actual}");
assert_eq!(actual, *expected);
let response = Failure {
jsonrpc: Some(Version::V2),
error: jsonrpc_core::Error {
code: ErrorCode::InternalError,
message: String::new(),
data: None,
},
id: Id::Null,
};
let _ = rpc_error(&response, &serde_json::Error::custom("Aha"));
}