use essrpc::essrpc; use essrpc::transports::{ BincodeAsyncClientTransport, BincodeTransport, JSONAsyncClientTransport, JSONTransport, }; use essrpc::{AsyncRPCClient, RPCServer}; use serde::{Deserialize, Serialize}; use std::result::Result; use std::{fmt, thread}; use tokio; #[derive(Debug, Deserialize, Serialize)] pub struct TestError { msg: String, } impl fmt::Display for TestError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "error: {}", self.msg) } } impl std::error::Error for TestError {} impl From for TestError { fn from(error: essrpc::RPCError) -> Self { TestError { msg: format!("{}", error), } } } #[essrpc(async, sync)] pub trait Foo { fn bar(&self, a: String, b: i32) -> Result; fn expect_error(&self) -> Result; fn big_buffer(&self) -> Result, TestError>; fn big_argument(&self, v: Vec) -> Result<(), TestError>; } struct FooImpl; impl FooImpl { fn new() -> Self { FooImpl {} } } const BIG_BUFFER_SIZE: usize = 256 * 1024; impl Foo for FooImpl { fn bar(&self, a: String, b: i32) -> Result { Ok(format!("{} is {}", a, b)) } fn expect_error(&self) -> Result { Err(TestError { msg: "iamerror".to_string(), }) } fn big_buffer(&self) -> Result, TestError> { let mut a: Vec = Vec::new(); a.resize(BIG_BUFFER_SIZE, 0); Ok(a) } fn big_argument(&self, _v: Vec) -> Result<(), TestError> { Ok(()) } } #[tokio::test] async fn basic_json_async() { let foo = json_foo(); match foo.bar("the answer".to_string(), 42).await { Ok(result) => assert_eq!("the answer is 42", result), Err(e) => panic!("error: {:?}", e), } } #[tokio::test] async fn basic_bincode_async() { let foo = bincode_foo(); match foo.bar("the answer".to_string(), 42).await { Ok(result) => assert_eq!("the answer is 42", result), Err(e) => panic!("error: {:?}", e), } } #[tokio::test] async fn big_buffer_async() { let foo = bincode_foo(); let buf = foo.big_buffer().await.unwrap(); assert_eq!(buf.len(), BIG_BUFFER_SIZE); } #[tokio::test] async fn big_buffer_argument() { let foo = bincode_foo(); let mut v = Vec::new(); v.resize(BIG_BUFFER_SIZE, 0); let res = foo.big_argument(v).await; assert!(res.is_ok()); } fn json_foo() -> impl FooAsync { let (s1, s2) = tokio::net::UnixStream::pair().unwrap(); // The server isn't actually async, so convert into a non-asyn Unix stream let s2 = s2.into_std().unwrap(); s2.set_nonblocking(false).unwrap(); thread::spawn(move || { let mut serve = FooRPCServer::new(FooImpl::new(), JSONTransport::new(s2)); serve.serve_single_call() }); FooAsyncRPCClient::new(JSONAsyncClientTransport::new_unframed(s1)) } fn bincode_foo() -> impl FooAsync { let (s1, s2) = tokio::net::UnixStream::pair().unwrap(); // The server isn't actually async, so convert into a non-asyn Unix stream let s2 = s2.into_std().unwrap(); s2.set_nonblocking(false).unwrap(); thread::spawn(move || { let mut serve = FooRPCServer::new(FooImpl::new(), BincodeTransport::new(s2)); serve.serve_single_call() }); FooAsyncRPCClient::new(BincodeAsyncClientTransport::new(s1)) }