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            },
32        ];
33
34        for req in variants {
35            let msg = IpcMessage {
36                id: 1,
37                payload: IpcPayload::Request(req),
38            };
39            let json = serde_json::to_string(&msg).unwrap();
40            let parsed: IpcMessage = serde_json::from_str(&json).unwrap();
41            assert_eq!(parsed.id, 1);
42        }
43    }
44
45    #[test]
46    fn response_serde_roundtrip() {
47        let ok = Response::Ok {
48            data: ResponseData::Pong,
49        };
50        let err = Response::Error {
51            message: "something failed".to_string(),
52        };
53
54        for resp in [ok, err] {
55            let msg = IpcMessage {
56                id: 2,
57                payload: IpcPayload::Response(resp),
58            };
59            let json = serde_json::to_string(&msg).unwrap();
60            let parsed: IpcMessage = serde_json::from_str(&json).unwrap();
61            assert_eq!(parsed.id, 2);
62        }
63    }
64
65    #[test]
66    fn daemon_event_roundtrip() {
67        let events: Vec<DaemonEvent> = vec![
68            DaemonEvent::SyncCompleted {
69                account_id: AccountId::new(),
70                messages_synced: 10,
71            },
72            DaemonEvent::SyncError {
73                account_id: AccountId::new(),
74                error: "timeout".to_string(),
75            },
76            DaemonEvent::MessageUnsnoozed {
77                message_id: MessageId::new(),
78            },
79        ];
80
81        for event in events {
82            let msg = IpcMessage {
83                id: 0,
84                payload: IpcPayload::Event(event),
85            };
86            let json = serde_json::to_string(&msg).unwrap();
87            let _parsed: IpcMessage = serde_json::from_str(&json).unwrap();
88        }
89    }
90
91    #[test]
92    fn codec_encode_decode() {
93        let mut codec = IpcCodec::new();
94        let msg = IpcMessage {
95            id: 42,
96            payload: IpcPayload::Request(Request::Ping),
97        };
98
99        let mut buf = BytesMut::new();
100        codec.encode(msg, &mut buf).unwrap();
101
102        let decoded = codec.decode(&mut buf).unwrap().unwrap();
103        assert_eq!(decoded.id, 42);
104    }
105
106    #[test]
107    fn codec_multiple_messages() {
108        let mut codec = IpcCodec::new();
109        let mut buf = BytesMut::new();
110
111        for i in 0..3 {
112            let msg = IpcMessage {
113                id: i,
114                payload: IpcPayload::Request(Request::Ping),
115            };
116            codec.encode(msg, &mut buf).unwrap();
117        }
118
119        for i in 0..3 {
120            let decoded = codec.decode(&mut buf).unwrap().unwrap();
121            assert_eq!(decoded.id, i);
122        }
123
124        // No more messages
125        assert!(codec.decode(&mut buf).unwrap().is_none());
126    }
127}