use super::*;
pub struct WebSocketTransport {
}
impl Default for WebSocketTransport {
fn default() -> Self {
Self::new()
}
}
impl WebSocketTransport {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new() -> Self {
Self {}
}
}
#[async_trait]
impl McpTransport for WebSocketTransport {
async fn send(&self, _message: McpMessage) -> Result<(), McpError> {
Ok(())
}
async fn receive(&self) -> Result<McpMessage, McpError> {
Err(McpError {
code: error_codes::INTERNAL_ERROR,
message: "Not implemented".to_string(),
data: None,
})
}
async fn close(&self) -> Result<(), McpError> {
Ok(())
}
}
pub struct HttpTransport {
}
impl Default for HttpTransport {
fn default() -> Self {
Self::new()
}
}
impl HttpTransport {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new() -> Self {
Self {}
}
}
#[async_trait]
impl McpTransport for HttpTransport {
async fn send(&self, _message: McpMessage) -> Result<(), McpError> {
Ok(())
}
async fn receive(&self) -> Result<McpMessage, McpError> {
Err(McpError {
code: error_codes::INTERNAL_ERROR,
message: "Not implemented".to_string(),
data: None,
})
}
async fn close(&self) -> Result<(), McpError> {
Ok(())
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod coverage_tests {
use super::*;
#[test]
fn test_websocket_transport_new() {
let transport = WebSocketTransport::new();
let _ = transport;
}
#[test]
fn test_websocket_transport_default() {
let transport = WebSocketTransport::default();
let _ = transport;
}
#[tokio::test]
async fn test_websocket_transport_send() {
let transport = WebSocketTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Request(McpRequest {
id: RequestId::Number(1),
method: "test".to_string(),
params: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_websocket_transport_send_notification() {
let transport = WebSocketTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Notification(McpNotification {
method: "initialized".to_string(),
params: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_websocket_transport_send_response() {
let transport = WebSocketTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Response(McpResponse {
id: RequestId::Number(1),
result: Some(serde_json::json!({"success": true})),
error: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_websocket_transport_receive() {
let transport = WebSocketTransport::new();
let result = transport.receive().await;
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.code, error_codes::INTERNAL_ERROR);
assert!(err.message.contains("Not implemented"));
assert!(err.data.is_none());
}
#[tokio::test]
async fn test_websocket_transport_close() {
let transport = WebSocketTransport::new();
let result = transport.close().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_websocket_transport_multiple_sends() {
let transport = WebSocketTransport::new();
for i in 0..10 {
let message = McpMessage::JsonRpc(JsonRpcMessage::Request(McpRequest {
id: RequestId::Number(i),
method: format!("method_{}", i),
params: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
}
#[tokio::test]
async fn test_websocket_transport_send_after_close() {
let transport = WebSocketTransport::new();
transport.close().await.unwrap();
let message = McpMessage::JsonRpc(JsonRpcMessage::Request(McpRequest {
id: RequestId::Number(1),
method: "test".to_string(),
params: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[test]
fn test_http_transport_new() {
let transport = HttpTransport::new();
let _ = transport;
}
#[test]
fn test_http_transport_default() {
let transport = HttpTransport::default();
let _ = transport;
}
#[tokio::test]
async fn test_http_transport_send() {
let transport = HttpTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Request(McpRequest {
id: RequestId::Number(1),
method: "test".to_string(),
params: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_http_transport_send_notification() {
let transport = HttpTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Notification(McpNotification {
method: "initialized".to_string(),
params: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_http_transport_send_response() {
let transport = HttpTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Response(McpResponse {
id: RequestId::String("req-123".to_string()),
result: Some(serde_json::json!({"data": "test"})),
error: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_http_transport_receive() {
let transport = HttpTransport::new();
let result = transport.receive().await;
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.code, error_codes::INTERNAL_ERROR);
assert!(err.message.contains("Not implemented"));
assert!(err.data.is_none());
}
#[tokio::test]
async fn test_http_transport_close() {
let transport = HttpTransport::new();
let result = transport.close().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_http_transport_multiple_sends() {
let transport = HttpTransport::new();
for i in 0..10 {
let message = McpMessage::JsonRpc(JsonRpcMessage::Request(McpRequest {
id: RequestId::Number(i),
method: format!("method_{}", i),
params: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
}
#[tokio::test]
async fn test_http_transport_send_after_close() {
let transport = HttpTransport::new();
transport.close().await.unwrap();
let message = McpMessage::JsonRpc(JsonRpcMessage::Request(McpRequest {
id: RequestId::Number(1),
method: "test".to_string(),
params: None,
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_both_transports_implement_mcp_transport() {
let ws: &dyn McpTransport = &WebSocketTransport::new();
let _ = ws.close().await;
let http: &dyn McpTransport = &HttpTransport::new();
let _ = http.close().await;
}
#[tokio::test]
async fn test_transports_can_be_used_in_arc() {
use std::sync::Arc;
let ws_transport: Arc<dyn McpTransport> = Arc::new(WebSocketTransport::new());
let http_transport: Arc<dyn McpTransport> = Arc::new(HttpTransport::new());
assert!(ws_transport.close().await.is_ok());
assert!(http_transport.close().await.is_ok());
}
#[tokio::test]
async fn test_transports_receive_error_codes() {
let ws_transport = WebSocketTransport::new();
let http_transport = HttpTransport::new();
let ws_err = ws_transport.receive().await.unwrap_err();
let http_err = http_transport.receive().await.unwrap_err();
assert_eq!(ws_err.code, http_err.code);
assert_eq!(ws_err.code, error_codes::INTERNAL_ERROR);
}
#[tokio::test]
async fn test_send_with_complex_params() {
let transport = WebSocketTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Request(McpRequest {
id: RequestId::String("complex-request".to_string()),
method: "tools/call".to_string(),
params: Some(serde_json::json!({
"name": "analyze",
"arguments": {
"path": "/src/main.rs",
"options": {
"deep": true,
"languages": ["rust", "python"]
}
}
})),
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_send_error_response() {
let transport = HttpTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Response(McpResponse {
id: RequestId::Number(1),
result: None,
error: Some(McpError {
code: error_codes::INVALID_PARAMS,
message: "Missing required parameter".to_string(),
data: Some(serde_json::json!({"parameter": "name"})),
}),
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_send_notification_with_params() {
let transport = WebSocketTransport::new();
let message = McpMessage::JsonRpc(JsonRpcMessage::Notification(McpNotification {
method: "notifications/resources/updated".to_string(),
params: Some(serde_json::json!({
"uri": "file:///path/to/file.rs",
"contents": [{"text": "updated content"}]
})),
}));
let result = transport.send(message).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_multiple_close_calls() {
let ws_transport = WebSocketTransport::new();
let http_transport = HttpTransport::new();
for _ in 0..5 {
assert!(ws_transport.close().await.is_ok());
assert!(http_transport.close().await.is_ok());
}
}
#[tokio::test]
async fn test_receive_called_multiple_times() {
let transport = WebSocketTransport::new();
for _ in 0..5 {
let result = transport.receive().await;
assert!(result.is_err());
assert_eq!(result.unwrap_err().code, error_codes::INTERNAL_ERROR);
}
}
}