refactor(tests): share one soulfind fixture across the e2e suites
The TUI suite had grown its own copy of the soulfind spawner the protocol suite already carried, and its own copy of the CLI suite's in-process client and settle helpers. All four suites now spawn, log in, settle and skip through `tests/common`: the CLI suite's own server goes too, and the fixture checks its child is still alive before calling the port answered, so a lost port cannot pass another server off as ours.
This commit is contained in:
@@ -11,8 +11,8 @@
|
||||
|
||||
mod common;
|
||||
|
||||
use common::{CLI_ENV_VARS, free_port, soulfind_binary};
|
||||
use soulseek_rs::{Client, ClientSettings, PeerAddress};
|
||||
use common::{CLI_ENV_VARS, Soulfind, free_port, login, settle};
|
||||
use soulseek_rs::Client;
|
||||
use std::io::Write;
|
||||
use std::net::{TcpStream, ToSocketAddrs};
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -508,8 +508,9 @@ static SERVER_GATE: std::sync::Mutex<()> = std::sync::Mutex::new(());
|
||||
struct TestServer {
|
||||
host: String,
|
||||
port: u16,
|
||||
child: Option<Child>,
|
||||
db: Option<PathBuf>,
|
||||
/// The soulfind spawned for this run; `None` against a server named by
|
||||
/// `SOULSEEK_TEST_SERVER`.
|
||||
_server: Option<Soulfind>,
|
||||
_gate: std::sync::MutexGuard<'static, ()>,
|
||||
/// Daemons started for this server, one per (user, session flags). Dropped
|
||||
/// with the server, which kills them.
|
||||
@@ -640,41 +641,17 @@ impl TestServer {
|
||||
return Some(Self {
|
||||
host: host.to_string(),
|
||||
port,
|
||||
child: None,
|
||||
db: None,
|
||||
_server: None,
|
||||
_gate: gate,
|
||||
daemons: std::sync::Mutex::new(std::collections::HashMap::new()),
|
||||
});
|
||||
}
|
||||
|
||||
let bin = soulfind_binary()?;
|
||||
let port = free_port()?;
|
||||
let db = std::env::temp_dir().join(format!("soulfind-cli-{port}.db"));
|
||||
let _ = std::fs::remove_file(&db);
|
||||
|
||||
let mut child = Command::new(&bin)
|
||||
.arg("-p")
|
||||
.arg(port.to_string())
|
||||
.arg("-d")
|
||||
.arg(&db)
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn()
|
||||
.ok()?;
|
||||
|
||||
if wait_until_listening("127.0.0.1", port, Duration::from_secs(5))
|
||||
.is_none()
|
||||
{
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
return None;
|
||||
}
|
||||
|
||||
let server = Soulfind::start()?;
|
||||
Some(Self {
|
||||
host: "127.0.0.1".to_string(),
|
||||
port,
|
||||
child: Some(child),
|
||||
db: Some(db),
|
||||
port: server.port(),
|
||||
_server: Some(server),
|
||||
_gate: gate,
|
||||
daemons: std::sync::Mutex::new(std::collections::HashMap::new()),
|
||||
})
|
||||
@@ -777,31 +754,7 @@ impl TestServer {
|
||||
|
||||
/// An in-process client, used to stand up the other end of a test.
|
||||
fn client(&self, user: &str, shares: Vec<String>) -> Client {
|
||||
let port = free_port().expect("peer port");
|
||||
let mut client = Client::with_settings(ClientSettings {
|
||||
username: user.to_string(),
|
||||
password: "pw".to_string(),
|
||||
server_address: PeerAddress::new(self.host.clone(), self.port),
|
||||
enable_listen: true,
|
||||
listen_port: port,
|
||||
shared_directories: shares,
|
||||
version: soulseek_rs::ClientVersion::default(),
|
||||
});
|
||||
client.connect().expect("peer connect");
|
||||
assert!(client.login().expect("peer login"), "peer should log in");
|
||||
client
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TestServer {
|
||||
fn drop(&mut self) {
|
||||
if let Some(child) = self.child.as_mut() {
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
}
|
||||
if let Some(db) = self.db.as_ref() {
|
||||
let _ = std::fs::remove_file(db);
|
||||
}
|
||||
login(&self.host, self.port, user, shares)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,17 +782,7 @@ macro_rules! server_or_skip {
|
||||
match TestServer::resolve() {
|
||||
Some(server) => server,
|
||||
None => {
|
||||
let required = std::env::var("SOULSEEK_E2E_REQUIRED")
|
||||
.is_ok_and(|v| v != "0" && !v.is_empty());
|
||||
assert!(
|
||||
!required,
|
||||
"SOULSEEK_E2E_REQUIRED is set but no soulfind server could \
|
||||
be started (set SOULFIND_BIN or SOULSEEK_TEST_SERVER)"
|
||||
);
|
||||
println!(
|
||||
"cli e2e skipped: no soulfind server (set SOULFIND_BIN or \
|
||||
SOULSEEK_TEST_SERVER to run)"
|
||||
);
|
||||
common::no_server("cli e2e");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -936,11 +879,6 @@ fn split_session_flags(args: &[&str]) -> (Vec<String>, Vec<String>) {
|
||||
(session, command)
|
||||
}
|
||||
|
||||
/// Wait out the SetWaitPort registrations so peer lookups resolve.
|
||||
fn settle() {
|
||||
std::thread::sleep(Duration::from_secs(1));
|
||||
}
|
||||
|
||||
/// Like [`cli`], but keeping a config file so a command that reads or writes
|
||||
/// one (the wishlist) sees it.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user