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