From 782da6f0e518f050af7e7b3fd79a777ad87bf200 Mon Sep 17 00:00:00 2001 From: Lucio Franco Date: Sat, 21 Sep 2019 16:02:10 -0600 Subject: [PATCH] implement last interop test --- tonic-build/src/service.rs | 4 ++ tonic-interop/src/bin/server.rs | 103 +++++++++++++++++++++++++++++++- tonic-interop/src/server.rs | 19 +++--- tonic-interop/test.sh | 5 +- tonic/src/transport/mod.rs | 1 + 5 files changed, 118 insertions(+), 14 deletions(-) diff --git a/tonic-build/src/service.rs b/tonic-build/src/service.rs index 924f27d..cbad4a7 100644 --- a/tonic-build/src/service.rs +++ b/tonic-build/src/service.rs @@ -28,6 +28,10 @@ pub(crate) fn generate(service: &Service, proto_path: &str) -> TokenStream { impl #server_make_service { pub fn new(inner: T) -> Self { let inner = Arc::new(inner); + Self::from_shared(inner) + } + + pub fn from_shared(inner: Arc) -> Self { Self { inner } } } diff --git a/tonic-interop/src/bin/server.rs b/tonic-interop/src/bin/server.rs index 1b46f34..6dfe384 100644 --- a/tonic-interop/src/bin/server.rs +++ b/tonic-interop/src/bin/server.rs @@ -21,8 +21,6 @@ async fn main() -> std::result::Result<(), Box> { let addr = "127.0.0.1:10000".parse().unwrap(); - let test_service = server::create(); - let mut builder = Server::builder(); if matches.use_tls { @@ -59,7 +57,106 @@ async fn main() -> std::result::Result<(), Box> { } }); - builder.serve(addr, test_service).await?; + builder + .serve( + addr, + router::Router { + test_service: std::sync::Arc::new(server::TestService), + unimplemented_service: std::sync::Arc::new(server::UnimplementedService), + }, + ) + .await?; Ok(()) } + +mod router { + use futures_util::future; + use http::{Request, Response}; + use std::sync::Arc; + use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, + }; + use tonic::{body::BoxBody, transport::Body}; + use tonic_interop::server::{ + TestService, TestServiceServer, UnimplementedService, UnimplementedServiceServer, + }; + use tower::Service; + + #[derive(Clone)] + pub struct Router { + pub test_service: Arc, + pub unimplemented_service: Arc, + } + + impl Service<()> for Router { + type Response = Router; + type Error = Never; + type Future = future::Ready>; + + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { + Ok(()).into() + } + + fn call(&mut self, _req: ()) -> Self::Future { + future::ok(self.clone()) + } + } + + impl Service> for Router { + type Response = Response; + type Error = Never; + type Future = + Pin, Never>> + Send + 'static>>; + + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { + Ok(()).into() + } + + fn call(&mut self, req: Request) -> Self::Future { + let mut segments = req.uri().path().split("/"); + segments.next(); + let service = segments.next().unwrap(); + + match service { + "grpc.testing.TestService" => { + let me = self.clone(); + Box::pin(async move { + let mut svc = TestServiceServer::from_shared(me.test_service); + let mut svc = svc.call(()).await.unwrap(); + + let res = svc.call(req).await.unwrap(); + Ok(res) + }) + } + + "grpc.testing.UnimplementedService" => { + let me = self.clone(); + Box::pin(async move { + let mut svc = + UnimplementedServiceServer::from_shared(me.unimplemented_service); + let mut svc = svc.call(()).await.unwrap(); + + let res = svc.call(req).await.unwrap(); + Ok(res) + }) + } + + _ => unimplemented!(), + } + } + } + + #[derive(Debug)] + pub enum Never {} + + impl std::fmt::Display for Never { + fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self {} + } + } + + impl std::error::Error for Never {} +} diff --git a/tonic-interop/src/server.rs b/tonic-interop/src/server.rs index 481dccb..6cbcb13 100644 --- a/tonic-interop/src/server.rs +++ b/tonic-interop/src/server.rs @@ -5,16 +5,10 @@ use std::pin::Pin; use std::time::{Duration, Instant}; use tonic::{Code, Request, Response, Status}; -pub fn create() -> pb::server::TestServiceServer { - server::TestServiceServer::new(TestService { - data: String::new(), - }) -} +pub use pb::server::{TestServiceServer, UnimplementedServiceServer}; #[derive(Default, Clone)] -pub struct TestService { - data: String, -} +pub struct TestService; type Result = std::result::Result, Status>; type Streaming = Request>; @@ -156,3 +150,12 @@ impl pb::server::TestService for TestService { Err(Status::unimplemented("")) } } + +pub struct UnimplementedService; + +#[tonic::async_trait] +impl pb::server::UnimplementedService for UnimplementedService { + async fn unimplemented_call(&self, _req: Request) -> Result { + Err(Status::unimplemented("")) + } +} diff --git a/tonic-interop/test.sh b/tonic-interop/test.sh index 598c020..42f0c0b 100755 --- a/tonic-interop/test.sh +++ b/tonic-interop/test.sh @@ -49,6 +49,5 @@ sleep 1 ./target/debug/client \ --test_case=empty_unary,large_unary,client_streaming,server_streaming,ping_pong,\ -empty_stream,status_code_and_message,special_status_message,unimplemented_method,custom_metadata $ARG -# ,unimplemented_service,custom_metadata - +empty_stream,status_code_and_message,special_status_message,unimplemented_method,\ +unimplemented_service,custom_metadata $ARG diff --git a/tonic/src/transport/mod.rs b/tonic/src/transport/mod.rs index 9650a46..9c2b57c 100644 --- a/tonic/src/transport/mod.rs +++ b/tonic/src/transport/mod.rs @@ -11,6 +11,7 @@ mod tls; pub use self::channel::Channel; pub use self::endpoint::Endpoint; pub use self::server::Server; +pub use hyper::Body; use std::{error, fmt};