use super::check_capability;
use crate::report::{TestCategory, TestResult};
use crate::tester::ServerTester;
use std::time::Instant;
pub async fn run_resources_conformance(tester: &mut ServerTester) -> Vec<TestResult> {
if let Some(skip) = check_capability(tester, "Resources", TestCategory::Resources, |caps| {
caps.resources.is_some()
}) {
return skip;
}
let mut results = Vec::new();
let (list_result, first_uri) = test_resources_list(tester).await;
results.push(list_result);
results.push(test_read_first_resource(tester, first_uri.as_deref()).await);
results.push(test_read_invalid_uri(tester).await);
results
}
async fn test_resources_list(tester: &mut ServerTester) -> (TestResult, Option<String>) {
let start = Instant::now();
let name = "Resources: list returns valid ResourceInfo";
match tester.list_resources().await {
Ok(result) => {
let resources = &result.resources;
let invalid: Vec<_> = resources
.iter()
.filter(|r| r.name.is_empty() || r.uri.is_empty())
.map(|r| r.name.clone())
.collect();
let first_uri = resources.first().map(|r| r.uri.clone());
if invalid.is_empty() {
(
TestResult::passed(
name,
TestCategory::Resources,
start.elapsed(),
format!("Found {} resources", resources.len()),
),
first_uri,
)
} else {
(
TestResult::failed(
name,
TestCategory::Resources,
start.elapsed(),
format!("Resources with empty name/uri: {:?}", invalid),
),
first_uri,
)
}
},
Err(e) => (
TestResult::failed(
name,
TestCategory::Resources,
start.elapsed(),
format!("resources/list failed: {e}"),
),
None,
),
}
}
async fn test_read_first_resource(
tester: &mut ServerTester,
first_uri: Option<&str>,
) -> TestResult {
let start = Instant::now();
let name = "Resources: read first resource";
let Some(uri) = first_uri else {
return TestResult::skipped(name, TestCategory::Resources, "No resources to read");
};
match tester.read_resource(uri).await {
Ok(_) => TestResult::passed(
name,
TestCategory::Resources,
start.elapsed(),
format!("Successfully read resource: {uri}"),
),
Err(e) => TestResult::failed(
name,
TestCategory::Resources,
start.elapsed(),
format!("resources/read failed: {e}"),
),
}
}
async fn test_read_invalid_uri(tester: &mut ServerTester) -> TestResult {
let start = Instant::now();
let name = "Resources: read invalid URI returns error";
match tester
.read_resource("___nonexistent_resource_conformance_test___")
.await
{
Ok(_) => TestResult::warning(
name,
TestCategory::Resources,
start.elapsed(),
"Server returned success for nonexistent resource URI",
),
Err(_) => TestResult::passed(
name,
TestCategory::Resources,
start.elapsed(),
"Server correctly rejected invalid URI",
),
}
}