1*0583cff8SDavid Pedersen use super::*; 2*0583cff8SDavid Pedersen 3*0583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")] 4*0583cff8SDavid Pedersen async fn client_enabled_server_enabled() { 5*0583cff8SDavid Pedersen let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10); 6*0583cff8SDavid Pedersen 7*0583cff8SDavid Pedersen #[derive(Clone, Copy)] 8*0583cff8SDavid Pedersen struct AssertCorrectAcceptEncoding<S>(S); 9*0583cff8SDavid Pedersen 10*0583cff8SDavid Pedersen impl<S, B> Service<http::Request<B>> for AssertCorrectAcceptEncoding<S> 11*0583cff8SDavid Pedersen where 12*0583cff8SDavid Pedersen S: Service<http::Request<B>>, 13*0583cff8SDavid Pedersen { 14*0583cff8SDavid Pedersen type Response = S::Response; 15*0583cff8SDavid Pedersen type Error = S::Error; 16*0583cff8SDavid Pedersen type Future = S::Future; 17*0583cff8SDavid Pedersen 18*0583cff8SDavid Pedersen fn poll_ready( 19*0583cff8SDavid Pedersen &mut self, 20*0583cff8SDavid Pedersen cx: &mut std::task::Context<'_>, 21*0583cff8SDavid Pedersen ) -> std::task::Poll<Result<(), Self::Error>> { 22*0583cff8SDavid Pedersen self.0.poll_ready(cx) 23*0583cff8SDavid Pedersen } 24*0583cff8SDavid Pedersen 25*0583cff8SDavid Pedersen fn call(&mut self, req: http::Request<B>) -> Self::Future { 26*0583cff8SDavid Pedersen assert_eq!( 27*0583cff8SDavid Pedersen req.headers().get("grpc-accept-encoding").unwrap(), 28*0583cff8SDavid Pedersen "gzip,identity" 29*0583cff8SDavid Pedersen ); 30*0583cff8SDavid Pedersen self.0.call(req) 31*0583cff8SDavid Pedersen } 32*0583cff8SDavid Pedersen } 33*0583cff8SDavid Pedersen 34*0583cff8SDavid Pedersen let svc = test_server::TestServer::new(Svc::default()).send_gzip(); 35*0583cff8SDavid Pedersen 36*0583cff8SDavid Pedersen let response_bytes_counter = Arc::new(AtomicUsize::new(0)); 37*0583cff8SDavid Pedersen 38*0583cff8SDavid Pedersen tokio::spawn({ 39*0583cff8SDavid Pedersen let response_bytes_counter = response_bytes_counter.clone(); 40*0583cff8SDavid Pedersen async move { 41*0583cff8SDavid Pedersen Server::builder() 42*0583cff8SDavid Pedersen .layer( 43*0583cff8SDavid Pedersen ServiceBuilder::new() 44*0583cff8SDavid Pedersen .layer(layer_fn(AssertCorrectAcceptEncoding)) 45*0583cff8SDavid Pedersen .layer(MapResponseBodyLayer::new(move |body| { 46*0583cff8SDavid Pedersen util::CountBytesBody { 47*0583cff8SDavid Pedersen inner: body, 48*0583cff8SDavid Pedersen counter: response_bytes_counter.clone(), 49*0583cff8SDavid Pedersen } 50*0583cff8SDavid Pedersen })) 51*0583cff8SDavid Pedersen .into_inner(), 52*0583cff8SDavid Pedersen ) 53*0583cff8SDavid Pedersen .add_service(svc) 54*0583cff8SDavid Pedersen .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>( 55*0583cff8SDavid Pedersen MockStream(server), 56*0583cff8SDavid Pedersen )])) 57*0583cff8SDavid Pedersen .await 58*0583cff8SDavid Pedersen .unwrap(); 59*0583cff8SDavid Pedersen } 60*0583cff8SDavid Pedersen }); 61*0583cff8SDavid Pedersen 62*0583cff8SDavid Pedersen let mut client = test_client::TestClient::new(mock_io_channel(client).await).accept_gzip(); 63*0583cff8SDavid Pedersen 64*0583cff8SDavid Pedersen for _ in 0..3 { 65*0583cff8SDavid Pedersen let res = client.compress_output_unary(()).await.unwrap(); 66*0583cff8SDavid Pedersen assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip"); 67*0583cff8SDavid Pedersen let bytes_sent = response_bytes_counter.load(SeqCst); 68*0583cff8SDavid Pedersen assert!(bytes_sent < UNCOMPRESSED_MIN_BODY_SIZE); 69*0583cff8SDavid Pedersen } 70*0583cff8SDavid Pedersen } 71*0583cff8SDavid Pedersen 72*0583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")] 73*0583cff8SDavid Pedersen async fn client_enabled_server_disabled() { 74*0583cff8SDavid Pedersen let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10); 75*0583cff8SDavid Pedersen 76*0583cff8SDavid Pedersen let svc = test_server::TestServer::new(Svc::default()); 77*0583cff8SDavid Pedersen 78*0583cff8SDavid Pedersen let response_bytes_counter = Arc::new(AtomicUsize::new(0)); 79*0583cff8SDavid Pedersen 80*0583cff8SDavid Pedersen tokio::spawn({ 81*0583cff8SDavid Pedersen let response_bytes_counter = response_bytes_counter.clone(); 82*0583cff8SDavid Pedersen async move { 83*0583cff8SDavid Pedersen Server::builder() 84*0583cff8SDavid Pedersen // no compression enable on the server so responses should not be compressed 85*0583cff8SDavid Pedersen .layer( 86*0583cff8SDavid Pedersen ServiceBuilder::new() 87*0583cff8SDavid Pedersen .layer(MapResponseBodyLayer::new(move |body| { 88*0583cff8SDavid Pedersen util::CountBytesBody { 89*0583cff8SDavid Pedersen inner: body, 90*0583cff8SDavid Pedersen counter: response_bytes_counter.clone(), 91*0583cff8SDavid Pedersen } 92*0583cff8SDavid Pedersen })) 93*0583cff8SDavid Pedersen .into_inner(), 94*0583cff8SDavid Pedersen ) 95*0583cff8SDavid Pedersen .add_service(svc) 96*0583cff8SDavid Pedersen .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>( 97*0583cff8SDavid Pedersen MockStream(server), 98*0583cff8SDavid Pedersen )])) 99*0583cff8SDavid Pedersen .await 100*0583cff8SDavid Pedersen .unwrap(); 101*0583cff8SDavid Pedersen } 102*0583cff8SDavid Pedersen }); 103*0583cff8SDavid Pedersen 104*0583cff8SDavid Pedersen let mut client = test_client::TestClient::new(mock_io_channel(client).await).accept_gzip(); 105*0583cff8SDavid Pedersen 106*0583cff8SDavid Pedersen let res = client.compress_output_unary(()).await.unwrap(); 107*0583cff8SDavid Pedersen 108*0583cff8SDavid Pedersen assert!(res.metadata().get("grpc-encoding").is_none()); 109*0583cff8SDavid Pedersen 110*0583cff8SDavid Pedersen let bytes_sent = response_bytes_counter.load(SeqCst); 111*0583cff8SDavid Pedersen assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE); 112*0583cff8SDavid Pedersen } 113*0583cff8SDavid Pedersen 114*0583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")] 115*0583cff8SDavid Pedersen async fn client_disabled() { 116*0583cff8SDavid Pedersen let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10); 117*0583cff8SDavid Pedersen 118*0583cff8SDavid Pedersen #[derive(Clone, Copy)] 119*0583cff8SDavid Pedersen struct AssertCorrectAcceptEncoding<S>(S); 120*0583cff8SDavid Pedersen 121*0583cff8SDavid Pedersen impl<S, B> Service<http::Request<B>> for AssertCorrectAcceptEncoding<S> 122*0583cff8SDavid Pedersen where 123*0583cff8SDavid Pedersen S: Service<http::Request<B>>, 124*0583cff8SDavid Pedersen { 125*0583cff8SDavid Pedersen type Response = S::Response; 126*0583cff8SDavid Pedersen type Error = S::Error; 127*0583cff8SDavid Pedersen type Future = S::Future; 128*0583cff8SDavid Pedersen 129*0583cff8SDavid Pedersen fn poll_ready( 130*0583cff8SDavid Pedersen &mut self, 131*0583cff8SDavid Pedersen cx: &mut std::task::Context<'_>, 132*0583cff8SDavid Pedersen ) -> std::task::Poll<Result<(), Self::Error>> { 133*0583cff8SDavid Pedersen self.0.poll_ready(cx) 134*0583cff8SDavid Pedersen } 135*0583cff8SDavid Pedersen 136*0583cff8SDavid Pedersen fn call(&mut self, req: http::Request<B>) -> Self::Future { 137*0583cff8SDavid Pedersen assert!(req.headers().get("grpc-accept-encoding").is_none()); 138*0583cff8SDavid Pedersen self.0.call(req) 139*0583cff8SDavid Pedersen } 140*0583cff8SDavid Pedersen } 141*0583cff8SDavid Pedersen 142*0583cff8SDavid Pedersen let svc = test_server::TestServer::new(Svc::default()).send_gzip(); 143*0583cff8SDavid Pedersen 144*0583cff8SDavid Pedersen let response_bytes_counter = Arc::new(AtomicUsize::new(0)); 145*0583cff8SDavid Pedersen 146*0583cff8SDavid Pedersen tokio::spawn({ 147*0583cff8SDavid Pedersen let response_bytes_counter = response_bytes_counter.clone(); 148*0583cff8SDavid Pedersen async move { 149*0583cff8SDavid Pedersen Server::builder() 150*0583cff8SDavid Pedersen .layer( 151*0583cff8SDavid Pedersen ServiceBuilder::new() 152*0583cff8SDavid Pedersen .layer(layer_fn(AssertCorrectAcceptEncoding)) 153*0583cff8SDavid Pedersen .layer(MapResponseBodyLayer::new(move |body| { 154*0583cff8SDavid Pedersen util::CountBytesBody { 155*0583cff8SDavid Pedersen inner: body, 156*0583cff8SDavid Pedersen counter: response_bytes_counter.clone(), 157*0583cff8SDavid Pedersen } 158*0583cff8SDavid Pedersen })) 159*0583cff8SDavid Pedersen .into_inner(), 160*0583cff8SDavid Pedersen ) 161*0583cff8SDavid Pedersen .add_service(svc) 162*0583cff8SDavid Pedersen .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>( 163*0583cff8SDavid Pedersen MockStream(server), 164*0583cff8SDavid Pedersen )])) 165*0583cff8SDavid Pedersen .await 166*0583cff8SDavid Pedersen .unwrap(); 167*0583cff8SDavid Pedersen } 168*0583cff8SDavid Pedersen }); 169*0583cff8SDavid Pedersen 170*0583cff8SDavid Pedersen let mut client = test_client::TestClient::new(mock_io_channel(client).await); 171*0583cff8SDavid Pedersen 172*0583cff8SDavid Pedersen let res = client.compress_output_unary(()).await.unwrap(); 173*0583cff8SDavid Pedersen 174*0583cff8SDavid Pedersen assert!(res.metadata().get("grpc-encoding").is_none()); 175*0583cff8SDavid Pedersen 176*0583cff8SDavid Pedersen let bytes_sent = response_bytes_counter.load(SeqCst); 177*0583cff8SDavid Pedersen assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE); 178*0583cff8SDavid Pedersen } 179*0583cff8SDavid Pedersen 180*0583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")] 181*0583cff8SDavid Pedersen async fn server_replying_with_unsupported_encoding() { 182*0583cff8SDavid Pedersen let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10); 183*0583cff8SDavid Pedersen 184*0583cff8SDavid Pedersen let svc = test_server::TestServer::new(Svc::default()).send_gzip(); 185*0583cff8SDavid Pedersen 186*0583cff8SDavid Pedersen fn add_weird_content_encoding<B>(mut response: http::Response<B>) -> http::Response<B> { 187*0583cff8SDavid Pedersen response 188*0583cff8SDavid Pedersen .headers_mut() 189*0583cff8SDavid Pedersen .insert("grpc-encoding", "br".parse().unwrap()); 190*0583cff8SDavid Pedersen response 191*0583cff8SDavid Pedersen } 192*0583cff8SDavid Pedersen 193*0583cff8SDavid Pedersen tokio::spawn(async move { 194*0583cff8SDavid Pedersen Server::builder() 195*0583cff8SDavid Pedersen .layer( 196*0583cff8SDavid Pedersen ServiceBuilder::new() 197*0583cff8SDavid Pedersen .map_response(add_weird_content_encoding) 198*0583cff8SDavid Pedersen .into_inner(), 199*0583cff8SDavid Pedersen ) 200*0583cff8SDavid Pedersen .add_service(svc) 201*0583cff8SDavid Pedersen .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>( 202*0583cff8SDavid Pedersen MockStream(server), 203*0583cff8SDavid Pedersen )])) 204*0583cff8SDavid Pedersen .await 205*0583cff8SDavid Pedersen .unwrap(); 206*0583cff8SDavid Pedersen }); 207*0583cff8SDavid Pedersen 208*0583cff8SDavid Pedersen let mut client = test_client::TestClient::new(mock_io_channel(client).await).accept_gzip(); 209*0583cff8SDavid Pedersen let status: Status = client.compress_output_unary(()).await.unwrap_err(); 210*0583cff8SDavid Pedersen 211*0583cff8SDavid Pedersen assert_eq!(status.code(), tonic::Code::Unimplemented); 212*0583cff8SDavid Pedersen assert_eq!( 213*0583cff8SDavid Pedersen status.message(), 214*0583cff8SDavid Pedersen "Content is compressed with `br` which isn't supported" 215*0583cff8SDavid Pedersen ); 216*0583cff8SDavid Pedersen } 217*0583cff8SDavid Pedersen 218*0583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")] 219*0583cff8SDavid Pedersen async fn disabling_compression_on_single_response() { 220*0583cff8SDavid Pedersen let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10); 221*0583cff8SDavid Pedersen 222*0583cff8SDavid Pedersen let svc = test_server::TestServer::new(Svc { 223*0583cff8SDavid Pedersen disable_compressing_on_response: true, 224*0583cff8SDavid Pedersen }) 225*0583cff8SDavid Pedersen .send_gzip(); 226*0583cff8SDavid Pedersen 227*0583cff8SDavid Pedersen let response_bytes_counter = Arc::new(AtomicUsize::new(0)); 228*0583cff8SDavid Pedersen 229*0583cff8SDavid Pedersen tokio::spawn({ 230*0583cff8SDavid Pedersen let response_bytes_counter = response_bytes_counter.clone(); 231*0583cff8SDavid Pedersen async move { 232*0583cff8SDavid Pedersen Server::builder() 233*0583cff8SDavid Pedersen .layer( 234*0583cff8SDavid Pedersen ServiceBuilder::new() 235*0583cff8SDavid Pedersen .layer(MapResponseBodyLayer::new(move |body| { 236*0583cff8SDavid Pedersen util::CountBytesBody { 237*0583cff8SDavid Pedersen inner: body, 238*0583cff8SDavid Pedersen counter: response_bytes_counter.clone(), 239*0583cff8SDavid Pedersen } 240*0583cff8SDavid Pedersen })) 241*0583cff8SDavid Pedersen .into_inner(), 242*0583cff8SDavid Pedersen ) 243*0583cff8SDavid Pedersen .add_service(svc) 244*0583cff8SDavid Pedersen .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>( 245*0583cff8SDavid Pedersen MockStream(server), 246*0583cff8SDavid Pedersen )])) 247*0583cff8SDavid Pedersen .await 248*0583cff8SDavid Pedersen .unwrap(); 249*0583cff8SDavid Pedersen } 250*0583cff8SDavid Pedersen }); 251*0583cff8SDavid Pedersen 252*0583cff8SDavid Pedersen let mut client = test_client::TestClient::new(mock_io_channel(client).await).accept_gzip(); 253*0583cff8SDavid Pedersen 254*0583cff8SDavid Pedersen let res = client.compress_output_unary(()).await.unwrap(); 255*0583cff8SDavid Pedersen assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip"); 256*0583cff8SDavid Pedersen let bytes_sent = response_bytes_counter.load(SeqCst); 257*0583cff8SDavid Pedersen assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE); 258*0583cff8SDavid Pedersen } 259*0583cff8SDavid Pedersen 260*0583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")] 261*0583cff8SDavid Pedersen async fn disabling_compression_on_response_but_keeping_compression_on_stream() { 262*0583cff8SDavid Pedersen let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10); 263*0583cff8SDavid Pedersen 264*0583cff8SDavid Pedersen let svc = test_server::TestServer::new(Svc { 265*0583cff8SDavid Pedersen disable_compressing_on_response: true, 266*0583cff8SDavid Pedersen }) 267*0583cff8SDavid Pedersen .send_gzip(); 268*0583cff8SDavid Pedersen 269*0583cff8SDavid Pedersen let response_bytes_counter = Arc::new(AtomicUsize::new(0)); 270*0583cff8SDavid Pedersen 271*0583cff8SDavid Pedersen tokio::spawn({ 272*0583cff8SDavid Pedersen let response_bytes_counter = response_bytes_counter.clone(); 273*0583cff8SDavid Pedersen async move { 274*0583cff8SDavid Pedersen Server::builder() 275*0583cff8SDavid Pedersen .layer( 276*0583cff8SDavid Pedersen ServiceBuilder::new() 277*0583cff8SDavid Pedersen .layer(MapResponseBodyLayer::new(move |body| { 278*0583cff8SDavid Pedersen util::CountBytesBody { 279*0583cff8SDavid Pedersen inner: body, 280*0583cff8SDavid Pedersen counter: response_bytes_counter.clone(), 281*0583cff8SDavid Pedersen } 282*0583cff8SDavid Pedersen })) 283*0583cff8SDavid Pedersen .into_inner(), 284*0583cff8SDavid Pedersen ) 285*0583cff8SDavid Pedersen .add_service(svc) 286*0583cff8SDavid Pedersen .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>( 287*0583cff8SDavid Pedersen MockStream(server), 288*0583cff8SDavid Pedersen )])) 289*0583cff8SDavid Pedersen .await 290*0583cff8SDavid Pedersen .unwrap(); 291*0583cff8SDavid Pedersen } 292*0583cff8SDavid Pedersen }); 293*0583cff8SDavid Pedersen 294*0583cff8SDavid Pedersen let mut client = test_client::TestClient::new(mock_io_channel(client).await).accept_gzip(); 295*0583cff8SDavid Pedersen 296*0583cff8SDavid Pedersen let res = client.compress_output_server_stream(()).await.unwrap(); 297*0583cff8SDavid Pedersen 298*0583cff8SDavid Pedersen assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip"); 299*0583cff8SDavid Pedersen 300*0583cff8SDavid Pedersen let mut stream: Streaming<SomeData> = res.into_inner(); 301*0583cff8SDavid Pedersen 302*0583cff8SDavid Pedersen stream 303*0583cff8SDavid Pedersen .next() 304*0583cff8SDavid Pedersen .await 305*0583cff8SDavid Pedersen .expect("stream empty") 306*0583cff8SDavid Pedersen .expect("item was error"); 307*0583cff8SDavid Pedersen assert!(response_bytes_counter.load(SeqCst) < UNCOMPRESSED_MIN_BODY_SIZE); 308*0583cff8SDavid Pedersen 309*0583cff8SDavid Pedersen stream 310*0583cff8SDavid Pedersen .next() 311*0583cff8SDavid Pedersen .await 312*0583cff8SDavid Pedersen .expect("stream empty") 313*0583cff8SDavid Pedersen .expect("item was error"); 314*0583cff8SDavid Pedersen assert!(response_bytes_counter.load(SeqCst) < UNCOMPRESSED_MIN_BODY_SIZE); 315*0583cff8SDavid Pedersen } 316*0583cff8SDavid Pedersen 317*0583cff8SDavid Pedersen #[tokio::test(flavor = "multi_thread")] 318*0583cff8SDavid Pedersen async fn disabling_compression_on_response_from_client_stream() { 319*0583cff8SDavid Pedersen let (client, server) = tokio::io::duplex(UNCOMPRESSED_MIN_BODY_SIZE * 10); 320*0583cff8SDavid Pedersen 321*0583cff8SDavid Pedersen let svc = test_server::TestServer::new(Svc { 322*0583cff8SDavid Pedersen disable_compressing_on_response: true, 323*0583cff8SDavid Pedersen }) 324*0583cff8SDavid Pedersen .send_gzip(); 325*0583cff8SDavid Pedersen 326*0583cff8SDavid Pedersen let response_bytes_counter = Arc::new(AtomicUsize::new(0)); 327*0583cff8SDavid Pedersen 328*0583cff8SDavid Pedersen tokio::spawn({ 329*0583cff8SDavid Pedersen let response_bytes_counter = response_bytes_counter.clone(); 330*0583cff8SDavid Pedersen async move { 331*0583cff8SDavid Pedersen Server::builder() 332*0583cff8SDavid Pedersen .layer( 333*0583cff8SDavid Pedersen ServiceBuilder::new() 334*0583cff8SDavid Pedersen .layer(MapResponseBodyLayer::new(move |body| { 335*0583cff8SDavid Pedersen util::CountBytesBody { 336*0583cff8SDavid Pedersen inner: body, 337*0583cff8SDavid Pedersen counter: response_bytes_counter.clone(), 338*0583cff8SDavid Pedersen } 339*0583cff8SDavid Pedersen })) 340*0583cff8SDavid Pedersen .into_inner(), 341*0583cff8SDavid Pedersen ) 342*0583cff8SDavid Pedersen .add_service(svc) 343*0583cff8SDavid Pedersen .serve_with_incoming(futures::stream::iter(vec![Ok::<_, std::io::Error>( 344*0583cff8SDavid Pedersen MockStream(server), 345*0583cff8SDavid Pedersen )])) 346*0583cff8SDavid Pedersen .await 347*0583cff8SDavid Pedersen .unwrap(); 348*0583cff8SDavid Pedersen } 349*0583cff8SDavid Pedersen }); 350*0583cff8SDavid Pedersen 351*0583cff8SDavid Pedersen let mut client = test_client::TestClient::new(mock_io_channel(client).await).accept_gzip(); 352*0583cff8SDavid Pedersen 353*0583cff8SDavid Pedersen let stream = futures::stream::iter(vec![]); 354*0583cff8SDavid Pedersen let req = Request::new(Box::pin(stream)); 355*0583cff8SDavid Pedersen 356*0583cff8SDavid Pedersen let res = client.compress_output_client_stream(req).await.unwrap(); 357*0583cff8SDavid Pedersen assert_eq!(res.metadata().get("grpc-encoding").unwrap(), "gzip"); 358*0583cff8SDavid Pedersen let bytes_sent = response_bytes_counter.load(SeqCst); 359*0583cff8SDavid Pedersen assert!(bytes_sent > UNCOMPRESSED_MIN_BODY_SIZE); 360*0583cff8SDavid Pedersen } 361