use folk_core::runtime::{Runtime, WorkerHandle};
use folk_protocol::RpcMessage;
use folk_runtime_embed::{EmbedConfig, EmbedRuntime};
use rmpv::Value;
fn make_runtime(script: Option<&str>) -> EmbedRuntime {
EmbedRuntime::new(EmbedConfig {
script: script.map(String::from),
})
.expect("failed to init embed runtime")
}
#[tokio::test]
async fn worker_boots_and_sends_ready() {
let runtime = make_runtime(None);
let mut handle = runtime.spawn().await.expect("spawn failed");
let msg = handle
.recv_control()
.await
.expect("recv_control failed")
.expect("expected control.ready");
match &msg {
RpcMessage::Notify { method, .. } => {
assert_eq!(method, "control.ready");
},
_ => panic!("expected Notify, got {msg:?}"),
}
handle.terminate().await.expect("terminate failed");
}
#[tokio::test]
async fn worker_echo_dispatch() {
let runtime = make_runtime(None);
let mut handle = runtime.spawn().await.expect("spawn failed");
let _ = handle.recv_control().await.unwrap().unwrap();
let params = Value::Map(vec![(
Value::String("key".into()),
Value::String("value".into()),
)]);
let request = RpcMessage::request(1, "test.echo", params.clone());
handle.send_task(request).await.expect("send failed");
let response = handle
.recv_task()
.await
.expect("recv failed")
.expect("expected response");
match response {
RpcMessage::Response {
msgid,
error,
result,
} => {
assert_eq!(msgid, 1);
assert!(error.is_nil(), "unexpected error: {error:?}");
assert_eq!(result, params);
},
_ => panic!("expected Response, got {response:?}"),
}
handle.terminate().await.expect("terminate failed");
}
#[tokio::test]
async fn multiple_workers_concurrent() {
let runtime = make_runtime(None);
let mut handles: Vec<Box<dyn WorkerHandle>> = Vec::new();
for _ in 0..4 {
let mut h = runtime.spawn().await.expect("spawn failed");
let _ = h.recv_control().await.unwrap().unwrap();
handles.push(h);
}
for (i, h) in handles.iter_mut().enumerate() {
let request = RpcMessage::request(
i as u32 + 1,
"test",
Value::String(format!("worker-{i}").into()),
);
h.send_task(request).await.expect("send failed");
}
for (i, h) in handles.iter_mut().enumerate() {
let resp = h.recv_task().await.unwrap().unwrap();
match resp {
RpcMessage::Response { msgid, .. } => {
assert_eq!(msgid, i as u32 + 1);
},
_ => panic!("expected Response"),
}
}
for h in &mut handles {
h.terminate().await.expect("terminate failed");
}
}
#[tokio::test]
async fn worker_handles_multiple_requests() {
let runtime = make_runtime(None);
let mut handle = runtime.spawn().await.expect("spawn failed");
let _ = handle.recv_control().await.unwrap().unwrap();
for i in 0..100 {
let request = RpcMessage::request(i, "test", Value::Integer(i.into()));
handle.send_task(request).await.expect("send failed");
let resp = handle.recv_task().await.unwrap().unwrap();
match resp {
RpcMessage::Response { msgid, .. } => assert_eq!(msgid, i),
_ => panic!("expected Response"),
}
}
handle.terminate().await.expect("terminate failed");
}