the port-bind test no longer loses its released port to other sockets
This commit is contained in:
parent
daf38e4c55
commit
c6d26a0904
1 changed files with 19 additions and 2 deletions
|
|
@ -486,10 +486,27 @@ mod tests {
|
||||||
use crate::events::Bus;
|
use crate::events::Bus;
|
||||||
use crate::login::LoginState;
|
use crate::login::LoginState;
|
||||||
|
|
||||||
/// A port another listener holds for a moment is waited out.
|
/// Hold a loopback port just below the kernel's ephemeral range. Once the
|
||||||
|
/// holder drops, nothing that binds `:0` or connects outward can take the
|
||||||
|
/// port, and the pid offset keeps concurrent test processes apart.
|
||||||
|
fn hold_port_below_ephemeral_range() -> tokio::net::TcpListener {
|
||||||
|
let low = std::fs::read_to_string("/proc/sys/net/ipv4/ip_local_port_range")
|
||||||
|
.ok()
|
||||||
|
.and_then(|s| s.split_whitespace().next()?.parse::<u16>().ok())
|
||||||
|
.unwrap_or(32768);
|
||||||
|
let start = low.saturating_sub(1 + (std::process::id() % 2000) as u16);
|
||||||
|
(1024..=start)
|
||||||
|
.rev()
|
||||||
|
.find_map(|port| try_bind(([127, 0, 0, 1], port).into()).ok())
|
||||||
|
.expect("a free port below the ephemeral range")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A port another listener holds for a moment is waited out. The paused
|
||||||
|
/// clock runs all retries in microseconds of real time, so the port must
|
||||||
|
/// not be one the kernel hands to other sockets once released.
|
||||||
#[tokio::test(start_paused = true)]
|
#[tokio::test(start_paused = true)]
|
||||||
async fn bind_waits_out_a_port_that_is_briefly_held() {
|
async fn bind_waits_out_a_port_that_is_briefly_held() {
|
||||||
let holder = try_bind("127.0.0.1:0".parse().expect("addr")).expect("holder");
|
let holder = hold_port_below_ephemeral_range();
|
||||||
let addr = holder.local_addr().expect("local addr");
|
let addr = holder.local_addr().expect("local addr");
|
||||||
let release = tokio::spawn(async move {
|
let release = tokio::spawn(async move {
|
||||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue