shep_core/protocol/
frame.rs1use serde::{Deserialize, Serialize};
12
13use crate::protocol::{BusEvent, Reply};
14
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
23#[serde(untagged)]
24#[non_exhaustive]
27pub enum ServerFrame {
28 Reply(Reply),
30 Event(BusEvent),
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37 use crate::protocol::{
38 BusEvent, ProcessEventKind, ProcessInfo, Reply, Response, RpcError, RpcErrorCode,
39 encode_frame,
40 };
41 use crate::status::ProcStatus;
42
43 fn sample_reply() -> Reply {
44 Reply {
45 id: 7,
46 result: Ok(Response::Pong),
47 }
48 }
49
50 fn sample_event() -> BusEvent {
51 BusEvent::Process {
52 event: ProcessEventKind::Online,
53 info: ProcessInfo {
54 id: 3,
55 name: "web".to_string(),
56 status: ProcStatus::Online,
57 pid: Some(4242),
58 restarts: 0,
59 uptime_ms: 0,
60 fold: None,
61 out_file: Some("/home/ada/.shep/logs/web-0-out.log".to_string()),
62 err_file: Some("/home/ada/.shep/logs/web-0-err.log".to_string()),
63 cpu_percent: None,
64 memory_bytes: None,
65 dog: None,
66 lambs: None,
67 last_exit: None,
68 smit: None,
69 instance: None,
70 handshook: None,
71 },
72 manually: false,
73 at_ms: 1_700_000_000_000,
74 }
75 }
76
77 #[test]
78 fn server_frame_decodes_both_directions_of_the_stream() {
79 let reply = r#"{"id":1,"result":{"Ok":{"kind":"pong"}}}"#;
82 assert!(matches!(
83 serde_json::from_str::<ServerFrame>(reply).unwrap(),
84 ServerFrame::Reply(Reply { id: 1, .. })
85 ));
86 let event = r#"{"event":"log_out","data":{"id":3,"line":"ready"}}"#;
87 assert!(matches!(
88 serde_json::from_str::<ServerFrame>(event).unwrap(),
89 ServerFrame::Event(BusEvent::LogOut { id: 3, .. })
90 ));
91 }
92
93 #[test]
94 fn server_frame_is_byte_identical_to_its_payload() {
95 let reply = sample_reply();
98 assert_eq!(
99 encode_frame(&ServerFrame::Reply(reply.clone())).unwrap(),
100 encode_frame(&reply).unwrap()
101 );
102 let event = sample_event();
103 assert_eq!(
104 encode_frame(&ServerFrame::Event(event.clone())).unwrap(),
105 encode_frame(&event).unwrap()
106 );
107 }
108
109 #[test]
110 fn an_error_reply_still_decodes_as_a_reply_frame() {
111 let err = Reply {
112 id: 2,
113 result: Err(RpcError {
114 code: RpcErrorCode::DeadlineExceeded,
115 message: "request deadline of 5000 ms expired".to_string(),
116 daemon_version: None,
117 }),
118 };
119 let json = serde_json::to_string(&err).unwrap();
120 assert_eq!(
121 serde_json::from_str::<ServerFrame>(&json).unwrap(),
122 ServerFrame::Reply(err)
123 );
124 }
125}