This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch test/document-datamapping-core-finders
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 6d5de5bda6ad2219aa9dd13cf8c024354075f2f7
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Sat Aug 15 14:11:04 2026 -0500

    Address contrarian review of the finders composition refactor
    
    - Fix a dangling Javadoc cross-reference in SingleResultFinderSpec to
      a nonexistent "field-ordering note".
    - Add an explicit 0 * query.projections() assertion in
      RxListResultFinderSpec so the "no distinct()" quirk documented in
      RxListResultFinder's class Javadoc is self-verifying rather than
      incidental.
    - Add a createFinderInvocation-level test for the And/Or literal-split
      quirk in DynamicFinderSpec; previously only buildMatchSpec (the
      compile-time matcher) exercised it, leaving the actual runtime path
      finders call unverified.
    
    Co-Authored-By: Claude Sonnet 5 <[email protected]>
---
 .../grails/datastore/gorm/finders/DynamicFinderSpec.groovy | 14 ++++++++++++++
 .../datastore/gorm/finders/SingleResultFinderSpec.groovy   |  7 ++++---
 .../grails/gorm/rx/finders/RxListResultFinderSpec.groovy   |  3 +++
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git 
a/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/finders/DynamicFinderSpec.groovy
 
b/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/finders/DynamicFinderSpec.groovy
index 71d4738907..360024a4ae 100644
--- 
a/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/finders/DynamicFinderSpec.groovy
+++ 
b/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/finders/DynamicFinderSpec.groovy
@@ -288,6 +288,20 @@ class DynamicFinderSpec extends Specification {
         thrown(MissingMethodException)
     }
 
+    void "createFinderInvocation's naive literal split on the And/Or operator 
can split inside an unrelated property name"() {
+        when:
+        // Mirrors the "buildMatchSpec's naive literal split..." test above, 
but through the actual
+        // runtime entry point real finders call, proving the split logic 
really is identical - not
+        // merely asserted to be by comment. "findByAndroidVersionAndTitle" is 
meant to be
+        // "androidVersion And title", but querySequence.split("And") splits 
on every literal
+        // occurrence of "And", including the one starting "AndroidVersion" 
itself, producing an
+        // empty leading segment.
+        findByGrammar.createFinderInvocation(FinderTestEntity, 
'findByAndroidVersionAndTitle', null, ['x', 'y'] as Object[])
+
+        then:
+        thrown(IllegalArgumentException)
+    }
+
     void "createFinderInvocation rethrows a ConversionException as 
MissingMethodException for a non-Basic property"() {
         given:
         // "age" (a plain Integer, non-Basic property) with an argument that 
genuinely needs
diff --git 
a/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/finders/SingleResultFinderSpec.groovy
 
b/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/finders/SingleResultFinderSpec.groovy
index d62ec34abe..c7cbfa7dfc 100644
--- 
a/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/finders/SingleResultFinderSpec.groovy
+++ 
b/grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/finders/SingleResultFinderSpec.groovy
@@ -34,9 +34,10 @@ import spock.lang.Unroll
  * Exercises {@link SingleResultFinder} - the composed replacement for the 
deleted
  * 
AbstractFindByFinder/FindByFinder/FindByBooleanFinder/FindOrCreateByFinder/FindOrSaveByFinder
  * class hierarchy. Every factory method builds its own {@link DynamicFinder} 
grammar instance
- * (never shared across finders - see {@code DynamicFinderSpec}'s 
field-ordering note for why that
- * matters), so each test constructs the specific factory under test directly 
rather than reusing
- * a single shared field.
+ * (never shared across finders, since a shared instance would be a real 
thread-safety hazard
+ * given finder instances are long-lived and invoked from arbitrary request 
threads), so each
+ * test constructs the specific factory under test directly rather than 
reusing a single shared
+ * field.
  */
 class SingleResultFinderSpec extends Specification {
 
diff --git 
a/grails-datamapping-rx/src/test/groovy/org/grails/gorm/rx/finders/RxListResultFinderSpec.groovy
 
b/grails-datamapping-rx/src/test/groovy/org/grails/gorm/rx/finders/RxListResultFinderSpec.groovy
index bd11405c3b..e96cca8f39 100644
--- 
a/grails-datamapping-rx/src/test/groovy/org/grails/gorm/rx/finders/RxListResultFinderSpec.groovy
+++ 
b/grails-datamapping-rx/src/test/groovy/org/grails/gorm/rx/finders/RxListResultFinderSpec.groovy
@@ -92,6 +92,9 @@ class RxListResultFinderSpec extends Specification {
         1 * query.add({ Query.Criterion it -> it instanceof Query.Junction })
         1 * query.findAll() >> observable
         0 * query.findAll(_)
+        // Unlike the synchronous ListResultFinder, RxListResultFinder never 
applies a distinct()
+        // projection - a pre-existing sync/rx inconsistency this refactor 
preserves, not fixes.
+        0 * query.projections()
         result.is(observable)
     }
 

Reply via email to