test(daemon): match a reply by its id instead of taking the next line

A connection that has joined a room receives event notifications on the
same socket as its replies, so a notification landing between a request
and its answer was read as the answer. Only replies carry an id.
This commit is contained in:
Michel de Graaf
2026-07-29 10:37:48 +02:00
parent ab5cef8cfe
commit 30698aa7ce
2 changed files with 17 additions and 1 deletions
+4
View File
@@ -0,0 +1,4 @@
# Generated and compared byte-for-byte by `daemon::openrpc::document_is_current`,
# which builds its expectation with `\n`. A CRLF checkout would fail that test on
# Windows.
docs/openrpc.json text eol=lf
+13 -1
View File
@@ -158,9 +158,21 @@ impl Connection {
} }
/// Send one line and read the reply, `None` if the daemon hung up first. /// Send one line and read the reply, `None` if the daemon hung up first.
///
/// Events share the socket with replies, so a subscribed connection can
/// have a notification land between the request and its answer. Only a
/// reply carries an `id`; skip everything that does not.
fn call(&mut self, line: &str) -> Option<String> { fn call(&mut self, line: &str) -> Option<String> {
self.send(line)?; self.send(line)?;
self.read() loop {
let reply = self.read()?;
let is_notification =
serde_json::from_str::<serde_json::Value>(&reply)
.is_ok_and(|parsed| parsed.get("id").is_none());
if !is_notification {
return Some(reply);
}
}
} }
fn send(&mut self, line: &str) -> Option<()> { fn send(&mut self, line: &str) -> Option<()> {