matrei commented on code in PR #15799:
URL: https://github.com/apache/grails-core/pull/15799#discussion_r3503549005


##########
grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy:
##########
@@ -122,4 +123,104 @@ class FooGrailsPlugin {
             xml.resources.resource.size() == 2
             xml.resources.resource.text() == "FooBar"
     }
+
+    void "isIsolatedBuild reflects the grails.isolated.build system 
property"() {
+        given:
+            String original = System.getProperty('grails.isolated.build')
+
+        when:
+            System.setProperty('grails.isolated.build', value)
+
+        then:
+            GlobalGrailsClassInjectorTransformation.isIsolatedBuild() == 
expected
+
+        cleanup:
+            if (original != null) {
+                System.setProperty('grails.isolated.build', original)
+            } else {
+                System.clearProperty('grails.isolated.build')
+            }
+
+        where:
+            value   || expected
+            'true'  || true
+            'false' || false
+            'TRUE'  || true
+            'yes'   || false
+    }

Review Comment:
   ```suggestion
       @RestoreSystemProperties
       void "isIsolatedBuild reflects the grails.isolated.build system 
property"() {
           when:
               System.setProperty('grails.isolated.build', value)
   
           then:
               GlobalGrailsClassInjectorTransformation.isIsolatedBuild() == 
expected
   
           where:
               value   || expected
               'true'  || true
               'false' || false
               'TRUE'  || true
               'y'     || true
               'null'  || false
               '1'     || true
               '0'     || false
               '-1'    || false
               ''      || false
       }
   ```



##########
grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy:
##########
@@ -122,4 +123,104 @@ class FooGrailsPlugin {
             xml.resources.resource.size() == 2
             xml.resources.resource.text() == "FooBar"
     }
+
+    void "isIsolatedBuild reflects the grails.isolated.build system 
property"() {
+        given:
+            String original = System.getProperty('grails.isolated.build')
+
+        when:
+            System.setProperty('grails.isolated.build', value)
+
+        then:
+            GlobalGrailsClassInjectorTransformation.isIsolatedBuild() == 
expected
+
+        cleanup:
+            if (original != null) {
+                System.setProperty('grails.isolated.build', original)
+            } else {
+                System.clearProperty('grails.isolated.build')
+            }
+
+        where:
+            value   || expected
+            'true'  || true
+            'false' || false
+            'TRUE'  || true
+            'yes'   || false
+    }
+
+    private SourceUnit sourceUnitWithTarget(File targetDirectory) {
+        def configuration = new CompilerConfiguration()
+        configuration.setTargetDirectory((File) targetDirectory)
+        Stub(SourceUnit) {
+            getConfiguration() >> configuration
+            getName() >> 'TestSource'
+        }
+    }
+
+    void "resolveCompilationTargetDirectory returns the configured target 
directory"() {
+        given:
+            File target = new File(System.getProperty('java.io.tmpdir'), 
'isolated-target/build/classes/groovy/main')
+            def source = sourceUnitWithTarget(target)
+
+        expect: "the configured directory is used regardless of build 
isolation"
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 false) == target
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 true) == target
+    }
+
+    void "resolveCompilationTargetDirectory falls back to the shared relative 
path for a non-isolated build"() {
+        given: "a source unit without a configured target directory"
+            def source = sourceUnitWithTarget(null)
+
+        when:
+            File resolved = 
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 false)
+
+        then: "the legacy relative fallback is used"
+            resolved == new File('build/classes/main')
+    }
+
+    void "resolveCompilationTargetDirectory fails fast instead of falling back 
for an isolated build"() {
+        given: "a source unit without a configured target directory"
+            def source = sourceUnitWithTarget(null)
+
+        when: "the target directory cannot be resolved in an isolated build"
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 true)
+
+        then: "the build fails loudly rather than writing to a shared location"
+            IllegalStateException e = thrown()
+            e.message.contains('GRAILS_ISOLATED_BUILD=true')
+    }
+
+    void "findSourceDirectory prefers the per-project base.dir system property 
when set"() {
+        given: "base.dir points at an existing directory"
+            File baseDir = File.createTempDir()
+            System.setProperty('base.dir', baseDir.absolutePath)
+            File target = new File(baseDir, 'build/classes/groovy/main')
+
+        when:
+            File resolved = 
GlobalGrailsClassInjectorTransformation.findSourceDirectory(target)
+
+        then: "the build-tool supplied base.dir wins"
+            resolved == baseDir
+
+        cleanup:
+            System.clearProperty('base.dir')
+            baseDir.deleteDir()
+    }
+
+    void "findSourceDirectory walks up to the project directory when base.dir 
is not set"() {
+        given: "no base.dir and a standard per-project compile target"
+            System.clearProperty('base.dir')

Review Comment:
   ```suggestion
   ```



##########
grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy:
##########
@@ -176,14 +176,43 @@ class GlobalGrailsClassInjectorTransformation implements 
ASTTransformation, Comp
         generatePluginXml(pluginClassNode, pluginVersion, transformedClasses, 
pluginXmlFile)
     }
 
+    /**
+     * The system property signalling that each project compiles into its own 
isolated output
+     * directory. When set, the transform must never fall back to a 
shared/guessed location, which can
+     * leak one module's generated metadata into another.
+     */
+    public static final String ISOLATED_BUILD_PROPERTY = 
'grails.isolated.build'
+
+    /**
+     * @return {@code true} when the {@code grails.isolated.build} system 
property is {@code true}.
+     */
+    static boolean isIsolatedBuild() {
+        return 
Boolean.parseBoolean(System.getProperty(ISOLATED_BUILD_PROPERTY))

Review Comment:
   ```suggestion
           System.getProperty(ISOLATED_BUILD_PROPERTY, 'false').toBoolean()
   ```



##########
grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy:
##########
@@ -122,4 +123,104 @@ class FooGrailsPlugin {
             xml.resources.resource.size() == 2
             xml.resources.resource.text() == "FooBar"
     }
+
+    void "isIsolatedBuild reflects the grails.isolated.build system 
property"() {
+        given:
+            String original = System.getProperty('grails.isolated.build')
+
+        when:
+            System.setProperty('grails.isolated.build', value)
+
+        then:
+            GlobalGrailsClassInjectorTransformation.isIsolatedBuild() == 
expected
+
+        cleanup:
+            if (original != null) {
+                System.setProperty('grails.isolated.build', original)
+            } else {
+                System.clearProperty('grails.isolated.build')
+            }
+
+        where:
+            value   || expected
+            'true'  || true
+            'false' || false
+            'TRUE'  || true
+            'yes'   || false
+    }
+
+    private SourceUnit sourceUnitWithTarget(File targetDirectory) {
+        def configuration = new CompilerConfiguration()
+        configuration.setTargetDirectory((File) targetDirectory)
+        Stub(SourceUnit) {
+            getConfiguration() >> configuration
+            getName() >> 'TestSource'
+        }
+    }
+
+    void "resolveCompilationTargetDirectory returns the configured target 
directory"() {
+        given:
+            File target = new File(System.getProperty('java.io.tmpdir'), 
'isolated-target/build/classes/groovy/main')
+            def source = sourceUnitWithTarget(target)
+
+        expect: "the configured directory is used regardless of build 
isolation"
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 false) == target
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 true) == target
+    }
+
+    void "resolveCompilationTargetDirectory falls back to the shared relative 
path for a non-isolated build"() {
+        given: "a source unit without a configured target directory"
+            def source = sourceUnitWithTarget(null)
+
+        when:
+            File resolved = 
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 false)
+
+        then: "the legacy relative fallback is used"
+            resolved == new File('build/classes/main')
+    }
+
+    void "resolveCompilationTargetDirectory fails fast instead of falling back 
for an isolated build"() {
+        given: "a source unit without a configured target directory"
+            def source = sourceUnitWithTarget(null)
+
+        when: "the target directory cannot be resolved in an isolated build"
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 true)
+
+        then: "the build fails loudly rather than writing to a shared location"
+            IllegalStateException e = thrown()
+            e.message.contains('GRAILS_ISOLATED_BUILD=true')
+    }
+
+    void "findSourceDirectory prefers the per-project base.dir system property 
when set"() {

Review Comment:
   ```suggestion
       @RestoreSystemProperties
       void "findSourceDirectory prefers the per-project base.dir system 
property when set"() {
   ```



##########
grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy:
##########
@@ -122,4 +123,104 @@ class FooGrailsPlugin {
             xml.resources.resource.size() == 2
             xml.resources.resource.text() == "FooBar"
     }
+
+    void "isIsolatedBuild reflects the grails.isolated.build system 
property"() {
+        given:
+            String original = System.getProperty('grails.isolated.build')
+
+        when:
+            System.setProperty('grails.isolated.build', value)
+
+        then:
+            GlobalGrailsClassInjectorTransformation.isIsolatedBuild() == 
expected
+
+        cleanup:
+            if (original != null) {
+                System.setProperty('grails.isolated.build', original)
+            } else {
+                System.clearProperty('grails.isolated.build')
+            }
+
+        where:
+            value   || expected
+            'true'  || true
+            'false' || false
+            'TRUE'  || true
+            'yes'   || false
+    }
+
+    private SourceUnit sourceUnitWithTarget(File targetDirectory) {
+        def configuration = new CompilerConfiguration()
+        configuration.setTargetDirectory((File) targetDirectory)
+        Stub(SourceUnit) {
+            getConfiguration() >> configuration
+            getName() >> 'TestSource'
+        }
+    }
+
+    void "resolveCompilationTargetDirectory returns the configured target 
directory"() {
+        given:
+            File target = new File(System.getProperty('java.io.tmpdir'), 
'isolated-target/build/classes/groovy/main')
+            def source = sourceUnitWithTarget(target)
+
+        expect: "the configured directory is used regardless of build 
isolation"
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 false) == target
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 true) == target
+    }
+
+    void "resolveCompilationTargetDirectory falls back to the shared relative 
path for a non-isolated build"() {
+        given: "a source unit without a configured target directory"
+            def source = sourceUnitWithTarget(null)
+
+        when:
+            File resolved = 
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 false)
+
+        then: "the legacy relative fallback is used"
+            resolved == new File('build/classes/main')
+    }
+
+    void "resolveCompilationTargetDirectory fails fast instead of falling back 
for an isolated build"() {
+        given: "a source unit without a configured target directory"
+            def source = sourceUnitWithTarget(null)
+
+        when: "the target directory cannot be resolved in an isolated build"
+            
GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source,
 true)
+
+        then: "the build fails loudly rather than writing to a shared location"
+            IllegalStateException e = thrown()
+            e.message.contains('GRAILS_ISOLATED_BUILD=true')
+    }
+
+    void "findSourceDirectory prefers the per-project base.dir system property 
when set"() {
+        given: "base.dir points at an existing directory"
+            File baseDir = File.createTempDir()
+            System.setProperty('base.dir', baseDir.absolutePath)
+            File target = new File(baseDir, 'build/classes/groovy/main')
+
+        when:
+            File resolved = 
GlobalGrailsClassInjectorTransformation.findSourceDirectory(target)
+
+        then: "the build-tool supplied base.dir wins"
+            resolved == baseDir
+
+        cleanup:
+            System.clearProperty('base.dir')

Review Comment:
   ```suggestion
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to