use serde_json::json;
#[test]
fn test_resources_list_request_format() {
let request = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"group": "test-group",
"cursor": null
}
});
assert_eq!(request["method"], "resources/list");
assert!(request["params"]["group"].is_string());
}
#[test]
fn test_resources_list_response_structure() {
let response = json!({
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///example.txt",
"name": "example.txt",
"title": "Example File",
"description": "An example text file",
"mimeType": "text/plain",
"size": 1024,
"annotations": {
"audience": ["user"],
"priority": 0.5,
"lastModified": "2025-01-08T00:00:00Z"
}
}
],
"nextCursor": "page2"
}
});
assert!(response["result"]["resources"].is_array());
let resource = &response["result"]["resources"][0];
assert!(resource["uri"].is_string());
assert!(resource["name"].is_string());
assert!(resource["size"].is_number() || resource["size"].is_null());
assert!(resource["annotations"].is_object() || resource["annotations"].is_null());
}
#[test]
fn test_resource_size_field() {
let resource_with_size = json!({
"uri": "file:///large.bin",
"name": "large.bin",
"size": 5242880
});
let resource_without_size = json!({
"uri": "file:///unknown.txt",
"name": "unknown.txt"
});
assert_eq!(resource_with_size["size"], 5242880);
assert!(resource_without_size["size"].is_null());
}
#[test]
fn test_resource_annotations() {
let resource = json!({
"uri": "file:///source.rs",
"name": "source.rs",
"annotations": {
"audience": ["user", "assistant"],
"priority": 0.9,
"lastModified": "2025-01-08T12:00:00Z"
}
});
let annotations = &resource["annotations"];
assert!(annotations["audience"].is_array());
assert!(annotations["priority"].is_number());
assert!(annotations["lastModified"].is_string());
}
#[test]
fn test_resource_icons() {
let resource = json!({
"uri": "file:///image.png",
"name": "image.png",
"icons": [
{
"src": "https://example.com/icon.png",
"mimeType": "image/png",
"sizes": ["16x16", "32x32", "48x48"]
}
]
});
let icons = &resource["icons"];
assert!(icons.is_array());
let icon = &icons[0];
assert!(icon["src"].is_string());
assert!(icon["mimeType"].is_string());
assert!(icon["sizes"].is_array());
}
#[test]
fn test_resources_read_request_format() {
let request = json!({
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"group": "test-group",
"uri": "file:///example.txt"
}
});
assert_eq!(request["method"], "resources/read");
assert!(request["params"]["group"].is_string());
assert!(request["params"]["uri"].is_string());
}
#[test]
fn test_resources_read_text_content() {
let response = json!({
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///example.txt",
"mimeType": "text/plain",
"text": "This is the file content"
}
]
}
});
assert!(response["result"]["contents"].is_array());
let content = &response["result"]["contents"][0];
assert!(content["uri"].is_string());
assert!(content["mimeType"].is_string());
assert!(content["text"].is_string());
}
#[test]
fn test_resources_read_blob_content() {
let response = json!({
"jsonrpc": "2.0",
"id": 3,
"result": {
"contents": [
{
"uri": "file:///image.png",
"mimeType": "image/png",
"blob": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
}
]
}
});
assert!(response["result"]["contents"].is_array());
let content = &response["result"]["contents"][0];
assert!(content["uri"].is_string());
assert!(content["blob"].is_string());
}
#[test]
fn test_resources_templates_list_request_format() {
let request = json!({
"jsonrpc": "2.0",
"id": 4,
"method": "resources/templates/list",
"params": {
"group": "test-group"
}
});
assert_eq!(request["method"], "resources/templates/list");
assert!(request["params"]["group"].is_string());
}
#[test]
fn test_resource_templates_structure() {
let template = json!({
"uriTemplate": "file:///{path}",
"name": "Local Files",
"description": "Access files in local filesystem",
"mimeType": "application/octet-stream",
"annotations": {
"audience": ["user"],
"priority": 0.5
},
"icons": [
{
"src": "https://example.com/file-icon.png",
"mimeType": "image/png"
}
]
});
assert!(template["uriTemplate"].is_string());
assert!(template["name"].is_string());
assert!(template["uriTemplate"].as_str().unwrap().contains("{"));
}
#[test]
fn test_multiple_resource_uri_schemes() {
let resources = [
json!({"uri": "file:///local/path", "name": "Local File", "size": 1024}),
json!({"uri": "https://example.com/resource", "name": "Web Resource", "size": 2048}),
json!({"uri": "git://example.com/repo/blob/main/file", "name": "Git File", "size": 512}),
json!({"uri": "custom://resource/id", "name": "Custom Resource"}),
];
for (idx, resource) in resources.iter().enumerate() {
assert!(resource["uri"].is_string());
let uri = resource["uri"].as_str().unwrap();
match idx {
0 => assert!(uri.starts_with("file://")),
1 => assert!(uri.starts_with("https://")),
2 => assert!(uri.starts_with("git://")),
3 => assert!(uri.starts_with("custom://")),
_ => unreachable!(),
}
}
}
#[test]
fn test_resources_list_pagination() {
let response = json!({
"resources": [
{"uri": "file:///a.txt", "name": "a.txt"},
{"uri": "file:///b.txt", "name": "b.txt"}
],
"nextCursor": "cursor_abc123"
});
assert!(response["resources"].is_array());
assert!(response["nextCursor"].is_string());
}
#[test]
fn test_resources_capability_declaration() {
let initialize = json!({
"capabilities": {
"resources": {
"subscribe": true
}
}
});
assert!(
initialize["capabilities"]["resources"].is_object(),
"resources capability must be present"
);
}
#[test]
fn test_resource_content_with_annotations() {
let response = json!({
"contents": [
{
"uri": "file:///document.txt",
"mimeType": "text/plain",
"text": "Content here",
"annotations": {
"lastModified": "2025-01-08T12:00:00Z",
"priority": 0.7,
"audience": ["user"]
}
}
]
});
let content = &response["contents"][0];
assert!(content["annotations"]["lastModified"].is_string());
assert!(content["annotations"]["priority"].is_number());
assert!(content["annotations"]["audience"].is_array());
}
#[test]
fn test_resources_api_error_codes() {
let errors = vec![
(
-32602,
json!({
"code": -32602,
"message": "Invalid params: missing group parameter"
}),
),
(
-32002,
json!({
"code": -32002,
"message": "Resource not found"
}),
),
(
-32603,
json!({
"code": -32603,
"message": "Internal error: failed to list resources"
}),
),
];
for (expected_code, error) in errors {
assert_eq!(error["code"], expected_code);
}
}
#[test]
fn test_empty_resources_list_response() {
let response = json!({
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": []
}
});
assert!(response["result"]["resources"].is_array());
assert_eq!(response["result"]["resources"].as_array().unwrap().len(), 0);
}
#[test]
fn test_resources_multiple_mime_types() {
let resources = vec![
json!({"uri": "file:///doc.txt", "mimeType": "text/plain"}),
json!({"uri": "file:///image.png", "mimeType": "image/png"}),
json!({"uri": "file:///data.json", "mimeType": "application/json"}),
json!({"uri": "file:///script.py", "mimeType": "text/x-python"}),
json!({"uri": "file:///archive.zip", "mimeType": "application/zip"}),
];
for resource in resources {
assert!(resource["mimeType"].is_string());
let mime = resource["mimeType"].as_str().unwrap();
assert!(mime.contains("/"));
}
}
#[test]
fn test_resource_templates_rfc6570_syntax() {
let templates = vec![
json!({
"uriTemplate": "file:///{path}",
"name": "Simple path"
}),
json!({
"uriTemplate": "git:///{repo}/blob/{branch}/{path}",
"name": "Git with multiple variables"
}),
json!({
"uriTemplate": "db:///{database}/{table}?filter={filter}",
"name": "Database with query"
}),
];
for template in templates {
let uri_template = template["uriTemplate"].as_str().unwrap();
assert!(uri_template.contains("{"));
assert!(uri_template.contains("}"));
}
}
#[test]
fn test_resource_full_annotations() {
let resource = json!({
"uri": "file:///complete.txt",
"name": "complete.txt",
"size": 2048,
"annotations": {
"audience": ["user", "assistant", "admin"],
"priority": 0.95,
"lastModified": "2025-01-08T15:30:45Z"
},
"icons": [
{
"src": "https://icons.example.com/text-file.svg",
"mimeType": "image/svg+xml",
"sizes": ["16x16", "24x24", "32x32", "48x48"]
},
{
"src": "https://icons.example.com/text-file-large.png",
"mimeType": "image/png",
"sizes": ["64x64", "128x128"]
}
]
});
assert!(resource["uri"].is_string());
assert_eq!(resource["size"], 2048);
assert!(resource["annotations"]["audience"].is_array());
assert_eq!(
resource["annotations"]["audience"]
.as_array()
.unwrap()
.len(),
3
);
assert_eq!(resource["annotations"]["priority"], 0.95);
assert!(resource["icons"].is_array());
assert_eq!(resource["icons"].as_array().unwrap().len(), 2);
}
#[test]
fn test_resource_size_field_present() {
let resource_json = json!({
"uri": "file:///large.bin",
"name": "large.bin",
"description": "A large binary file",
"mimeType": "application/octet-stream",
"size": 5242880
});
assert_eq!(resource_json["size"], 5242880);
assert_eq!(resource_json["name"], "large.bin");
}
#[test]
fn test_resource_without_size_field() {
let resource_json = json!({
"uri": "file:///test.txt",
"name": "test.txt",
"mimeType": "text/plain"
});
assert!(resource_json["size"].is_null());
assert_eq!(resource_json["name"], "test.txt");
}
#[test]
fn test_resource_template_structure() {
let template_json = json!({
"uriTemplate": "file:///{path}",
"name": "Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream"
});
assert_eq!(template_json["uriTemplate"], "file:///{path}");
assert_eq!(template_json["name"], "Project Files");
assert_eq!(
template_json["description"],
"Access files in the project directory"
);
assert_eq!(template_json["mimeType"], "application/octet-stream");
}
#[test]
fn test_resource_template_minimal() {
let template_json = json!({
"uriTemplate": "git:///{repo}/blob/{ref}/{path}",
"name": "Git Files"
});
assert_eq!(
template_json["uriTemplate"],
"git:///{repo}/blob/{ref}/{path}"
);
assert_eq!(template_json["name"], "Git Files");
assert!(template_json["description"].is_null());
}
#[test]
fn test_resources_list_response_format_with_size() {
let list_response = json!({
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Entry point",
"mimeType": "text/x-rust",
"size": 2048,
"annotations": {
"audience": ["user", "assistant"],
"priority": 0.8
}
},
{
"uri": "file:///project/data.bin",
"name": "data.bin",
"size": 1048576,
"mimeType": "application/octet-stream"
}
],
"nextCursor": "next-page"
});
assert!(list_response["resources"].is_array());
assert_eq!(list_response["resources"][0]["size"], 2048);
assert_eq!(list_response["resources"][1]["size"], 1048576);
assert_eq!(list_response["nextCursor"], "next-page");
}
#[test]
fn test_resources_templates_list_response_format() {
let templates_response = json!({
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Local Files",
"description": "Access files in local filesystem",
"mimeType": "application/octet-stream"
},
{
"uriTemplate": "git:///{repo}/blob/{ref}/{path}",
"name": "Git Repository Files",
"description": "Access files in git repositories"
}
]
});
assert!(templates_response["resourceTemplates"].is_array());
assert_eq!(
templates_response["resourceTemplates"]
.as_array()
.unwrap()
.len(),
2
);
assert_eq!(
templates_response["resourceTemplates"][0]["uriTemplate"],
"file:///{path}"
);
assert_eq!(
templates_response["resourceTemplates"][1]["name"],
"Git Repository Files"
);
}
#[test]
fn test_resource_with_icons_and_size() {
let resource_json = json!({
"uri": "file:///image.png",
"name": "image.png",
"mimeType": "image/png",
"size": 512000,
"icons": [
{
"src": "https://example.com/icon-48.png",
"mimeType": "image/png",
"sizes": ["48x48"]
}
]
});
assert_eq!(resource_json["size"], 512000);
assert!(resource_json["icons"].is_array());
assert_eq!(
resource_json["icons"][0]["src"],
"https://example.com/icon-48.png"
);
}
#[test]
fn test_resource_read_response_with_annotations() {
let read_response = json!({
"contents": [
{
"uri": "file:///source.rs",
"mimeType": "text/x-rust",
"text": "fn main() { println!(\"Hello\"); }",
"annotations": {
"lastModified": "2025-01-08T20:00:00Z",
"priority": 0.9
}
}
]
});
assert!(read_response["contents"].is_array());
assert_eq!(read_response["contents"][0]["uri"], "file:///source.rs");
assert_eq!(
read_response["contents"][0]["annotations"]["lastModified"],
"2025-01-08T20:00:00Z"
);
}
#[test]
fn test_different_resource_uri_schemes() {
let resources = [
json!({"uri": "file:///local/path", "name": "Local File", "size": 1024}),
json!({"uri": "https://example.com/resource", "name": "Web Resource", "size": 2048}),
json!({"uri": "git://example.com/repo/blob/main/file.txt", "name": "Git File", "size": 512}),
];
for (idx, resource) in resources.iter().enumerate() {
assert!(resource["uri"].is_string());
assert!(resource["size"].is_number());
match idx {
0 => assert!(resource["uri"].as_str().unwrap().starts_with("file://")),
1 => assert!(resource["uri"].as_str().unwrap().starts_with("https://")),
2 => assert!(resource["uri"].as_str().unwrap().starts_with("git://")),
_ => unreachable!(),
}
}
}