Skip to content

Commit 6fde012

Browse files
committed
GROOVY-11997: Add @ForkedJvm and @ExpectedToFail JUnit extensions to groovy-test-junit6 (additional tests converted)
1 parent 49a8738 commit 6fde012

17 files changed

Lines changed: 106 additions & 66 deletions

File tree

.github/workflows/groovy-build-test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ jobs:
3636
env-no-color: '1'
3737
- java: 17
3838
os: macos-latest
39+
- java: 25
40+
os: ubuntu-latest
41+
junit-network: '-Djunit.network=true'
3942
runs-on: ${{ matrix.os }}
4043
env:
4144
NO_COLOR: ${{ matrix.env-no-color }}
@@ -55,7 +58,7 @@ jobs:
5558
- name: "🔍 Setup TestLens"
5659
uses: testlens-app/setup-testlens@v1
5760
- name: "🏃Test with Gradle"
58-
run: ./gradlew test -Ptarget.java.home="$JAVA_HOME_${{ matrix.java }}_${{ runner.arch }}"
61+
run: ./gradlew test ${{ matrix.junit-network }} -Ptarget.java.home="$JAVA_HOME_${{ matrix.java }}_${{ runner.arch }}"
5962
shell: bash
6063
timeout-minutes: 60
6164
- name: "🚀Upload reports"

build-logic/src/main/groovy/org.apache.groovy-tested.gradle

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,22 @@ Closure buildExcludeFilter(boolean legacyTestSuite) {
177177
}
178178
}
179179

180+
// Warn (rather than silently NO-SOURCE) when the groovy/grape exclusion
181+
// swallows the entirety of a project's test source set. A plain
182+
// `:groovy-grape-test:test` invocation otherwise reports BUILD SUCCESSFUL
183+
// with zero tests executed — easy to mistake for a passing run.
184+
afterEvaluate {
185+
if (!providers.systemProperty('junit.network').getOrNull()) {
186+
boolean hasGrapeTests = sourceSets.test.allSource.srcDirs.any {
187+
new File(it, 'groovy/grape').isDirectory()
188+
}
189+
if (hasGrapeTests) {
190+
String testPath = (project.path == ':' ? '' : project.path) + ':test'
191+
logger.warn("WARNING: ${testPath} will skip groovy/grape/* tests; set -Djunit.network=true to include them")
192+
}
193+
}
194+
}
195+
180196
interface TestServices {
181197
@javax.inject.Inject
182198
FileSystemOperations getFileSystemOperations()

src/test/groovy/bugs/Groovy11046.groovy

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package bugs
2020

21+
import groovy.junit6.plugin.ForkedJvm
2122
import org.junit.jupiter.api.Test
2223

2324
import static groovy.test.GroovyAssert.assertScript
@@ -35,12 +36,15 @@ final class Groovy11046 {
3536
}
3637

3738
@Test
39+
@ForkedJvm(systemProperties = [
40+
'Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector'])
3841
void testMissingDependency2() {
42+
// Log4jContextSelector is read by log4j at class-load time, so it must
43+
// be set on the JVM command line — we run in a forked child to keep
44+
// the rest of the suite from inheriting log4j routing changes.
3945
def err = shouldFail '''
4046
@Grab('org.apache.logging.log4j:log4j-core:2.22.0')
4147
org.apache.logging.log4j.core.async.AsyncLogger log
42-
System.setProperty('Log4jContextSelector',
43-
'org.apache.logging.log4j.core.async.AsyncLoggerContextSelector')
4448
log = org.apache.logging.log4j.LogManager.getLogger(getClass()) //XXX
4549
'''
4650
assert err instanceof NoClassDefFoundError // CompilationFailedException (previously)

src/test/groovy/groovy/grape/GrabResolverTest.groovy

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,29 @@
1818
*/
1919
package groovy.grape
2020

21+
import groovy.junit6.plugin.ForkedJvm
2122
import groovy.transform.CompileDynamic
2223
import groovy.transform.CompileStatic
2324
import org.codehaus.groovy.control.CompilationFailedException
24-
import org.junit.jupiter.api.AfterAll
25-
import org.junit.jupiter.api.BeforeAll
2625
import org.junit.jupiter.api.BeforeEach
2726
import org.junit.jupiter.api.Test
2827

2928
import static groovy.test.GroovyAssert.assertScript
3029
import static groovy.test.GroovyAssert.shouldFail
3130

3231
@CompileStatic
32+
@ForkedJvm(inheritProperties = ['grape.root', 'user.home', 'gradle.home'])
3333
final class GrabResolverTest {
3434

35-
private static String originalGrapeRoot
36-
37-
@BeforeAll
38-
static void setUpTestSuite() {
39-
originalGrapeRoot = System.getProperty('grape.root')
40-
}
41-
4235
@BeforeEach @CompileDynamic
4336
void setUp() {
37+
// Lifecycle hooks fire in BOTH the parent test JVM and each forked
38+
// child; the parent never runs the test bodies, so its Grape state
39+
// and grape.root must stay untouched. The previous BeforeAll/AfterAll
40+
// save/restore dance becomes redundant once nothing in the parent
41+
// mutates grape.root.
42+
if (!Boolean.parseBoolean(System.getProperty('groovy.junit6.forked'))) return
43+
4444
Grape.@instance = null // isolate each test
4545

4646
// create a new grape root directory for each test for isolation
@@ -62,17 +62,6 @@ final class GrabResolverTest {
6262
}
6363
}
6464

65-
@AfterAll
66-
static void tearDownTestSuite() {
67-
if (originalGrapeRoot == null) {
68-
System.clearProperty('grape.root')
69-
} else {
70-
System.setProperty('grape.root', originalGrapeRoot)
71-
}
72-
73-
Grape.@instance = null // isolate tests
74-
}
75-
7665
@Test
7766
void testResolverDefinitionIsRequired() {
7867
shouldFail CompilationFailedException, '''

src/test/groovy/groovy/lang/GroovyClassLoaderTest.groovy

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package groovy.lang
2020

21+
import groovy.junit6.plugin.ForkedJvm
2122
import org.codehaus.groovy.ast.ClassHelper
2223
import org.codehaus.groovy.ast.ClassNode
2324
import org.codehaus.groovy.ast.CompileUnit
@@ -207,21 +208,19 @@ final class GroovyClassLoaderTest {
207208
}
208209

209210
@Test
211+
@ForkedJvm(systemProperties = ['file.encoding=US-ASCII'])
210212
void testSourceEncoding() {
211-
String oldEncoding = System.getProperty('file.encoding')
212-
System.setProperty('file.encoding', 'US-ASCII')
213-
try {
214-
def gcl = new GroovyClassLoader(this.class.classLoader, new CompilerConfiguration().tap{sourceEncoding = 'UTF-8'})
215-
def clazz = gcl.parseClass('return "\u20AC"') // EURO currency symbol
216-
def result = clazz.getDeclaredConstructor().newInstance().run()
217-
int i = result[0]
218-
// 0xFFFD is used if the original character was not found,
219-
// it is the famous ? that can often be seen. So if this here
220-
// fails, then the String conversion failed at one point
221-
assert i != 0xFFFD
222-
} finally {
223-
System.setProperty('file.encoding', oldEncoding)
224-
}
213+
// file.encoding is JVM-global (and consulted by JDK internals at
214+
// class-load time on some platforms), so we set it via the forked
215+
// command line rather than mutating the running JVM.
216+
def gcl = new GroovyClassLoader(this.class.classLoader, new CompilerConfiguration().tap{sourceEncoding = 'UTF-8'})
217+
def clazz = gcl.parseClass('return "\u20AC"') // EURO currency symbol
218+
def result = clazz.getDeclaredConstructor().newInstance().run()
219+
int i = result[0]
220+
// 0xFFFD is used if the original character was not found,
221+
// it is the famous ? that can often be seen. So if this here
222+
// fails, then the String conversion failed at one point
223+
assert i != 0xFFFD
225224
}
226225

227226
// GROOVY-3537

src/test/groovy/org/codehaus/groovy/control/CompilerConfigurationTest.java

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,14 @@
1818
*/
1919
package org.codehaus.groovy.control;
2020

21+
import groovy.junit6.plugin.ForkedJvm;
2122
import org.codehaus.groovy.control.customizers.ImportCustomizer;
2223
import org.codehaus.groovy.control.messages.WarningMessage;
23-
import org.junit.jupiter.api.AfterEach;
24-
import org.junit.jupiter.api.BeforeEach;
2524
import org.junit.jupiter.api.Test;
2625

2726
import java.io.File;
2827
import java.util.Arrays;
2928
import java.util.Collections;
30-
import java.util.Properties;
3129

3230
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
3331
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -42,19 +40,6 @@
4240
*/
4341
public final class CompilerConfigurationTest {
4442

45-
private Properties savedProperties;
46-
47-
@BeforeEach
48-
public void setUp() {
49-
savedProperties = System.getProperties();
50-
System.setProperties(new Properties(savedProperties));
51-
}
52-
53-
@AfterEach
54-
public void tearDown() {
55-
System.setProperties(savedProperties);
56-
}
57-
5843
@Test
5944
public void testDefaultConstructor() {
6045
CompilerConfiguration config = CompilerConfiguration.DEFAULT;
@@ -76,13 +61,17 @@ public void testDefaultConstructor() {
7661
}
7762

7863
@Test
64+
@ForkedJvm(systemProperties = {
65+
"groovy.warnings=PaRaNoiA",
66+
"groovy.output.verbose=trUE",
67+
"groovy.mem.stub=true",
68+
"groovy.generate.stub.in.memory=true",
69+
"groovy.recompile.minimumInterval=867892345"})
7970
public void testSetViaSystemProperties() {
80-
System.setProperty("groovy.warnings", "PaRaNoiA");
81-
System.setProperty("groovy.output.verbose", "trUE");
82-
System.setProperty("groovy.mem.stub", "true");
83-
System.setProperty("groovy.generate.stub.in.memory", "true");
84-
System.setProperty("groovy.recompile.minimumInterval", "867892345");
85-
71+
// Properties are set on the JVM command line via @ForkedJvm; the
72+
// forked child reads them through the normal System.getProperties()
73+
// path the production code uses, and parent-JVM state stays clean
74+
// for all the other (read-only) tests in this class.
8675
assertEquals("PaRaNoiA", System.getProperty("groovy.warnings"));
8776

8877
CompilerConfiguration config = new CompilerConfiguration(System.getProperties());

src/test/groovy/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.codehaus.groovy.transform.traitx
2020

21+
import groovy.junit6.plugin.ForkedJvm
2122
import groovy.transform.AnnotationCollector
2223
import groovy.transform.SelfType
2324
import org.codehaus.groovy.ast.ClassHelper
@@ -3376,6 +3377,7 @@ final class TraitASTTransformationTest {
33763377

33773378
// GROOVY-10521
33783379
@Test
3380+
@ForkedJvm(systemProperties = ['spock.iKnowWhatImDoing.disableGroovyVersionCheck=true'])
33793381
void testVariadicMethodOfPrecompiledTrait() {
33803382
assertScript shell, """import org.codehaus.groovy.ast.*
33813383
class CT implements ${T10521.name} {
@@ -3390,7 +3392,6 @@ final class TraitASTTransformationTest {
33903392
assert td == 'm(java.lang.Class,[java.lang.Object):java.lang.Object'
33913393
"""
33923394

3393-
System.setProperty('spock.iKnowWhatImDoing.disableGroovyVersionCheck','true')
33943395
assertScript shell, """
33953396
@Grab('org.spockframework:spock-core:2.4-groovy-5.0')
33963397
@GrabExclude('org.codehaus.groovy:groovy-all')

subprojects/groovy-grape-ivy/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ dependencies {
2626
transitive = false
2727
}
2828
testImplementation projects.groovyTest
29+
testImplementation projects.groovyTestJunit6
2930
}
3031

3132
// The only Java source is a package-private implementation class;

subprojects/groovy-grape-ivy/src/test/groovy/groovy/grape/ivy/GrapeIvyTest.groovy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package groovy.grape.ivy
2020

2121
import groovy.grape.Grape
22+
import groovy.junit6.plugin.ForkedJvm
2223

2324
import org.codehaus.groovy.control.CompilationFailedException
2425
import org.junit.jupiter.api.BeforeAll
@@ -264,6 +265,7 @@ final class GrapeIvyTest {
264265
}
265266

266267
@Test // GROOVY-8372
268+
@ForkedJvm(inheritProperties = ['grape.root', 'user.home', 'gradle.home'])
267269
void testConf2() {
268270
assumeTrue(Grape.instance instanceof GrapeIvy) // only GrapeIvy uses <ivysettings>
269271
def tempDir = File.createTempDir()
@@ -496,6 +498,7 @@ final class GrapeIvyTest {
496498
}
497499

498500
@Test // GROOVY-7548
501+
@ForkedJvm(inheritProperties = ['grape.root', 'user.home', 'gradle.home'])
499502
void testSystemProperties() {
500503
System.setProperty('groovy7548prop', 'x')
501504
assert System.getProperty('groovy7548prop') == 'x'

subprojects/groovy-grape-maven/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ dependencies {
2424
api rootProject
2525
implementation "org.apache.maven:maven-resolver-provider:${versions.mavenResolverProvider}"
2626
implementation "org.apache.maven.resolver:maven-resolver-supplier-mvn4:${versions.mavenResolverSupplier}"
27+
// Maven Resolver's supplier instantiates components annotated with javax.inject (JSR-330);
28+
// without javax.inject on the classpath, RepositorySystemSupplier.get() fails with
29+
// NoClassDefFoundError: javax/inject/Provider. The supplier's POM doesn't declare this
30+
// transitively as of 2.0.17, so we provide it explicitly.
31+
implementation "javax.inject:javax.inject:${versions.javaxInject}"
2732
}
2833

2934
tasks.withType(Javadoc).configureEach {

0 commit comments

Comments
 (0)