use std::sync::Arc; use tonic::{Request, Response, Status}; use roto_runtime::RotoOwned; use roto_tonic::{BufferPool, generated::helloworld::{Greeter, GreeterServer, OwnedHelloRequest, OwnedHelloReply, HelloReplyBuilder, HelloBuilder}}; use std::net::SocketAddr; use tokio::net::TcpListener; struct MyGreeter; #[tonic::async_trait] impl Greeter for MyGreeter { async fn say_hello(&self, request: Request) -> std::result::Result, Status> { let req = request.into_inner(); let hello_req = req.reader(); // Extract name from the nested Hello message in HelloRequest let name = match hello_req.request() { Ok(req_bytes) => { let hello = roto_tonic::generated::helloworld::Hello::new(req_bytes).unwrap(); hello.name_or_default().unwrap().to_string() }, Err(_) => "Unknown".to_string(), }; // Build the Hello response message let mut hello_buf = [0u8; 1024]; let mut hello_builder = HelloBuilder::builder(&mut hello_buf); hello_builder = hello_builder.name(&format!("Hello, {}!", name)) .map_err(|e| Status::internal(format!("Build error: {:?}", e)))?; let hello_bytes = hello_builder.finish() .map_err(|e| Status::internal(format!("Finish error: {:?}", e)))?; // Build the HelloReply message containing the Hello bytes let mut reply_buf = [0u8; 1024]; let mut reply_builder = HelloReplyBuilder::builder(&mut reply_buf); reply_builder = reply_builder.response(hello_bytes) .map_err(|e| Status::internal(format!("Build error: {:?}", e)))?; let reply_bytes = reply_builder.finish() .map_err(|e| Status::internal(format!("Finish error: {:?}", e)))?; Ok(Response::new(OwnedHelloReply { data: reply_bytes.to_vec().into(), })) } } #[tokio::test] async fn test_say_hello_handler() { let greeter = MyGreeter; // Manually construct a valid proto buffer for HelloRequest // HelloRequest { request: Hello { name: "World" } } let mut hello_buf = [0u8; 1024]; let mut hb = HelloBuilder::builder(&mut hello_buf); hb = hb.name("World").unwrap(); let hello_bytes = hb.finish().unwrap(); let mut req_buf = [0u8; 1024]; let mut rb = roto_tonic::generated::helloworld::HelloRequestBuilder::builder(&mut req_buf); rb = rb.request(hello_bytes).unwrap(); let req_bytes = rb.finish().unwrap(); let request = Request::new(OwnedHelloRequest { data: req_bytes.to_vec().into(), }); let response = greeter.say_hello(request).await.unwrap(); let reply = response.into_inner(); let reply_reader = reply.reader(); let response_msg_bytes = reply_reader.response().expect("Response field missing"); let response_msg = roto_tonic::generated::helloworld::Hello::new(response_msg_bytes).expect("Invalid Hello message"); assert_eq!(response_msg.name_or_default().unwrap(), "Hello, World!"); } #[tokio::test] async fn test_server_start() { let pool = Arc::new(BufferPool::new(1024)); let greeter = Arc::new(MyGreeter); let server = GreeterServer::new(greeter, pool); let addr = SocketAddr::from(([127, 0, 0, 1], 0)); let listener = TcpListener::bind(addr).await.unwrap(); let _local_addr = listener.local_addr().unwrap(); let server_handle = tokio::spawn(async move { tonic::transport::Server::builder() .add_service(server) .serve_with_incoming(tokio_stream::wrappers::TcpListenerStream::new(listener)) .await .unwrap(); }); // Just verify it can start without crashing tokio::time::sleep(std::time::Duration::from_millis(100)).await; server_handle.abort(); }