Skip to content

feat(cli): Add better unit testing.#3378

Merged
c-r33d merged 5 commits intomainfrom
add-more-unit-test-coverage
Apr 24, 2026
Merged

feat(cli): Add better unit testing.#3378
c-r33d merged 5 commits intomainfrom
add-more-unit-test-coverage

Conversation

@c-r33d
Copy link
Copy Markdown
Contributor

@c-r33d c-r33d commented Apr 23, 2026

Summary

Tighten unit-test coverage and simplify design across the namespaced-policy migration planner. Package coverage 78.2% → 80.9%, with targeted behavioral gaps closed in the planner pipeline.

Design changes

  • Removed dead code: ActionReference/ActionReferenceKind accumulator and ErrDuplicateCanonicalMatch sentinel (never surfaced to users or callers).
  • First-match resolution: the 5 resolveExisting* matchers now return the first canonical match instead of erroring on duplicates, keeping resolver behavior consistent across all target types.
  • Plan-time dependency validation: registered resources and obligation triggers now validate their action dependencies during resolve (matching subject mappings), rather than failing later at execute time.
  • Typed sentinel errors for dependency failures (ErrMissingActionID, ErrUnresolvedActionDependency, etc.) so tests can assert via errors.Is while preserving contextual wrapping.
  • Consistent nil-candidate handling: all 5 candidate types in deriveTargets now skip nil entries instead of mixing error/skip behavior.
  • Documented the interactive-path vs initial-pass convergence on ensureRegisteredResourceActionResolution.

Test additions

  • canonical.go: table-driven tests for all 5 *CanonicalEqual wrappers covering nil, cosmetic-equivalence (case/whitespace/order), distinguishing cases, and empty-field gating.
  • resolved.go: first-match-wins tests; typed-error assertions for all dependency validation paths; scope-gating drops; already-migrated routing for SCS/SM/OT.
  • derived.go: nil-skip tests for all 5 candidate types; namespace-accumulator dedupe; FQN-fallback resolution.
  • interactive_commit.go: abort propagation test (reviewer returns ErrInteractiveReviewAborted and stops prompting).
  • plan.go: LookupActionTarget and LookupSubjectConditionSetTarget table-driven tests (nil, empty inputs, match, not-found).
  • summary.go: recordTargetStatus table-driven test covering all 4 status branches plus accumulation.

Coverage deltas

File Before After
canonical.go ~85% 95.7%
resolved.go ~88% 94.4%
plan.go 68.9% 84.2%
summary.go 85.1% 86.5%
Package total 78.2% 80.9%

Summary by CodeRabbit

  • Bug Fixes

    • More robust handling of missing, nil, or ambiguous dependencies during policy migration and resolution; clearer, specific error outcomes and stable nil-handling to avoid partial/misleading results.
  • Refactor

    • Simplified plan and resolution model: removed namespace-level aggregation and propagated reference metadata, streamlined target determination and interactive review flows.
  • Tests

    • Expanded unit and e2e coverage for canonical equality, derivation, resolution, interactive aborts, cross-namespace migration, and many edge-case nil/missing scenarios.

@c-r33d c-r33d requested a review from a team as a code owner April 23, 2026 17:33
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request improves the robustness and maintainability of the namespaced-policy migration planner by tightening unit test coverage and simplifying internal design. Key changes include removing dead code, standardizing resolver behavior, and improving error handling with typed sentinels. These updates ensure more predictable behavior during the migration pipeline and provide better diagnostic information when issues arise.

Highlights

  • Code Cleanup: Removed unused ActionReference/ActionReferenceKind accumulators and ErrDuplicateCanonicalMatch sentinel to simplify the codebase.
  • Resolver Logic: Updated matchers to adopt a 'first-match-wins' strategy, ensuring consistent behavior across all target types.
  • Error Handling: Introduced typed sentinel errors for dependency failures, allowing for better assertion using errors.Is while maintaining context.
  • Test Coverage: Significantly increased package test coverage from 78.2% to 80.9% by adding comprehensive table-driven tests for canonical equality, dependency validation, and candidate handling.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.


The tests were thin and sparse of late, We tightened up the migration state. With sentinels and logic clear, The code now runs without a fear.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

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
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat(cli): Add better unit testing.' is overly vague and generic—it uses non-descriptive language ('better unit testing') that does not convey the specific nature of the substantial design simplifications and refactoring. The PR involves significant changes (removing ActionReference machinery, simplifying plan structure, adding targeted error types, and closing coverage gaps), but the title only vaguely gestures toward testing additions without clarifying the core objectives. Revise the title to be more specific about the primary changes, such as: 'refactor(migrations): Simplify plan structure and dependency validation' or 'refactor: Remove ActionReference accumulator and add targeted error types to namespaced-policy planner'
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-more-unit-test-coverage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the namespaced policy migration logic by removing action reference tracking and simplifying the resolution process. It introduces more robust nil checks when iterating over candidates and adds comprehensive unit tests for canonical equality, target derivation, and dependency resolution. One critical issue was identified where calling GetId() on potentially nil action objects in dependency resolution functions could lead to panics.

Comment thread otdfctl/migrations/namespacedpolicy/resolved.go
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 179.896867ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 92.953852ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 433.935228ms
Throughput 230.45 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 43.760869705s
Average Latency 436.161655ms
Throughput 114.26 requests/second

@c-r33d
Copy link
Copy Markdown
Contributor Author

c-r33d commented Apr 23, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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 `@otdfctl/migrations/namespacedpolicy/derived_test.go`:
- Around line 380-439: Replace brittle require.EqualError usages with typed
error assertions: in tests that assert missing target namespace (e.g., within
TestDeriveTargetsFailsWhenNamespaceRefNotFound and any other tests referencing
ErrMissingTargetNamespace), use require.ErrorIs(err, ErrMissingTargetNamespace)
to check error identity and keep assert.Contains checks for contextual messages
(like the mapping id and host fragment) instead of asserting the exact error
string; update any require.EqualError(err, ...) calls that compare to
ErrMissingTargetNamespace to this pattern.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b0b6cd3a-e626-43c4-9350-68ceed36d150

📥 Commits

Reviewing files that changed from the base of the PR and between e4884c1 and 6dbf5e9.

📒 Files selected for processing (2)
  • otdfctl/migrations/namespacedpolicy/derived.go
  • otdfctl/migrations/namespacedpolicy/derived_test.go

Comment thread otdfctl/migrations/namespacedpolicy/derived_test.go
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 186.348787ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 102.870333ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 428.812018ms
Throughput 233.20 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 42.702867392s
Average Latency 425.230875ms
Throughput 117.09 requests/second

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
otdfctl/migrations/namespacedpolicy/interactive_review.go (2)

417-436: ⚠️ Potential issue | 🟡 Minor

Dead branch: else if item.Source == nil is unreachable.

resolvedActionByID (lines 451-459) only returns entries that already satisfy action.Source != nil && action.Source.GetId() == sourceID. So whenever item != nil here, item.Source is guaranteed non-nil and the else if block can never execute.

♻️ Proposed cleanup
 	item := resolvedActionByID(resolved.Actions, action.GetId())
 	if item == nil {
 		source, err := cloneAction(action)
 		if err != nil {
 			return err
 		}
 
 		item = &ResolvedAction{
 			Source:  source,
 			Results: make([]*ResolvedActionResult, 0, 1),
 		}
 		resolved.Actions = append(resolved.Actions, item)
-	} else if item.Source == nil {
-		source, err := cloneAction(action)
-		if err != nil {
-			return err
-		}
-
-		item.Source = source
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@otdfctl/migrations/namespacedpolicy/interactive_review.go` around lines 417 -
436, The else-if branch checking "item.Source == nil" in the interactive_review
logic is dead because resolvedActionByID only returns entries with a non-nil
Source (see resolvedActionByID), so remove the unreachable else-if block and any
associated cloneAction call; keep the initial creation path that appends a new
ResolvedAction (using cloneAction) when item == nil, and ensure no other code
expects the dead branch to run by leaving ResolvedAction.Source initialization
only in the creation branch.

410-415: ⚠️ Potential issue | 🟠 Major

Use the typed sentinel errors for dependency failures.

Lines 410–415 return plain errors.New where the PR's typed sentinel errors should be used. Per the PR objective to introduce typed sentinels for dependency failures, and consistent with ErrNilResolvedTargets already returned at line 405, replace these with:

  • ErrMissingActionID (defined in plan.go)
  • ErrNilInteractiveReviewHandler (defined in interactive_review.go)

This allows callers/tests to assert these failure modes via errors.Is, completing the typed-error refactor for the hard-error paths documented in this function.

Fix
 	if action == nil || strings.TrimSpace(action.GetId()) == "" {
-		return errors.New("registered resource binding action is missing")
+		return ErrMissingActionID
 	}
 	if actionResolver == nil {
-		return errors.New("action resolver required for plan resolution")
+		return ErrNilInteractiveReviewHandler
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@otdfctl/migrations/namespacedpolicy/interactive_review.go` around lines 410 -
415, Replace the plain errors.New returns in the plan resolution checks with the
typed sentinel errors: where the code currently returns errors.New("registered
resource binding action is missing") change it to return ErrMissingActionID, and
where it returns errors.New("action resolver required for plan resolution")
change it to return ErrNilInteractiveReviewHandler; these symbols are defined in
plan.go and interactive_review.go respectively and should be used alongside the
existing ErrNilResolvedTargets at the earlier check so callers can use errors.Is
to detect these dependency failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@otdfctl/migrations/namespacedpolicy/interactive_review.go`:
- Around line 71-81: The doc comment for reviewRegisteredResource uses a
non-idiomatic "// ! " prefix causing literal "!" to appear in godoc; remove the
"! " prefix from each line in that comment block so all lines begin with plain
"//" and match the style used elsewhere (e.g.,
ensureRegisteredResourceActionResolution) to render properly in go
doc/pkg.go.dev.

---

Outside diff comments:
In `@otdfctl/migrations/namespacedpolicy/interactive_review.go`:
- Around line 417-436: The else-if branch checking "item.Source == nil" in the
interactive_review logic is dead because resolvedActionByID only returns entries
with a non-nil Source (see resolvedActionByID), so remove the unreachable
else-if block and any associated cloneAction call; keep the initial creation
path that appends a new ResolvedAction (using cloneAction) when item == nil, and
ensure no other code expects the dead branch to run by leaving
ResolvedAction.Source initialization only in the creation branch.
- Around line 410-415: Replace the plain errors.New returns in the plan
resolution checks with the typed sentinel errors: where the code currently
returns errors.New("registered resource binding action is missing") change it to
return ErrMissingActionID, and where it returns errors.New("action resolver
required for plan resolution") change it to return
ErrNilInteractiveReviewHandler; these symbols are defined in plan.go and
interactive_review.go respectively and should be used alongside the existing
ErrNilResolvedTargets at the earlier check so callers can use errors.Is to
detect these dependency failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6c9e995b-7ab9-4a30-b628-297d5f66e707

📥 Commits

Reviewing files that changed from the base of the PR and between 6dbf5e9 and 0b3f402.

📒 Files selected for processing (7)
  • otdfctl/e2e/migrate-namespaced-policy.bats
  • otdfctl/migrations/namespacedpolicy/finalize_plan.go
  • otdfctl/migrations/namespacedpolicy/finalize_plan_test.go
  • otdfctl/migrations/namespacedpolicy/interactive_review.go
  • otdfctl/migrations/namespacedpolicy/plan.go
  • otdfctl/migrations/namespacedpolicy/planner.go
  • otdfctl/migrations/namespacedpolicy/planner_test.go

Comment thread otdfctl/migrations/namespacedpolicy/interactive_review.go Outdated
@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 1.687157337s

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 726.365852ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 3.316809769s
Throughput 30.15 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 6m11.966423479s
Average Latency 3.712162132s
Throughput 13.44 requests/second

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 146.889108ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 80.294497ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 387.873109ms
Throughput 257.82 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 41.230261978s
Average Latency 410.382078ms
Throughput 121.27 requests/second

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
otdfctl/migrations/namespacedpolicy/interactive_review.go (1)

410-415: ⚠️ Potential issue | 🟡 Minor

Use typed sentinel error ErrMissingActionID for consistency with the non-interactive resolver path.

The typed sentinel ErrMissingActionID is defined in plan.go:16 and used consistently throughout resolved.go (lines 400, 423, 436) and tested with errors.Is() assertions in tests. Line 411 should wrap or return ErrMissingActionID instead of a bare errors.New("...") to ensure callers can use errors.Is(err, ErrMissingActionID) on errors from the interactive review flow. This maintains consistency with the non-interactive resolver path and preserves the sentinel error contract.

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

In `@otdfctl/migrations/namespacedpolicy/interactive_review.go` around lines 410 -
415, Replace the bare error returned when action ID is missing with the typed
sentinel ErrMissingActionID (from plan.go) so callers can use errors.Is;
specifically, in the block that checks action == nil ||
strings.TrimSpace(action.GetId()) == "" (and not the actionResolver check),
return or wrap ErrMissingActionID (e.g. fmt.Errorf("registered resource binding
action is missing: %w", ErrMissingActionID) or simply return ErrMissingActionID)
and add fmt to imports if you choose to wrap.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@otdfctl/migrations/namespacedpolicy/interactive_review.go`:
- Around line 410-415: Replace the bare error returned when action ID is missing
with the typed sentinel ErrMissingActionID (from plan.go) so callers can use
errors.Is; specifically, in the block that checks action == nil ||
strings.TrimSpace(action.GetId()) == "" (and not the actionResolver check),
return or wrap ErrMissingActionID (e.g. fmt.Errorf("registered resource binding
action is missing: %w", ErrMissingActionID) or simply return ErrMissingActionID)
and add fmt to imports if you choose to wrap.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f7de7af3-f0df-46fc-8db3-0f705a7d0f2c

📥 Commits

Reviewing files that changed from the base of the PR and between 0b3f402 and bb486da.

📒 Files selected for processing (2)
  • otdfctl/e2e/migrate-namespaced-policy.bats
  • otdfctl/migrations/namespacedpolicy/interactive_review.go

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 192.223607ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 98.176239ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 404.925416ms
Throughput 246.96 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 42.278815734s
Average Latency 421.177576ms
Throughput 118.26 requests/second

@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Govulncheck found vulnerabilities ⚠️

The following modules have known vulnerabilities:

  • examples
  • otdfctl
  • sdk
  • service
  • lib/fixtures
  • tests-bdd

See the workflow run for details.

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
otdfctl/e2e/migrate-namespaced-policy.bats (1)

1605-1615: 🧹 Nitpick | 🔵 Trivial

Track inline-created NS_B canonical fixtures for per-test teardown.

existing_rr_b_id and existing_rr_b_value_id are created inline here (bypassing create_global_registered_resource / create_registered_resource_value because they need to be namespaced), but neither is passed to track_registered_resource_id / track_registered_resource_value_id. The same omission exists for existing_trigger_b_id at lines 1704-1707. Other pre-existing canonical fixtures in this file (e.g. existing_sm_b_scs_id, existing_mapping_standard_id at lines 1517-1518) are tracked via their create_* helpers.

Consequence: these rows survive per-test teardown() and are only reaped when NS_B is deleted in teardown_file. Within a single file run, leftover state in NS_B could subtly influence later tests (state deltas stay correct since they're relative, but any fixed-count or uniqueness assumption added later would be fragile).

🧹 Proposed fix for lines 1605-1615 and 1704-1707
   run_otdfctl_registered_resources create --name "$rr_b_name" --namespace "$NS_B_ID" --label "test_case=registered-resources" --label "fixture=${TEST_PREFIX}-existing-rr-b" --json
-  assert_success
   existing_rr_b_id=$(echo "$output" | jq -r '.id // empty')
   assert_not_equal "$existing_rr_b_id" ""
+  track_registered_resource_id "$existing_rr_b_id"

   run_otdfctl_registered_resource_values create --resource "$existing_rr_b_id" --value "$rr_b_value" --action-attribute-value "$ns_b_read_action_id;$ATTR_B_VAL_1_ID" --label "test_case=registered-resources" --label "fixture=${TEST_PREFIX}-existing-rr-b-value" --json
-  assert_success
   existing_rr_b_value_id=$(echo "$output" | jq -r '.id // empty')
   assert_not_equal "$existing_rr_b_value_id" ""
+  track_registered_resource_value_id "$existing_rr_b_value_id"

And analogously for the obligation trigger:

   run_otdfctl_obligation_triggers create --attribute-value "$ATTR_B_VAL_1_ID" --action "$ns_b_read_action_id" --obligation-value "$obligation_b_value_id" --client-id "$trigger_b_client_id" --label "test_case=obligation-triggers" --label "fixture=${TEST_PREFIX}-existing-trigger-b" --json
-  assert_success
   existing_trigger_b_id=$(echo "$output" | jq -r '.id // empty')
   assert_not_equal "$existing_trigger_b_id" ""
+  track_obligation_trigger_id "$existing_trigger_b_id"

The redundant assert_success removals are a minor bonus — run_otdfctl_* already asserts success internally (lines 62-65, 67-70, 82-85).

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

In `@otdfctl/e2e/migrate-namespaced-policy.bats` around lines 1605 - 1615, The
created namespaced fixtures existing_rr_b_id and existing_rr_b_value_id (from
run_otdfctl_registered_resources/create and
run_otdfctl_registered_resource_values/create) aren’t being tracked for per-test
teardown; after each creation (where you set existing_rr_b_id and
existing_rr_b_value_id) call track_registered_resource_id "$existing_rr_b_id"
and track_registered_resource_value_id "$existing_rr_b_value_id" to ensure they
get cleaned up, and do the same for existing_trigger_b_id (call track_trigger_id
"$existing_trigger_b_id" after its creation). Optionally remove the redundant
assert_success lines since the run_otdfctl_* helpers already assert success.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@otdfctl/e2e/migrate-namespaced-policy.bats`:
- Around line 1605-1615: The created namespaced fixtures existing_rr_b_id and
existing_rr_b_value_id (from run_otdfctl_registered_resources/create and
run_otdfctl_registered_resource_values/create) aren’t being tracked for per-test
teardown; after each creation (where you set existing_rr_b_id and
existing_rr_b_value_id) call track_registered_resource_id "$existing_rr_b_id"
and track_registered_resource_value_id "$existing_rr_b_value_id" to ensure they
get cleaned up, and do the same for existing_trigger_b_id (call track_trigger_id
"$existing_trigger_b_id" after its creation). Optionally remove the redundant
assert_success lines since the run_otdfctl_* helpers already assert success.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7042dcba-a2cc-4141-92f9-10d2acb9f20f

📥 Commits

Reviewing files that changed from the base of the PR and between bb486da and 199552c.

📒 Files selected for processing (1)
  • otdfctl/e2e/migrate-namespaced-policy.bats

@c-r33d c-r33d added this pull request to the merge queue Apr 24, 2026
Merged via the queue into main with commit 3ad33dc Apr 24, 2026
40 checks passed
@c-r33d c-r33d deleted the add-more-unit-test-coverage branch April 24, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants