-
Notifications
You must be signed in to change notification settings - Fork 0
π§ͺ Test gap analysis β 4 persistent gaps in compile/, mcp_metadata.rsΒ #112
Copy link
Copy link
Open
Labels
Description
Test Gap Analysis
Test suite snapshot: 418 unit tests, 29 integration tests (compiler), 5 MCP firewall tests, 9 proxy tests β 461 total. All tests passing. Up 6 since previous run (2026-03-31); the core gaps from issue #22 remain unresolved.
Priority Gaps
| Module | Function/Path | Why It Matters | Suggested Test |
|---|---|---|---|
compile/standalone.rs |
generate_allowed_domains |
Security-critical β controls the egress network allowlist passed to AWF. Wrong domains = agent can reach blocked hosts or be denied needed ones. | Test with MCP enabled (verify MCP hosts included), with network.allow hosts (verify user hosts appended), with blocked-only config |
compile/standalone.rs |
generate_setup_job, generate_teardown_job, generate_prepare_steps, generate_finalize_steps, generate_agentic_depends_on, generate_memory_download, generate_memory_prompt |
7 of 9 non-trivial private helpers have zero tests; only generate_firewall_config is covered |
Test each helper returns correct YAML structure with expected pool/displayName/steps |
compile/onees.rs |
generate_agent_context_root, generate_mcp_configuration, generate_inline_steps, generate_setup_job, generate_teardown_job |
Module has 0 unit tests; single integration test only checks no \{\{ marker }} strings remain |
Unit-test each helper in isolation; add 1ES fixture for setup+teardown |
compile/common.rs |
replace_with_indent, generate_repositories, generate_checkout_steps, generate_source_path, generate_pipeline_path, generate_acquire_ado_token, generate_copilot_ado_env, generate_executor_ado_env, format_step_yaml |
9 public helpers have no unit tests; replace_with_indent is the foundational indent-preserving template substitution used everywhere |
See suggested cases below |
mcp_metadata.rs |
get_tools, has_tool, builtin_mcp_names, tool_names |
4 of 7 public methods untested β metadata lookups are used by the firewall config generator | Test has_tool with known/unknown MCP and tool names; builtin_mcp_names returns only non-custom entries |
Suggested Test Cases
1. generate_allowed_domains β security-critical egress allowlist
#[test]
fn test_generate_allowed_domains_includes_core_hosts() {
let fm = minimal_front_matter(); // no MCPs, no network config
let domains = generate_allowed_domains(&fm);
assert!(domains.contains("dev.azure.com"), "core ADO host must be present");
assert!(domains.contains("github.com"), "core GitHub host must be present");
}
#[test]
fn test_generate_allowed_domains_includes_mcp_hosts() {
let mut fm = minimal_front_matter();
fm.mcp_servers.insert("ado".to_string(), McpConfig::Enabled(true));
let domains = generate_allowed_domains(&fm);
// ado MCP requires *.dev.azure.com β verify it's in the list
assert!(domains.contains("dev.azure.com"));
}
#[test]
fn test_generate_allowed_domains_includes_user_network_allow() {
let mut fm = minimal_front_matter();
fm.network = Some(NetworkConfig { allow: vec!["*.mycompany.com".to_string()], blocked: vec![] });
let domains = generate_allowed_domains(&fm);
assert!(domains.contains("*.mycompany.com"), "user-specified host must be included");
}
#[test]
fn test_generate_allowed_domains_disabled_mcp_not_included() {
let mut fm = minimal_front_matter();
fm.mcp_servers.insert("kusto".to_string(), McpConfig::Enabled(false));
let domains_without = generate_allowed_domains(&fm);
fm.mcp_servers.insert("kusto".to_string(), McpConfig::Enabled(true));
let domains_with = generate_allowed_domains(&fm);
// If kusto adds distinct hosts, the enabled version should have more
let _ = (domains_without, domains_with); // assert host counts or specific kusto domains
}2. replace_with_indent β foundational template substitution
#[test]
fn test_replace_with_indent_preserves_leading_spaces() {
let template = " \{\{ foo }}";
let result = replace_with_indent(template, "\{\{ foo }}", "line1\nline2");
assert_eq!(result, " line1\n line2");
}
#[test]
fn test_replace_with_indent_no_match_returns_original() {
let template = "hello \{\{ bar }}";
let result = replace_with_indent(template, "\{\{ foo }}", "replacement");
assert_eq!(result, "hello \{\{ bar }}");
}
#[test]
fn test_replace_with_indent_empty_replacement_removes_line() {
let template = "before\n \{\{ foo }}\nafter";
let result = replace_with_indent(template, "\{\{ foo }}", "");
assert!(!result.contains("\{\{ foo }}"));
}3. generate_acquire_ado_token β ADO token acquisition step
#[test]
fn test_generate_acquire_ado_token_with_service_connection() {
let result = generate_acquire_ado_token(Some("my-arm-sc"), "SC_READ_TOKEN");
assert!(result.contains("AzureCLI@2"));
assert!(result.contains("my-arm-sc"));
assert!(result.contains("SC_READ_TOKEN"));
assert!(result.contains("issecret=true"), "token must be marked secret");
}
#[test]
fn test_generate_acquire_ado_token_none_returns_empty() {
assert_eq!(generate_acquire_ado_token(None, "SC_READ_TOKEN"), "");
}
#[test]
fn test_generate_copilot_ado_env_with_connection() {
let result = generate_copilot_ado_env(Some("my-sc"));
assert!(result.contains("AZURE_DEVOPS_EXT_PAT: $(SC_READ_TOKEN)"));
assert!(result.contains("SYSTEM_ACCESSTOKEN: $(SC_READ_TOKEN)"));
}
#[test]
fn test_generate_executor_ado_env_none_returns_empty() {
assert_eq!(generate_executor_ado_env(None), "");
}4. mcp_metadata β has_tool / builtin_mcp_names / tool_names
#[test]
fn test_has_tool_known_mcp_and_tool() {
let registry = McpMetadataRegistry::bundled();
// Pick a known built-in MCP (e.g. "ado") and one of its tools
let mcp_name = registry.mcp_names().into_iter().next().unwrap();
let tools = registry.get_tools(mcp_name).unwrap();
let first_tool = tools[0].name.as_str();
assert!(registry.has_tool(mcp_name, first_tool));
}
#[test]
fn test_has_tool_unknown_tool_returns_false() {
let registry = McpMetadataRegistry::bundled();
assert!(!registry.has_tool("ado", "this_tool_does_not_exist_xyz"));
}
#[test]
fn test_builtin_mcp_names_excludes_custom() {
let registry = McpMetadataRegistry::bundled();
let names = registry.builtin_mcp_names();
// builtin names should be non-empty and should not include anything with "custom" marker
assert!(!names.is_empty());
}
#[test]
fn test_tool_names_returns_nonempty_for_known_mcp() {
let registry = McpMetadataRegistry::bundled();
let mcp = registry.mcp_names().into_iter().next().unwrap();
assert!(!registry.tool_names(mcp).is_empty());
}
#[test]
fn test_get_tools_unknown_mcp_returns_none() {
let registry = McpMetadataRegistry::bundled();
assert!(registry.get_tools("nonexistent_mcp_xyz").is_none());
}5. compile/onees.rs β generate_agent_context_root / generate_mcp_configuration
#[test]
fn test_generate_agent_context_root_repo() {
assert_eq!(generate_agent_context_root("repo"), "$(Build.Repository.Name)");
}
#[test]
fn test_generate_agent_context_root_root() {
assert_eq!(generate_agent_context_root("root"), ".");
}
#[test]
fn test_generate_mcp_configuration_single_mcp() {
let mut mcps = HashMap::new();
mcps.insert("ado".to_string(), McpConfig::Enabled(true));
let result = generate_mcp_configuration(&mcps);
assert!(result.contains("ado:"));
assert!(result.contains("mcp-ado-service-connection"));
}
#[test]
fn test_generate_mcp_configuration_custom_mcp_skipped() {
let mut mcps = HashMap::new();
mcps.insert("my-tool".to_string(), McpConfig::WithOptions(McpOptions {
command: Some("node".to_string()),
..Default::default()
}));
let result = generate_mcp_configuration(&mcps);
assert!(!result.contains("my-tool"), "custom MCPs should be excluded from 1ES config");
}Coverage Summary
| Module | Public Fns | Tests | Coverage Estimate |
|---|---|---|---|
compile/standalone.rs |
9 | 7 | ~25% (only generate_firewall_config covered) |
compile/onees.rs |
5 private + 2 trait | 0 unit | 0% unit (1 integration marker check only) |
compile/common.rs |
25 | 37 | ~55% (9 pub fns have zero tests) |
mcp_metadata.rs |
7 | 3 | ~40% (4 methods untested) |
| All other modules | β | 414 | Well-covered |
Automated test gap finder β run 2026-04-01. Previous run: 2026-03-31 (issue #22 closed, gaps unresolved). Modules audited this cycle: all 29 source files. Tests: 461 total (+6 since last run).
Generated by Test Gap Finder Β· β·
Warning
β οΈ Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
dev.azure.com
To allow these domains, add them to the network.allowed list in your workflow frontmatter:
network:
allowed:
- defaults
- "dev.azure.com"See Network Configuration for more information.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Type
Fields
Give feedbackNo fields configured for issues without a type.