use super::*;
use crate::agents::registry::AgentRegistry;
use std::sync::Arc;
pub struct AgentStateResource {
_registry: Arc<AgentRegistry>,
}
impl AgentStateResource {
pub fn new(registry: Arc<AgentRegistry>) -> Self {
Self {
_registry: registry,
}
}
}
#[async_trait]
impl McpResource for AgentStateResource {
fn template(&self) -> ResourceTemplate {
ResourceTemplate {
uri_template: "agent://state/{agent_id}".to_string(),
name: "Agent State".to_string(),
description: Some("Current state of an agent".to_string()),
mime_type: Some("application/json".to_string()),
}
}
async fn read(&self, uri: &str) -> Result<ResourceContent, McpError> {
Ok(ResourceContent {
uri: uri.to_string(),
mime_type: Some("application/json".to_string()),
content: ResourceContentType::Text {
text: "{}".to_string(),
},
})
}
fn subscribe(&self, _uri: &str) -> Option<tokio::sync::watch::Receiver<ResourceContent>> {
None
}
}
pub struct MetricsResource {
_registry: Arc<AgentRegistry>,
}
impl MetricsResource {
pub fn new(registry: Arc<AgentRegistry>) -> Self {
Self {
_registry: registry,
}
}
}
#[async_trait]
impl McpResource for MetricsResource {
fn template(&self) -> ResourceTemplate {
ResourceTemplate {
uri_template: "metrics://{type}".to_string(),
name: "System Metrics".to_string(),
description: Some("System and agent metrics".to_string()),
mime_type: Some("application/json".to_string()),
}
}
async fn read(&self, uri: &str) -> Result<ResourceContent, McpError> {
Ok(ResourceContent {
uri: uri.to_string(),
mime_type: Some("application/json".to_string()),
content: ResourceContentType::Text {
text: "{}".to_string(),
},
})
}
fn subscribe(&self, _uri: &str) -> Option<tokio::sync::watch::Receiver<ResourceContent>> {
None
}
}
pub struct QualityReportResource;
impl Default for QualityReportResource {
fn default() -> Self {
Self::new()
}
}
impl QualityReportResource {
pub fn new() -> Self {
Self
}
}
#[async_trait]
impl McpResource for QualityReportResource {
fn template(&self) -> ResourceTemplate {
ResourceTemplate {
uri_template: "quality://report/{id}".to_string(),
name: "Quality Report".to_string(),
description: Some("Code quality analysis report".to_string()),
mime_type: Some("application/json".to_string()),
}
}
async fn read(&self, uri: &str) -> Result<ResourceContent, McpError> {
Ok(ResourceContent {
uri: uri.to_string(),
mime_type: Some("application/json".to_string()),
content: ResourceContentType::Text {
text: "{}".to_string(),
},
})
}
fn subscribe(&self, _uri: &str) -> Option<tokio::sync::watch::Receiver<ResourceContent>> {
None
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod coverage_tests {
use super::*;
use crate::agents::registry::AgentRegistry;
#[test]
fn test_agent_state_resource_new() {
let registry = Arc::new(AgentRegistry::new());
let resource = AgentStateResource::new(registry);
let _ = resource;
}
#[test]
fn test_agent_state_resource_template() {
let registry = Arc::new(AgentRegistry::new());
let resource = AgentStateResource::new(registry);
let template = resource.template();
assert_eq!(template.uri_template, "agent://state/{agent_id}");
assert_eq!(template.name, "Agent State");
assert!(template.description.is_some());
assert!(template.description.as_ref().unwrap().contains("state"));
assert_eq!(template.mime_type, Some("application/json".to_string()));
}
#[tokio::test]
async fn test_agent_state_resource_read() {
let registry = Arc::new(AgentRegistry::new());
let resource = AgentStateResource::new(registry);
let content = resource.read("agent://state/test-agent-123").await.unwrap();
assert_eq!(content.uri, "agent://state/test-agent-123");
assert_eq!(content.mime_type, Some("application/json".to_string()));
match content.content {
ResourceContentType::Text { text } => {
assert_eq!(text, "{}");
}
_ => panic!("Expected Text content type"),
}
}
#[tokio::test]
async fn test_agent_state_resource_read_various_uris() {
let registry = Arc::new(AgentRegistry::new());
let resource = AgentStateResource::new(registry);
for uri in [
"agent://state/abc",
"agent://state/123",
"agent://state/test-agent",
"agent://state/uuid-1234-5678",
] {
let content = resource.read(uri).await.unwrap();
assert_eq!(content.uri, uri);
}
}
#[test]
fn test_agent_state_resource_subscribe_returns_none() {
let registry = Arc::new(AgentRegistry::new());
let resource = AgentStateResource::new(registry);
let subscription = resource.subscribe("agent://state/test");
assert!(subscription.is_none());
}
#[test]
fn test_metrics_resource_new() {
let registry = Arc::new(AgentRegistry::new());
let resource = MetricsResource::new(registry);
let _ = resource;
}
#[test]
fn test_metrics_resource_template() {
let registry = Arc::new(AgentRegistry::new());
let resource = MetricsResource::new(registry);
let template = resource.template();
assert_eq!(template.uri_template, "metrics://{type}");
assert_eq!(template.name, "System Metrics");
assert!(template.description.is_some());
assert!(template.description.as_ref().unwrap().contains("metrics"));
assert_eq!(template.mime_type, Some("application/json".to_string()));
}
#[tokio::test]
async fn test_metrics_resource_read() {
let registry = Arc::new(AgentRegistry::new());
let resource = MetricsResource::new(registry);
let content = resource.read("metrics://cpu").await.unwrap();
assert_eq!(content.uri, "metrics://cpu");
assert_eq!(content.mime_type, Some("application/json".to_string()));
match content.content {
ResourceContentType::Text { text } => {
assert_eq!(text, "{}");
}
_ => panic!("Expected Text content type"),
}
}
#[tokio::test]
async fn test_metrics_resource_read_various_types() {
let registry = Arc::new(AgentRegistry::new());
let resource = MetricsResource::new(registry);
for uri in [
"metrics://cpu",
"metrics://memory",
"metrics://disk",
"metrics://network",
"metrics://agent-performance",
] {
let content = resource.read(uri).await.unwrap();
assert_eq!(content.uri, uri);
}
}
#[test]
fn test_metrics_resource_subscribe_returns_none() {
let registry = Arc::new(AgentRegistry::new());
let resource = MetricsResource::new(registry);
let subscription = resource.subscribe("metrics://cpu");
assert!(subscription.is_none());
}
#[test]
fn test_quality_report_resource_new() {
let resource = QualityReportResource::new();
let _ = resource;
}
#[test]
fn test_quality_report_resource_default() {
let resource = QualityReportResource::default();
let _ = resource;
}
#[test]
fn test_quality_report_resource_template() {
let resource = QualityReportResource::new();
let template = resource.template();
assert_eq!(template.uri_template, "quality://report/{id}");
assert_eq!(template.name, "Quality Report");
assert!(template.description.is_some());
assert!(template.description.as_ref().unwrap().contains("quality"));
assert_eq!(template.mime_type, Some("application/json".to_string()));
}
#[tokio::test]
async fn test_quality_report_resource_read() {
let resource = QualityReportResource::new();
let content = resource.read("quality://report/abc-123").await.unwrap();
assert_eq!(content.uri, "quality://report/abc-123");
assert_eq!(content.mime_type, Some("application/json".to_string()));
match content.content {
ResourceContentType::Text { text } => {
assert_eq!(text, "{}");
}
_ => panic!("Expected Text content type"),
}
}
#[tokio::test]
async fn test_quality_report_resource_read_various_ids() {
let resource = QualityReportResource::new();
for uri in [
"quality://report/1",
"quality://report/test-report",
"quality://report/uuid-abc-def",
"quality://report/latest",
] {
let content = resource.read(uri).await.unwrap();
assert_eq!(content.uri, uri);
}
}
#[test]
fn test_quality_report_resource_subscribe_returns_none() {
let resource = QualityReportResource::new();
let subscription = resource.subscribe("quality://report/test");
assert!(subscription.is_none());
}
#[test]
fn test_all_resources_have_unique_uri_templates() {
let registry = Arc::new(AgentRegistry::new());
let templates = vec![
AgentStateResource::new(Arc::clone(®istry))
.template()
.uri_template,
MetricsResource::new(Arc::clone(®istry))
.template()
.uri_template,
QualityReportResource::new().template().uri_template,
];
let mut unique_templates = templates.clone();
unique_templates.sort();
unique_templates.dedup();
assert_eq!(
templates.len(),
unique_templates.len(),
"All resource URI templates should be unique"
);
}
#[test]
fn test_all_resources_have_unique_names() {
let registry = Arc::new(AgentRegistry::new());
let names = vec![
AgentStateResource::new(Arc::clone(®istry))
.template()
.name,
MetricsResource::new(Arc::clone(®istry)).template().name,
QualityReportResource::new().template().name,
];
let mut unique_names = names.clone();
unique_names.sort();
unique_names.dedup();
assert_eq!(
names.len(),
unique_names.len(),
"All resource names should be unique"
);
}
#[test]
fn test_all_resources_return_json_mime_type() {
let registry = Arc::new(AgentRegistry::new());
let mime_types = vec![
AgentStateResource::new(Arc::clone(®istry))
.template()
.mime_type,
MetricsResource::new(Arc::clone(®istry))
.template()
.mime_type,
QualityReportResource::new().template().mime_type,
];
for mime_type in mime_types {
assert_eq!(mime_type, Some("application/json".to_string()));
}
}
#[tokio::test]
async fn test_all_resources_return_valid_content() {
let registry = Arc::new(AgentRegistry::new());
let agent_resource = AgentStateResource::new(Arc::clone(®istry));
let content = agent_resource.read("agent://state/test").await.unwrap();
assert!(!content.uri.is_empty());
let metrics_resource = MetricsResource::new(Arc::clone(®istry));
let content = metrics_resource.read("metrics://cpu").await.unwrap();
assert!(!content.uri.is_empty());
let quality_resource = QualityReportResource::new();
let content = quality_resource.read("quality://report/1").await.unwrap();
assert!(!content.uri.is_empty());
}
#[tokio::test]
async fn test_resources_handle_empty_uri() {
let registry = Arc::new(AgentRegistry::new());
let agent_resource = AgentStateResource::new(Arc::clone(®istry));
let content = agent_resource.read("").await.unwrap();
assert_eq!(content.uri, "");
let metrics_resource = MetricsResource::new(Arc::clone(®istry));
let content = metrics_resource.read("").await.unwrap();
assert_eq!(content.uri, "");
let quality_resource = QualityReportResource::new();
let content = quality_resource.read("").await.unwrap();
assert_eq!(content.uri, "");
}
#[tokio::test]
async fn test_resources_handle_special_characters_in_uri() {
let registry = Arc::new(AgentRegistry::new());
let agent_resource = AgentStateResource::new(registry);
let uri = "agent://state/test-agent_with.special+chars";
let content = agent_resource.read(uri).await.unwrap();
assert_eq!(content.uri, uri);
}
#[tokio::test]
async fn test_resources_handle_unicode_in_uri() {
let registry = Arc::new(AgentRegistry::new());
let agent_resource = AgentStateResource::new(registry);
let uri = "agent://state/日本語テスト";
let content = agent_resource.read(uri).await.unwrap();
assert_eq!(content.uri, uri);
}
#[tokio::test]
async fn test_resources_handle_very_long_uri() {
let registry = Arc::new(AgentRegistry::new());
let long_id = "x".repeat(1000);
let agent_resource = AgentStateResource::new(registry);
let uri = format!("agent://state/{}", long_id);
let content = agent_resource.read(&uri).await.unwrap();
assert_eq!(content.uri, uri);
}
#[test]
fn test_resource_template_clone() {
let resource = QualityReportResource::new();
let template = resource.template();
let cloned = template.clone();
assert_eq!(template.uri_template, cloned.uri_template);
assert_eq!(template.name, cloned.name);
assert_eq!(template.description, cloned.description);
assert_eq!(template.mime_type, cloned.mime_type);
}
#[tokio::test]
async fn test_resource_content_clone() {
let resource = QualityReportResource::new();
let content = resource.read("quality://report/test").await.unwrap();
let cloned = content.clone();
assert_eq!(content.uri, cloned.uri);
assert_eq!(content.mime_type, cloned.mime_type);
}
}