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