-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Test Gap Analysis
Test suite snapshot: 240 unit tests, 23 integration tests (9 compiler + 5 mcp_firewall + 9 proxy), 4 test fixtures
Previous gaps from the last run (types.rs, execute.rs, common.rs trigger functions, pipeline-trigger fixture) have been resolved in commit d767022. This cycle audited the remaining helpers.
Priority Gaps
| Module | Function/Path | Why It Matters | Suggested Test |
|---|---|---|---|
compile/standalone.rs |
generate_allowed_domains |
Security-critical β determines which hosts agents can reach over the network; wrong output lets agents exfiltrate data | Test that default hosts appear, user-specified network.allow entries are appended, and MCP-specific hosts are included |
compile/onees.rs |
generate_mcp_configuration |
Security-relevant β controls which MCP service connections are wired up in 1ES pipelines; custom MCPs should be silently excluded | Test that Enabled(true) MCPs generate service connection YAML, custom MCPs with command: are filtered out, and Enabled(false) MCPs are skipped |
compile/onees.rs |
All 5 helpers + no 1ES integration test | The 1ES compile path (target: 1es) has no integration test verifying zero unreplaced \{\{ marker }} tokens in output |
Add a test mirroring test_compiled_output_no_unreplaced_markers but compiling fixtures/1es-test-agent.md |
mcp_metadata.rs |
has_tool, get_tools, builtin_mcp_names, tool_names |
has_tool is used by the firewall for allow-list enforcement; a wrong result could expose or block tools unexpectedly |
Test known tool names return true, unknown names return false, non-existent MCPs return false |
compile/common.rs |
generate_source_path, generate_pipeline_path |
These paths feed into Stage 2 execution and integrity checks; wrong paths cause silent runtime failures | Test root vs repo workspace produces correct $(Build.SourcesDirectory) prefix |
compile/standalone.rs |
generate_acquire_ado_token, generate_copilot_ado_env |
These inject secrets into the pipeline β wrong output leaks tokens or breaks auth | Test None service connection β empty string; Some("my-conn") β contains correct AzureCLI@2 step and env vars |
Suggested Test Cases
1. generate_allowed_domains β network allow-list includes user hosts and MCP hosts
#[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 should appear");
assert!(domains.contains("github.com"), "core hosts should always appear");
}
#[test]
fn test_generate_allowed_domains_includes_mcp_hosts() {
let mut fm = minimal_front_matter();
fm.mcp_servers.insert("kusto".to_string(), McpConfig::Enabled(true));
let domains = generate_allowed_domains(&fm);
// kusto MCP requires its own endpoints
assert!(!domains.is_empty());
assert!(domains.contains("github.com"));
}2. generate_mcp_configuration (onees.rs) β service connections and custom MCP exclusion
#[test]
fn test_generate_mcp_configuration_builtin_enabled() {
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("serviceConnection: mcp-ado-service-connection"));
}
#[test]
fn test_generate_mcp_configuration_custom_mcp_excluded() {
let mut mcps = HashMap::new();
mcps.insert("my-tool".to_string(), McpConfig::WithOptions(McpOptions {
command: Some("node".to_string()),
args: vec!["server.js".to_string()],
allowed: vec!["*".to_string()],
..Default::default()
}));
let result = generate_mcp_configuration(&mcps);
assert!(!result.contains("my-tool"), "custom MCPs must be excluded from 1ES config");
}
#[test]
fn test_generate_mcp_configuration_disabled_mcp_excluded() {
let mut mcps = HashMap::new();
mcps.insert("ado".to_string(), McpConfig::Enabled(false));
let result = generate_mcp_configuration(&mcps);
assert!(!result.contains("ado:"));
}3. 1ES integration test β no unreplaced markers
#[test]
fn test_1es_fixture_compiled_output_no_unreplaced_markers() {
let fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("fixtures")
.join("1es-test-agent.md");
let output_path = std::env::temp_dir().join("1es-test-agent.yml");
let status = std::process::Command::new(env!("CARGO_BIN_EXE_ado-aw"))
.args(["compile", fixture_path.to_str().unwrap(), "-o", output_path.to_str().unwrap()])
.status()
.expect("Failed to run ado-aw compile");
assert!(status.success(), "1ES compilation should succeed");
let output = fs::read_to_string(&output_path).expect("Should read 1ES output");
// No unreplaced \{\{ markers }} should remain (but $\{\{ }} template expressions are OK)
let unreplaced: Vec<_> = output.lines()
.filter(|l| {
let s = l.trim();
s.contains("\{\{") && !s.contains("$\{\{")
})
.collect();
assert!(unreplaced.is_empty(), "Unreplaced markers found: {:?}", unreplaced);
}4. mcp_metadata.rs β has_tool and get_tools
#[test]
fn test_has_tool_returns_true_for_known_tool() {
let metadata = McpMetadataFile::bundled();
// "ado" MCP should have at least one tool; pick a known one
let tools = metadata.get_tools("ado").expect("ado should have tools");
let first_tool = &tools[0].name;
assert!(metadata.has_tool("ado", first_tool));
}
#[test]
fn test_has_tool_returns_false_for_unknown_tool() {
let metadata = McpMetadataFile::bundled();
assert!(!metadata.has_tool("ado", "nonexistent_tool_xyz"));
}
#[test]
fn test_has_tool_returns_false_for_unknown_mcp() {
let metadata = McpMetadataFile::bundled();
assert!(!metadata.has_tool("nonexistent_mcp", "any_tool"));
}
#[test]
fn test_builtin_mcp_names_returns_only_builtins() {
let metadata = McpMetadataFile::bundled();
let builtins = metadata.builtin_mcp_names();
assert!(builtins.contains(&"ado"));
// All returned names should be marked builtin
for name in &builtins {
let mcp = metadata.get(name).unwrap();
assert!(mcp.builtin, "{} should be builtin", name);
}
}
#[test]
fn test_tool_names_returns_names_for_known_mcp() {
let metadata = McpMetadataFile::bundled();
let names = metadata.tool_names("ado");
assert!(!names.is_empty(), "ado should have tool names");
}
#[test]
fn test_tool_names_returns_empty_for_unknown_mcp() {
let metadata = McpMetadataFile::bundled();
let names = metadata.tool_names("nonexistent");
assert!(names.is_empty());
}5. generate_source_path / generate_pipeline_path (common.rs)
#[test]
fn test_generate_source_path_root_workspace() {
let path = std::path::Path::new("/agents/my-agent.md");
let result = generate_source_path(path);
assert!(result.contains("agents/my-agent.md"));
}
#[test]
fn test_generate_pipeline_path_filename_only() {
let path = std::path::Path::new("/pipelines/my-pipeline.yml");
let result = generate_pipeline_path(path);
assert!(result.contains("my-pipeline.yml"));
assert!(!result.contains("/pipelines/"), "should use workspace-relative path");
}6. generate_acquire_ado_token / generate_copilot_ado_env
#[test]
fn test_generate_acquire_ado_token_none_returns_empty() {
let result = generate_acquire_ado_token(&None);
assert!(result.is_empty());
}
#[test]
fn test_generate_acquire_ado_token_some_returns_azure_cli_step() {
let result = generate_acquire_ado_token(&Some("my-arm-connection".to_string()));
assert!(result.contains("AzureCLI@2"));
assert!(result.contains("my-arm-connection"));
assert!(result.contains("SC_ACCESS_TOKEN"));
}
#[test]
fn test_generate_copilot_ado_env_none_returns_empty() {
let result = generate_copilot_ado_env(&None);
assert!(result.is_empty());
}
#[test]
fn test_generate_copilot_ado_env_some_includes_token_vars() {
let result = generate_copilot_ado_env(&Some("my-conn".to_string()));
assert!(result.contains("AZURE_DEVOPS_EXT_PAT"));
assert!(result.contains("SYSTEM_ACCESSTOKEN"));
assert!(result.contains("SC_ACCESS_TOKEN"));
}Coverage Summary
| Module | Public Fns | Private Fns | Tests | Key Gap |
|---|---|---|---|---|
compile/standalone.rs |
1 | 10 | 7 | generate_allowed_domains and 9 other helpers untested |
compile/onees.rs |
0 (impl via trait) | 5 | 0 | All helpers untested; no 1ES integration test |
mcp_metadata.rs |
7 | 0 | 3 | has_tool, get_tools, builtin_mcp_names, tool_names untested |
compile/common.rs |
22 | 0 | 33 | generate_source_path, generate_pipeline_path, generate_repositories, generate_checkout_steps, replace_with_indent, format_step_yaml untested |
This issue was created by the automated test gap finder. Previous run: 2026-03-09 (resolved in #21). Modules audited this cycle: all 23 source modules. Total tests found: 263 (240 unit + 23 integration).
Generated by Test Gap Finder Β· β·
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request