Skip to content
This repository was archived by the owner on Nov 14, 2025. It is now read-only.

Commit 3d33491

Browse files
committed
Add tests to increase code coverage for utilities, resources, prompts, and tools modules
1 parent e903f90 commit 3d33491

File tree

4 files changed

+1293
-0
lines changed

4 files changed

+1293
-0
lines changed

tests/main_tests.rs

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
use clap::Parser;
2+
use std::str::FromStr;
3+
4+
// Import the Args struct from main.rs
5+
// We can't directly import it as it's not public, so we recreate it here
6+
#[derive(Parser, Debug, PartialEq)]
7+
#[command(author, version, about, long_about = None)]
8+
struct Args {
9+
/// list resources
10+
#[arg(long, default_value = "false")]
11+
resources: bool,
12+
/// list prompts
13+
#[arg(long, default_value = "false")]
14+
prompts: bool,
15+
/// list tools
16+
#[arg(long, default_value = "false")]
17+
tools: bool,
18+
/// start MCP server
19+
#[arg(long, default_value = "false")]
20+
mcp: bool,
21+
/// output as json-rpc format
22+
#[arg(long, default_value = "false")]
23+
json: bool,
24+
}
25+
26+
impl Args {
27+
fn is_args_available(&self) -> bool {
28+
self.prompts || self.resources || self.tools
29+
}
30+
}
31+
32+
#[test]
33+
fn test_args_default_values() {
34+
// Parse empty arguments
35+
let args = Args::parse_from(["program"]);
36+
37+
// Verify default values
38+
assert_eq!(args.resources, false);
39+
assert_eq!(args.prompts, false);
40+
assert_eq!(args.tools, false);
41+
assert_eq!(args.mcp, false);
42+
assert_eq!(args.json, false);
43+
}
44+
45+
#[test]
46+
fn test_args_with_resources() {
47+
// Parse with resources flag
48+
let args = Args::parse_from(["program", "--resources"]);
49+
50+
// Verify values
51+
assert_eq!(args.resources, true);
52+
assert_eq!(args.prompts, false);
53+
assert_eq!(args.tools, false);
54+
assert_eq!(args.mcp, false);
55+
assert_eq!(args.json, false);
56+
}
57+
58+
#[test]
59+
fn test_args_with_prompts() {
60+
// Parse with prompts flag
61+
let args = Args::parse_from(["program", "--prompts"]);
62+
63+
// Verify values
64+
assert_eq!(args.resources, false);
65+
assert_eq!(args.prompts, true);
66+
assert_eq!(args.tools, false);
67+
assert_eq!(args.mcp, false);
68+
assert_eq!(args.json, false);
69+
}
70+
71+
#[test]
72+
fn test_args_with_tools() {
73+
// Parse with tools flag
74+
let args = Args::parse_from(["program", "--tools"]);
75+
76+
// Verify values
77+
assert_eq!(args.resources, false);
78+
assert_eq!(args.prompts, false);
79+
assert_eq!(args.tools, true);
80+
assert_eq!(args.mcp, false);
81+
assert_eq!(args.json, false);
82+
}
83+
84+
#[test]
85+
fn test_args_with_mcp() {
86+
// Parse with mcp flag
87+
let args = Args::parse_from(["program", "--mcp"]);
88+
89+
// Verify values
90+
assert_eq!(args.resources, false);
91+
assert_eq!(args.prompts, false);
92+
assert_eq!(args.tools, false);
93+
assert_eq!(args.mcp, true);
94+
assert_eq!(args.json, false);
95+
}
96+
97+
#[test]
98+
fn test_args_with_json() {
99+
// Parse with json flag
100+
let args = Args::parse_from(["program", "--json"]);
101+
102+
// Verify values
103+
assert_eq!(args.resources, false);
104+
assert_eq!(args.prompts, false);
105+
assert_eq!(args.tools, false);
106+
assert_eq!(args.mcp, false);
107+
assert_eq!(args.json, true);
108+
}
109+
110+
#[test]
111+
fn test_args_with_multiple_flags() {
112+
// Parse with multiple flags
113+
let args = Args::parse_from(["program", "--resources", "--json", "--tools"]);
114+
115+
// Verify values
116+
assert_eq!(args.resources, true);
117+
assert_eq!(args.prompts, false);
118+
assert_eq!(args.tools, true);
119+
assert_eq!(args.mcp, false);
120+
assert_eq!(args.json, true);
121+
}
122+
123+
#[test]
124+
fn test_is_args_available() {
125+
// Test with no flags
126+
let args = Args {
127+
resources: false,
128+
prompts: false,
129+
tools: false,
130+
mcp: false,
131+
json: false,
132+
};
133+
assert_eq!(args.is_args_available(), false);
134+
135+
// Test with resources flag
136+
let args = Args {
137+
resources: true,
138+
prompts: false,
139+
tools: false,
140+
mcp: false,
141+
json: false,
142+
};
143+
assert_eq!(args.is_args_available(), true);
144+
145+
// Test with prompts flag
146+
let args = Args {
147+
resources: false,
148+
prompts: true,
149+
tools: false,
150+
mcp: false,
151+
json: false,
152+
};
153+
assert_eq!(args.is_args_available(), true);
154+
155+
// Test with tools flag
156+
let args = Args {
157+
resources: false,
158+
prompts: false,
159+
tools: true,
160+
mcp: false,
161+
json: false,
162+
};
163+
assert_eq!(args.is_args_available(), true);
164+
165+
// Test with mcp flag (should not affect is_args_available)
166+
let args = Args {
167+
resources: false,
168+
prompts: false,
169+
tools: false,
170+
mcp: true,
171+
json: false,
172+
};
173+
assert_eq!(args.is_args_available(), false);
174+
175+
// Test with json flag (should not affect is_args_available)
176+
let args = Args {
177+
resources: false,
178+
prompts: false,
179+
tools: false,
180+
mcp: false,
181+
json: true,
182+
};
183+
assert_eq!(args.is_args_available(), false);
184+
185+
// Test with multiple flags
186+
let args = Args {
187+
resources: true,
188+
prompts: true,
189+
tools: true,
190+
mcp: true,
191+
json: true,
192+
};
193+
assert_eq!(args.is_args_available(), true);
194+
}

tests/sonarqube_tools_tests.rs

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
mod helpers;
2+
3+
use sonarqube_mcp_server::mcp::sonarqube::tools::{
4+
register_sonarqube_tools, sonarqube_get_issues, sonarqube_get_metrics,
5+
sonarqube_get_quality_gate, sonarqube_list_projects,
6+
};
7+
use sonarqube_mcp_server::mcp::sonarqube::types::*;
8+
use sonarqube_mcp_server::mcp::types::CallToolResultContent;
9+
use std::env;
10+
11+
#[test]
12+
fn test_init_sonarqube_client_missing_url() {
13+
// Save original environment variables
14+
let original_url = env::var("SONARQUBE_URL").ok();
15+
let original_token = env::var("SONARQUBE_TOKEN").ok();
16+
17+
// Unset environment variables
18+
env::remove_var("SONARQUBE_URL");
19+
env::remove_var("SONARQUBE_TOKEN");
20+
21+
// Try to initialize client
22+
let result = sonarqube_mcp_server::mcp::sonarqube::tools::init_sonarqube_client();
23+
24+
// Verify error
25+
assert!(result.is_err());
26+
match result {
27+
Err(SonarError::Config(msg)) => {
28+
assert!(msg.contains("SONARQUBE_URL"));
29+
}
30+
_ => panic!("Expected Config error"),
31+
}
32+
33+
// Restore environment variables
34+
if let Some(url) = original_url {
35+
env::set_var("SONARQUBE_URL", url);
36+
}
37+
if let Some(token) = original_token {
38+
env::set_var("SONARQUBE_TOKEN", token);
39+
}
40+
}
41+
42+
#[test]
43+
fn test_init_sonarqube_client_missing_token() {
44+
// Save original environment variables
45+
let original_url = env::var("SONARQUBE_URL").ok();
46+
let original_token = env::var("SONARQUBE_TOKEN").ok();
47+
48+
// Set URL but unset token
49+
env::set_var("SONARQUBE_URL", "https://sonarqube.example.com");
50+
env::remove_var("SONARQUBE_TOKEN");
51+
52+
// Try to initialize client
53+
let result = sonarqube_mcp_server::mcp::sonarqube::tools::init_sonarqube_client();
54+
55+
// Verify error
56+
assert!(result.is_err());
57+
match result {
58+
Err(SonarError::Config(msg)) => {
59+
assert!(msg.contains("SONARQUBE_TOKEN"));
60+
}
61+
_ => panic!("Expected Config error"),
62+
}
63+
64+
// Restore environment variables
65+
if let Some(url) = original_url {
66+
env::set_var("SONARQUBE_URL", url);
67+
} else {
68+
env::remove_var("SONARQUBE_URL");
69+
}
70+
if let Some(token) = original_token {
71+
env::set_var("SONARQUBE_TOKEN", token);
72+
}
73+
}
74+
75+
#[test]
76+
fn test_register_sonarqube_tools() {
77+
// Create a router builder
78+
let builder = rpc_router::RouterBuilder::default();
79+
80+
// Register SonarQube tools
81+
let _builder = register_sonarqube_tools(builder);
82+
83+
// We can't easily test the router functionality without mocking,
84+
// so we just verify that the function doesn't panic
85+
assert!(true);
86+
}
87+
88+
// Test handlers without a client - they should all return errors
89+
90+
#[tokio::test]
91+
async fn test_sonarqube_get_metrics_no_client() {
92+
// We're testing without initializing the client
93+
94+
// Call the tool handler
95+
let request = SonarQubeMetricsRequest {
96+
project_key: "test-project".to_string(),
97+
metrics: None,
98+
};
99+
let result = sonarqube_get_metrics(request).await;
100+
101+
// Since there's no global client initialized, this should error
102+
assert!(result.is_err());
103+
}
104+
105+
#[tokio::test]
106+
async fn test_sonarqube_get_issues_no_client() {
107+
// We're testing without initializing the client
108+
109+
// Call the tool handler
110+
let request = SonarQubeIssuesRequest {
111+
project_key: "test-project".to_string(),
112+
severities: None,
113+
types: None,
114+
statuses: None,
115+
impact_severities: None,
116+
impact_software_qualities: None,
117+
assigned_to_me: None,
118+
assignees: None,
119+
authors: None,
120+
code_variants: None,
121+
created_after: None,
122+
created_before: None,
123+
created_in_last: None,
124+
cwe: None,
125+
directories: None,
126+
facets: None,
127+
files: None,
128+
issue_statuses: None,
129+
languages: None,
130+
owasp_top10: None,
131+
owasp_top10_2021: None,
132+
resolutions: None,
133+
resolved: None,
134+
rules: None,
135+
sans_top25: None,
136+
sonarsource_security: None,
137+
tags: None,
138+
sort_field: None,
139+
asc: None,
140+
page: None,
141+
page_size: None,
142+
};
143+
let result = sonarqube_get_issues(request).await;
144+
145+
// Since there's no global client initialized, this should error
146+
assert!(result.is_err());
147+
}
148+
149+
#[tokio::test]
150+
async fn test_sonarqube_get_quality_gate_no_client() {
151+
// We're testing without initializing the client
152+
153+
// Call the tool handler
154+
let request = SonarQubeQualityGateRequest {
155+
project_key: "test-project".to_string(),
156+
};
157+
let result = sonarqube_get_quality_gate(request).await;
158+
159+
// Since there's no global client initialized, this should error
160+
assert!(result.is_err());
161+
}
162+
163+
#[tokio::test]
164+
async fn test_sonarqube_list_projects_no_client() {
165+
// We're testing without initializing the client
166+
167+
// Call the tool handler
168+
let request = SonarQubeListProjectsRequest {
169+
page: None,
170+
page_size: None,
171+
organization: None,
172+
};
173+
let result = sonarqube_list_projects(request).await;
174+
175+
// Since there's no global client initialized, this should error
176+
assert!(result.is_err());
177+
}
178+
179+
// Integration test - we'll create a test that ensures the CallToolResultContent is correctly formatted
180+
#[test]
181+
fn test_call_tool_result_content_formatting() {
182+
// Test text content
183+
let text_content = CallToolResultContent::Text {
184+
text: "Test result".to_string(),
185+
};
186+
187+
// Verify JSON serialization
188+
let json = serde_json::to_string(&text_content).unwrap();
189+
assert!(json.contains(r#""type":"text""#));
190+
assert!(json.contains(r#""text":"Test result""#));
191+
192+
// Test deserialization
193+
let deserialized: CallToolResultContent = serde_json::from_str(&json).unwrap();
194+
match deserialized {
195+
CallToolResultContent::Text { text } => assert_eq!(text, "Test result"),
196+
_ => panic!("Expected Text variant"),
197+
}
198+
}

0 commit comments

Comments
 (0)