use serde::{Deserialize, Serialize};
use crate::protocol::{BusEvent, Reply};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
#[non_exhaustive]
pub enum ServerFrame {
Reply(Reply),
Event(BusEvent),
}
#[cfg(test)]
mod tests {
use super::*;
use crate::protocol::{
BusEvent, ProcessEventKind, ProcessInfo, Reply, Response, RpcError, RpcErrorCode,
encode_frame,
};
use crate::status::ProcStatus;
fn sample_reply() -> Reply {
Reply {
id: 7,
result: Ok(Response::Pong),
}
}
fn sample_event() -> BusEvent {
BusEvent::Process {
event: ProcessEventKind::Online,
info: ProcessInfo {
id: 3,
name: "web".to_string(),
status: ProcStatus::Online,
pid: Some(4242),
restarts: 0,
uptime_ms: 0,
fold: None,
out_file: Some("/home/ada/.shep/logs/web-0-out.log".to_string()),
err_file: Some("/home/ada/.shep/logs/web-0-err.log".to_string()),
cpu_percent: None,
memory_bytes: None,
dog: None,
lambs: None,
last_exit: None,
smit: None,
instance: None,
handshook: None,
dog_stale: None,
pending: None,
overridden: None,
},
manually: false,
at_ms: 1_700_000_000_000,
}
}
#[test]
fn server_frame_decodes_both_directions_of_the_stream() {
let reply = r#"{"id":1,"result":{"Ok":{"kind":"pong"}}}"#;
assert!(matches!(
serde_json::from_str::<ServerFrame>(reply).unwrap(),
ServerFrame::Reply(Reply { id: 1, .. })
));
let event = r#"{"event":"log_out","data":{"id":3,"line":"ready"}}"#;
assert!(matches!(
serde_json::from_str::<ServerFrame>(event).unwrap(),
ServerFrame::Event(BusEvent::LogOut { id: 3, .. })
));
}
#[test]
fn server_frame_is_byte_identical_to_its_payload() {
let reply = sample_reply();
assert_eq!(
encode_frame(&ServerFrame::Reply(reply.clone())).unwrap(),
encode_frame(&reply).unwrap()
);
let event = sample_event();
assert_eq!(
encode_frame(&ServerFrame::Event(event.clone())).unwrap(),
encode_frame(&event).unwrap()
);
}
#[test]
fn an_error_reply_still_decodes_as_a_reply_frame() {
let err = Reply {
id: 2,
result: Err(RpcError {
code: RpcErrorCode::DeadlineExceeded,
message: "request deadline of 5000 ms expired".to_string(),
daemon_version: None,
}),
};
let json = serde_json::to_string(&err).unwrap();
assert_eq!(
serde_json::from_str::<ServerFrame>(&json).unwrap(),
ServerFrame::Reply(err)
);
}
}