use std::sync::Arc; use service_rpc::{serve, RpcClient, RpcError, RpcResult, RpcService}; use tokio::net::TcpListener; struct Doubler; #[async_trait::async_trait] impl RpcService for Doubler { type Request = i32; type Response = i32; fn service_name(&self) -> &'static str { "doubler" } async fn call(&self, request: i32) -> RpcResult { if request == 0 { return Err(RpcError::Rejected("zero is not allowed".to_owned())); } Ok(request * 2) } } #[tokio::test] async fn error_reaches_caller() { let listener = TcpListener::bind("127.0.0.1:0").await.expect("bind"); let endpoint = listener.local_addr().expect("addr").to_string(); tokio::spawn(async move { let _ = serve(listener, Arc::new(Doubler)).await; }); let client: RpcClient = RpcClient::with_pool_size(endpoint, 1); assert_eq!(client.call(&5).await.expect("ok call"), 10); match client.call(&0).await { Err(RpcError::Rejected(message)) => assert_eq!(message, "zero is not allowed"), other => panic!("expected a rejection, got {other:?}"), } assert_eq!( client.call(&7).await.expect("connection survived the error"), 14 ); }