Skip to content

src/cluster/mod.rs: 0% test coverage on cluster dispatch/handler logic #4

Description

@jordigilh

Summary

src/cluster/mod.rs (the cluster create/delete/list/kubeconfig/load-image/kubectl dispatch and handler layer) has 0% test coverage: no #[cfg(test)] mod tests block exists in the file at all, across 315 lines and 19 top-level functions (dispatch + 6 handle_* command handlers + 12 private helpers for lookup, state upsert, phase transitions, dry-run/success reporting). This is despite the logic being straightforward, unit-testable business logic — cluster-by-name lookup, KIND-name derivation, state upsert/phase transitions, and dry-run reporting — that doesn't require a live KIND cluster to exercise.

Sibling command modules already establish the exact pattern needed here, via the CommandRunner trait's MockRunner test double (src/command/runner.rs):

  • src/command/down.rs — has a #[cfg(test)] mod tests block (228 lines) using MockRunner
  • src/command/up.rs — has a #[cfg(test)] mod tests block (730 lines) using MockRunner
  • src/command/status.rs — has a #[cfg(test)] mod tests block (316 lines) using MockRunner

cluster/mod.rs needs no new test infrastructure — it can drive dispatch() (or the individual handle_* functions) with a MockRunner exactly the way down.rs/up.rs/status.rs already do for kind_ops-backed calls (kind_ops::create_cluster, kind_ops::delete_cluster, kind_ops::list_clusters, kind_ops::get_kubeconfig, kind_ops::load_image, kind_ops::run_kubectl all bottom out in ctx.runner: &dyn CommandRunner calls, per src/cluster/kind.rs).

Evidence

Re-verified against fresh upstream/main (9abe12b, 2026-08-07):

  • src/cluster/mod.rs: 315 lines total, 19 fn/pub fn declarations (line numbers: 25, 47, 71, 94, 100, 112, 133, 150, 163, 168, 184, 203, 212, 235, 247, 258, 269, 280, 300), zero occurrences of cfg(test) or mod tests.
  • Contrast with src/command/down.rs, src/command/up.rs, src/command/status.rs, each of which has its own #[cfg(test)] mod tests block built on crate::command::runner::MockRunner.

Untested logic includes, concretely:

  • lookup_cluster (line 150) — returns ForgeError::Config for an unknown cluster name; the "cluster not found" error path is completely unexercised.
  • upsert_cluster_state (line 184) — the insert-vs-update branch (new cluster vs. existing cluster whose phase changes) has no coverage for either branch.
  • create_if_missing (line 168) and update_phase_gone (line 203) — the phase-transition logic (RunningGone, and short-circuiting when a KIND cluster already exists) is untested.
  • handle_create/handle_delete/handle_load_image dry-run branches (ctx.dry_run short-circuit before touching kind_ops or state) — untested.
  • render_list and report_* helpers' OutputFormat::Json vs. OutputFormat::Text branches — untested.

Risk

  • This is the dispatch/handler layer for a user-facing CLI surface (forge cluster create|delete|list|kubeconfig|load-image|kubectl) with no regression safety net; a change to lookup, state-upsert, or phase-transition logic can silently break dry-run reporting or state consistency and only surface in manual testing or a full E2E run.
  • The gap is inconsistent with this repo's own CONTRIBUTING.md testing requirements ("New capabilities require: 1. Unit tests covering the implementation... A feature without appropriate tests is not complete") and with sibling command modules' established coverage levels.

Suggested fix

Add a #[cfg(test)] mod tests block to src/cluster/mod.rs mirroring the MockRunner-based structure already used in src/command/{down,up,status}.rs:

  1. Unit-test the pure-logic helpers directly (no runner needed): lookup_cluster (found / not-found), upsert_cluster_state (insert vs. update branch), cluster_kind_name.
  2. Integration-style tests for the handle_* functions using MockRunner to stub kind_ops calls (cluster exists / doesn't exist, create success/failure, delete, list, kubeconfig write-to-file vs. stdout, load-image, kubectl passthrough), plus the ctx.dry_run short-circuit branch for each handler that has one.
  3. Cover both OutputFormat::Text and OutputFormat::Json branches in the report_*/render_list helpers.

No new test infrastructure is required; this is a direct application of the existing MockRunner pattern.

Severity: Medium

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions