10583cff8SDavid Pedersen use super::*;
2e8cb48fcSQuentin Perez use http_body::Body;
3a585a722SMarcus Griep use tonic::codec::CompressionEncoding;
40583cff8SDavid Pedersen 
5e8cb48fcSQuentin Perez util::parametrized_tests! {
6e8cb48fcSQuentin Perez     client_enabled_server_enabled,
7e8cb48fcSQuentin Perez     zstd: CompressionEncoding::Zstd,
8e8cb48fcSQuentin Perez     gzip: CompressionEncoding::Gzip,
9*79a06cc8SIlya Averyanov     deflate: CompressionEncoding::Deflate,
10e8cb48fcSQuentin Perez }
11e8cb48fcSQuentin Perez 
12e8cb48fcSQuentin Perez #[allow(dead_code)]
client_enabled_server_enabled(encoding: CompressionEncoding)13e8cb48fcSQuentin Perez async fn client_enabled_server_enabled(encoding: CompressionEncoding) {
140583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
150583cff8SDavid Pedersen 
16e8cb48fcSQuentin Perez     let svc = test_server::TestServer::new(Svc::default()).accept_compressed(encoding);
170583cff8SDavid Pedersen 
180583cff8SDavid Pedersen     let request_bytes_counter = Arc::new(AtomicUsize::new(0));
190583cff8SDavid Pedersen 
20e8cb48fcSQuentin Perez     #[derive(Clone)]
21e8cb48fcSQuentin Perez     pub struct AssertRightEncoding {
22e8cb48fcSQuentin Perez         encoding: CompressionEncoding,
23e8cb48fcSQuentin Perez     }
24e8cb48fcSQuentin Perez 
25e8cb48fcSQuentin Perez     #[allow(dead_code)]
26e8cb48fcSQuentin Perez     impl AssertRightEncoding {
27e8cb48fcSQuentin Perez         pub fn new(encoding: CompressionEncoding) -> Self {
28e8cb48fcSQuentin Perez             Self { encoding }
29e8cb48fcSQuentin Perez         }
30e8cb48fcSQuentin Perez 
31e8cb48fcSQuentin Perez         pub fn call<B: Body>(self, req: http::Request<B>) -> http::Request<B> {
32e8cb48fcSQuentin Perez             let expected = match self.encoding {
33e8cb48fcSQuentin Perez                 CompressionEncoding::Gzip => "gzip",
34e8cb48fcSQuentin Perez                 CompressionEncoding::Zstd => "zstd",
35*79a06cc8SIlya Averyanov                 CompressionEncoding::Deflate => "deflate",
36e8cb48fcSQuentin Perez                 _ => panic!("unexpected encoding {:?}", self.encoding),
37e8cb48fcSQuentin Perez             };
38e8cb48fcSQuentin Perez             assert_eq!(req.headers().get("grpc-encoding").unwrap(), expected);
39e8cb48fcSQuentin Perez 
400583cff8SDavid Pedersen             req
410583cff8SDavid Pedersen         }
42e8cb48fcSQuentin Perez     }
430583cff8SDavid Pedersen 
440583cff8SDavid Pedersen     tokio::spawn({
450583cff8SDavid Pedersen         let request_bytes_counter = request_bytes_counter.clone();
460583cff8SDavid Pedersen         async move {
470583cff8SDavid Pedersen             Server::builder()
480583cff8SDavid Pedersen                 .layer(
490583cff8SDavid Pedersen                     ServiceBuilder::new()
50e8cb48fcSQuentin Perez                         .map_request(move |req| {
51e8cb48fcSQuentin Perez                             AssertRightEncoding::new(encoding).clone().call(req)
52e8cb48fcSQuentin Perez                         })
530583cff8SDavid Pedersen                         .layer(measure_request_body_size_layer(
540583cff8SDavid Pedersen                             request_bytes_counter.clone(),
550583cff8SDavid Pedersen                         ))
560583cff8SDavid Pedersen                         .into_inner(),
570583cff8SDavid Pedersen                 )
580583cff8SDavid Pedersen                 .add_service(svc)
59f089e7a0Stottoto                 .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server)))
600583cff8SDavid Pedersen                 .await
610583cff8SDavid Pedersen                 .unwrap();
620583cff8SDavid Pedersen         }
630583cff8SDavid Pedersen     });
640583cff8SDavid Pedersen 
65e8cb48fcSQuentin Perez     let mut client =
66e8cb48fcSQuentin Perez         test_client::TestClient::new(mock_io_channel(client).await).send_compressed(encoding);
670583cff8SDavid Pedersen 
680583cff8SDavid Pedersen     let data = [0_u8; UNCOMPRESSED_MIN_BODY_SIZE].to_vec();
6923602b47Stottoto     let stream = tokio_stream::iter(vec![SomeData { data: data.clone() }, SomeData { data }]);
700583cff8SDavid Pedersen     let req = Request::new(Box::pin(stream));
710583cff8SDavid Pedersen 
720583cff8SDavid Pedersen     client.compress_input_client_stream(req).await.unwrap();
730583cff8SDavid Pedersen 
740583cff8SDavid Pedersen     let bytes_sent = request_bytes_counter.load(SeqCst);
750583cff8SDavid Pedersen     assert!(bytes_sent < UNCOMPRESSED_MIN_BODY_SIZE);
760583cff8SDavid Pedersen }
770583cff8SDavid Pedersen 
78e8cb48fcSQuentin Perez util::parametrized_tests! {
79e8cb48fcSQuentin Perez     client_disabled_server_enabled,
80e8cb48fcSQuentin Perez     zstd: CompressionEncoding::Zstd,
81e8cb48fcSQuentin Perez     gzip: CompressionEncoding::Gzip,
82*79a06cc8SIlya Averyanov     deflate: CompressionEncoding::Deflate,
83e8cb48fcSQuentin Perez }
84e8cb48fcSQuentin Perez 
85e8cb48fcSQuentin Perez #[allow(dead_code)]
client_disabled_server_enabled(encoding: CompressionEncoding)86e8cb48fcSQuentin Perez async fn client_disabled_server_enabled(encoding: CompressionEncoding) {
870583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
880583cff8SDavid Pedersen 
89e8cb48fcSQuentin Perez     let svc = test_server::TestServer::new(Svc::default()).accept_compressed(encoding);
900583cff8SDavid Pedersen 
910583cff8SDavid Pedersen     let request_bytes_counter = Arc::new(AtomicUsize::new(0));
920583cff8SDavid Pedersen 
930583cff8SDavid Pedersen     fn assert_right_encoding<B>(req: http::Request<B>) -> http::Request<B> {
940583cff8SDavid Pedersen         assert!(req.headers().get("grpc-encoding").is_none());
950583cff8SDavid Pedersen         req
960583cff8SDavid Pedersen     }
970583cff8SDavid Pedersen 
980583cff8SDavid Pedersen     tokio::spawn({
990583cff8SDavid Pedersen         let request_bytes_counter = request_bytes_counter.clone();
1000583cff8SDavid Pedersen         async move {
1010583cff8SDavid Pedersen             Server::builder()
1020583cff8SDavid Pedersen                 .layer(
1030583cff8SDavid Pedersen                     ServiceBuilder::new()
1040583cff8SDavid Pedersen                         .map_request(assert_right_encoding)
1050583cff8SDavid Pedersen                         .layer(measure_request_body_size_layer(
1060583cff8SDavid Pedersen                             request_bytes_counter.clone(),
1070583cff8SDavid Pedersen                         ))
1080583cff8SDavid Pedersen                         .into_inner(),
1090583cff8SDavid Pedersen                 )
1100583cff8SDavid Pedersen                 .add_service(svc)
111f089e7a0Stottoto                 .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server)))
1120583cff8SDavid Pedersen                 .await
1130583cff8SDavid Pedersen                 .unwrap();
1140583cff8SDavid Pedersen         }
1150583cff8SDavid Pedersen     });
1160583cff8SDavid Pedersen 
1170583cff8SDavid Pedersen     let mut client = test_client::TestClient::new(mock_io_channel(client).await);
1180583cff8SDavid Pedersen 
1190583cff8SDavid Pedersen     let data = [0_u8; UNCOMPRESSED_MIN_BODY_SIZE].to_vec();
12023602b47Stottoto     let stream = tokio_stream::iter(vec![SomeData { data: data.clone() }, SomeData { data }]);
1210583cff8SDavid Pedersen     let req = Request::new(Box::pin(stream));
1220583cff8SDavid Pedersen 
1230583cff8SDavid Pedersen     client.compress_input_client_stream(req).await.unwrap();
1240583cff8SDavid Pedersen 
1250583cff8SDavid Pedersen     let bytes_sent = request_bytes_counter.load(SeqCst);
1260583cff8SDavid Pedersen     assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE);
1270583cff8SDavid Pedersen }
1280583cff8SDavid Pedersen 
129e8cb48fcSQuentin Perez util::parametrized_tests! {
130e8cb48fcSQuentin Perez     client_enabled_server_disabled,
131e8cb48fcSQuentin Perez     zstd: CompressionEncoding::Zstd,
132e8cb48fcSQuentin Perez     gzip: CompressionEncoding::Gzip,
133*79a06cc8SIlya Averyanov     deflate: CompressionEncoding::Deflate,
134e8cb48fcSQuentin Perez }
135e8cb48fcSQuentin Perez 
136e8cb48fcSQuentin Perez #[allow(dead_code)]
client_enabled_server_disabled(encoding: CompressionEncoding)137e8cb48fcSQuentin Perez async fn client_enabled_server_disabled(encoding: CompressionEncoding) {
1380583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
1390583cff8SDavid Pedersen 
1400583cff8SDavid Pedersen     let svc = test_server::TestServer::new(Svc::default());
1410583cff8SDavid Pedersen 
1420583cff8SDavid Pedersen     tokio::spawn(async move {
1430583cff8SDavid Pedersen         Server::builder()
1440583cff8SDavid Pedersen             .add_service(svc)
145f089e7a0Stottoto             .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server)))
1460583cff8SDavid Pedersen             .await
1470583cff8SDavid Pedersen             .unwrap();
1480583cff8SDavid Pedersen     });
1490583cff8SDavid Pedersen 
150e8cb48fcSQuentin Perez     let mut client =
151e8cb48fcSQuentin Perez         test_client::TestClient::new(mock_io_channel(client).await).send_compressed(encoding);
1520583cff8SDavid Pedersen 
1530583cff8SDavid Pedersen     let data = [0_u8; UNCOMPRESSED_MIN_BODY_SIZE].to_vec();
15423602b47Stottoto     let stream = tokio_stream::iter(vec![SomeData { data: data.clone() }, SomeData { data }]);
1550583cff8SDavid Pedersen     let req = Request::new(Box::pin(stream));
1560583cff8SDavid Pedersen 
1570583cff8SDavid Pedersen     let status = client.compress_input_client_stream(req).await.unwrap_err();
1580583cff8SDavid Pedersen 
1590583cff8SDavid Pedersen     assert_eq!(status.code(), tonic::Code::Unimplemented);
160e8cb48fcSQuentin Perez     let expected = match encoding {
161e8cb48fcSQuentin Perez         CompressionEncoding::Gzip => "gzip",
162e8cb48fcSQuentin Perez         CompressionEncoding::Zstd => "zstd",
163*79a06cc8SIlya Averyanov         CompressionEncoding::Deflate => "deflate",
164e8cb48fcSQuentin Perez         _ => panic!("unexpected encoding {:?}", encoding),
165e8cb48fcSQuentin Perez     };
1660583cff8SDavid Pedersen     assert_eq!(
1670583cff8SDavid Pedersen         status.message(),
168e8cb48fcSQuentin Perez         format!(
169e8cb48fcSQuentin Perez             "Content is compressed with `{}` which isn't supported",
170e8cb48fcSQuentin Perez             expected
171e8cb48fcSQuentin Perez         )
1720583cff8SDavid Pedersen     );
1730583cff8SDavid Pedersen }
1740583cff8SDavid Pedersen 
175e8cb48fcSQuentin Perez util::parametrized_tests! {
176e8cb48fcSQuentin Perez     compressing_response_from_client_stream,
177e8cb48fcSQuentin Perez     zstd: CompressionEncoding::Zstd,
178e8cb48fcSQuentin Perez     gzip: CompressionEncoding::Gzip,
179*79a06cc8SIlya Averyanov     deflate: CompressionEncoding::Deflate,
180e8cb48fcSQuentin Perez }
181e8cb48fcSQuentin Perez 
182e8cb48fcSQuentin Perez #[allow(dead_code)]
compressing_response_from_client_stream(encoding: CompressionEncoding)183e8cb48fcSQuentin Perez async fn compressing_response_from_client_stream(encoding: CompressionEncoding) {
1840583cff8SDavid Pedersen     let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10);
1850583cff8SDavid Pedersen 
186e8cb48fcSQuentin Perez     let svc = test_server::TestServer::new(Svc::default()).send_compressed(encoding);
1870583cff8SDavid Pedersen 
1880583cff8SDavid Pedersen     let response_bytes_counter = Arc::new(AtomicUsize::new(0));
1890583cff8SDavid Pedersen 
1900583cff8SDavid Pedersen     tokio::spawn({
1910583cff8SDavid Pedersen         let response_bytes_counter = response_bytes_counter.clone();
1920583cff8SDavid Pedersen         async move {
1930583cff8SDavid Pedersen             Server::builder()
1940583cff8SDavid Pedersen                 .layer(
1950583cff8SDavid Pedersen                     ServiceBuilder::new()
1960583cff8SDavid Pedersen                         .layer(MapResponseBodyLayer::new(move |body| {
1970583cff8SDavid Pedersen                             util::CountBytesBody {
1980583cff8SDavid Pedersen                                 inner: body,
1990583cff8SDavid Pedersen                                 counter: response_bytes_counter.clone(),
2000583cff8SDavid Pedersen                             }
2010583cff8SDavid Pedersen                         }))
2020583cff8SDavid Pedersen                         .into_inner(),
2030583cff8SDavid Pedersen                 )
2040583cff8SDavid Pedersen                 .add_service(svc)
205f089e7a0Stottoto                 .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server)))
2060583cff8SDavid Pedersen                 .await
2070583cff8SDavid Pedersen                 .unwrap();
2080583cff8SDavid Pedersen         }
2090583cff8SDavid Pedersen     });
2100583cff8SDavid Pedersen 
211e8cb48fcSQuentin Perez     let mut client =
212e8cb48fcSQuentin Perez         test_client::TestClient::new(mock_io_channel(client).await).accept_compressed(encoding);
2130583cff8SDavid Pedersen 
214f089e7a0Stottoto     let req = Request::new(Box::pin(tokio_stream::empty()));
2150583cff8SDavid Pedersen 
2160583cff8SDavid Pedersen     let res = client.compress_output_client_stream(req).await.unwrap();
217e8cb48fcSQuentin Perez     let expected = match encoding {
218e8cb48fcSQuentin Perez         CompressionEncoding::Gzip => "gzip",
219e8cb48fcSQuentin Perez         CompressionEncoding::Zstd => "zstd",
220*79a06cc8SIlya Averyanov         CompressionEncoding::Deflate => "deflate",
221e8cb48fcSQuentin Perez         _ => panic!("unexpected encoding {:?}", encoding),
222e8cb48fcSQuentin Perez     };
223e8cb48fcSQuentin Perez     assert_eq!(res.metadata().get("grpc-encoding").unwrap(), expected);
2240583cff8SDavid Pedersen     let bytes_sent = response_bytes_counter.load(SeqCst);
2250583cff8SDavid Pedersen     assert!(bytes_sent < UNCOMPRESSED_MIN_BODY_SIZE);
2260583cff8SDavid Pedersen }
227