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