test: wait for complete isolated server address records
This commit is contained in:
@@ -974,10 +974,18 @@ impl ManagedProcess {
|
|||||||
fn wait_for_address(&self, marker: &str, timeout: Duration) -> Result<String> {
|
fn wait_for_address(&self, marker: &str, timeout: Duration) -> Result<String> {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
loop {
|
loop {
|
||||||
let output = self.output();
|
// stdout/stderrの結合で補った改行をready記録と誤認しない。
|
||||||
if let Some(address) = parse_address_after(&output, marker) {
|
// readerが受信した各streamの完全な行だけを判定する。
|
||||||
|
let address = [&self.stdout, &self.stderr]
|
||||||
|
.into_iter()
|
||||||
|
.find_map(|capture| {
|
||||||
|
let bytes = capture.lock().ok()?;
|
||||||
|
parse_address_after(&String::from_utf8_lossy(&bytes), marker)
|
||||||
|
});
|
||||||
|
if let Some(address) = address {
|
||||||
return Ok(address);
|
return Ok(address);
|
||||||
}
|
}
|
||||||
|
let output = self.output();
|
||||||
if start.elapsed() >= timeout {
|
if start.elapsed() >= timeout {
|
||||||
return Err(HarnessError::Protocol(format!(
|
return Err(HarnessError::Protocol(format!(
|
||||||
"timed out waiting for {} address after {marker:?}; bounded output: {}",
|
"timed out waiting for {} address after {marker:?}; bounded output: {}",
|
||||||
@@ -1106,14 +1114,22 @@ fn capture_stream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_address_after(output: &str, marker: &str) -> Option<String> {
|
fn parse_address_after(output: &str, marker: &str) -> Option<String> {
|
||||||
let rest = output.split(marker).nth(1)?;
|
output
|
||||||
let address = rest
|
.split_inclusive('\n')
|
||||||
.trim_start()
|
.filter(|line| line.ends_with('\n'))
|
||||||
.split(|character: char| character.is_whitespace() || character == ';' || character == '`')
|
.find_map(|line| {
|
||||||
.next()?
|
let rest = line.split_once(marker)?.1;
|
||||||
.trim_start_matches("http://")
|
let address = rest
|
||||||
.trim_end_matches('/');
|
.trim_start()
|
||||||
(!address.is_empty()).then(|| address.to_string())
|
.split(|character: char| {
|
||||||
|
character.is_whitespace() || character == ';' || character == '`'
|
||||||
|
})
|
||||||
|
.next()?
|
||||||
|
.trim_start_matches("http://")
|
||||||
|
.trim_end_matches('/');
|
||||||
|
let socket: std::net::SocketAddr = address.parse().ok()?;
|
||||||
|
(socket.port() != 0).then(|| address.to_string())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_absent_or_empty(path: &Path, label: &str) -> Result<()> {
|
fn assert_absent_or_empty(path: &Path, label: &str) -> Result<()> {
|
||||||
@@ -1156,3 +1172,36 @@ fn bounded_text(bytes: &[u8], limit: usize) -> String {
|
|||||||
fn io_error(operation: &str, error: std::io::Error) -> HarnessError {
|
fn io_error(operation: &str, error: std::io::Error) -> HarnessError {
|
||||||
HarnessError::Protocol(format!("{operation}: {error}"))
|
HarnessError::Protocol(format!("{operation}: {error}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod startup_address_tests {
|
||||||
|
use super::parse_address_after;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn startup_address_waits_for_complete_valid_socket_record() {
|
||||||
|
let record = "yoi-server listening on http://127.0.0.1:49123\n";
|
||||||
|
for boundary in 0..record.len() {
|
||||||
|
assert_eq!(parse_address_after(&record[..boundary], "on http://"), None);
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
parse_address_after(record, "on http://").as_deref(),
|
||||||
|
Some("127.0.0.1:49123")
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_address_after("on http://[::1]:12345\n", "on http://").as_deref(),
|
||||||
|
Some("[::1]:12345")
|
||||||
|
);
|
||||||
|
for invalid in [
|
||||||
|
"127",
|
||||||
|
"127.0.0.1",
|
||||||
|
"127.0.0.1:0",
|
||||||
|
"hostname:123",
|
||||||
|
"127.0.0.1:99999",
|
||||||
|
] {
|
||||||
|
assert_eq!(
|
||||||
|
parse_address_after(&format!("on http://{invalid}\n"), "on http://"),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user