133 lines
4.5 KiB
Rust
133 lines
4.5 KiB
Rust
//! How long `BrokerPort` waits for `brokerd`, per tool: `[broker] timeout_ms` for every tool but
|
|
//! `ask_memory`, which waits 180 s or the timeout, whichever is longer (M5c spec, sections 9 and
|
|
//! 11). `with_ask_wait` shortens the wait here, so no test waits long. Do not edit.
|
|
|
|
#[path = "support/broker.rs"]
|
|
mod fake;
|
|
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
|
|
use bxcore::{ToolRequest, ToolResponse};
|
|
use fake::{broker, in_ms, request, result, send};
|
|
use loopd::broker_port::{ASK_MEMORY_WAIT, BrokerPort, UNAVAILABLE};
|
|
use loopd::tools::ToolPort;
|
|
|
|
/// How long the slow fake `brokerd` takes to answer.
|
|
const SLOW: Duration = Duration::from_millis(1_500);
|
|
/// A wait shorter than `SLOW`, and one far longer.
|
|
const SHORT: Duration = Duration::from_millis(300);
|
|
const LONG: Duration = Duration::from_secs(20);
|
|
|
|
fn ask_memory() -> ToolRequest {
|
|
ToolRequest {
|
|
tool: "ask_memory".to_string(),
|
|
arguments: r#"{"question":"What does the owner prefer?"}"#.to_string(),
|
|
..request()
|
|
}
|
|
}
|
|
|
|
fn recall() -> ToolRequest {
|
|
ToolRequest {
|
|
tool: "recall".to_string(),
|
|
arguments: r#"{"query":"owner"}"#.to_string(),
|
|
..request()
|
|
}
|
|
}
|
|
|
|
/// One call of `req`, through a port with `timeout` and an `ask_memory` wait of `ask_wait`, to a
|
|
/// fake `brokerd` that answers after `SLOW`, optionally after a pending frame that expires at once.
|
|
fn slow_call(
|
|
timeout: Duration,
|
|
ask_wait: Duration,
|
|
req: &ToolRequest,
|
|
pending_first: bool,
|
|
) -> ToolResponse {
|
|
let (socket, broker) = broker(move |stream, request| {
|
|
if pending_first {
|
|
let pending = ToolResponse::PendingApproval {
|
|
approval: 3,
|
|
expires: in_ms(50),
|
|
};
|
|
send(stream, request.id, false, pending);
|
|
}
|
|
thread::sleep(SLOW);
|
|
send(stream, request.id, true, result("the answer"));
|
|
});
|
|
let port = BrokerPort::with_log(socket, timeout, Box::new(|_| {})).with_ask_wait(ask_wait);
|
|
let response = port.call(req, &mut |_| {});
|
|
broker.join().unwrap();
|
|
response
|
|
}
|
|
|
|
fn quiet(timeout: Duration) -> BrokerPort {
|
|
BrokerPort::with_log("unused.sock".into(), timeout, Box::new(|_| {}))
|
|
}
|
|
|
|
fn unavailable() -> ToolResponse {
|
|
ToolResponse::Failed {
|
|
message: UNAVAILABLE.to_string(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn the_wait_for_each_tool() {
|
|
assert_eq!(ASK_MEMORY_WAIT, Duration::from_secs(180));
|
|
let port = BrokerPort::new("unused.sock".into(), Duration::from_secs(120));
|
|
assert_eq!(port.timeout_for("ask_memory"), ASK_MEMORY_WAIT);
|
|
for tool in ["recall", "memory", "read_file", "shell", "clock", "ask"] {
|
|
assert_eq!(port.timeout_for(tool), Duration::from_secs(120), "{tool}");
|
|
}
|
|
// A configured timeout longer than 180 s is kept for ask_memory too.
|
|
let port = BrokerPort::new("unused.sock".into(), Duration::from_secs(300));
|
|
assert_eq!(port.timeout_for("ask_memory"), Duration::from_secs(300));
|
|
let port = quiet(Duration::from_secs(120));
|
|
assert_eq!(
|
|
port.timeout_for("ask_memory"),
|
|
ASK_MEMORY_WAIT,
|
|
"with_log as new"
|
|
);
|
|
assert_eq!(port.timeout_for("recall"), Duration::from_secs(120));
|
|
let port = quiet(SHORT).with_ask_wait(LONG);
|
|
assert_eq!(port.timeout_for("ask_memory"), LONG);
|
|
assert_eq!(port.timeout_for("recall"), SHORT);
|
|
let port = quiet(LONG).with_ask_wait(SHORT);
|
|
assert_eq!(
|
|
port.timeout_for("ask_memory"),
|
|
LONG,
|
|
"the longer of the two"
|
|
);
|
|
}
|
|
|
|
/// A slow answer reaches `ask_memory`, whose wait is long, and not `recall` or `read_file`,
|
|
/// which have the short timeout.
|
|
#[test]
|
|
fn a_slow_answer_reaches_ask_memory_only() {
|
|
assert_eq!(
|
|
slow_call(SHORT, LONG, &ask_memory(), false),
|
|
result("the answer")
|
|
);
|
|
assert_eq!(slow_call(SHORT, LONG, &recall(), false), unavailable());
|
|
assert_eq!(slow_call(SHORT, LONG, &request(), false), unavailable());
|
|
}
|
|
|
|
/// With a longer timeout than `ask_memory`'s own wait, `ask_memory` waits the timeout.
|
|
#[test]
|
|
fn a_longer_timeout_is_kept_for_ask_memory() {
|
|
assert_eq!(
|
|
slow_call(LONG, SHORT, &ask_memory(), false),
|
|
result("the answer")
|
|
);
|
|
}
|
|
|
|
/// After a pending frame, the port waits for the expiry plus the call's own wait: for
|
|
/// `ask_memory`, its long wait, not the short timeout.
|
|
#[test]
|
|
fn after_a_pending_frame_ask_memory_keeps_its_wait() {
|
|
assert_eq!(
|
|
slow_call(SHORT, LONG, &ask_memory(), true),
|
|
result("the answer")
|
|
);
|
|
assert_eq!(slow_call(SHORT, LONG, &recall(), true), unavailable());
|
|
}
|