test(e2e): give a soulfind that dies on startup a fresh port
free_port() hands out a port that is free when asked, not when soulfind binds it, and soulfind exits when the port has gone. The library harness also gave soulfind only five seconds and did not notice a child that had died, so either read as "no soulfind server" and failed the test. It now waits ten seconds like the CLI harness, never takes a child that has exited as up, and retries on a fresh port; the CLI harness gets the same retry. A listener that takes the port first can still answer before soulfind has got as far as binding, so the two library tests that bind listeners outside the server gate now take it too: while a soulfind starts, no other test in that binary binds anything.
This commit is contained in:
@@ -60,12 +60,16 @@ pub struct Soulfind {
|
||||
}
|
||||
|
||||
impl Soulfind {
|
||||
/// soulfind exits if its port is taken between `free_port()` handing it
|
||||
/// out and soulfind binding it, so a start that fails gets a fresh port.
|
||||
pub fn start() -> Option<Self> {
|
||||
let port = free_port()?;
|
||||
let db = std::env::temp_dir().join(format!("soulfind-{port}.db"));
|
||||
let _ = std::fs::remove_file(&db);
|
||||
let child = Self::spawn(port, &db)?;
|
||||
Some(Self { child, db, port })
|
||||
(0..3).find_map(|_| {
|
||||
let port = free_port()?;
|
||||
let db = std::env::temp_dir().join(format!("soulfind-{port}.db"));
|
||||
let _ = std::fs::remove_file(&db);
|
||||
let child = Self::spawn(port, &db)?;
|
||||
Some(Self { child, db, port })
|
||||
})
|
||||
}
|
||||
|
||||
fn spawn(port: u16, db: &Path) -> Option<Child> {
|
||||
@@ -78,8 +82,8 @@ impl Soulfind {
|
||||
|
||||
let deadline = Instant::now() + Duration::from_secs(10);
|
||||
while Instant::now() < deadline {
|
||||
// Whoever answers on the port has to be this child: one that
|
||||
// lost the port and died would otherwise pass as up.
|
||||
// A child that has exited is never taken as up: soulfind exits
|
||||
// when its port is gone, and whoever took it may answer instead.
|
||||
if child.try_wait().ok().flatten().is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user