Skip to content

Add unit tests for internal packages#2656

Open
abrarshivani wants to merge 13 commits into
NVIDIA:mainfrom
abrarshivani:unit-test-internal
Open

Add unit tests for internal packages#2656
abrarshivani wants to merge 13 commits into
NVIDIA:mainfrom
abrarshivani:unit-test-internal

Conversation

@abrarshivani

@abrarshivani abrarshivani commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Description

Adds unit tests to raise coverage across the internal/ packages, plus a few small production changes noted below. Each package was driven to full statement coverage of every reachable path (both success and error paths), verified with go test -covermode=count.

Packages covered

  • internal/imageImagePath: tag vs sha256: digest joining, kbld image pass-through, CR-over-env priority, env fallback, and the error paths (unset/empty env, and incomplete-spec validation — see below). 100%
  • internal/infoGetVersionParts / GetVersionString: with/without gitCommit, empty/whitespace values, variadic joining, fresh-slice / no-mutation guarantees. 100%
  • internal/conditions — ClusterPolicy and NVIDIADriver updaters: Ready/Error success, type-assertion guard, failed-Get, unknown-status-type default, retry-on-conflict, non-conflict update-error propagation, and status.state defaulting/preservation. Uses the controller-runtime fake client + interceptors; condition assertions use cmp.Diff; schemes are built per-test. 100%
  • internal/utilsGetFilesWithSuffix (recursion, multiple suffixes, no-match, traversal error, empty dir, file-as-base, multi-suffix match) and the object-hash helpers. 100%
  • internal/nodeinfo — the previously untested Reset methods on both filter builders. 100%
  • internal/validatorValidate error paths (driver-list failure, invalid listed selector, node-list failure). 100%
  • internal/nvidiadriverAssignOwners error paths (driver-list, node-list, owner-label patch add/remove). 98.5% (one unreachable nil-map guard).

Production changes

While writing the tests, a few production issues surfaced that were fixed rather than characterized in the tests:

  1. internal/utils/utils.goGetStringHash: removed an unreachable error branch. fnv.New32a's Write never returns an error (per the hash.Hash contract), so the error check and the panic it guarded were dead code.
  2. internal/image/image.go + api/nvidia/v1/clusterpolicy_types.goImagePath/imagePath: reject an incomplete CR spec instead of emitting an invalid reference. Previously, when a component set repository or version but left repository or image empty, the parts were concatenated into a malformed ref like "/image:tag", "repo/:tag", or "/@sha256:...", which only failed much later at image pull with an opaque error. Both (duplicated) implementations now return a clear "invalid image specification: both repository and image must be set" error. The kbld/carvel passthrough (repository and version both empty) and the env-var fallback are unchanged.
  3. internal/utils/utils.goGetFilesWithSuffix: deduplicate results. The function appended a path once per matching suffix, so a file matching more than one of the provided suffixes was returned multiple times. It now breaks after the first matching suffix (behavior-identical for the only current caller, which passes the non-overlapping yaml/yml/json).
  4. internal/utils/utils.goGetObjectHashIgnoreEmptyKeys: documented (no behavior change) that the argument must be a struct or pointer-to-struct and that other kinds/nil panic, matching what all callers already pass.

Tests were updated to match: the former characterization cases that asserted the malformed ImagePath output and the duplicated GetFilesWithSuffix result now assert the corrected behavior, and a new api/nvidia/v1 test covers ImagePath.

Checklist

  • No secrets, sensitive information, or unrelated changes
  • Lint checks passing (make lint)
  • 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

go test ./internal/... ./api/... ./controllers/... -covermode=count
golangci-lint run ./...     # 0 issues (run with GOOS=linux; pathrs-lite is Linux-only)

internal/image, info, conditions, utils, nodeinfo, validator at 100%; nvidiadriver at 98.5% (one intentional defensive guard). Affected suites (api, controllers, internal/state) all pass with the production changes — no caller relied on the malformed-path or duplicate-file behavior.

@copy-pr-bot

copy-pr-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@abrarshivani abrarshivani changed the title Add unit tests for internal/image and internal/info Add unit tests for internal packages Jul 22, 2026
@abrarshivani abrarshivani self-assigned this Jul 22, 2026
@abrarshivani
abrarshivani marked this pull request as ready for review July 22, 2026 20:50
Add table-driven unit tests covering the previously untested
internal/image (ImagePath) and internal/info (GetVersionParts,
GetVersionString) packages.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Cover positive and negative edge cases:
- internal/image: tag vs digest selection (including empty digest, missing
  colon, and case-sensitive sha256 prefix), kbld passthrough, partial-CR
  paths taking priority over env, env fallback, no-input-validation edges,
  and the error path with its message contents.
- internal/info: empty/whitespace version and commit, variadic joining with
  empty elements, and fresh-slice / no-mutation guarantees.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Cover every path in clusterpolicy.go: SetConditionsReady/SetConditionsError
success cases, the type-assertion guard for non-ClusterPolicy objects, the
Ready->Error transition, the failed-Get path, the unknown-status-type default
branch, retry-on-conflict, and non-conflict status-update error propagation.
clusterpolicy.go reaches 100% statement coverage.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Cover the paths in nvidiadriver.go not exercised by the existing tests:
the type-assertion guard for non-NVIDIADriver objects, the failed-Get path,
the unknown-status-type default branch, retry-on-conflict, non-conflict
status-update error propagation, and the status.state defaulting/preservation
logic in the Error case. The internal/conditions package now reaches 100%
statement coverage.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Cover the previously untested GetFilesWithSuffix: recursive matching across
subdirectories, multiple suffixes, no-match and no-suffix cases, the
traversal-error path for a missing directory, an empty directory, a file
passed as the base path, and a file matching more than one suffix.

The only remaining uncovered line in the package is the defensive panic in
GetStringHash, which is unreachable: fnv.New32a's Write never returns an
error and the hasher is constructed internally.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
fnv.New32a's Write never returns an error (guaranteed by the hash.Hash
contract: "Write ... never returns an error"), so the error check and the
panic it guarded were dead code that could never execute. Drop them and
ignore the always-nil error explicitly. This makes internal/utils reach
100% statement coverage.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Cover the previously untested Reset methods on NodeLabelFilterBuilder and
NodeLabelNoValFilterBuilder, verifying that Reset clears accumulated label
criteria. internal/nodeinfo now reaches 100% statement coverage.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Cover the driver-list failure, GPU-node-list failure, and owner-label patch
failures for both the add/update and removal cases, using fake-client
interceptors. The only remaining uncovered line is the defensive nil-Labels
guard, which is unreachable in AssignOwners because nodes are listed by the
GPU-present label and therefore always carry labels.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Cover the driver-list failure, an invalid nodeSelector on a listed driver,
and the node-list failure. internal/validator now reaches 100% statement
coverage.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Address maintainer naming preference (avoid abbreviations, per review
feedback on prior unit-test PRs): rename the local cp variable to
clusterPolicy in clusterpolicy_test.go.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
Adopt Kubernetes-idiomatic testing patterns in the conditions and validator
tests:
- Replace field-by-field metav1.Condition assertions with a single
  cmp.Diff against the expected condition slice (ignoring server-set
  LastTransitionTime/ObservedGeneration), which reads clearer and prints a
  precise diff on failure.
- Build a fresh runtime.NewScheme() per test instead of mutating the global
  client-go scheme.Scheme, keeping the tests hermetic.

Promotes github.com/google/go-cmp to a direct dependency and vendors
cmp/cmpopts. Coverage unchanged (100%).

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
…d refs

When a CR component sets repository or version but leaves repository or image
empty, ImagePath previously concatenated the parts into a structurally invalid
reference such as "/image:tag", "repo/:tag" or "/@sha256:...". These
malformed paths would only fail much later at image pull with an opaque error.

Validate the branch that builds "repo/image:tag"/"@digest" and return a
clear error when repository or image is empty, in both image.ImagePath
(internal/image) and the duplicated api/nvidia/v1 imagePath used by
v1.ImagePath. The kbld/carvel passthrough (repository and version both empty)
and the env-var fallback are unchanged.

Update the internal/image tests: the former characterization cases that
asserted the malformed output now assert the validation error, and add an
api/nvidia/v1 test covering ImagePath's valid, kbld, incomplete-spec and
unsupported-type paths.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
GetFilesWithSuffix appended a path once per matching suffix, so a file that
matched more than one of the provided suffixes was returned multiple times.
Break after the first matching suffix so each file is returned at most once;
this is behavior-identical for non-overlapping suffixes (the only current
caller passes yaml/yml/json). Update the test to assert the single result.

Also document that GetObjectHashIgnoreEmptyKeys requires a struct (or pointer
to struct) and panics on other kinds, matching what all callers already pass.

Signed-off-by: Abrar Shivani <ashivani@nvidia.com>
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.

1 participant