10583cff8SDavid Pedersen use super::*;
2*a585a722SMarcus Griep use tonic::codec::CompressionEncoding;
30583cff8SDavid Pedersen 
40583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")]
50583cff8SDavid Pedersen async fn client_enabled_server_enabled() {
60583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
70583cff8SDavid Pedersen 
80583cff8SDavid Pedersen     #[derive(Clone, Copy)]
90583cff8SDavid Pedersen     struct AssertCorrectAcceptEncoding<S>(S);
100583cff8SDavid Pedersen 
110583cff8SDavid Pedersen     impl<S, B> Service<http::Request<B>> for AssertCorrectAcceptEncoding<S>
120583cff8SDavid Pedersen     where
130583cff8SDavid Pedersen         S: Service<http::Request<B>>,
140583cff8SDavid Pedersen     {
150583cff8SDavid Pedersen         type Response = S::Response;
160583cff8SDavid Pedersen         type Error = S::Error;
170583cff8SDavid Pedersen         type Future = S::Future;
180583cff8SDavid Pedersen 
190583cff8SDavid Pedersen         fn poll_ready(
200583cff8SDavid Pedersen             &mut self,
210583cff8SDavid Pedersen             cx: &mut std::task::Context<'_>,
220583cff8SDavid Pedersen         ) -> std::task::Poll<Result<(), Self::Error>> {
230583cff8SDavid Pedersen             self.0.poll_ready(cx)
240583cff8SDavid Pedersen         }
250583cff8SDavid Pedersen 
260583cff8SDavid Pedersen         fn call(&mut self, req: http::Request<B>) -> Self::Future {
270583cff8SDavid Pedersen             assert_eq!(
280583cff8SDavid Pedersen                 req.headers().get("grpc-accept-encoding").unwrap(),
290583cff8SDavid Pedersen                 "gzip,identity"
300583cff8SDavid Pedersen             );
310583cff8SDavid Pedersen             self.0.call(req)
320583cff8SDavid Pedersen         }
330583cff8SDavid Pedersen     }
340583cff8SDavid Pedersen 
35*a585a722SMarcus Griep     let svc =
36*a585a722SMarcus Griep         test_server::TestServer::new(Svc::default()).send_compressed(CompressionEncoding::Gzip);
370583cff8SDavid Pedersen 
380583cff8SDavid Pedersen     let response_bytes_counter = Arc::new(AtomicUsize::new(0));
390583cff8SDavid Pedersen 
400583cff8SDavid Pedersen     tokio::spawn({
410583cff8SDavid Pedersen         let response_bytes_counter = response_bytes_counter.clone();
420583cff8SDavid Pedersen         async move {
430583cff8SDavid Pedersen             Server::builder()
440583cff8SDavid Pedersen                 .layer(
450583cff8SDavid Pedersen                     ServiceBuilder::new()
460583cff8SDavid Pedersen                         .layer(layer_fn(AssertCorrectAcceptEncoding))
470583cff8SDavid Pedersen                         .layer(MapResponseBodyLayer::new(move |body| {
480583cff8SDavid Pedersen                             util::CountBytesBody {
490583cff8SDavid Pedersen                                 inner: body,
500583cff8SDavid Pedersen                                 counter: response_bytes_counter.clone(),
510583cff8SDavid Pedersen                             }
520583cff8SDavid Pedersen                         }))
530583cff8SDavid Pedersen                         .into_inner(),
540583cff8SDavid Pedersen                 )
550583cff8SDavid Pedersen                 .add_service(svc)
56d4973642SLucio Franco                 .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>(server)]))
570583cff8SDavid Pedersen                 .await
580583cff8SDavid Pedersen                 .unwrap();
590583cff8SDavid Pedersen         }
600583cff8SDavid Pedersen     });
610583cff8SDavid Pedersen 
62*a585a722SMarcus Griep     let mut client = test_client::TestClient::new(mock_io_channel(client).await)
63*a585a722SMarcus Griep         .accept_compressed(CompressionEncoding::Gzip);
640583cff8SDavid Pedersen 
650583cff8SDavid Pedersen     for _ in 0..3 {
660583cff8SDavid Pedersen         let res = client.compress_output_unary(()).await.unwrap();
670583cff8SDavid Pedersen         assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip");
680583cff8SDavid Pedersen         let bytes_sent = response_bytes_counter.load(SeqCst);
690583cff8SDavid Pedersen         assert!(bytes_sent < UNCOMPRESSED_MIN_BODY_SIZE);
700583cff8SDavid Pedersen     }
710583cff8SDavid Pedersen }
720583cff8SDavid Pedersen 
730583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")]
740583cff8SDavid Pedersen async fn client_enabled_server_disabled() {
750583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
760583cff8SDavid Pedersen 
770583cff8SDavid Pedersen     let svc = test_server::TestServer::new(Svc::default());
780583cff8SDavid Pedersen 
790583cff8SDavid Pedersen     let response_bytes_counter = Arc::new(AtomicUsize::new(0));
800583cff8SDavid Pedersen 
810583cff8SDavid Pedersen     tokio::spawn({
820583cff8SDavid Pedersen         let response_bytes_counter = response_bytes_counter.clone();
830583cff8SDavid Pedersen         async move {
840583cff8SDavid Pedersen             Server::builder()
850583cff8SDavid Pedersen                 // no compression enable on the server so responses should not be compressed
860583cff8SDavid Pedersen                 .layer(
870583cff8SDavid Pedersen                     ServiceBuilder::new()
880583cff8SDavid Pedersen                         .layer(MapResponseBodyLayer::new(move |body| {
890583cff8SDavid Pedersen                             util::CountBytesBody {
900583cff8SDavid Pedersen                                 inner: body,
910583cff8SDavid Pedersen                                 counter: response_bytes_counter.clone(),
920583cff8SDavid Pedersen                             }
930583cff8SDavid Pedersen                         }))
940583cff8SDavid Pedersen                         .into_inner(),
950583cff8SDavid Pedersen                 )
960583cff8SDavid Pedersen                 .add_service(svc)
97d4973642SLucio Franco                 .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>(server)]))
980583cff8SDavid Pedersen                 .await
990583cff8SDavid Pedersen                 .unwrap();
1000583cff8SDavid Pedersen         }
1010583cff8SDavid Pedersen     });
1020583cff8SDavid Pedersen 
103*a585a722SMarcus Griep     let mut client = test_client::TestClient::new(mock_io_channel(client).await)
104*a585a722SMarcus Griep         .accept_compressed(CompressionEncoding::Gzip);
1050583cff8SDavid Pedersen 
1060583cff8SDavid Pedersen     let res = client.compress_output_unary(()).await.unwrap();
1070583cff8SDavid Pedersen 
1080583cff8SDavid Pedersen     assert!(res.metadata().get("grpc-encoding").is_none());
1090583cff8SDavid Pedersen 
1100583cff8SDavid Pedersen     let bytes_sent = response_bytes_counter.load(SeqCst);
1110583cff8SDavid Pedersen     assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE);
1120583cff8SDavid Pedersen }
1130583cff8SDavid Pedersen 
1140583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")]
1150583cff8SDavid Pedersen async fn client_disabled() {
1160583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
1170583cff8SDavid Pedersen 
1180583cff8SDavid Pedersen     #[derive(Clone, Copy)]
1190583cff8SDavid Pedersen     struct AssertCorrectAcceptEncoding<S>(S);
1200583cff8SDavid Pedersen 
1210583cff8SDavid Pedersen     impl<S, B> Service<http::Request<B>> for AssertCorrectAcceptEncoding<S>
1220583cff8SDavid Pedersen     where
1230583cff8SDavid Pedersen         S: Service<http::Request<B>>,
1240583cff8SDavid Pedersen     {
1250583cff8SDavid Pedersen         type Response = S::Response;
1260583cff8SDavid Pedersen         type Error = S::Error;
1270583cff8SDavid Pedersen         type Future = S::Future;
1280583cff8SDavid Pedersen 
1290583cff8SDavid Pedersen         fn poll_ready(
1300583cff8SDavid Pedersen             &mut self,
1310583cff8SDavid Pedersen             cx: &mut std::task::Context<'_>,
1320583cff8SDavid Pedersen         ) -> std::task::Poll<Result<(), Self::Error>> {
1330583cff8SDavid Pedersen             self.0.poll_ready(cx)
1340583cff8SDavid Pedersen         }
1350583cff8SDavid Pedersen 
1360583cff8SDavid Pedersen         fn call(&mut self, req: http::Request<B>) -> Self::Future {
1370583cff8SDavid Pedersen             assert!(req.headers().get("grpc-accept-encoding").is_none());
1380583cff8SDavid Pedersen             self.0.call(req)
1390583cff8SDavid Pedersen         }
1400583cff8SDavid Pedersen     }
1410583cff8SDavid Pedersen 
142*a585a722SMarcus Griep     let svc =
143*a585a722SMarcus Griep         test_server::TestServer::new(Svc::default()).send_compressed(CompressionEncoding::Gzip);
1440583cff8SDavid Pedersen 
1450583cff8SDavid Pedersen     let response_bytes_counter = Arc::new(AtomicUsize::new(0));
1460583cff8SDavid Pedersen 
1470583cff8SDavid Pedersen     tokio::spawn({
1480583cff8SDavid Pedersen         let response_bytes_counter = response_bytes_counter.clone();
1490583cff8SDavid Pedersen         async move {
1500583cff8SDavid Pedersen             Server::builder()
1510583cff8SDavid Pedersen                 .layer(
1520583cff8SDavid Pedersen                     ServiceBuilder::new()
1530583cff8SDavid Pedersen                         .layer(layer_fn(AssertCorrectAcceptEncoding))
1540583cff8SDavid Pedersen                         .layer(MapResponseBodyLayer::new(move |body| {
1550583cff8SDavid Pedersen                             util::CountBytesBody {
1560583cff8SDavid Pedersen                                 inner: body,
1570583cff8SDavid Pedersen                                 counter: response_bytes_counter.clone(),
1580583cff8SDavid Pedersen                             }
1590583cff8SDavid Pedersen                         }))
1600583cff8SDavid Pedersen                         .into_inner(),
1610583cff8SDavid Pedersen                 )
1620583cff8SDavid Pedersen                 .add_service(svc)
163d4973642SLucio Franco                 .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>(server)]))
1640583cff8SDavid Pedersen                 .await
1650583cff8SDavid Pedersen                 .unwrap();
1660583cff8SDavid Pedersen         }
1670583cff8SDavid Pedersen     });
1680583cff8SDavid Pedersen 
1690583cff8SDavid Pedersen     let mut client = test_client::TestClient::new(mock_io_channel(client).await);
1700583cff8SDavid Pedersen 
1710583cff8SDavid Pedersen     let res = client.compress_output_unary(()).await.unwrap();
1720583cff8SDavid Pedersen 
1730583cff8SDavid Pedersen     assert!(res.metadata().get("grpc-encoding").is_none());
1740583cff8SDavid Pedersen 
1750583cff8SDavid Pedersen     let bytes_sent = response_bytes_counter.load(SeqCst);
1760583cff8SDavid Pedersen     assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE);
1770583cff8SDavid Pedersen }
1780583cff8SDavid Pedersen 
1790583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")]
1800583cff8SDavid Pedersen async fn server_replying_with_unsupported_encoding() {
1810583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
1820583cff8SDavid Pedersen 
183*a585a722SMarcus Griep     let svc =
184*a585a722SMarcus Griep         test_server::TestServer::new(Svc::default()).send_compressed(CompressionEncoding::Gzip);
1850583cff8SDavid Pedersen 
1860583cff8SDavid Pedersen     fn add_weird_content_encoding<B>(mut response: http::Response<B>) -> http::Response<B> {
1870583cff8SDavid Pedersen         response
1880583cff8SDavid Pedersen             .headers_mut()
1890583cff8SDavid Pedersen             .insert("grpc-encoding", "br".parse().unwrap());
1900583cff8SDavid Pedersen         response
1910583cff8SDavid Pedersen     }
1920583cff8SDavid Pedersen 
1930583cff8SDavid Pedersen     tokio::spawn(async move {
1940583cff8SDavid Pedersen         Server::builder()
1950583cff8SDavid Pedersen             .layer(
1960583cff8SDavid Pedersen                 ServiceBuilder::new()
1970583cff8SDavid Pedersen                     .map_response(add_weird_content_encoding)
1980583cff8SDavid Pedersen                     .into_inner(),
1990583cff8SDavid Pedersen             )
2000583cff8SDavid Pedersen             .add_service(svc)
201d4973642SLucio Franco             .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>(server)]))
2020583cff8SDavid Pedersen             .await
2030583cff8SDavid Pedersen             .unwrap();
2040583cff8SDavid Pedersen     });
2050583cff8SDavid Pedersen 
206*a585a722SMarcus Griep     let mut client = test_client::TestClient::new(mock_io_channel(client).await)
207*a585a722SMarcus Griep         .accept_compressed(CompressionEncoding::Gzip);
2080583cff8SDavid Pedersen     let status: Status = client.compress_output_unary(()).await.unwrap_err();
2090583cff8SDavid Pedersen 
2100583cff8SDavid Pedersen     assert_eq!(status.code(), tonic::Code::Unimplemented);
2110583cff8SDavid Pedersen     assert_eq!(
2120583cff8SDavid Pedersen         status.message(),
2130583cff8SDavid Pedersen         "Content is compressed with `br` which isn't supported"
2140583cff8SDavid Pedersen     );
2150583cff8SDavid Pedersen }
2160583cff8SDavid Pedersen 
2170583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")]
2180583cff8SDavid Pedersen async fn disabling_compression_on_single_response() {
2190583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
2200583cff8SDavid Pedersen 
2210583cff8SDavid Pedersen     let svc = test_server::TestServer::new(Svc {
2220583cff8SDavid Pedersen         disable_compressing_on_response: true,
2230583cff8SDavid Pedersen     })
224*a585a722SMarcus Griep     .send_compressed(CompressionEncoding::Gzip);
2250583cff8SDavid Pedersen 
2260583cff8SDavid Pedersen     let response_bytes_counter = Arc::new(AtomicUsize::new(0));
2270583cff8SDavid Pedersen 
2280583cff8SDavid Pedersen     tokio::spawn({
2290583cff8SDavid Pedersen         let response_bytes_counter = response_bytes_counter.clone();
2300583cff8SDavid Pedersen         async move {
2310583cff8SDavid Pedersen             Server::builder()
2320583cff8SDavid Pedersen                 .layer(
2330583cff8SDavid Pedersen                     ServiceBuilder::new()
2340583cff8SDavid Pedersen                         .layer(MapResponseBodyLayer::new(move |body| {
2350583cff8SDavid Pedersen                             util::CountBytesBody {
2360583cff8SDavid Pedersen                                 inner: body,
2370583cff8SDavid Pedersen                                 counter: response_bytes_counter.clone(),
2380583cff8SDavid Pedersen                             }
2390583cff8SDavid Pedersen                         }))
2400583cff8SDavid Pedersen                         .into_inner(),
2410583cff8SDavid Pedersen                 )
2420583cff8SDavid Pedersen                 .add_service(svc)
243d4973642SLucio Franco                 .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>(server)]))
2440583cff8SDavid Pedersen                 .await
2450583cff8SDavid Pedersen                 .unwrap();
2460583cff8SDavid Pedersen         }
2470583cff8SDavid Pedersen     });
2480583cff8SDavid Pedersen 
249*a585a722SMarcus Griep     let mut client = test_client::TestClient::new(mock_io_channel(client).await)
250*a585a722SMarcus Griep         .accept_compressed(CompressionEncoding::Gzip);
2510583cff8SDavid Pedersen 
2520583cff8SDavid Pedersen     let res = client.compress_output_unary(()).await.unwrap();
2530583cff8SDavid Pedersen     assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip");
2540583cff8SDavid Pedersen     let bytes_sent = response_bytes_counter.load(SeqCst);
2550583cff8SDavid Pedersen     assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE);
2560583cff8SDavid Pedersen }
2570583cff8SDavid Pedersen 
2580583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")]
2590583cff8SDavid Pedersen async fn disabling_compression_on_response_but_keeping_compression_on_stream() {
2600583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
2610583cff8SDavid Pedersen 
2620583cff8SDavid Pedersen     let svc = test_server::TestServer::new(Svc {
2630583cff8SDavid Pedersen         disable_compressing_on_response: true,
2640583cff8SDavid Pedersen     })
265*a585a722SMarcus Griep     .send_compressed(CompressionEncoding::Gzip);
2660583cff8SDavid Pedersen 
2670583cff8SDavid Pedersen     let response_bytes_counter = Arc::new(AtomicUsize::new(0));
2680583cff8SDavid Pedersen 
2690583cff8SDavid Pedersen     tokio::spawn({
2700583cff8SDavid Pedersen         let response_bytes_counter = response_bytes_counter.clone();
2710583cff8SDavid Pedersen         async move {
2720583cff8SDavid Pedersen             Server::builder()
2730583cff8SDavid Pedersen                 .layer(
2740583cff8SDavid Pedersen                     ServiceBuilder::new()
2750583cff8SDavid Pedersen                         .layer(MapResponseBodyLayer::new(move |body| {
2760583cff8SDavid Pedersen                             util::CountBytesBody {
2770583cff8SDavid Pedersen                                 inner: body,
2780583cff8SDavid Pedersen                                 counter: response_bytes_counter.clone(),
2790583cff8SDavid Pedersen                             }
2800583cff8SDavid Pedersen                         }))
2810583cff8SDavid Pedersen                         .into_inner(),
2820583cff8SDavid Pedersen                 )
2830583cff8SDavid Pedersen                 .add_service(svc)
284d4973642SLucio Franco                 .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>(server)]))
2850583cff8SDavid Pedersen                 .await
2860583cff8SDavid Pedersen                 .unwrap();
2870583cff8SDavid Pedersen         }
2880583cff8SDavid Pedersen     });
2890583cff8SDavid Pedersen 
290*a585a722SMarcus Griep     let mut client = test_client::TestClient::new(mock_io_channel(client).await)
291*a585a722SMarcus Griep         .accept_compressed(CompressionEncoding::Gzip);
2920583cff8SDavid Pedersen 
2930583cff8SDavid Pedersen     let res = client.compress_output_server_stream(()).await.unwrap();
2940583cff8SDavid Pedersen 
2950583cff8SDavid Pedersen     assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip");
2960583cff8SDavid Pedersen 
2970583cff8SDavid Pedersen     let mut stream: Streaming<SomeData> = res.into_inner();
2980583cff8SDavid Pedersen 
2990583cff8SDavid Pedersen     stream
3000583cff8SDavid Pedersen         .next()
3010583cff8SDavid Pedersen         .await
3020583cff8SDavid Pedersen         .expect("stream empty")
3030583cff8SDavid Pedersen         .expect("item was error");
3040583cff8SDavid Pedersen     assert!(response_bytes_counter.load(SeqCst) < UNCOMPRESSED_MIN_BODY_SIZE);
3050583cff8SDavid Pedersen 
3060583cff8SDavid Pedersen     stream
3070583cff8SDavid Pedersen         .next()
3080583cff8SDavid Pedersen         .await
3090583cff8SDavid Pedersen         .expect("stream empty")
3100583cff8SDavid Pedersen         .expect("item was error");
3110583cff8SDavid Pedersen     assert!(response_bytes_counter.load(SeqCst) < UNCOMPRESSED_MIN_BODY_SIZE);
3120583cff8SDavid Pedersen }
3130583cff8SDavid Pedersen 
3140583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")]
3150583cff8SDavid Pedersen async fn disabling_compression_on_response_from_client_stream() {
3160583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
3170583cff8SDavid Pedersen 
3180583cff8SDavid Pedersen     let svc = test_server::TestServer::new(Svc {
3190583cff8SDavid Pedersen         disable_compressing_on_response: true,
3200583cff8SDavid Pedersen     })
321*a585a722SMarcus Griep     .send_compressed(CompressionEncoding::Gzip);
3220583cff8SDavid Pedersen 
3230583cff8SDavid Pedersen     let response_bytes_counter = Arc::new(AtomicUsize::new(0));
3240583cff8SDavid Pedersen 
3250583cff8SDavid Pedersen     tokio::spawn({
3260583cff8SDavid Pedersen         let response_bytes_counter = response_bytes_counter.clone();
3270583cff8SDavid Pedersen         async move {
3280583cff8SDavid Pedersen             Server::builder()
3290583cff8SDavid Pedersen                 .layer(
3300583cff8SDavid Pedersen                     ServiceBuilder::new()
3310583cff8SDavid Pedersen                         .layer(MapResponseBodyLayer::new(move |body| {
3320583cff8SDavid Pedersen                             util::CountBytesBody {
3330583cff8SDavid Pedersen                                 inner: body,
3340583cff8SDavid Pedersen                                 counter: response_bytes_counter.clone(),
3350583cff8SDavid Pedersen                             }
3360583cff8SDavid Pedersen                         }))
3370583cff8SDavid Pedersen                         .into_inner(),
3380583cff8SDavid Pedersen                 )
3390583cff8SDavid Pedersen                 .add_service(svc)
340d4973642SLucio Franco                 .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>(server)]))
3410583cff8SDavid Pedersen                 .await
3420583cff8SDavid Pedersen                 .unwrap();
3430583cff8SDavid Pedersen         }
3440583cff8SDavid Pedersen     });
3450583cff8SDavid Pedersen 
346*a585a722SMarcus Griep     let mut client = test_client::TestClient::new(mock_io_channel(client).await)
347*a585a722SMarcus Griep         .accept_compressed(CompressionEncoding::Gzip);
3480583cff8SDavid Pedersen 
3490583cff8SDavid Pedersen     let stream = futures::stream::iter(vec![]);
3500583cff8SDavid Pedersen     let req = Request::new(Box::pin(stream));
3510583cff8SDavid Pedersen 
3520583cff8SDavid Pedersen     let res = client.compress_output_client_stream(req).await.unwrap();
3530583cff8SDavid Pedersen     assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip");
3540583cff8SDavid Pedersen     let bytes_sent = response_bytes_counter.load(SeqCst);
3550583cff8SDavid Pedersen     assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE);
3560583cff8SDavid Pedersen }
357