Skip to content

Commit 4145f0b

Browse files
authored
test: add jsonrpc payload coverage (#420)
Summary: - Extract JSONRPC payload parse/dispatch into a small testable helper while preserving `start_server` behavior. - Add tests for valid payload dispatch and malformed JSON rejection without handler invocation. - Covers the first `pet-jsonrpc` slice from the #389 coverage plan. Validation: - cargo test -p pet-jsonrpc - cargo fmt --all - cargo clippy --all -- -D warnings Refs #389
1 parent c9667bc commit 4145f0b

File tree

1 file changed

+49
-5
lines changed

1 file changed

+49
-5
lines changed

crates/pet-jsonrpc/src/server.rs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,8 @@ pub fn start_server<C>(handlers: &HandlersKeyedByMethodName<C>) -> ! {
120120
Ok(_) => {
121121
let request =
122122
String::from_utf8_lossy(&buffer[..content_length]).to_string();
123-
match serde_json::from_str(&request) {
124-
Ok(request) => handlers.handle_request(request),
125-
Err(err) => {
126-
eprint!("Failed to parse LINE: {request}, {err:?}")
127-
}
123+
if let Err(err) = handle_payload(handlers, &request) {
124+
eprint!("Failed to parse LINE: {request}, {err:?}")
128125
}
129126
continue;
130127
}
@@ -141,6 +138,15 @@ pub fn start_server<C>(handlers: &HandlersKeyedByMethodName<C>) -> ! {
141138
}
142139
}
143140

141+
fn handle_payload<C>(
142+
handlers: &HandlersKeyedByMethodName<C>,
143+
payload: &str,
144+
) -> Result<(), serde_json::Error> {
145+
let request = serde_json::from_str(payload)?;
146+
handlers.handle_request(request);
147+
Ok(())
148+
}
149+
144150
/// Parses the content length from the given line.
145151
fn get_content_length(line: &str) -> Result<usize, String> {
146152
let line = line.trim();
@@ -237,6 +243,44 @@ mod tests {
237243
assert_eq!(*context.notification.lock().unwrap(), Some(json!(["item"])));
238244
}
239245

246+
#[test]
247+
fn handle_payload_routes_valid_jsonrpc_payload() {
248+
let context = Arc::new(TestContext::default());
249+
let mut handlers = HandlersKeyedByMethodName::new(context.clone());
250+
handlers.add_request_handler("request/method", |context, id, params| {
251+
*context.request.lock().unwrap() = Some((id, params));
252+
});
253+
254+
handle_payload(
255+
&handlers,
256+
r#"{"jsonrpc":"2.0","id":9,"method":"request/method","params":{"ok":true}}"#,
257+
)
258+
.unwrap();
259+
260+
assert_eq!(
261+
*context.request.lock().unwrap(),
262+
Some((9, json!({ "ok": true })))
263+
);
264+
}
265+
266+
#[test]
267+
fn handle_payload_rejects_malformed_json_without_dispatching() {
268+
let context = Arc::new(TestContext::default());
269+
let mut handlers = HandlersKeyedByMethodName::new(context.clone());
270+
handlers.add_request_handler("request/method", |context, id, params| {
271+
*context.request.lock().unwrap() = Some((id, params));
272+
});
273+
274+
let error = handle_payload(
275+
&handlers,
276+
r#"{"jsonrpc":"2.0","id":9,"method":"request/method","params": "#,
277+
)
278+
.unwrap_err();
279+
280+
assert!(error.is_eof());
281+
assert!(context.request.lock().unwrap().is_none());
282+
}
283+
240284
#[test]
241285
fn handle_request_reports_unknown_methods_without_invoking_known_handlers() {
242286
let context = Arc::new(TestContext::default());

0 commit comments

Comments
 (0)