tests(cli): prevent request send test teardown hang (#408)

This commit is contained in:
Gregory Schier
2026-02-26 08:58:13 -08:00
committed by GitHub
parent ffc80d234c
commit 3a6630a14d
4 changed files with 40 additions and 18 deletions

View File

@@ -1,9 +1,14 @@
use std::io::{Read, Write};
use std::net::TcpListener;
use std::net::{SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
pub struct TestHttpServer {
pub url: String,
addr: SocketAddr,
shutdown: Arc<AtomicBool>,
handle: Option<thread::JoinHandle<()>>,
}
@@ -12,29 +17,46 @@ impl TestHttpServer {
let listener = TcpListener::bind("127.0.0.1:0").expect("Failed to bind test HTTP server");
let addr = listener.local_addr().expect("Failed to get local addr");
let url = format!("http://{addr}/test");
listener.set_nonblocking(true).expect("Failed to set test server listener nonblocking");
let shutdown = Arc::new(AtomicBool::new(false));
let shutdown_signal = Arc::clone(&shutdown);
let body_bytes = body.as_bytes().to_vec();
let handle = thread::spawn(move || {
if let Ok((mut stream, _)) = listener.accept() {
let mut request_buf = [0u8; 4096];
let _ = stream.read(&mut request_buf);
while !shutdown_signal.load(Ordering::Relaxed) {
match listener.accept() {
Ok((mut stream, _)) => {
let _ = stream.set_read_timeout(Some(Duration::from_secs(1)));
let mut request_buf = [0u8; 4096];
let _ = stream.read(&mut request_buf);
let response = format!(
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: {}\r\nConnection: close\r\n\r\n",
body_bytes.len()
);
let _ = stream.write_all(response.as_bytes());
let _ = stream.write_all(&body_bytes);
let _ = stream.flush();
let response = format!(
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: {}\r\nConnection: close\r\n\r\n",
body_bytes.len()
);
let _ = stream.write_all(response.as_bytes());
let _ = stream.write_all(&body_bytes);
let _ = stream.flush();
break;
}
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
thread::sleep(Duration::from_millis(10));
}
Err(_) => break,
}
}
});
Self { url, handle: Some(handle) }
Self { url, addr, shutdown, handle: Some(handle) }
}
}
impl Drop for TestHttpServer {
fn drop(&mut self) {
self.shutdown.store(true, Ordering::Relaxed);
let _ = TcpStream::connect(self.addr);
if let Some(handle) = self.handle.take() {
let _ = handle.join();
}