Skip to content

Commit e1af378

Browse files
authored
chore: consolidate repeated rmcp tests (modelcontextprotocol#931)
1 parent 4b9bea7 commit e1af378

14 files changed

Lines changed: 306 additions & 332 deletions

crates/rmcp/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ tracing-subscriber = { version = "0.3", features = [
200200
"fmt",
201201
] }
202202
async-trait = "0.1"
203+
rstest = "0.26.1"
203204
[[test]]
204205
name = "test_tool_macros"
205206
required-features = ["server", "client"]

crates/rmcp/src/handler/server/common.rs

Lines changed: 53 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ pub trait AsRequestContext {
233233

234234
#[cfg(test)]
235235
mod tests {
236+
use rstest::rstest;
237+
236238
use super::*;
237239

238240
#[derive(serde::Serialize, serde::Deserialize, JsonSchema)]
@@ -245,46 +247,44 @@ mod tests {
245247
value: i32,
246248
}
247249

248-
#[test]
249-
fn test_schema_for_type_handles_primitive() {
250-
let schema = schema_for_type::<i32>();
251-
252-
assert_eq!(schema.get("type"), Some(&serde_json::json!("integer")));
250+
#[rstest]
251+
#[case::primitive(schema_for_type::<i32>, "integer")]
252+
#[case::array(schema_for_type::<Vec<i32>>, "array")]
253+
#[case::struct_object(schema_for_type::<TestObject>, "object")]
254+
fn schema_for_type_sets_expected_root_type(
255+
#[case] schema_fn: fn() -> Arc<JsonObject>,
256+
#[case] expected_type: &str,
257+
) {
258+
let schema = schema_fn();
259+
260+
assert_eq!(schema.get("type"), Some(&serde_json::json!(expected_type)));
253261
}
254262

255263
#[test]
256-
fn test_schema_for_type_handles_array() {
264+
fn schema_for_type_sets_array_item_type() {
257265
let schema = schema_for_type::<Vec<i32>>();
266+
let items = schema.get("items").and_then(|v| v.as_object()).unwrap();
258267

259-
assert_eq!(schema.get("type"), Some(&serde_json::json!("array")));
260-
let items = schema.get("items").and_then(|v| v.as_object());
261-
assert_eq!(
262-
items.unwrap().get("type"),
263-
Some(&serde_json::json!("integer"))
264-
);
268+
assert_eq!(items.get("type"), Some(&serde_json::json!("integer")));
265269
}
266270

267271
#[test]
268-
fn test_schema_for_type_handles_struct() {
272+
fn schema_for_type_sets_struct_properties() {
269273
let schema = schema_for_type::<TestObject>();
274+
let properties = schema
275+
.get("properties")
276+
.and_then(|v| v.as_object())
277+
.unwrap();
270278

271-
assert_eq!(schema.get("type"), Some(&serde_json::json!("object")));
272-
let properties = schema.get("properties").and_then(|v| v.as_object());
273-
assert!(properties.unwrap().contains_key("value"));
274-
}
275-
276-
#[test]
277-
fn test_schema_for_type_caches_primitive_types() {
278-
let schema1 = schema_for_type::<i32>();
279-
let schema2 = schema_for_type::<i32>();
280-
281-
assert!(Arc::ptr_eq(&schema1, &schema2));
279+
assert!(properties.contains_key("value"));
282280
}
283281

284-
#[test]
285-
fn test_schema_for_type_caches_struct_types() {
286-
let schema1 = schema_for_type::<TestObject>();
287-
let schema2 = schema_for_type::<TestObject>();
282+
#[rstest]
283+
#[case::primitive(schema_for_type::<i32>)]
284+
#[case::struct_object(schema_for_type::<TestObject>)]
285+
fn test_schema_for_type_caches_schemas(#[case] schema_fn: fn() -> Arc<JsonObject>) {
286+
let schema1 = schema_fn();
287+
let schema2 = schema_fn();
288288

289289
assert!(Arc::ptr_eq(&schema1, &schema2));
290290
}
@@ -305,51 +305,36 @@ mod tests {
305305
assert!(Arc::ptr_eq(&schema, &cloned));
306306
}
307307

308-
#[test]
309-
fn test_schema_for_output_rejects_primitive() {
310-
let result = schema_for_output::<i32>();
311-
assert!(result.is_err(),);
312-
}
313-
314-
#[test]
315-
fn test_schema_for_output_accepts_object() {
316-
let result = schema_for_output::<TestObject>();
317-
assert!(result.is_ok(),);
318-
}
319-
320-
#[test]
321-
fn test_schema_for_output_strips_top_level_title() {
322-
let schema = schema_for_output::<TestObject>().unwrap();
323-
assert!(!schema.contains_key("title"));
324-
}
325-
326-
#[test]
327-
fn test_schema_for_output_strips_top_level_description() {
328-
let schema = schema_for_output::<TestObject>().unwrap();
329-
assert!(!schema.contains_key("description"));
330-
}
331-
332-
#[test]
333-
fn test_schema_for_input_rejects_primitive() {
334-
let result = schema_for_input::<i32>();
308+
#[rstest]
309+
#[case::output(schema_for_output::<i32>)]
310+
#[case::input(schema_for_input::<i32>)]
311+
fn test_schema_for_object_wrappers_reject_primitives(
312+
#[case] schema_fn: fn() -> Result<Arc<JsonObject>, String>,
313+
) {
314+
let result = schema_fn();
335315
assert!(result.is_err());
336316
}
337317

338-
#[test]
339-
fn test_schema_for_input_accepts_object() {
340-
let result = schema_for_input::<TestObject>();
318+
#[rstest]
319+
#[case::output(schema_for_output::<TestObject>)]
320+
#[case::input(schema_for_input::<TestObject>)]
321+
fn test_schema_for_object_wrappers_accept_objects(
322+
#[case] schema_fn: fn() -> Result<Arc<JsonObject>, String>,
323+
) {
324+
let result = schema_fn();
341325
assert!(result.is_ok());
342326
}
343327

344-
#[test]
345-
fn test_schema_for_input_strips_top_level_title() {
346-
let schema = schema_for_input::<TestObject>().unwrap();
347-
assert!(!schema.contains_key("title"));
348-
}
349-
350-
#[test]
351-
fn test_schema_for_input_strips_top_level_description() {
352-
let schema = schema_for_input::<TestObject>().unwrap();
353-
assert!(!schema.contains_key("description"));
328+
#[rstest]
329+
#[case::output_title(schema_for_output::<TestObject>, "title")]
330+
#[case::output_description(schema_for_output::<TestObject>, "description")]
331+
#[case::input_title(schema_for_input::<TestObject>, "title")]
332+
#[case::input_description(schema_for_input::<TestObject>, "description")]
333+
fn test_schema_for_object_wrappers_strip_top_level_metadata(
334+
#[case] schema_fn: fn() -> Result<Arc<JsonObject>, String>,
335+
#[case] field: &str,
336+
) {
337+
let schema = schema_fn().unwrap();
338+
assert!(!schema.contains_key(field));
354339
}
355340
}

crates/rmcp/src/model/elicitation_schema.rs

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,49 +1701,70 @@ impl ElicitationSchemaBuilder {
17011701
#[cfg(test)]
17021702
mod tests {
17031703
use anyhow::anyhow;
1704+
use rstest::rstest;
17041705
use serde_json::json;
17051706

17061707
use super::*;
17071708

1708-
#[test]
1709-
fn test_string_schema_serialization() {
1710-
let schema = StringSchema::email().description("Email address");
1711-
let json = serde_json::to_value(&schema).unwrap();
1712-
1713-
assert_eq!(json["type"], "string");
1714-
assert_eq!(json["format"], "email");
1715-
assert_eq!(json["description"], "Email address");
1709+
fn string_schema_json() -> serde_json::Value {
1710+
serde_json::to_value(StringSchema::email().description("Email address")).unwrap()
17161711
}
17171712

1718-
#[test]
1719-
fn test_number_schema_serialization() {
1720-
let schema = NumberSchema::new()
1721-
.range(0.0, 100.0)
1722-
.description("Percentage");
1723-
let json = serde_json::to_value(&schema).unwrap();
1724-
1725-
assert_eq!(json["type"], "number");
1726-
assert_eq!(json["minimum"], 0.0);
1727-
assert_eq!(json["maximum"], 100.0);
1713+
fn number_schema_json() -> serde_json::Value {
1714+
serde_json::to_value(
1715+
NumberSchema::new()
1716+
.range(0.0, 100.0)
1717+
.description("Percentage"),
1718+
)
1719+
.unwrap()
17281720
}
17291721

1730-
#[test]
1731-
fn test_integer_schema_serialization() {
1732-
let schema = IntegerSchema::new().range(0, 150);
1733-
let json = serde_json::to_value(&schema).unwrap();
1734-
1735-
assert_eq!(json["type"], "integer");
1736-
assert_eq!(json["minimum"], 0);
1737-
assert_eq!(json["maximum"], 150);
1722+
fn integer_schema_json() -> serde_json::Value {
1723+
serde_json::to_value(IntegerSchema::new().range(0, 150)).unwrap()
17381724
}
17391725

1740-
#[test]
1741-
fn test_boolean_schema_serialization() {
1742-
let schema = BooleanSchema::new().with_default(true);
1743-
let json = serde_json::to_value(&schema).unwrap();
1726+
fn boolean_schema_json() -> serde_json::Value {
1727+
serde_json::to_value(BooleanSchema::new().with_default(true)).unwrap()
1728+
}
17441729

1745-
assert_eq!(json["type"], "boolean");
1746-
assert_eq!(json["default"], true);
1730+
#[rstest]
1731+
#[case::string_schema(
1732+
string_schema_json,
1733+
json!({
1734+
"type": "string",
1735+
"format": "email",
1736+
"description": "Email address",
1737+
})
1738+
)]
1739+
#[case::number_schema(
1740+
number_schema_json,
1741+
json!({
1742+
"type": "number",
1743+
"description": "Percentage",
1744+
"minimum": 0.0,
1745+
"maximum": 100.0,
1746+
})
1747+
)]
1748+
#[case::integer_schema(
1749+
integer_schema_json,
1750+
json!({
1751+
"type": "integer",
1752+
"minimum": 0,
1753+
"maximum": 150,
1754+
})
1755+
)]
1756+
#[case::boolean_schema(
1757+
boolean_schema_json,
1758+
json!({
1759+
"type": "boolean",
1760+
"default": true,
1761+
})
1762+
)]
1763+
fn primitive_schema_serializes_to_expected_json(
1764+
#[case] schema_json: fn() -> serde_json::Value,
1765+
#[case] expected: serde_json::Value,
1766+
) {
1767+
assert_eq!(schema_json(), expected);
17471768
}
17481769

17491770
#[test]

0 commit comments

Comments
 (0)