tests_integration/grpc/
network.rs1#[cfg(test)]
17#[allow(deprecated)]
18mod tests {
19 use std::io;
20 use std::pin::Pin;
21 use std::task::{Context, Poll};
22 use std::time::Duration;
23
24 use client::Client;
25 use common_grpc::channel_manager::ChannelManager;
26 use futures_util::future::BoxFuture;
27 use http::Uri;
28 use hyper_util::rt::TokioIo;
29 use servers::grpc::GrpcServerConfig;
30 use servers::server::Server;
31 use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
32 use tokio::net::TcpStream;
33 use tokio::sync::mpsc;
34 use tower::Service;
35
36 use crate::test_util::{StorageType, setup_grpc_server_with};
37
38 struct NetworkTrafficMonitorableConnector {
39 interested_tx: mpsc::Sender<String>,
40 }
41
42 impl Service<Uri> for NetworkTrafficMonitorableConnector {
43 type Response = TokioIo<CollectGrpcResponseFrameTypeStream>;
44 type Error = String;
45 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
46
47 fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
48 Poll::Ready(Ok(()))
49 }
50
51 fn call(&mut self, uri: Uri) -> Self::Future {
52 let frame_types = self.interested_tx.clone();
53
54 Box::pin(async move {
55 let addr = format!(
56 "{}:{}",
57 uri.host().unwrap_or("localhost"),
58 uri.port_u16().unwrap_or(4001),
59 );
60 let inner = TcpStream::connect(addr).await.map_err(|e| e.to_string())?;
61 Ok(TokioIo::new(CollectGrpcResponseFrameTypeStream {
62 inner,
63 frame_types,
64 }))
65 })
66 }
67 }
68
69 struct CollectGrpcResponseFrameTypeStream {
70 inner: TcpStream,
71 frame_types: mpsc::Sender<String>,
72 }
73
74 impl AsyncRead for CollectGrpcResponseFrameTypeStream {
75 fn poll_read(
76 mut self: Pin<&mut Self>,
77 cx: &mut Context<'_>,
78 buf: &mut ReadBuf<'_>,
79 ) -> Poll<io::Result<()>> {
80 let before_len = buf.filled().len();
81
82 let result = Pin::new(&mut self.inner).poll_read(cx, buf);
83 if let Poll::Ready(Ok(())) = &result {
84 let after_len = buf.filled().len();
85
86 let new_data = &buf.filled()[before_len..after_len];
87 if let Some(frame_type) = maybe_decode_frame_type(new_data)
88 && let Err(_) = self.frame_types.try_send(frame_type.to_string())
89 {
90 return Poll::Ready(Err(io::Error::other("interested party has gone")));
91 }
92 }
93 result
94 }
95 }
96
97 fn maybe_decode_frame_type(data: &[u8]) -> Option<&str> {
98 (data.len() >= 9).then(|| match data[3] {
99 0x0 => "DATA",
100 0x1 => "HEADERS",
101 0x2 => "PRIORITY",
102 0x3 => "RST_STREAM",
103 0x4 => "SETTINGS",
104 0x5 => "PUSH_PROMISE",
105 0x6 => "PING",
106 0x7 => "GOAWAY",
107 0x8 => "WINDOW_UPDATE",
108 0x9 => "CONTINUATION",
109 _ => "UNKNOWN",
110 })
111 }
112
113 impl AsyncWrite for CollectGrpcResponseFrameTypeStream {
114 fn poll_write(
115 mut self: Pin<&mut Self>,
116 cx: &mut Context<'_>,
117 buf: &[u8],
118 ) -> Poll<Result<usize, io::Error>> {
119 Pin::new(&mut self.inner).poll_write(cx, buf)
120 }
121
122 fn poll_flush(
123 mut self: Pin<&mut Self>,
124 cx: &mut Context<'_>,
125 ) -> Poll<Result<(), io::Error>> {
126 Pin::new(&mut self.inner).poll_flush(cx)
127 }
128
129 fn poll_shutdown(
130 mut self: Pin<&mut Self>,
131 cx: &mut Context<'_>,
132 ) -> Poll<Result<(), io::Error>> {
133 Pin::new(&mut self.inner).poll_shutdown(cx)
134 }
135 }
136
137 #[tokio::test(flavor = "multi_thread", worker_threads = 4)]
138 async fn test_grpc_max_connection_age() {
139 let config = GrpcServerConfig {
140 max_connection_age: Some(Duration::from_secs(1)),
141 ..Default::default()
142 };
143 let (_db, server) = setup_grpc_server_with(
144 StorageType::File,
145 "test_grpc_max_connection_age",
146 None,
147 Some(config),
148 None,
149 )
150 .await;
151 let addr = server.bind_addr().unwrap().to_string();
152
153 let channel_manager = ChannelManager::new();
154 let client = Client::with_manager_and_urls(channel_manager.clone(), vec![&addr]);
155
156 let (tx, mut rx) = mpsc::channel(1024);
157 channel_manager
158 .reset_with_connector(
159 &addr,
160 NetworkTrafficMonitorableConnector { interested_tx: tx },
161 )
162 .unwrap();
163
164 let recv = tokio::spawn(async move {
165 let sleep = tokio::time::sleep(Duration::from_secs(3));
166 tokio::pin!(sleep);
167
168 let mut frame_types = vec![];
169 loop {
170 tokio::select! {
171 x = rx.recv() => {
172 if let Some(x) = x {
173 frame_types.push(x);
174 } else {
175 break;
176 }
177 }
178 _ = &mut sleep => {
179 break;
180 }
181 }
182 }
183 frame_types
184 });
185
186 let _ = client.health_check().await;
188
189 let frame_types = recv.await.unwrap();
190 assert!(
192 frame_types.iter().any(|x| x == "GOAWAY"),
193 "{:?}",
194 frame_types
195 );
196
197 server.shutdown().await.unwrap();
198 }
199}