Skip to content

test(config): real-DB test for GetPurchaseHistoryFiltered dual-column account filter - #994

Merged
cristim merged 1 commit into
LeanerCloud:mainfrom
IAmJSD:fix/issue-23
Oct 16, 2026
Merged

cristim merged 1 commit into
LeanerCloud:mainfrom
IAmJSD:fix/issue-23

Conversation

@IAmJSD

@IAmJSD IAmJSD commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

What

Adds TestGetPurchaseHistoryFiltered_DualColumnAccount_Integration, a testcontainers (real Postgres) test for the dual-column account predicate in GetPurchaseHistoryFiltered:

cloud_account_id = ANY($uuids)
  OR ((provider = '' OR LOWER(provider) = LOWER($p)) AND account_id = ANY($exts))

It goes in the existing internal/config/store_postgres_history_account_provider_integration_test.go. No production code changes.

Seed: two aws cloud_accounts (A = 111122223333, C = 444455556666) and seven purchase_history rows covering each combination of the two account columns (UUID-only, UUID+external, NULL-UUID external-only, NULL-UUID empty provider, azure row reusing A's external number, account C by UUID and by external number).

Case Filter Expected
both halves ORed AccountIDs=[A], aws:[111122223333] both, ext-empty-provider, ext-only, uuid-only
UUID only AccountIDs=[A] both, uuid-only
external only aws:[111122223333] both, ext-empty-provider, ext-only (no azure leak)
provider mismatch AccountIDs=[A], azure:[111122223333] azure-same-ext, both, ext-empty-provider, uuid-only (no aws NULL-UUID leak)
OR group inside the AND chain Provider=aws, AccountIDs=[C], aws:[111122223333] both, ext-only, other-uuid

The empty-provider expectations follow the current semantics from #931 (an empty stored provider matches on account_id alone).

Why / status of the issue's two parts

  • (a) Broken integration suite: already fixed on main. Commit 86a4435 (feat(plans): surface legacy no-account plans as Unassigned (closes #973) cloud-commitments-cli#994, before the repo split) replaced PurchasePlanFilter{} with config.PurchasePlanFilter{} and removed the pf(...) helper usage in internal/config/store_postgres_test.go. On current main, go vet -tags integration ./internal/config/ passes and the full integration suite runs green. No change needed here.
  • (b) Real-DB test: partly covered. fix(config): match purchase history with an empty or differently cased provider #931 added TestAccountPredicate_ProviderCaseAndEmpty_Integration, but that test only exercises the external-id half (every seeded row has cloud_account_id IS NULL). Until this PR, the UUID half, the OR between the two halves, and the parenthesisation of the OR inside the surrounding AND chain were checked only by pgxmock SQL-text tests. This PR adds that missing coverage.

Verification

All tests ran with AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null.

go build ./...                                                    # ok
go vet ./internal/config/ && go vet -tags integration ./internal/config/   # ok
go test ./internal/config/ -count=1                               # ok
go test -tags integration ./internal/config/ -count=1             # ok (full suite, ~426s)
go test -race -tags integration ./internal/config/ -count=1 -run 'DualColumnAccount|ProviderCaseAndEmpty'   # ok
golangci-lint v2.10.1 run --allow-parallel-runners ./internal/config/...                          # 0 issues
golangci-lint v2.10.1 run --allow-parallel-runners --build-tags integration ./internal/config/... # 0 issues
bash scripts/test-git-secrets-allowlist.sh                        # 42 PASS, 0 FAIL
git secrets --scan (temp copy of the tree, isolated HOME)         # no findings

Fail-before evidence (mutations of appendAccountPredicate in internal/config/store_postgres.go, each applied alone, then reverted)

Mutation Failing subtests of the new test
UUID half replaced by FALSE both-halves, UUID-only, provider-mismatch, OR-group
external half replaced by FALSE both-halves, external-only, provider-mismatch, OR-group
provider gate removed (account_id = ANY for any provider) both-halves, external-only, provider-mismatch
OR between halves changed to AND both-halves, provider-mismatch, OR-group
parentheses around the OR group dropped OR-group

All five subtests pass with the predicate unchanged.

Out of scope

Labels

Please mirror the issue's labels onto this PR (I have no label permission on the upstream repo): priority/p2, severity/medium, urgency/this-sprint, impact/internal, type/chore, triaged, effort/m.

Closes #23

🤖 Generated with Claude Code

… account filter

Run the account predicate
  cloud_account_id = ANY($uuids)
    OR ((provider = '' OR LOWER(provider) = LOWER($p)) AND account_id = ANY($exts))
against a testcontainers Postgres. Until now the UUID half and the OR
between the two halves were checked only by pgxmock SQL-text tests.

The new table covers: both halves ORed (a NULL-cloud_account_id row
comes back next to UUID-only rows), UUID only, external only, a
provider mismatch on the same external number, the empty-provider row
(LeanerCloud#931 semantics), and the OR group inside a surrounding Provider clause.

Closes LeanerCloud#23

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 1 billable file and costs up to $0.25.

Or wait 35 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: LeanerCloud/cloud-commitments-platform/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1080bd6e-9232-4825-b10f-f8e59147c114
📥 Commits

Reviewing files that changed from the base of the PR and between adcd80c and 0738071.

📒 Files selected for processing: 1
  • internal/config/store_postgres_history_account_provider_integration_test.go
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@IAmJSD IAmJSD added priority/p2 Backlog-worthy severity/medium Moderate harm urgency/this-sprint Within the current sprint impact/internal Team-internal only type/chore Maintenance / non-user-visible triaged Item has been triaged effort/m Days labels Oct 16, 2026

@cristim cristim left a comment

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.

Independent review of 0738071: draft: blocks ready

Findings: none actionable. Test-only, +127 lines in one file (three-dot diff vs main).

What I attacked

  • Real DB: setupTestContainerDB (store_postgres_db_test.go:35) starts a testcontainers Postgres. The test calls the real GetPurchaseHistoryFiltered (store_postgres.go:2535), which builds the predicate in appendAccountPredicate (store_postgres.go:2467-2491), so it runs the production SQL. Run at this SHA: go test -tags integration -run 'DualColumnAccount|AccountPredicate' ./internal/config/ passes, and the integration package compiles (issue #23 part (a) is already satisfied on main).
  • Both columns: cases cover UUID-only match (uuid-only, account_id deliberately unrelated), external-only match (ext-only, cloud_account_id NULL), both matching (both, returned once), UUID-only filter ignoring account_id, and provider-scoped external half (azure-same-ext excluded from aws filters). Cross-account exclusion: other-uuid / other-ext (account C) never appear in account A cases, and other-uuid appears only when C is the UUID filter.
  • Vacuous pass: every case asserts an exact non-empty sorted ID list, not "no error" or length, and the seeded rows are asserted by name.
  • Mutation probes in a scratch worktree (each reverted; tree clean): UUID half set to FALSE -> 4 subtests fail; UUID half pointed at account_id -> 4 fail; external half set to FALSE -> 4 fail; drop provider = '' -> 3 fail; provider gate neutralised -> 3 fail; OR joined with AND -> 3 fail; parentheses removed -> the compose-with-provider case fails. All 7 killed.
  • Consistency with #931: the new fixtures (ext-empty-provider) reuse the same semantics as the existing TestAccountPredicate_ProviderCaseAndEmpty_Integration in the same file; no helper duplication beyond purchaseIDs, which is reused. The expiry index from #942 is not touched.
  • Issue #23 (b): NULL cloud_account_id + populated account_id returned by UUID filter (via the resolved external pair), and same external number under another provider not returned: both covered.

NON-BLOCKING

  • The doc comment names the raw predicate in the test header; it will drift if the SQL changes. Minor.
  • The test relies on a resolved (provider, external) pair being passed alongside the UUID, as the API handler does; the resolver itself is not in scope.

Gate status

  • Independent review: this comment, SHA above.
  • CI: checks on this SHA are still pending (including Integration Tests and Lint); fork runs may need approval. Must be green before merge.
  • Local verification: real-DB run on macOS plus mutation evidence above.
  • Labels: priority/p2, severity/medium, urgency/this-sprint, impact/internal, type/chore, effort/m, triaged; they match the closing issue's triage set as reported by the PR (issue #23 labels not re-fetched by me beyond the closing reference).
  • CodeRabbit: only a bot summary comment, no inline threads; not pinged.

Blocks ready

  1. CI green on this SHA (Integration Tests, Lint, pre-commit).
  2. Take the PR out of draft.
  3. Re-review if the head moves.

@cristim

cristim commented Oct 16, 2026

Copy link
Copy Markdown
Member

Gate record for 0738071 (origin/main CLAUDE.md "Review gate"):

  • Independent review of 0738071: no actionable findings.

    • The test runs the real GetPurchaseHistoryFiltered (store_postgres.go:2535, with appendAccountPredicate at :2467-2491) against testcontainers Postgres.
    • It covers UUID-only rows, external-only rows, rows matching both columns (returned once), and provider-scoped exclusion.
    • Every case asserts an exact, non-empty ID list.
  • CI on 0738071: CI Success and Run pre-commit hooks pass.

  • Local verification (macOS, testcontainers): 7 mutations of the predicate each fail the test, and all were reverted. The mutations were:

    • UUID half off;
    • UUID half on the wrong column;
    • external half off;
    • provider = '' dropped;
    • provider gate neutralised;
    • OR changed to AND;
    • parentheses removed.

    Test-only change.

  • CR skipped: draft and quota-limited; covered by the independent review plus local verification.

  • Labels mirrored from test(config): repair broken integration suite + add real-DB test for GetPurchaseHistoryFiltered dual-column account filter #23.

Marking ready (owner-authorized) and merging at 0738071 with --match-head-commit.

@cristim
cristim marked this pull request as ready for review October 16, 2026 15:50
@cristim
cristim merged commit 04154e6 into LeanerCloud:main Oct 16, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/m Days impact/internal Team-internal only priority/p2 Backlog-worthy severity/medium Moderate harm triaged Item has been triaged type/chore Maintenance / non-user-visible urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test(config): repair broken integration suite + add real-DB test for GetPurchaseHistoryFiltered dual-column account filter

2 participants