10583cff8SDavid Pedersen use super::*; 2a585a722SMarcus 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 35a585a722SMarcus Griep let svc = 36a585a722SMarcus 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) 56*f089e7a0Stottoto .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) 570583cff8SDavid Pedersen .await 580583cff8SDavid Pedersen .unwrap(); 590583cff8SDavid Pedersen } 600583cff8SDavid Pedersen }); 610583cff8SDavid Pedersen 62a585a722SMarcus Griep let mut client = test_client::TestClient::new(mock_io_channel(client).await) 63a585a722SMarcus 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) 97*f089e7a0Stottoto .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) 980583cff8SDavid Pedersen .await 990583cff8SDavid Pedersen .unwrap(); 1000583cff8SDavid Pedersen } 1010583cff8SDavid Pedersen }); 1020583cff8SDavid Pedersen 103a585a722SMarcus Griep let mut client = test_client::TestClient::new(mock_io_channel(client).await) 104a585a722SMarcus 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 142a585a722SMarcus Griep let svc = 143a585a722SMarcus 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) 163*f089e7a0Stottoto .serve_with_incoming(tokio_stream::once(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 183a585a722SMarcus Griep let svc = 184a585a722SMarcus 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) 201*f089e7a0Stottoto .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) 2020583cff8SDavid Pedersen .await 2030583cff8SDavid Pedersen .unwrap(); 2040583cff8SDavid Pedersen }); 2050583cff8SDavid Pedersen 206a585a722SMarcus Griep let mut client = test_client::TestClient::new(mock_io_channel(client).await) 207a585a722SMarcus 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 }) 224a585a722SMarcus 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) 243*f089e7a0Stottoto .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) 2440583cff8SDavid Pedersen .await 2450583cff8SDavid Pedersen .unwrap(); 2460583cff8SDavid Pedersen } 2470583cff8SDavid Pedersen }); 2480583cff8SDavid Pedersen 249a585a722SMarcus Griep let mut client = test_client::TestClient::new(mock_io_channel(client).await) 250a585a722SMarcus 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 }) 265a585a722SMarcus 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) 284*f089e7a0Stottoto .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) 2850583cff8SDavid Pedersen .await 2860583cff8SDavid Pedersen .unwrap(); 2870583cff8SDavid Pedersen } 2880583cff8SDavid Pedersen }); 2890583cff8SDavid Pedersen 290a585a722SMarcus Griep let mut client = test_client::TestClient::new(mock_io_channel(client).await) 291a585a722SMarcus 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 }) 321a585a722SMarcus 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) 340*f089e7a0Stottoto .serve_with_incoming(tokio_stream::once(Ok::<_, std::io::Error>(server))) 3410583cff8SDavid Pedersen .await 3420583cff8SDavid Pedersen .unwrap(); 3430583cff8SDavid Pedersen } 3440583cff8SDavid Pedersen }); 3450583cff8SDavid Pedersen 346a585a722SMarcus Griep let mut client = test_client::TestClient::new(mock_io_channel(client).await) 347a585a722SMarcus Griep .accept_compressed(CompressionEncoding::Gzip); 3480583cff8SDavid Pedersen 349*f089e7a0Stottoto let req = Request::new(Box::pin(tokio_stream::empty())); 3500583cff8SDavid Pedersen 3510583cff8SDavid Pedersen let res = client.compress_output_client_stream(req).await.unwrap(); 3520583cff8SDavid Pedersen assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip"); 3530583cff8SDavid Pedersen let bytes_sent = response_bytes_counter.load(SeqCst); 3540583cff8SDavid Pedersen assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE); 3550583cff8SDavid Pedersen } 356