Skip to main content

mxr_protocol/
lib.rs

1mod codec;
2mod types;
3
4pub use codec::IpcCodec;
5pub use types::*;
6
7#[cfg(test)]
8mod tests {
9    use super::*;
10    use bytes::BytesMut;
11    use mxr_core::id::*;
12    use tokio_util::codec::{Decoder, Encoder};
13
14    #[test]
15    fn request_serde_roundtrip() {
16        let variants: Vec<Request> = vec![
17            Request::Ping,
18            Request::Shutdown,
19            Request::ListEnvelopes {
20                label_id: None,
21                account_id: None,
22                limit: 50,
23                offset: 0,
24            },
25            Request::GetEnvelope {
26                message_id: MessageId::new(),
27            },
28            Request::Search {
29                query: "test".to_string(),
30                limit: 10,
31                mode: None,
32                explain: false,
33            },
34        ];
35
36        for req in variants {
37            let msg = IpcMessage {
38                id: 1,
39                payload: IpcPayload::Request(req),
40            };
41            let json = serde_json::to_string(&msg).unwrap();
42            let parsed: IpcMessage = serde_json::from_str(&json).unwrap();
43            assert_eq!(parsed.id, 1);
44        }
45    }
46
47    #[test]
48    fn response_serde_roundtrip() {
49        let ok = Response::Ok {
50            data: ResponseData::Pong,
51        };
52        let err = Response::Error {
53            message: "something failed".to_string(),
54        };
55
56        for resp in [ok, err] {
57            let msg = IpcMessage {
58                id: 2,
59                payload: IpcPayload::Response(resp),
60            };
61            let json = serde_json::to_string(&msg).unwrap();
62            let parsed: IpcMessage = serde_json::from_str(&json).unwrap();
63            assert_eq!(parsed.id, 2);
64        }
65    }
66
67    #[test]
68    fn daemon_event_roundtrip() {
69        let events: Vec<DaemonEvent> = vec![
70            DaemonEvent::SyncCompleted {
71                account_id: AccountId::new(),
72                messages_synced: 10,
73            },
74            DaemonEvent::SyncError {
75                account_id: AccountId::new(),
76                error: "timeout".to_string(),
77            },
78            DaemonEvent::MessageUnsnoozed {
79                message_id: MessageId::new(),
80            },
81        ];
82
83        for event in events {
84            let msg = IpcMessage {
85                id: 0,
86                payload: IpcPayload::Event(event),
87            };
88            let json = serde_json::to_string(&msg).unwrap();
89            let _parsed: IpcMessage = serde_json::from_str(&json).unwrap();
90        }
91    }
92
93    #[test]
94    fn codec_encode_decode() {
95        let mut codec = IpcCodec::new();
96        let msg = IpcMessage {
97            id: 42,
98            payload: IpcPayload::Request(Request::Ping),
99        };
100
101        let mut buf = BytesMut::new();
102        codec.encode(msg, &mut buf).unwrap();
103
104        let decoded = codec.decode(&mut buf).unwrap().unwrap();
105        assert_eq!(decoded.id, 42);
106    }
107
108    #[test]
109    fn codec_multiple_messages() {
110        let mut codec = IpcCodec::new();
111        let mut buf = BytesMut::new();
112
113        for i in 0..3 {
114            let msg = IpcMessage {
115                id: i,
116                payload: IpcPayload::Request(Request::Ping),
117            };
118            codec.encode(msg, &mut buf).unwrap();
119        }
120
121        for i in 0..3 {
122            let decoded = codec.decode(&mut buf).unwrap().unwrap();
123            assert_eq!(decoded.id, i);
124        }
125
126        // No more messages
127        assert!(codec.decode(&mut buf).unwrap().is_none());
128    }
129}