Skip to content

Add unit tests for internal/conditions/gpucluster - #2889

Open
abrarshivani wants to merge 1 commit into
NVIDIA:mainfrom
abrarshivani:unit-test-gpucluster-conditions
Open

abrarshivani wants to merge 1 commit into
NVIDIA:mainfrom
abrarshivani:unit-test-gpucluster-conditions

Conversation

@abrarshivani

Copy link
Copy Markdown
Contributor

Description

internal/conditions/gpucluster.go had no unit tests. This adds them, taking the
conditions package from 64.6% to 100.0% of statements. Tests only, no production
code changed.

They follow the shape of the existing nvidiadriver_test.go and
clusterpolicy_test.go: fake client with a status subresource for the happy paths,
interceptor.Funcs to inject a conflict on the first status update and a plain
failure on every one.

gpucluster.go largely mirrors nvidiadriver.go. The one real difference is how the
error branch resolves status.state:

// nvidiadriver.go                          // gpucluster.go
instance.Status.State = cr.Status.State     if instance.Status.State == "" {
                                                instance.Status.State = cr.Status.State
                                            }

NVIDIADriverReconciler sets status.state in memory without persisting it and then
writes conditions, so its updater has to copy the caller's value over.
GPUClusterReconciler.updateCRStatus persists the desired state first, so the stored
value is already authoritative and is only filled in when empty. Both are correct for
their own controller, and neither was covered. SetConditionsErrorStateResolution
covers the four combinations of stored and caller state;
SetConditionsReadyLeavesStateAlone covers the ready branch, which does not touch
status.state at all.

Not addressed here because it needs a production change: a typed-nil
*nvidiav1alpha1.GPUCluster satisfies the type assertion in SetConditionsReady and
SetConditionsError and then panics on cr.Name. All three updaters in this package
share that gap.

Checklist

  • No secrets, sensitive information, or unrelated changes
  • Lint checks passing (make lint) — no new findings. make lint does report 3
    pre-existing staticcheck deprecation warnings in controllers/object_controls.go
    and internal/state/driver_volumes.go; both files are untouched by this PR and the
    warnings are present on main.
  • Generated assets in-sync (make validate-generated-assets)
  • Go mod artifacts in-sync (make validate-modules)
  • Test cases are added for new code paths

Testing

Unit tests only.

  • 12 tests, 16 subtests, passing under -race
  • gpucluster.go at 100% of statements, every function; package 64.6% to 100.0%
  • Every assertion was checked for liveness by mutating gpucluster.go and confirming
    a test fails: 11 mutants, all killed. One assertion did not start out live.
    GetError matched only the wrapper text, so a %w to %v regression survived; it
    now asserts apierrors.IsNotFound through the wrapper. RetryOnConflict counts
    Get calls as well as update calls, which is what distinguishes a refetch inside
    the retry loop from one hoisted out of it.

Takes the conditions package from 64.6% to 100.0% of statements. Tests
only, no production source changed.

The tests follow the shape already used by nvidiadriver_test.go and
clusterpolicy_test.go: the controller-runtime fake client with a status
subresource for the happy paths, and interceptor.Funcs to inject a
conflict on the first status update and a plain failure on every one, so
the retry wrapper and the error return are exercised rather than restated.

Most of gpucluster.go mirrors nvidiadriver.go, so most of these tests
mirror its tests. The one place the two genuinely diverge is how the error
branch resolves status.state, and that is what the bulk of the new
assertions pin. NVIDIADriverReconciler sets status.state in memory without
persisting it and then writes conditions, so its updater has to copy the
caller's value over unconditionally. GPUClusterReconciler.updateCRStatus
persists the desired state before every SetConditionsError call, so the
stored value is already authoritative and the updater only fills it in
when empty. SetConditionsErrorStateResolution covers the four combinations
of stored and caller state, and SetConditionsReadyLeavesStateAlone covers
the ready branch, which does not touch status.state at all. Together they
fail if the two updaters are ever folded into one without accounting for
the difference.

GetError asserts apierrors.IsNotFound through the wrapper rather than only
matching the wrapper text, so a %w that regresses to %v is caught.
RetryOnConflict counts Get calls as well as update calls, which is what
actually distinguishes a refetch inside the retry loop from one hoisted
out of it.

The error logged in setConditions before the return is not asserted.
Checking it needs a log sink and the returned error already covers the
same path. The backoff policy in retry.RetryOnConflict is not asserted
either; the tests check that a conflict is retried and that a non-conflict
error is not, which is the part this package owns.

A typed-nil *nvidiav1alpha1.GPUCluster satisfies the type assertion in
SetConditionsReady and SetConditionsError and then panics on cr.Name. All
three updaters in this package share that gap, so fixing it belongs in a
change that can touch production code.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 413459ac-9eee-4cfd-bc71-22d86b6e35ef

📥 Commits

Reviewing files that changed from the base of the PR and between 3fc63e2 and cae1579.

📒 Files selected for processing (1)
  • internal/conditions/gpucluster_test.go

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.


📝 Walkthrough

Walkthrough

Added comprehensive tests for the GPUCluster condition updater. The tests cover construction, object validation, not-found errors, ready and error transitions, status resolution, state preservation, unknown status errors, conflict retries with refetching, and non-conflict update failures.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to cae15

The added tests do not introduce an actionable merge risk.


Comment @coderabbitai help to get the list of available commands.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@rahulait

Copy link
Copy Markdown
Contributor

@coderabbitai approve

@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

@abrarshivani abrarshivani self-assigned this Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants