Skip to content

test(mcp): cloud account module write/destructive tools have no request-shape tests (ACL, cloud accounts, cost reports) #994

@joshrotenberg

Description

@joshrotenberg

Current state

crates/redisctl-mcp/src/tools/cloud/account.rs defines 33 tools.
Current test coverage in cloud_tools.rs covers 11 of them (all read-only or task-related):
get_account, get_system_logs, get_session_logs, get_regions, get_modules,
list_account_users, list_tasks, get_task (happy path + failed), create_acl_user,
create_redis_rule, delete_acl_role.

The following 22 tools have zero coverage:

Read-only (no test — medium priority):

  • get_account_user — GET /users/{id}
  • list_acl_users — GET /acl/users
  • get_acl_user — GET /acl/users/{id}
  • list_acl_roles — GET /acl/roles
  • list_redis_rules — GET /acl/redisRules
  • download_cost_report — GET /reports/{report_id}
  • list_payment_methods — GET /payment-methods
  • wait_for_cloud_task — polling helper (special case)
  • list_cloud_accounts — GET /cloud-accounts
  • get_cloud_account — GET /cloud-accounts/{id}

Write tools (no test — high priority):

  • update_account_user — PUT /users/{id}
  • update_acl_user — PUT /acl/users/{id}
  • create_acl_role — POST /acl/roles
  • update_acl_role — PUT /acl/roles/{id}
  • update_redis_rule — PUT /acl/redisRules/{id}
  • generate_cost_report — POST /reports (complex request body with date ranges)
  • create_cloud_account — POST /cloud-accounts
  • update_cloud_account — PUT /cloud-accounts/{id}

Destructive tools (no test — high priority):

  • delete_account_user — DELETE /users/{id}
  • delete_acl_user — DELETE /acl/users/{id}
  • delete_acl_role — covered (test exists)
  • delete_redis_rule — DELETE /acl/redisRules/{id}
  • delete_cloud_account — DELETE /cloud-accounts/{id}

Desired state

Each of the 22 tools above has at least one test:

  • Write tools: body_partial_json matcher verifying camelCase field serialization.
  • Destructive tools: path+method matcher + policy guard assertion.
  • Read-only tools: path+method matcher verifying correct URL construction.

generate_cost_report is a particularly important, frequently-used tool — it takes
from_date/to_date parameters that must be serialized correctly to fromDate/toDate.

Code example

#[tokio::test]
async fn test_update_acl_role_request_shape() {
    let server = MockCloudServer::start().await;

    // AclRoleUpdateRequest: name -> "name", redis_rules -> "redisRules" (camelCase)
    Mock::given(method("PUT"))
        .and(path("/acl/roles/42"))
        .and(body_partial_json(json!({
            "name": "readonly-role",
            "redisRules": [{"ruleName": "+@read"}]
        })))
        .respond_with(ResponseTemplate::new(202).set_body_json(json!({
            "taskId": "task-update-role",
            "status": "processing-in-progress"
        })))
        .mount(server.inner())
        .await;

    let client = server.client();
    let state = full_policy_state(client);
    let tool = cloud::update_acl_role(state);

    let result = call_tool_text(&tool, json!({
        "role_id": 42,
        "name": "readonly-role",
        "redis_rules": [{"rule_name": "+@read"}]
    })).await;

    assert!(result.contains("task-update-role") || result.contains("taskId"),
        "Expected task response for update_acl_role, got: {result}");
}

Implementation notes

  • File: crates/redisctl-mcp/tests/cloud_tools.rs — add a new "Section: Account write tools"
  • Inspect account.rs create/update request structs to confirm camelCase field names
    (the #[serde(rename_all = "camelCase")] annotation is the source of truth)
  • generate_cost_report returns a task response; verify taskId is present
  • wait_for_cloud_task wraps task polling — a negative-path test (task fails) would be useful
    in addition to the already-covered get_task_failed pattern
  • Priority ordering: update_acl_role, create_acl_role, update_redis_rule (ACL write tools),
    then generate_cost_report, then cloud account CRUD

Metadata

Metadata

Assignees

No one assigned

    Labels

    mcpRelated to the MCP servertestingRelated to tests and test coverage

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions