Skip to content

CM-902: Add table-driven unit tests and improve coverage#385

Open
anandkuma77 wants to merge 7 commits intoopenshift:masterfrom
anandkuma77:CM-902-add-testcases
Open

CM-902: Add table-driven unit tests and improve coverage#385
anandkuma77 wants to merge 7 commits intoopenshift:masterfrom
anandkuma77:CM-902-add-testcases

Conversation

@anandkuma77
Copy link
Copy Markdown
Contributor

@anandkuma77 anandkuma77 commented Mar 18, 2026

What

Adds or expands _test.go coverage for controller common utilities (client helpers, errors, utils) including fake controller-runtime client tests.
Adds tests for deployment flows (credentials_request, deployment_overrides).
Adds istiocsr utils tests and trustmanager utils / controller tests, using table-driven patterns where appropriate.
Adds operator tests for applyconfigurations (certmanagerconfig, utils) and assets/bindata validation.

Why

Increases confidence when refactoring controllers and shared helpers by locking in current behavior with explicit, maintainable tests.
Table-driven tests make edge cases and regressions easier to see and extend.
Improves coverage in areas that were previously untested or lightly tested, reducing risk for future CM-902–related and general maintenance work.

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 18, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Mar 18, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 18, 2026

Important

Review skipped

Auto reviews are limited based on label configuration.

🚫 Review skipped — only excluded labels are configured. (1)
  • do-not-merge/work-in-progress

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6d95a84b-686b-4505-a973-fcbfccfb5916

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds many new Go unit tests across controller and operator packages covering client wrapping, error classification/conversion, fake client behavior, utility helpers, deployment hooks, resource-diff logic, trustmanager helpers, apply-configuration helpers, and embedded asset APIs; also updates NewClient(manager.Manager) to return an error when passed a nil manager.

Changes

Cohort / File(s) Summary
Controller — common tests & client change
pkg/controller/common/client_test.go, pkg/controller/common/errors_test.go, pkg/controller/common/fakes/fake_ctrl_client_test.go, pkg/controller/common/utils_test.go, pkg/controller/common/client.go
Adds unit tests for NewClient behavior and wrapping; ReconcileError constructors/classifiers/converters; FakeCtrlClient Exists/Get call-capture and behavior; utilities for namespace/labels/annotations and metadata/object comparison. Also changes NewClient to validate m != nil and return an error for a nil manager.
Controller — deployment tests
pkg/controller/deployment/credentials_request_test.go, pkg/controller/deployment/deployment_overrides_test.go
Adds table-driven tests for withCloudCredentials and multiple deployment override hooks (operand image override, proxy env, CA configmap, SA bound token) plus test fakes for informers/listers and assertions on volumes, mounts, env vars, and retry/not-found flows.
Controller — istiocsr tests
pkg/controller/istiocsr/utils_test.go
Adds extensive tests for hasObjectChanged and many spec-level comparators (RBAC, Deployments, Services, Certificates, ConfigMaps, NetworkPolicies), including panic/edge-case checks and fine-grained spec mutation scenarios.
Controller — trustmanager tests
pkg/controller/trustmanager/controller_test.go, pkg/controller/trustmanager/utils_test.go
Adds TestCleanUp and tests for managed label diffing, trustmanager config validation, and ServiceAccount decoding helper; introduces a fake event recorder and decode helper tests.
Operator — applyconfigurations tests
pkg/operator/applyconfigurations/operator/v1alpha1/certmanagerconfig_test.go, pkg/operator/applyconfigurations/utils_test.go
Adds tests for CertManagerConfigApplyConfiguration.WithIssuerRef (including nil-receiver panic) and NewTypeConverter behavior with nil and non-nil runtime.Scheme.
Operator — assets tests
pkg/operator/assets/bindata_test.go
Adds comprehensive tests for embedded assets API: Asset/AssetNames/AssetDir/AssetInfo/MustAsset behavior, path normalization, empty/unknown name error cases, and content checks for specific YAML assets.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@anandkuma77 anandkuma77 force-pushed the CM-902-add-testcases branch from e98875a to 948bd64 Compare March 20, 2026 08:34
@anandkuma77 anandkuma77 changed the title Add unit tests for modified functions to improve coverage CM-902: Add table-driven unit tests and improve coverage Mar 20, 2026
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Mar 20, 2026

@anandkuma77: This pull request references CM-902 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target either version "4.22." or "openshift-4.22.", but it targets "cert-manager-1.19" instead.

Details

In response to this:

This PR adds unit tests for modified functions (from the golangci-lint / refactor work) to improve branch and statement coverage:

  1. deployment: withCloudCredentials (including infra-not-found and platform branches), and the four deployment-override hooks: withOperandImageOverrideHook, withProxyEnv, withCAConfigMap, withSABoundToken
  2. istiocsr: deploymentSpecModified (selector, template labels, container count/args/name, ports, readiness probe, serviceAccountName), and hasObjectChanged for Role, RoleBinding, and ClusterRoleBinding (rules, RoleRef, Subjects)
  3. trustmanager: cleanUp, and utils: decodeServiceAccountObjBytes (success and panic paths), getResourceLabels (including empty labels), managedLabelsModified (including nil/empty desired labels)
  4. common: error helpers and ObjectMetadataModified (including nil vs non-nil label cases)
  5. New/updated test files: credentials_request_test.go, deployment_overrides_test.go (hook tests), istiocsr/utils_test.go, trustmanager/controller_test.go, trustmanager/utils_test.go, common/errors_test.go, common/utils_test.go.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 20, 2026
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Mar 20, 2026

@anandkuma77: This pull request references CM-902 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target either version "4.22." or "openshift-4.22.", but it targets "cert-manager-1.19" instead.

Details

In response to this:

What

Adds or expands _test.go coverage for controller common utilities (client helpers, errors, utils) including fake controller-runtime client tests.
Adds tests for deployment flows (credentials_request, deployment_overrides).
Adds istiocsr utils tests and trustmanager utils / controller tests, using table-driven patterns where appropriate.
Adds operator tests for applyconfigurations (certmanagerconfig, utils) and assets/bindata validation.

Why

Increases confidence when refactoring controllers and shared helpers by locking in current behavior with explicit, maintainable tests.
Table-driven tests make edge cases and regressions easier to see and extend.
Improves coverage in areas that were previously untested or lightly tested, reducing risk for future CM-902–related and general maintenance work.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

1 similar comment
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Mar 20, 2026

@anandkuma77: This pull request references CM-902 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target either version "4.22." or "openshift-4.22.", but it targets "cert-manager-1.19" instead.

Details

In response to this:

What

Adds or expands _test.go coverage for controller common utilities (client helpers, errors, utils) including fake controller-runtime client tests.
Adds tests for deployment flows (credentials_request, deployment_overrides).
Adds istiocsr utils tests and trustmanager utils / controller tests, using table-driven patterns where appropriate.
Adds operator tests for applyconfigurations (certmanagerconfig, utils) and assets/bindata validation.

Why

Increases confidence when refactoring controllers and shared helpers by locking in current behavior with explicit, maintainable tests.
Table-driven tests make edge cases and regressions easier to see and extend.
Improves coverage in areas that were previously untested or lightly tested, reducing risk for future CM-902–related and general maintenance work.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@anandkuma77 anandkuma77 marked this pull request as ready for review March 20, 2026 08:39
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 20, 2026
@openshift-ci openshift-ci bot requested review from mytreya-rh and swghosh March 20, 2026 08:40
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (5)
pkg/operator/applyconfigurations/utils_test.go (2)

54-57: Tautological assertion provides no value.

The condition if !didPanic && conv != nil already guarantees conv != nil, so assert.NotNil(t, conv, ...) will always pass. This makes the assertion meaningless and obscures the test's intent.

♻️ Proposed fix: simplify to documentation-only
 			// Document: for nil scheme, either conv is nil (if we returned) or we panicked.
-			if !didPanic && conv != nil {
-				assert.NotNil(t, conv, tt.description)
+			if !didPanic {
+				t.Logf("nil scheme returned converter (nil=%v): %s", conv == nil, tt.description)
 			}

Alternatively, if behavior should be locked in, assert a specific expected outcome rather than a condition that's always true.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/operator/applyconfigurations/utils_test.go` around lines 54 - 57, The
assertion `assert.NotNil(t, conv, tt.description)` inside the `if !didPanic &&
conv != nil` branch is tautological and should be removed or replaced; update
the test in utils_test.go by either deleting that redundant assertion and
leaving a clarifying comment explaining that the branch only runs when `conv` is
non-nil, or replace it with a concrete expected-state check (e.g., assert
properties of `conv` or assert specific error/return behavior) so the test
actually verifies behavior of `conv` rather than restating the if-condition.

16-21: Remove unused expectError field.

The expectError field is declared but never referenced in the test logic. This dead code harms maintainability and suggests incomplete test design.

♻️ Proposed fix
 	tests := []struct {
 		name        string
 		scheme      *runtime.Scheme
-		expectError bool
 		description string
 	}{

Also update the test cases to remove expectError: false, from each entry.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/operator/applyconfigurations/utils_test.go` around lines 16 - 21, The
tests table in utils_test.go declares an unused field expectError inside the
tests slice literal; remove the expectError field from the struct definition and
delete any expectError: false entries from each test case so the tests struct
only contains name, scheme, and description; update any code referencing
expectError (none expected) and run the tests to confirm compilation.
pkg/controller/deployment/credentials_request_test.go (1)

118-122: Avoid hardcoding test case names in conditional logic.

This check couples test execution logic to the test case name string, making refactoring fragile. Consider adding a dedicated field to the test struct (e.g., addDifferentSecret bool) to control this behavior.

♻️ Suggested improvement
 	tests := []struct {
 		name           string
 		deploymentName string
 		secretName     string
 		secretInStore  bool
 		platformType   configv1.PlatformType
 		wantErr        string
 		wantVolumes    int
 		wantMountPath  string
 		wantAWSEnv     bool
 		noInfra        bool
+		addOtherSecret bool // if true, add a different secret to trigger retry
 	}{

Then update the test case:

 		{
 			name:           "secret not found returns retry error",
 			deploymentName: certmanagerControllerDeployment,
 			secretName:     "missing-secret",
 			secretInStore:  false,
 			platformType:   configv1.AWSPlatformType,
 			wantErr:        "Retrying",
 			wantVolumes:    0,
+			addOtherSecret: true,
 		},

And update the setup code:

-			if tt.name == "secret not found returns retry error" {
-				kubeClient = fake.NewSimpleClientset(&corev1.Secret{
-					ObjectMeta: metav1.ObjectMeta{Name: "other", Namespace: "cert-manager"},
-				})
-			}
+			if tt.addOtherSecret {
+				kubeClient = fake.NewSimpleClientset(&corev1.Secret{
+					ObjectMeta: metav1.ObjectMeta{Name: "other", Namespace: "cert-manager"},
+				})
+			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/controller/deployment/credentials_request_test.go` around lines 118 -
122, The test currently branches on the literal test name string ("secret not
found returns retry error"); add a boolean field to the test case struct (e.g.,
addDifferentSecret bool) and set it on the specific test case instead of
matching tt.name, then update the setup to use that field (if
tt.addDifferentSecret { kubeClient =
fake.NewSimpleClientset(&corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name:
"other", Namespace: "cert-manager"},}) } ). Update any test case definitions to
set addDifferentSecret = true for the case that needs the different secret; keep
the rest of the setup and assertions unchanged (look for tt, kubeClient, and the
fake.NewSimpleClientset call to locate the code to modify).
pkg/controller/trustmanager/utils_test.go (1)

240-244: Panic assertion is too permissive and can hide regressions.

Allowing any panic containing "interface" can pass unrelated failure modes. Match only the expected substring for this case.

Proposed tightening
-						if !strings.Contains(msg, tt.panicSubstr) && !strings.Contains(msg, "interface") {
+						if !strings.Contains(msg, tt.panicSubstr) {
 							t.Errorf("panic message = %q, want substring %q", msg, tt.panicSubstr)
 						}
As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/controller/trustmanager/utils_test.go` around lines 240 - 244, The panic
assertion in the test currently accepts any panic message containing "interface"
which is too permissive; update the check in the recovery block (where
tt.panicSubstr is used) to require only that the panic message contains
tt.panicSubstr (remove the "|| strings.Contains(msg, \"interface\")" fallback)
so failures only pass when the expected substring matches; if you intended to
special-case a known "interface" panic, make that explicit by setting
tt.panicSubstr to "interface" in the test case instead of allowing it
implicitly.
pkg/controller/istiocsr/utils_test.go (1)

57-69: Remove the duplicated panic scenario from the table.

The cases on Line 57–62 and Line 64–69 assert the same input/output behavior (ClusterRole vs ClusterRoleBinding with "same type" panic). Keeping one avoids redundant maintenance.

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/controller/istiocsr/utils_test.go` around lines 57 - 69, There is a
duplicated test case asserting a panic for mismatched types (ClusterRole vs
ClusterRoleBinding): remove the second entry named "mismatched types (CR vs CRB)
panics" so only one table row remains for the ClusterRole vs ClusterRoleBinding
panic scenario; update the test table in pkg/controller/istiocsr/utils_test.go
(the entries with name "different types panics" and "mismatched types (CR vs
CRB) panics") by deleting the redundant block and keep a single canonical case
to avoid duplicate assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/controller/common/client_test.go`:
- Around line 51-53: Replace the nil sentinel client with a non-nil sentinel
instance so the test actually verifies wiring through the manager: initialize cl
to a concrete non-nil value that implements client.Client (e.g., a small test
stub instance), set fakeManager.client = cl, call NewClient(...) and assert the
returned client is the exact same instance (pointer/identity) as cl; update any
other test occurrences (the second cl at the other test block and its assertion)
to use the same non-nil sentinel to prevent NewClient from silently returning
nil and to strengthen the regression check.

In `@pkg/controller/trustmanager/utils_test.go`:
- Around line 155-187: Add a positive test case to
TestValidateTrustManagerConfig that constructs a valid v1alpha1.TrustManager
(populate Spec.TrustManagerConfig with fields that meet
validateTrustManagerConfig requirements) and set wantErr: false; run the
existing assertions against that case so validateTrustManagerConfig is exercised
on a success path. Reference TestValidateTrustManagerConfig and the
validateTrustManagerConfig call, and use v1alpha1.TrustManager /
v1alpha1.TrustManagerSpec / v1alpha1.TrustManagerConfig when building the valid
input.

---

Nitpick comments:
In `@pkg/controller/deployment/credentials_request_test.go`:
- Around line 118-122: The test currently branches on the literal test name
string ("secret not found returns retry error"); add a boolean field to the test
case struct (e.g., addDifferentSecret bool) and set it on the specific test case
instead of matching tt.name, then update the setup to use that field (if
tt.addDifferentSecret { kubeClient =
fake.NewSimpleClientset(&corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name:
"other", Namespace: "cert-manager"},}) } ). Update any test case definitions to
set addDifferentSecret = true for the case that needs the different secret; keep
the rest of the setup and assertions unchanged (look for tt, kubeClient, and the
fake.NewSimpleClientset call to locate the code to modify).

In `@pkg/controller/istiocsr/utils_test.go`:
- Around line 57-69: There is a duplicated test case asserting a panic for
mismatched types (ClusterRole vs ClusterRoleBinding): remove the second entry
named "mismatched types (CR vs CRB) panics" so only one table row remains for
the ClusterRole vs ClusterRoleBinding panic scenario; update the test table in
pkg/controller/istiocsr/utils_test.go (the entries with name "different types
panics" and "mismatched types (CR vs CRB) panics") by deleting the redundant
block and keep a single canonical case to avoid duplicate assertions.

In `@pkg/controller/trustmanager/utils_test.go`:
- Around line 240-244: The panic assertion in the test currently accepts any
panic message containing "interface" which is too permissive; update the check
in the recovery block (where tt.panicSubstr is used) to require only that the
panic message contains tt.panicSubstr (remove the "|| strings.Contains(msg,
\"interface\")" fallback) so failures only pass when the expected substring
matches; if you intended to special-case a known "interface" panic, make that
explicit by setting tt.panicSubstr to "interface" in the test case instead of
allowing it implicitly.

In `@pkg/operator/applyconfigurations/utils_test.go`:
- Around line 54-57: The assertion `assert.NotNil(t, conv, tt.description)`
inside the `if !didPanic && conv != nil` branch is tautological and should be
removed or replaced; update the test in utils_test.go by either deleting that
redundant assertion and leaving a clarifying comment explaining that the branch
only runs when `conv` is non-nil, or replace it with a concrete expected-state
check (e.g., assert properties of `conv` or assert specific error/return
behavior) so the test actually verifies behavior of `conv` rather than restating
the if-condition.
- Around line 16-21: The tests table in utils_test.go declares an unused field
expectError inside the tests slice literal; remove the expectError field from
the struct definition and delete any expectError: false entries from each test
case so the tests struct only contains name, scheme, and description; update any
code referencing expectError (none expected) and run the tests to confirm
compilation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b9605116-c267-4862-9294-9bdc97489909

📥 Commits

Reviewing files that changed from the base of the PR and between 8eb5d9e and 948bd64.

📒 Files selected for processing (12)
  • pkg/controller/common/client_test.go
  • pkg/controller/common/errors_test.go
  • pkg/controller/common/fakes/fake_ctrl_client_test.go
  • pkg/controller/common/utils_test.go
  • pkg/controller/deployment/credentials_request_test.go
  • pkg/controller/deployment/deployment_overrides_test.go
  • pkg/controller/istiocsr/utils_test.go
  • pkg/controller/trustmanager/controller_test.go
  • pkg/controller/trustmanager/utils_test.go
  • pkg/operator/applyconfigurations/operator/v1alpha1/certmanagerconfig_test.go
  • pkg/operator/applyconfigurations/utils_test.go
  • pkg/operator/assets/bindata_test.go

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/controller/common/client_test.go`:
- Around line 121-124: The test currently expects a panic for a nil manager
which locks in crash-on-nil behavior; update the test cases in
pkg/controller/common/client_test.go (the cases referencing m: nil and
expectPanic) to instead expect an error from NewClient/GetClient and assert the
returned error is non-nil and no panic occurs, and in production ensure
NewClient (or the GetClient method on the client factory) defensively checks for
a nil manager and returns a descriptive error (e.g., "nil manager") rather than
panicking so the test and code rely on returned errors not panics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 38d701bb-dc31-4e06-b884-df97dc6093a1

📥 Commits

Reviewing files that changed from the base of the PR and between 948bd64 and 5be0f10.

📒 Files selected for processing (2)
  • pkg/controller/common/client_test.go
  • pkg/controller/trustmanager/utils_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/controller/trustmanager/utils_test.go

@anandkuma77
Copy link
Copy Markdown
Contributor Author

/re-test

@bharath-b-rh
Copy link
Copy Markdown
Contributor

/lgtm
/approve

no user facing changes, PR is for improving the unit test coverage. Hence adding other required labels.
/label docs-approved
/label qe-approved
/label px approved

@openshift-ci openshift-ci bot added docs-approved Signifies that Docs has signed off on this PR qe-approved Signifies that QE has signed off on this PR labels Mar 24, 2026
@bharath-b-rh
Copy link
Copy Markdown
Contributor

/retest

@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Mar 24, 2026

@anandkuma77: This pull request references CM-902 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target either version "4.22." or "openshift-4.22.", but it targets "cert-manager-1.19" instead.

Details

In response to this:

What

Adds or expands _test.go coverage for controller common utilities (client helpers, errors, utils) including fake controller-runtime client tests.
Adds tests for deployment flows (credentials_request, deployment_overrides).
Adds istiocsr utils tests and trustmanager utils / controller tests, using table-driven patterns where appropriate.
Adds operator tests for applyconfigurations (certmanagerconfig, utils) and assets/bindata validation.

Why

Increases confidence when refactoring controllers and shared helpers by locking in current behavior with explicit, maintainable tests.
Table-driven tests make edge cases and regressions easier to see and extend.
Improves coverage in areas that were previously untested or lightly tested, reducing risk for future CM-902–related and general maintenance work.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 24, 2026
@openshift-ci openshift-ci bot added lgtm Indicates that a PR is ready to be merged. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Mar 24, 2026
Anand Kumar added 2 commits March 24, 2026 13:59
- Add unit tests for modified functions to improve coverage
- Align trustmanager utils tests with table-driven style
- Add table-driven tests for refactor safety across controller packages
- Update common and deployment test files; remove obsolete istiocsr test

Made-with: Cursor
- Use a non-nil sentinel client.Client in client tests so happy path
  asserts manager client is wired by pointer identity, not nil==nil.
- Add a valid TrustManagerConfig case to TestValidateTrustManagerConfig
  to exercise validateTrustManagerConfig success path.

Made-with: Cursor
@anandkuma77 anandkuma77 force-pushed the CM-902-add-testcases branch from 5be0f10 to 5a89fe2 Compare March 24, 2026 08:29
@openshift-ci openshift-ci bot removed lgtm Indicates that a PR is ready to be merged. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. labels Mar 24, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
pkg/controller/common/client_test.go (1)

121-145: ⚠️ Potential issue | 🟠 Major

Don’t lock NewClient(nil) panic into the contract.

Line 121 and Line 128-135 make panic the expected behavior for nil manager input. That cements crash behavior and blocks a safer error-return contract, while pkg/controller/common/client.go currently has no nil guard.

Suggested adjustment
--- a/pkg/controller/common/client_test.go
+++ b/pkg/controller/common/client_test.go
@@
-       expectPanic bool
+       expectErr   bool
@@
-           name:        "nil manager - GetClient panics",
+           name:      "nil manager returns error",
            m:           nil,
-           expectPanic: true,
+           expectErr: true,
@@
-           if tt.expectPanic {
-               defer func() {
-                   r := recover()
-                   if r == nil {
-                       t.Fatal("expected panic but got none")
-                   }
-                   t.Logf("NewClient(nil) panicked as expected: %v", r)
-               }()
-           }
            got, err := NewClient(tt.m)
-           if !tt.expectPanic {
-               require.NoError(t, err)
-               require.NotNil(t, got)
-               ...
-           }
+           if tt.expectErr {
+               require.Error(t, err)
+               require.Nil(t, got)
+               return
+           }
+           require.NoError(t, err)
+           require.NotNil(t, got)
+           ...
// pkg/controller/common/client.go
func NewClient(m manager.Manager) (CtrlClient, error) {
    if m == nil {
        return nil, fmt.Errorf("nil manager")
    }
    return &ctrlClientImpl{Client: m.GetClient()}, nil
}
#!/bin/bash
set -euo pipefail

# Verify NewClient currently dereferences manager without nil guard.
rg -n --type=go 'func\s+NewClient\s*\(m manager\.Manager\)' pkg/controller/common/client.go -A8 -B2

# Verify the test currently expects panic for nil manager.
rg -n --type=go 'expectPanic|recover\(|nil manager - GetClient panics' pkg/controller/common/client_test.go -A4 -B4

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/controller/common/client_test.go` around lines 121 - 145, The test and
implementation should not require NewClient(m manager.Manager) to panic on nil;
instead add a nil-guard in NewClient that returns (nil, fmt.Errorf("nil
manager")) when m == nil and otherwise returns &ctrlClientImpl{Client:
m.GetClient()}, nil; then update the test case currently named "nil manager -
GetClient panics" to expect an error (require.Error) and a nil result rather
than deferring a recover, while leaving the non-nil assertions unchanged
(require.NoError, require.NotNil, type assert to *ctrlClientImpl and verify the
wrapped Client equals m.GetClient()).
🧹 Nitpick comments (3)
pkg/operator/assets/bindata_test.go (2)

59-64: Duplicate test case.

This case tests the exact same input (tokenRequestRBAsset) as the first test case at lines 29-34 with only a different expectedMin threshold. Consider removing it or testing a distinct scenario.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/operator/assets/bindata_test.go` around lines 59 - 64, The test suite
contains a duplicate test entry that uses the same input tokenRequestRBAsset as
the earlier case but only changes expectedMin, so remove or replace this
duplicate case: either delete the test case object that has name "boundary -
single known asset from AssetNames" or change it to exercise a distinct scenario
(e.g., use a different input variable than tokenRequestRBAsset or alter
expectedMin and the input to validate the different threshold). Locate the
duplicated test entry in the table of test cases (the struct literal containing
name, input: tokenRequestRBAsset, expectedMin, expectError) and update or remove
it accordingly so each test case is unique.

231-238: Unsafe type assertion may cause secondary panic.

r.(string) will panic if the recovered value is not a string. Use fmt.Sprintf("%v", r) or a type switch for robustness.

♻️ Proposed fix
 	t.Run("panic on unknown asset", func(t *testing.T) {
 		defer func() {
 			r := recover()
 			require.NotNil(t, r, "MustAsset must panic when asset not found")
-			assert.Contains(t, r.(string), "not found")
+			assert.Contains(t, fmt.Sprintf("%v", r), "not found")
 		}()
 		_ = MustAsset("nonexistent.yaml")
 	})

Note: Add "fmt" to imports if applying this fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/operator/assets/bindata_test.go` around lines 231 - 238, The test's
deferred recover uses an unsafe type assertion r.(string) which can panic if the
recovered value isn't a string; update the panic check in the t.Run "panic on
unknown asset" to format the recovered value safely (e.g. use fmt.Sprintf("%v",
r) or a type switch) when asserting the message contains "not found" and add
"fmt" to imports if you choose fmt.Sprintf; keep the existing require.NotNil(t,
r, ...) and assert.Contains call but pass the formatted string instead of
r.(string), referencing the MustAsset call that triggers the panic.
pkg/controller/deployment/credentials_request_test.go (1)

118-122: Avoid name-coupled test setup logic

Using tt.name == "secret not found returns retry error" to drive fixture behavior is brittle and easy to break during case renames. Prefer an explicit scenario flag in the test table.

Proposed refactor
 	tests := []struct {
 		name           string
 		deploymentName string
 		secretName     string
 		secretInStore  bool
+		seedOtherSecret bool
 		platformType   configv1.PlatformType
 		wantErr        string
@@
 		{
 			name:           "secret not found returns retry error",
 			deploymentName: certmanagerControllerDeployment,
 			secretName:     "missing-secret",
 			secretInStore:  false,
+			seedOtherSecret: true,
 			platformType:   configv1.AWSPlatformType,
 			wantErr:        "Retrying",
 			wantVolumes:    0,
 		},
@@
-			if tt.name == "secret not found returns retry error" {
+			if tt.seedOtherSecret {
 				kubeClient = fake.NewSimpleClientset(&corev1.Secret{
 					ObjectMeta: metav1.ObjectMeta{Name: "other", Namespace: "cert-manager"},
 				})
 			}

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/controller/deployment/credentials_request_test.go` around lines 118 -
122, The test currently uses a brittle name check (tt.name == "secret not found
returns retry error") to drive fixture setup; change the table-driven tests to
include an explicit scenario flag (e.g., tt.secretMissing or tt.setupSecret
func) and use that flag to decide the kubeClient fixture creation instead of
comparing tt.name, update each test case to set the new flag for the
secret-not-found scenario, and adjust the setup code that creates kubeClient
(the fake.NewSimpleClientset(...) branch) to read
tt.secretMissing/tt.setupSecret so renaming tt.name no longer affects behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/controller/common/utils_test.go`:
- Line 124: The test uses an undefined function HasObjectChanged causing a
compile error; replace each call to HasObjectChanged(...) in
pkg/controller/common/utils_test.go with the existing helper
ObjectMetadataModified(...) (preserving the same arguments, e.g., change
HasObjectChanged(sa, cm) to ObjectMetadataModified(sa, cm)) for all occurrences
reported so the code references the defined function.

In `@pkg/controller/deployment/credentials_request_test.go`:
- Around line 190-194: The test currently skips asserting when tt.wantMountPath
is set but no VolumeMounts exist; update the test in credentials_request_test.go
to explicitly fail when wantMountPath != "" and
deployment.Spec.Template.Spec.Containers[0].VolumeMounts is empty (e.g., call
t.Fatalf or t.Errorf with a clear message about missing VolumeMount), then
proceed to check
deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath ==
tt.wantMountPath as before; reference the tt.wantMountPath variable and the
deployment.Spec.Template.Spec.Containers[0].VolumeMounts slice when adding the
presence assertion.
- Around line 171-177: The test currently treats any NotFound error as
acceptable for all failure cases, which can mask incorrect behavior; update the
assertion logic in the test block that checks tt.wantErr to only accept
apierrors.IsNotFound when the test case explicitly expects a NotFound (e.g., add
a test-case field like wantNotFound or encode "NotFound" in tt.wantErr),
otherwise require the returned error string to contain tt.wantErr; modify the
conditional that references err, tt.wantErr and apierrors.IsNotFound so that
apierrors.IsNotFound is only considered a pass when the test case indicates
NotFound is the expected outcome (locate and change the assertion around
tt.wantErr, err and apierrors.IsNotFound in credentials_request_test.go).

In `@pkg/controller/trustmanager/utils_test.go`:
- Around line 215-227: The test case uses tm as &v1alpha1.TrustManager but the
table expects a *trustManagerBuilder and later calls tt.tm.Build(), and wantErr
is declared as a string but given a bool; fix by replacing the literal tm value
with a call to testTrustManager(...) that returns a *trustManagerBuilder (so
tt.tm is the correct type and tt.tm.Build() compiles), and change the wantErr
field to the correct bool type (or adjust the table's wantErr to bool) so the
test case types match the struct declaration; ensure references to Build() and
the trustManagerBuilder type remain consistent.

---

Duplicate comments:
In `@pkg/controller/common/client_test.go`:
- Around line 121-145: The test and implementation should not require
NewClient(m manager.Manager) to panic on nil; instead add a nil-guard in
NewClient that returns (nil, fmt.Errorf("nil manager")) when m == nil and
otherwise returns &ctrlClientImpl{Client: m.GetClient()}, nil; then update the
test case currently named "nil manager - GetClient panics" to expect an error
(require.Error) and a nil result rather than deferring a recover, while leaving
the non-nil assertions unchanged (require.NoError, require.NotNil, type assert
to *ctrlClientImpl and verify the wrapped Client equals m.GetClient()).

---

Nitpick comments:
In `@pkg/controller/deployment/credentials_request_test.go`:
- Around line 118-122: The test currently uses a brittle name check (tt.name ==
"secret not found returns retry error") to drive fixture setup; change the
table-driven tests to include an explicit scenario flag (e.g., tt.secretMissing
or tt.setupSecret func) and use that flag to decide the kubeClient fixture
creation instead of comparing tt.name, update each test case to set the new flag
for the secret-not-found scenario, and adjust the setup code that creates
kubeClient (the fake.NewSimpleClientset(...) branch) to read
tt.secretMissing/tt.setupSecret so renaming tt.name no longer affects behavior.

In `@pkg/operator/assets/bindata_test.go`:
- Around line 59-64: The test suite contains a duplicate test entry that uses
the same input tokenRequestRBAsset as the earlier case but only changes
expectedMin, so remove or replace this duplicate case: either delete the test
case object that has name "boundary - single known asset from AssetNames" or
change it to exercise a distinct scenario (e.g., use a different input variable
than tokenRequestRBAsset or alter expectedMin and the input to validate the
different threshold). Locate the duplicated test entry in the table of test
cases (the struct literal containing name, input: tokenRequestRBAsset,
expectedMin, expectError) and update or remove it accordingly so each test case
is unique.
- Around line 231-238: The test's deferred recover uses an unsafe type assertion
r.(string) which can panic if the recovered value isn't a string; update the
panic check in the t.Run "panic on unknown asset" to format the recovered value
safely (e.g. use fmt.Sprintf("%v", r) or a type switch) when asserting the
message contains "not found" and add "fmt" to imports if you choose fmt.Sprintf;
keep the existing require.NotNil(t, r, ...) and assert.Contains call but pass
the formatted string instead of r.(string), referencing the MustAsset call that
triggers the panic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 52f733c1-5fd5-4277-9e5d-0eae7c9f6657

📥 Commits

Reviewing files that changed from the base of the PR and between 5be0f10 and 5a89fe2.

📒 Files selected for processing (12)
  • pkg/controller/common/client_test.go
  • pkg/controller/common/errors_test.go
  • pkg/controller/common/fakes/fake_ctrl_client_test.go
  • pkg/controller/common/utils_test.go
  • pkg/controller/deployment/credentials_request_test.go
  • pkg/controller/deployment/deployment_overrides_test.go
  • pkg/controller/istiocsr/utils_test.go
  • pkg/controller/trustmanager/controller_test.go
  • pkg/controller/trustmanager/utils_test.go
  • pkg/operator/applyconfigurations/operator/v1alpha1/certmanagerconfig_test.go
  • pkg/operator/applyconfigurations/utils_test.go
  • pkg/operator/assets/bindata_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/operator/applyconfigurations/operator/v1alpha1/certmanagerconfig_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/operator/applyconfigurations/utils_test.go
  • pkg/controller/deployment/deployment_overrides_test.go

Anand Kumar added 2 commits March 24, 2026 14:12
…lder

- Use ObjectMetadataModified in common utils tests (HasObjectChanged does not exist).
- Fix ValidateTrustManagerConfig case to use trustManagerBuilder and drop invalid wantErr.

Made-with: Cursor
Return (nil, error) from NewClient when manager is nil instead of panicking.
Tighten withCloudCredentials tests: decoy-secret flag, NotFound only when
expected, required VolumeMounts when wantMountPath is set.
Remove duplicate bindata Asset case; format MustAsset panic recovery safely.

Made-with: Cursor
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/controller/deployment/credentials_request_test.go (1)

127-140: Decouple fixture setup from expected outcome

Using tt.wantErr != "" to decide informer seeding/sync makes test setup implicit and brittle. Prefer explicit fixture flags (e.g., seedSecretInformer, waitForSecretSync) so new error cases don’t accidentally get a pre-seeded secret.

As per coding guidelines, "Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/controller/deployment/credentials_request_test.go` around lines 127 -
140, The test currently uses tt.wantErr != "" to decide seeding and cache sync
which couples expected outcome to fixture setup; update the table-driven tests
to include explicit boolean flags (e.g., seedSecretInformer and
waitForSecretSync) and replace uses of tt.wantErr != "" in the setup block and
cache sync condition with those flags; specifically modify the setup around
kubeInformers.Core().V1().Secrets().Informer().GetStore().Add(...) and the
cache.WaitForCacheSync(...) call so they check tt.seedSecretInformer and
tt.waitForSecretSync respectively, and ensure the decoySecretOnly logic still
applies when seedSecretInformer is true.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/controller/deployment/credentials_request_test.go`:
- Around line 178-185: The test currently treats any NotFound error as
acceptable when tt.wantNotFoundOK is true, which can mask unrelated NotFounds;
update the logic in the error-checking block (where matchSubstring,
matchNotFound, apierrors.IsNotFound(err), tt.wantNotFoundOK and tt.wantErr are
referenced) to require both apierrors.IsNotFound(err) AND
strings.Contains(err.Error(), tt.wantErr) when tt.wantNotFoundOK is true (i.e.,
set matchNotFound = tt.wantNotFoundOK && apierrors.IsNotFound(err) &&
matchSubstring or adjust the overall if logic accordingly), and update the
t.Errorf messages to reflect that the test expects a NotFound with the specified
substring.

---

Nitpick comments:
In `@pkg/controller/deployment/credentials_request_test.go`:
- Around line 127-140: The test currently uses tt.wantErr != "" to decide
seeding and cache sync which couples expected outcome to fixture setup; update
the table-driven tests to include explicit boolean flags (e.g.,
seedSecretInformer and waitForSecretSync) and replace uses of tt.wantErr != ""
in the setup block and cache sync condition with those flags; specifically
modify the setup around
kubeInformers.Core().V1().Secrets().Informer().GetStore().Add(...) and the
cache.WaitForCacheSync(...) call so they check tt.seedSecretInformer and
tt.waitForSecretSync respectively, and ensure the decoySecretOnly logic still
applies when seedSecretInformer is true.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2f5fbb24-94ee-4da1-bcc4-40a5ee1b7157

📥 Commits

Reviewing files that changed from the base of the PR and between 39cf860 and 864dc89.

📒 Files selected for processing (4)
  • pkg/controller/common/client.go
  • pkg/controller/common/client_test.go
  • pkg/controller/deployment/credentials_request_test.go
  • pkg/operator/assets/bindata_test.go

When wantNotFoundOK is set, pass only if apierrors.IsNotFound(err) and the
error message contains wantErr, avoiding unrelated NotFound matches.

Made-with: Cursor
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need to concern UT coverage under path pkg/operator/applyconfigurations/ or pkg/operator/assets/ at all? They are auto-generated code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have removed the testcases for these.

@lunarwhite
Copy link
Copy Markdown
Member

/label tide/merge-method-squash

@openshift-ci openshift-ci bot added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label Mar 25, 2026
@anandkuma77
Copy link
Copy Markdown
Contributor Author

/retest

Drop tests that only exercised go-bindata and applyconfiguration-gen
output. Coverage should focus on hand-written operator logic; generated
packages are not maintained as test targets.

Made-with: Cursor
@arun717
Copy link
Copy Markdown
Contributor

arun717 commented Apr 1, 2026

/lgtm

@openshift-ci openshift-ci bot added lgtm Indicates that a PR is ready to be merged. and removed lgtm Indicates that a PR is ready to be merged. labels Apr 1, 2026
The manager is always non-nil when controllers construct the client;
removing the guard simplifies the code path for test coverage.

Made-with: Cursor
@anandkuma77 anandkuma77 force-pushed the CM-902-add-testcases branch from 1b9bc8a to c09cebd Compare April 2, 2026 06:54
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Apr 2, 2026

@anandkuma77: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@arun717
Copy link
Copy Markdown
Contributor

arun717 commented Apr 2, 2026

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Apr 2, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Apr 2, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: anandkuma77, arun717, bharath-b-rh

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@anandkuma77
Copy link
Copy Markdown
Contributor Author

/label px-approved

@anandkuma77
Copy link
Copy Markdown
Contributor Author

/label docs-approved

@anandkuma77
Copy link
Copy Markdown
Contributor Author

/px-approved

@bharath-b-rh
Copy link
Copy Markdown
Contributor

/hold

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. docs-approved Signifies that Docs has signed off on this PR jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. qe-approved Signifies that QE has signed off on this PR tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants