running_process/broker/protocol/
validate.rs1use crate::broker::protocol::registry::PROTOCOL_VERSION;
16use crate::broker::protocol::{Frame, FrameKind, PayloadEncoding};
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25pub enum FrameValidationError {
26 EnvelopeVersion {
28 actual: u32,
30 },
31 Kind {
33 expected: FrameKind,
35 actual: i32,
37 },
38 PayloadProtocol {
40 expected: u32,
42 actual: u32,
44 },
45 PayloadEncoding {
47 actual: i32,
49 },
50}
51
52pub fn validate_frame_envelope(
58 frame: &Frame,
59 expected_kind: FrameKind,
60 expected_payload_protocol: u32,
61) -> Result<(), FrameValidationError> {
62 if frame.envelope_version != PROTOCOL_VERSION {
63 return Err(FrameValidationError::EnvelopeVersion {
64 actual: frame.envelope_version,
65 });
66 }
67 if FrameKind::try_from(frame.kind) != Ok(expected_kind) {
68 return Err(FrameValidationError::Kind {
69 expected: expected_kind,
70 actual: frame.kind,
71 });
72 }
73 if frame.payload_protocol != expected_payload_protocol {
74 return Err(FrameValidationError::PayloadProtocol {
75 expected: expected_payload_protocol,
76 actual: frame.payload_protocol,
77 });
78 }
79 if PayloadEncoding::try_from(frame.payload_encoding) != Ok(PayloadEncoding::None) {
80 return Err(FrameValidationError::PayloadEncoding {
81 actual: frame.payload_encoding,
82 });
83 }
84 Ok(())
85}
86
87#[cfg(test)]
88mod tests {
89 use super::{validate_frame_envelope, FrameValidationError};
90 use crate::broker::protocol::registry::{
91 CONTROL_PAYLOAD_PROTOCOL, HANDOFF_PAYLOAD_PROTOCOL, PROTOCOL_VERSION,
92 };
93 use crate::broker::protocol::{Frame, FrameKind, PayloadEncoding};
94
95 fn valid_frame(kind: FrameKind, payload_protocol: u32) -> Frame {
96 Frame {
97 envelope_version: PROTOCOL_VERSION,
98 kind: kind as i32,
99 payload_protocol,
100 payload: Vec::new(),
101 request_id: 7,
102 payload_encoding: PayloadEncoding::None as i32,
103 deadline_unix_ms: 0,
104 traceparent: String::new(),
105 tracestate: String::new(),
106 }
107 }
108
109 #[test]
110 fn accepts_well_formed_envelope() {
111 let frame = valid_frame(FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL);
112 assert_eq!(
113 validate_frame_envelope(&frame, FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL),
114 Ok(())
115 );
116 }
117
118 #[test]
119 fn rejects_wrong_envelope_version_first() {
120 let mut frame = valid_frame(FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL);
121 frame.envelope_version = 2;
122 frame.payload_protocol = HANDOFF_PAYLOAD_PROTOCOL;
124 assert_eq!(
125 validate_frame_envelope(&frame, FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL),
126 Err(FrameValidationError::EnvelopeVersion { actual: 2 })
127 );
128 }
129
130 #[test]
131 fn rejects_unexpected_kind() {
132 let frame = valid_frame(FrameKind::Event, CONTROL_PAYLOAD_PROTOCOL);
133 assert_eq!(
134 validate_frame_envelope(&frame, FrameKind::Response, CONTROL_PAYLOAD_PROTOCOL),
135 Err(FrameValidationError::Kind {
136 expected: FrameKind::Response,
137 actual: FrameKind::Event as i32,
138 })
139 );
140 }
141
142 #[test]
143 fn rejects_unknown_kind_value() {
144 let mut frame = valid_frame(FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL);
145 frame.kind = 99;
146 assert_eq!(
147 validate_frame_envelope(&frame, FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL),
148 Err(FrameValidationError::Kind {
149 expected: FrameKind::Request,
150 actual: 99,
151 })
152 );
153 }
154
155 #[test]
156 fn rejects_unexpected_payload_protocol() {
157 let frame = valid_frame(FrameKind::Request, HANDOFF_PAYLOAD_PROTOCOL);
158 assert_eq!(
159 validate_frame_envelope(&frame, FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL),
160 Err(FrameValidationError::PayloadProtocol {
161 expected: CONTROL_PAYLOAD_PROTOCOL,
162 actual: HANDOFF_PAYLOAD_PROTOCOL,
163 })
164 );
165 }
166
167 #[test]
168 fn rejects_compressed_payload() {
169 let mut frame = valid_frame(FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL);
170 frame.payload_encoding = PayloadEncoding::Zstd as i32;
171 assert_eq!(
172 validate_frame_envelope(&frame, FrameKind::Request, CONTROL_PAYLOAD_PROTOCOL),
173 Err(FrameValidationError::PayloadEncoding {
174 actual: PayloadEncoding::Zstd as i32,
175 })
176 );
177 }
178}