Skip to content

(3/3) test: add core-class unit tests for the GormRegistry O(M+N) rewrite#15790

Open
borinquenkid wants to merge 4 commits into
feat/gorm-registry-core-implfrom
test/gorm-registry-core-tests
Open

(3/3) test: add core-class unit tests for the GormRegistry O(M+N) rewrite#15790
borinquenkid wants to merge 4 commits into
feat/gorm-registry-core-implfrom
test/gorm-registry-core-tests

Conversation

@borinquenkid

@borinquenkid borinquenkid commented Jun 29, 2026

Copy link
Copy Markdown
Member

📖 Reading order: 3 of 3 — this GormRegistry O(M+N) scaling change is split across three PRs; please review them in order:

  1. (1/3) (1/3) feat: add SessionResolver infrastructure and extend core datastore APIs #15779 — SessionResolver infrastructure & core datastore API extensions
  2. (2/3) (2/3) feat: GORM O(M+N) scaling — GormRegistry, GormEnhancer, and core API refactor #15780 — GormRegistry implementation (core production code)
  3. (3/3) (3/3) test: add core-class unit tests for the GormRegistry O(M+N) rewrite #15790 — core-class unit tests

You are reading (3/3).


What

Adds the net-new unit-test coverage for the GormRegistry O(M+N) rewrite's core classes that
the core-impl branch (#15780) was missing. Tests-only — no production code is touched.

Stacked on #15780 (feat/gorm-registry-core-impl), so the diff here is just the new specs.

Coverage added (23 specs)

  • GormApiResolver and the four datastore selectors — PreferredDatastoreSelector,
    QualifiedDatastoreSelector, ActiveSessionDatastoreSelector, DefaultDatastoreSelector
  • GormRegistry — concurrency, entity registration, factory lookup
  • API registriesAbstractGormApiRegistry, GormStaticApiRegistry, GormInstanceApiRegistry,
    GormValidationApiRegistry, GormApiRegistry, plus GormInstanceApi
  • GormApiFactory SPIDefaultGormApiFactory, GormApiFactory
  • Multi-tenancy coreCurrentTenantHolder, Tenants, the @CurrentTenant transform
    (MultiTenantCurrentTenantTransformSpec), MultiTenantEventListener
  • MiscConnectionSourceNameResolver, DefaultTransactionTemplateFactory, a service-transform spec

Notes

All 23 specs pass against core-impl's implementation (:grails-datamapping-core:test, 0 failures; codeStyle clean).

Two adjustments from the originally-drafted specs:

  • ServiceTransformSpec: aligned the no-datastore exception assertion to core-impl's actual message
    ("No GORM implementations configured", thrown by GormApiResolver.findSingleDatastore).
  • Dropped TenantContextProfilingSpec: a timing micro-benchmark (prints durations, asserts only true) —
    brittle/non-deterministic and not portable unit coverage.

🤖 Generated with Claude Code

Harvest the net-new GormRegistry unit specs onto core-impl so the rewrite's core classes have
dedicated coverage they were missing: GormApiResolver and the four datastore selectors
(Preferred/Qualified/ActiveSession/Default), GormRegistry (concurrency, entity registration, factory),
the api registries (Abstract/Static/Instance/Validation) and the GormApiFactory SPI
(Default/GormApiFactory), CurrentTenantHolder, Tenants, the @CurrentTenant transform
(MultiTenantCurrentTenantTransformSpec), MultiTenantEventListener, ConnectionSourceNameResolver,
DefaultTransactionTemplateFactory, and a service transform spec.

All 23 specs pass against core-impl's implementation. Two adjustments from the source specs:
- ServiceTransformSpec: align the no-datastore exception assertion to core-impl's actual message
  ("No GORM implementations configured" from GormApiResolver.findSingleDatastore).
- Dropped TenantContextProfilingSpec: a timing micro-benchmark (prints durations, asserts only true) —
  brittle and non-deterministic, not portable unit coverage.

Tests-only change; no production code touched. Branched from the GormRegistry core-impl work.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@borinquenkid borinquenkid force-pushed the test/gorm-registry-core-tests branch from 7bab6ad to 1ccec90 Compare June 30, 2026 04:24
@borinquenkid borinquenkid changed the title test: add core-class unit tests for the GormRegistry O(M+N) rewrite (3/3) test: add core-class unit tests for the GormRegistry O(M+N) rewrite Jul 1, 2026
Copilot AI review requested due to automatic review settings July 2, 2026 16:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a comprehensive new Spock unit test suite in grails-datamapping-core to cover the new GormRegistry-based O(M+N) GORM API registration/lookup architecture introduced in the prior stacked PRs. It is test-only, focused on validating registry lookups, qualifier/tenant datastore selection, API factory behavior, and related multi-tenancy/service-transform integration points.

Changes:

  • Add new unit specs for GormRegistry, GormApiResolver, API registries, and GormApiFactory/DefaultGormApiFactory.
  • Add new unit specs for datastore-selection helpers (Preferred*, Qualified*, ActiveSession*, Default*) and connection-source name resolution.
  • Add/extend unit coverage for multi-tenancy helpers/event listener behavior and service transformation behavior.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/transactions/DefaultTransactionTemplateFactorySpec.groovy Adds unit coverage for DefaultTransactionTemplateFactory overloads returning GrailsTransactionTemplate.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/QualifiedDatastoreSelectorSpec.groovy Tests qualifier-based datastore selection (TX-bound, registry, multi-connection, multi-tenant).
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/PreferredDatastoreSelectorSpec.groovy Tests preferred datastore routing behavior for default and qualified lookups.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/multitenancy/MultiTenantEventListenerSpec.groovy Adds unit coverage for discriminator multi-tenancy event listener tenant-id assignment behavior.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormValidationApiRegistrySpec.groovy Verifies validation API registry resolution by qualifier.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormStaticApiRegistrySpec.groovy Verifies static API registry resolution by qualifier.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormRegistryFactorySpec.groovy Tests API factory override lookup and resolver exposure on the registry.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormRegistryEntityRegistrationSpec.groovy Tests API registration and entity-to-datastore registration/normalization behaviors.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormRegistryConcurrencySpec.groovy Adds concurrency-focused hot-path coverage for normalization and registry lookups.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormInstanceApiSpec.groovy Tests GormInstanceApi save(validate:false) behavior around skipValidation state.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormInstanceApiRegistrySpec.groovy Verifies instance API registry resolution by qualifier.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormApiResolverSpec.groovy Exercises resolver paths (type lookup, qualifier lookup, preferred DS, recursion guard, multi-tenant edge cases).
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormApiRegistrySpec.groovy Verifies common registry storage/lookup semantics for static/instance/validation registries.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/GormApiFactorySpec.groovy Defines/validates GormApiFactory contract expectations (create APIs, dynamic finders).
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/DefaultGormApiFactorySpec.groovy Tests default factory configuration application and default dynamic finder set.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/DefaultDatastoreSelectorSpec.groovy Tests tenant-aware default datastore selection behavior.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/ConnectionSourceNameResolverSpec.groovy Tests resolving connection source names/defaults from a datastore/provider.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/ActiveSessionDatastoreSelectorSpec.groovy Tests active-session datastore selection behavior.
grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/AbstractGormApiRegistrySpec.groovy Tests AbstractGormApiRegistry core behaviors (register/get/qualify/clear/exceptions).
grails-datamapping-core/src/test/groovy/grails/gorm/services/transform/ServiceTransformSpec.groovy Adds/updates transformation tests to align with registry-based datastore resolution.
grails-datamapping-core/src/test/groovy/grails/gorm/services/transform/ServiceTransformClasses.groovy Supplies entities/services used by the service-transform test suite.
grails-datamapping-core/src/test/groovy/grails/gorm/multitenancy/TenantsSpec.groovy Adds unit coverage for Tenants helper APIs (withId/currentId/withoutId nesting).
grails-datamapping-core/src/test/groovy/grails/gorm/multitenancy/CurrentTenantHolderSpec.groovy Adds unit coverage for CurrentTenantHolder set/get/remove/withTenant behaviors.
grails-datamapping-core/src/test/groovy/grails/gorm/annotation/multitenancy/MultiTenantCurrentTenantTransformSpec.groovy Adds AST transform coverage for @CurrentTenant / @WithoutTenant behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +63 to +66
then:
template != null
template instanceof GrailsTransactionTemplate
}
Comment on lines +30 to +33
static class DummyTenantId extends TenantId {
DummyTenantId() { super(null, null, "tenantId", Long) }
org.grails.datastore.mapping.model.PropertyMapping getMapping() { null }
}
Comment on lines +120 to +125
startLatch.countDown() // Release all threads
endLatch.await(5, TimeUnit.SECONDS)
long endTime = System.currentTimeMillis()
executor.shutdown()

println "Concurrency test completed in ${endTime - startTime}ms for ${numThreads * iterationsPerThread} operations"
Comment on lines +111 to +114
} catch (Throwable e) {
e.printStackTrace()
errorCount.incrementAndGet()
} finally {
Comment on lines +47 to +49
int numThreads = 10
int iterationsPerThread = 100000
ExecutorService executor = Executors.newFixedThreadPool(numThreads)
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 49.6674%. Comparing base (e4773df) to head (62f351b).

Files with missing lines Patch % Lines
...implementers/AbstractStringQueryImplementer.groovy 88.8889% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@                          Coverage Diff                           @@
##             feat/gorm-registry-core-impl     #15790        +/-   ##
======================================================================
+ Coverage                         49.5761%   49.6674%   +0.0913%     
- Complexity                          17080      17136        +56     
======================================================================
  Files                                1961       1961                
  Lines                               93654      93653         -1     
  Branches                            16454      16454                
======================================================================
+ Hits                                46430      46515        +85     
+ Misses                              39972      39893        -79     
+ Partials                             7252       7245         -7     
Files with missing lines Coverage Δ
...implementers/AbstractStringQueryImplementer.groovy 69.8113% <88.8889%> (+3.9022%) ⬆️

... and 27 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

borinquenkid and others added 2 commits July 2, 2026 13:25
- DefaultTransactionTemplateFactorySpec: remove unused import; strengthen
  the TransactionDefinition overload test to assert the definition's
  propagation/isolation/timeout/readOnly were actually applied to the
  created template, not just its type.
- MultiTenantEventListenerSpec: DummyTenantId declared a Long type while
  the existing tests exercise String tenant ids, masking the
  Number-coercion branch in MultiTenantEventListener (ConnectionSource.
  DEFAULT + numeric tenantId type -> 0L). Fix the fixture's declared
  type to match, and add coverage for both branches of that condition.
- GormRegistryConcurrencySpec: assert on the CountDownLatch#await return
  value instead of ignoring it (so a stuck worker thread fails the test
  loudly instead of silently passing), capture worker exceptions instead
  of printStackTrace-ing them, and reduce iterationsPerThread from
  100000 to 20000 to cut flakiness risk under @timeout(10) on slower CI
  runners (verified stable at ~1s locally, down from ~3.25s).

Also correct my own earlier fix on this stack: AbstractStringQueryImplementer's
constant-@query substring checks looked like dead/hacky code from the
GString-based tests in grails.gorm.services.ServiceTransformSpec, but a
second spec (grails.gorm.services.transform.ServiceTransformSpec) uses
single-quoted (non-GString) @query values that genuinely depend on them.
Restore the checks, narrowed to the actual token shapes used ($wrong /
f.wrong, and "from java.lang.String") instead of a bare substring match,
so legitimate queries that merely mention those words elsewhere no
longer false-positive.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@testlens-app

testlens-app Bot commented Jul 2, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 62f351b
▶️ Tests: 32250 executed
⚪️ Checks: 39/39 completed


Learn more about TestLens at testlens.app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants