You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/04/23 20:24:22 UTC

[groovy] branch master updated: stop writing classes to project basedir

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

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 059f54fe6b stop writing classes to project basedir
059f54fe6b is described below

commit 059f54fe6b8bf547cc61265e93111258f8a01c41
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Apr 23 15:17:25 2022 -0500

    stop writing classes to project basedir
---
 ...onditionalInterruptibleASTTransformation.groovy |  23 +-
 .../transform/ConditionalInterruptTest.groovy      | 261 ++++++------
 src/test/groovy/transform/LazyTest.groovy          | 118 +++---
 src/test/groovy/transform/ReadWriteLockTest.groovy | 295 +++++++-------
 .../groovy/transform/ThreadInterruptTest.groovy    | 432 ++++++++++----------
 .../groovy/transform/TimedInterruptTest.groovy     | 450 ++++++++++-----------
 .../ClosureWriterGeneratedAnnotationTest.groovy    |  75 ++--
 .../classgen/asm/sc/BugsStaticCompileTest.groovy   |   3 +-
 ...ticCompileClosureGeneratedAnnotationTest.groovy |  81 ++--
 .../TransformsAndCustomClassLoadersTest.groovy     |   2 +-
 10 files changed, 853 insertions(+), 887 deletions(-)

diff --git a/src/main/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
index 90fce9c7c6..594f87b41d 100644
--- a/src/main/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
+++ b/src/main/groovy/org/codehaus/groovy/transform/ConditionalInterruptibleASTTransformation.groovy
@@ -28,12 +28,10 @@ import org.codehaus.groovy.ast.FieldNode
 import org.codehaus.groovy.ast.MethodNode
 import org.codehaus.groovy.ast.Parameter
 import org.codehaus.groovy.ast.PropertyNode
-import org.codehaus.groovy.ast.expr.ArgumentListExpression
 import org.codehaus.groovy.ast.expr.ClosureExpression
 import org.codehaus.groovy.ast.expr.Expression
-import org.codehaus.groovy.ast.expr.MethodCallExpression
-import org.codehaus.groovy.ast.expr.VariableExpression
 import org.codehaus.groovy.ast.tools.ClosureUtils
+import org.codehaus.groovy.ast.tools.GeneralUtils
 import org.codehaus.groovy.control.CompilePhase
 
 /**
@@ -48,25 +46,21 @@ import org.codehaus.groovy.control.CompilePhase
 @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
 class ConditionalInterruptibleASTTransformation extends AbstractInterruptibleASTTransformation {
 
-    private static final ClassNode MY_TYPE = ClassHelper.make(ConditionalInterrupt)
-
     private ClosureExpression conditionNode
     private String conditionMethod
-    private MethodCallExpression conditionCallExpression
     private ClassNode currentClass
 
     protected ClassNode type() {
-        MY_TYPE
+        ClassHelper.make(ConditionalInterrupt)
     }
 
-    @SuppressWarnings('Instanceof')
     protected void setupTransform(AnnotationNode node) {
         super.setupTransform(node)
-        ClosureExpression member = (ClosureExpression) node.getMember('value')
-        if (!member || !(member instanceof ClosureExpression)) internalError("Expected closure value for annotation parameter 'value'. Found $member")
-        conditionNode = member
+        def member = node.getMember('value')
+        if (member !instanceof ClosureExpression)
+            internalError("Expected closure value for annotation parameter 'value'. Found $member")
+        conditionNode = (ClosureExpression) member
         conditionMethod = 'conditionalTransform' + node.hashCode() + '$condition'
-        conditionCallExpression = new MethodCallExpression(new VariableExpression('this'), conditionMethod, new ArgumentListExpression())
     }
 
     protected String getErrorMessage() {
@@ -75,15 +69,14 @@ class ConditionalInterruptibleASTTransformation extends AbstractInterruptibleAST
 
     void visitClass(ClassNode type) {
         currentClass = type
-        def method = type.addMethod(conditionMethod, ACC_PRIVATE | ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, conditionNode.code)
-        method.synthetic = true
+        type.addSyntheticMethod(conditionMethod, ACC_PRIVATE, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, conditionNode.code)
         if (applyToAllMembers) {
             super.visitClass(type)
         }
     }
 
     protected Expression createCondition() {
-        conditionCallExpression
+        GeneralUtils.callThisX(conditionMethod)
     }
 
     @Override
diff --git a/src/test/groovy/transform/ConditionalInterruptTest.groovy b/src/test/groovy/transform/ConditionalInterruptTest.groovy
index 60b218fdeb..cb86990292 100644
--- a/src/test/groovy/transform/ConditionalInterruptTest.groovy
+++ b/src/test/groovy/transform/ConditionalInterruptTest.groovy
@@ -18,186 +18,193 @@
  */
 package groovy.transform
 
-import groovy.test.GroovyTestCase
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.customizers.ImportCustomizer
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
 
 /**
- * Test for {@link ConditionalInterrupt} AST Transformation.
+ * Tests for the {@link ConditionalInterrupt} AST transform.
  */
-class ConditionalInterruptTest extends GroovyTestCase {
+final class ConditionalInterruptTest {
 
-    void testMethodIsVisited_AndExceptionMessage() {
+    private final GroovyShell shell = new GroovyShell(new CompilerConfiguration().addCompilationCustomizers(
+        new ImportCustomizer().tap {
+            addStarImports('groovy.transform')
+            addStaticImport('groovy.test.GroovyAssert', 'shouldFail')
+        }
+    ))
 
-        def c = new GroovyClassLoader().parseClass('''
-            import groovy.transform.ConditionalInterrupt
-            @ConditionalInterrupt({ visited = true })
-            class MyClass {
-              boolean visited = false
-              def myMethod() { }
+    @Test
+    void testMethodIsVisited_AndExceptionMessage() {
+        assertScript shell, '''
+            @ConditionalInterrupt(applyToAllClasses=false, value={ visited = true })
+            class C {
+                protected boolean visited
+                def m() { }
             }
-        ''')
 
-        def instance = c.newInstance()
-        def message = shouldFail(InterruptedException) {
-            instance.myMethod()
-        }
-        assert message == 'Execution interrupted. The following condition failed: { visited = true }'
-        assert instance.visited
+            def obj = new C()
+            def err = shouldFail(InterruptedException) {
+                obj.m()
+            }
+            assert obj.visited
+            assert err.message == 'Execution interrupted. The following condition failed: { visited = true }'
+        '''
     }
 
+    @Test
     void testMethodIsVisitedCompileStatic() {
-        def c = new GroovyClassLoader().parseClass('''
-            import groovy.transform.*
+        assertScript shell, '''
             @CompileStatic
-            @ConditionalInterrupt({ visited = true })
-            class MyClass {
-              boolean visited = false
-              def myMethod() { }
-            }
-        ''')
-        def instance = c.newInstance()
-        def message = shouldFail(InterruptedException) {
-            instance.myMethod()
-        }
-        assert message == 'Execution interrupted. The following condition failed: { visited = true }'
-        assert instance.visited
+            @ConditionalInterrupt(applyToAllClasses=false, value={ visited = true })
+            class C {
+                protected boolean visited
+                def m() { }
+            }
+
+            def obj = new C()
+            def err = shouldFail(InterruptedException) {
+                obj.m()
+            }
+            assert obj.visited
+            assert err.message == 'Execution interrupted. The following condition failed: { visited = true }'
+        '''
     }
 
+    @Test
     void testMethodIsVisited_AndCustomExceptionMessage() {
-
-        def c = new GroovyClassLoader(this.class.classLoader).parseClass('''
-            import groovy.transform.ConditionalInterrupt
-            @ConditionalInterrupt(thrown=groovy.transform.CustomException, value={ visited = true })
-            class MyClass {
-              boolean visited = false
-              def myMethod() { }
+        assertScript shell, '''
+            @ConditionalInterrupt(applyToAllClasses=false, thrown=CustomException, value={ visited = true })
+            class C {
+                protected boolean visited
+                def m() { }
             }
-        ''')
 
-        def instance = c.newInstance()
-        def message = shouldFail(CustomException) {
-            instance.myMethod()
-        }
-        assert message == 'Execution interrupted. The following condition failed: { visited = true }'
-        assert instance.visited
+            def obj = new C()
+            def err = shouldFail(CustomException) {
+                obj.m()
+            }
+            assert obj.visited
+            assert err.message == 'Execution interrupted. The following condition failed: { visited = true }'
+        '''
     }
 
+    @Test
     void testStaticMethodIsNotVisited() {
-         def c = new GroovyClassLoader().parseClass('''
-            import groovy.transform.ConditionalInterrupt
-            @ConditionalInterrupt({ visited = true })
-            class MyClass {
-              boolean visited = false
-              static def myMethod() { }
-            }
-        ''')
-
-        def instance = c.newInstance()
-        instance.myMethod()
-        assert !instance.visited
+        assertScript shell, '''
+            @ConditionalInterrupt(applyToAllClasses=false, value={ visited = true })
+            class C {
+                protected boolean visited
+                static m() { }
+            }
+
+            def obj = new C()
+            obj.m()
+
+            assert !obj.visited
+        '''
     }
 
+    @Test
     void testClosureFieldIsVisited() {
-
-        def c = new GroovyClassLoader().parseClass('''
-            import groovy.transform.ConditionalInterrupt
-            @ConditionalInterrupt({ visited = true })
-            class MyClass {
-              boolean visited = false
-              def myMethod = { }
+        assertScript shell, '''
+            @ConditionalInterrupt(applyToAllClasses=false, value={ visited = true })
+            class C {
+                protected boolean visited
+                def m = { -> }
             }
-        ''')
 
-        def instance = c.newInstance()
-        shouldFail(InterruptedException) {
-            instance.myMethod()
-        }
-        assert instance.visited
+            def obj = new C()
+            shouldFail(InterruptedException) {
+                obj.m()
+            }
+            assert obj.visited
+        '''
     }
 
+    @Test
     void testWhileLoopVisited() {
-        def c = new GroovyClassLoader().parseClass('''
-            import groovy.transform.ConditionalInterrupt
-            @ConditionalInterrupt({ count > 5 })
-            class MyClass {
-                int count = 0
-                def myMethod = {
+        assertScript shell, '''
+            @ConditionalInterrupt(applyToAllClasses=false, value={ count > 5 })
+            class C {
+                protected int count
+                def m = { ->
                     while (count < 10) {
-                        count++
+                        count += 1
                     }
                 }
             }
-        ''')
 
-        def instance = c.newInstance()
-        shouldFail(InterruptedException) {
-            instance.myMethod()
-        }
-        assert 6 == instance.count
+            def obj = new C()
+            shouldFail(InterruptedException) {
+                obj.m()
+            }
+            assert obj.count == 6
+        '''
     }
 
+    @Test
     void testForLoopVisited() {
-
-        def c = new GroovyClassLoader().parseClass('''
-            import groovy.transform.ConditionalInterrupt
-            @ConditionalInterrupt({ count > 5 })
-            class MyClass {
-                int count = 0
-                def myMethod = {
-                    for (int x = 0; x < 10; x++) {
-                        count++
+        assertScript shell, '''
+            @ConditionalInterrupt(applyToAllClasses=false, value={ count > 5 })
+            class C {
+                protected int count
+                def m = {
+                    for (int i = 0; i < 10; i += 1) {
+                        count += 1
                     }
                 }
             }
-        ''')
 
-        def instance = c.newInstance()
-        shouldFail(InterruptedException) {
-            instance.myMethod()
-        }
-        assert 6 == instance.count
+            def obj = new C()
+            shouldFail(InterruptedException) {
+                obj.m()
+            }
+            assert obj.count == 6
+        '''
     }
 
+    @Test
     void testStaticClosureFieldNotVisited() {
-
-        def c = new GroovyClassLoader().parseClass('''
-            import groovy.transform.ConditionalInterrupt
-            @ConditionalInterrupt({ visited = true })
-            class MyClass {
-                boolean visited = false
-                static def myMethod = { }
+        assertScript shell, '''
+            @ConditionalInterrupt(applyToAllClasses=false, value={ visited = true })
+            class C {
+                protected boolean visited
+                static m = { -> }
             }
-        ''')
 
-        def instance = c.newInstance()
-        instance.myMethod()
-        assert !instance.visited
+            def obj = new C()
+            obj.m()
+
+            assert !obj.visited
+        '''
     }
 
+    @Test
     void testSharedContext() {
-        def shell = new GroovyShell()
-
-        def script = shell.parse('''
-            import groovy.transform.ConditionalInterrupt
-
+        assertScript shell, '''
             class Helper {
-                static int i=0
-                static def shouldInterrupt() { i++>1 }
+                static int i
+                static def shouldInterrupt() { ++i > 1 }
             }
 
-            @ConditionalInterrupt({ Helper.shouldInterrupt() })
-            class MyClass {
-                def myMethod() { }
+            @ConditionalInterrupt(applyToAllClasses=false, value={ Helper.shouldInterrupt() })
+            class C {
+                def m = { -> }
             }
 
-            @ConditionalInterrupt({ Helper.shouldInterrupt() })
-            class MyOtherClass {
-                def myOtherMethod() { new MyClass().myMethod() }
+            @ConditionalInterrupt(applyToAllClasses=false, value={ Helper.shouldInterrupt() })
+            class D {
+                def m() {
+                    new C().m()
+                }
             }
 
-            new MyOtherClass().myOtherMethod()
-        ''', 'myScript')
-        shouldFail(InterruptedException) {
-            script.run()
-        }
+            shouldFail(InterruptedException) {
+                new D().m()
+            }
+        '''
     }
 }
diff --git a/src/test/groovy/transform/LazyTest.groovy b/src/test/groovy/transform/LazyTest.groovy
index 1e22cd1a45..bdfc19e059 100644
--- a/src/test/groovy/transform/LazyTest.groovy
+++ b/src/test/groovy/transform/LazyTest.groovy
@@ -18,72 +18,82 @@
  */
 package groovy.transform
 
-import groovy.test.GroovyTestCase
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.customizers.ImportCustomizer
+import org.junit.Test
 
-import java.lang.ref.SoftReference
-import java.lang.reflect.Modifier
+import static groovy.test.GroovyAssert.assertScript
 
 /**
- * Unit tests for the Lazy annotation
+ * Tests for the {@link Lazy} AST transform.
  */
-class LazyTest extends GroovyTestCase {
+final class LazyTest {
+
+    private final GroovyShell shell = new GroovyShell(new CompilerConfiguration().addCompilationCustomizers(
+        new ImportCustomizer().tap { addStaticStars('java.lang.reflect.Modifier') }
+    ))
+
+    @Test
     void testLazyPrimitiveWrapping() {
-        def tester = new GroovyClassLoader().parseClass(
-          '''class MyClass {
-            |    @Lazy int index = { ->
-            |        1
-            |    }
-            |}'''.stripMargin() )
-        // Should be a private non-volatile Integer
-        def field = tester.getDeclaredField( '$index' )
-        assert field
-        assert Modifier.isPrivate(field.modifiers)
-        assert !Modifier.isVolatile(field.modifiers)
-        assert field.type == Integer
+        assertScript shell, '''
+            class C {
+                @Lazy int index = { -> 1 }
+            }
+
+            def field = C.getDeclaredField('$index')
+            assert field
+            assert field.type == Integer
+            assert isPrivate(field.modifiers)
+            assert !isVolatile(field.modifiers)
+        '''
     }
 
+    @Test
     void testLazyVolatilePrimitiveWrapping() {
-        def tester = new GroovyClassLoader().parseClass(
-          '''class MyClass {
-            |    @Lazy volatile int index = { ->
-            |        1
-            |    }
-            |}'''.stripMargin() )
-        // Should be a private volatile Integer
-        def field = tester.getDeclaredField( '$index' )
-        assert field
-        assert Modifier.isPrivate(field.modifiers)
-        assert Modifier.isVolatile(field.modifiers)
-        assert field.type == Integer
+        assertScript shell, '''
+            class C {
+                @Lazy volatile int index = { -> 1 }
+            }
+
+            def field = C.getDeclaredField('$index')
+            assert field
+            assert field.type == Integer
+            assert isPrivate(field.modifiers)
+            assert isVolatile(field.modifiers)
+        '''
     }
 
+    @Test
     void testLazySoftPrimitiveWrapping() {
-        def tester = new GroovyClassLoader().parseClass(
-          '''class MyClass {
-            |    @Lazy(soft=true) int index = { ->
-            |        1
-            |    }
-            |}'''.stripMargin() )
-        // Should be a private non-volatile SoftReference
-        def field = tester.getDeclaredField( '$index' )
-        assert field
-        assert Modifier.isPrivate(field.modifiers)
-        assert !Modifier.isVolatile(field.modifiers)
-        assert field.type == SoftReference
+        assertScript shell, '''
+            import java.lang.ref.SoftReference as SoftRef
+
+            class C {
+                @Lazy(soft=true) int index = { -> 1 }
+            }
+
+            def field = C.getDeclaredField('$index')
+            assert field
+            assert field.type == SoftRef
+            assert isPrivate(field.modifiers)
+            assert !isVolatile(field.modifiers)
+        '''
     }
 
+    @Test
     void testLazyVolatileSoftPrimitiveWrapping() {
-        def tester = new GroovyClassLoader().parseClass(
-          '''class MyClass {
-            |    @Lazy(soft=true) volatile int index = { ->
-            |        1
-            |    }
-            |}'''.stripMargin() )
-        // Should be a private volatile SoftReference
-        def field = tester.getDeclaredField( '$index' )
-        assert field
-        assert Modifier.isPrivate(field.modifiers)
-        assert Modifier.isVolatile(field.modifiers)
-        assert field.type == SoftReference
+        assertScript shell, '''
+            import java.lang.ref.SoftReference as SoftRef
+
+            class C {
+                @Lazy(soft=true) volatile int index = { -> 1 }
+            }
+
+            def field = C.getDeclaredField('$index')
+            assert field
+            assert field.type == SoftRef
+            assert isPrivate(field.modifiers)
+            assert isVolatile(field.modifiers)
+        '''
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/groovy/transform/ReadWriteLockTest.groovy b/src/test/groovy/transform/ReadWriteLockTest.groovy
index a36fcbae27..7a77bb05a9 100644
--- a/src/test/groovy/transform/ReadWriteLockTest.groovy
+++ b/src/test/groovy/transform/ReadWriteLockTest.groovy
@@ -18,82 +18,92 @@
  */
 package groovy.transform
 
-import groovy.test.GroovyTestCase
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.customizers.ImportCustomizer
+import org.junit.Test
 
-import java.util.concurrent.locks.ReentrantReadWriteLock
-import java.lang.reflect.Modifier
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
 
 /**
- * Unit test for WithReadLock and WithWriteLock annotations.
+ * Tests for the {@link WithReadLock} and {@link WithWriteLock} AST transforms.
  */
-class ReadWriteLockTest extends GroovyTestCase {
+final class ReadWriteLockTest {
 
-    void testLockFieldDefaultsForReadLock() {
-        def tester = new GroovyClassLoader().parseClass('''
-        class MyClass {
-            @groovy.transform.WithReadLock
-            public void readerMethod1() { }
+    private final GroovyShell shell = new GroovyShell(new CompilerConfiguration().addCompilationCustomizers(
+        new ImportCustomizer().tap {
+            addStarImports('groovy.transform')
+            addStaticStars('java.lang.reflect.Modifier')
+            addImport('java.util.concurrent.locks.ReentrantReadWriteLock')
         }
-''')
-        def field = tester.getDeclaredField('$reentrantlock')
-        assert Modifier.isPrivate(field.modifiers)
-        assert !Modifier.isTransient(field.modifiers)
-        assert Modifier.isFinal(field.modifiers)
-        assert !Modifier.isStatic(field.modifiers)
-
-        assert field.type == ReentrantReadWriteLock
+    ))
+
+    @Test
+    void testLockFieldDefaultsForReadLock() {
+        assertScript shell, '''
+            class C {
+                @WithReadLock void m() { }
+            }
+
+            def field = C.getDeclaredField('$reentrantlock')
+            assert field.type == ReentrantReadWriteLock
+            assert !isTransient(field.modifiers)
+            assert isPrivate(field.modifiers)
+            assert !isStatic(field.modifiers)
+            assert isFinal(field.modifiers)
+        '''
     }
 
+    @Test
     void testLockFieldDefaultsForWriteLock() {
-        def tester = new GroovyClassLoader().parseClass('''
-        class MyClass {
-            @groovy.transform.WithWriteLock
-            public void readerMethod1() { }
-        }
-''')
-        def field = tester.getDeclaredField('$reentrantlock')
-        assert Modifier.isPrivate(field.modifiers)
-        assert !Modifier.isTransient(field.modifiers)
-        assert Modifier.isFinal(field.modifiers)
-        assert !Modifier.isStatic(field.modifiers)
-
-        assert field.type == ReentrantReadWriteLock
+        assertScript shell, '''
+            class C {
+                @WithWriteLock void m() { }
+            }
+
+            def field = C.getDeclaredField('$reentrantlock')
+            assert field.type == ReentrantReadWriteLock
+            assert !isTransient(field.modifiers)
+            assert isPrivate(field.modifiers)
+            assert !isStatic(field.modifiers)
+            assert isFinal(field.modifiers)
+        '''
     }
 
+    @Test
     void testLockFieldDefaultsForStaticReadLock() {
-        def tester = new GroovyClassLoader().parseClass('''
-        class MyClass {
-            @groovy.transform.WithReadLock
-            public static void readerMethod1() { }
-        }
-''')
-        def field = tester.getDeclaredField('$REENTRANTLOCK')
-        assert Modifier.isPrivate(field.modifiers)
-        assert !Modifier.isTransient(field.modifiers)
-        assert Modifier.isFinal(field.modifiers)
-        assert Modifier.isStatic(field.modifiers)
-
-        assert field.type == ReentrantReadWriteLock
+        assertScript shell, '''
+            class C {
+                @WithReadLock static void m() { }
+            }
+
+            def field = C.getDeclaredField('$REENTRANTLOCK')
+            assert field.type == ReentrantReadWriteLock
+            assert !isTransient(field.modifiers)
+            assert isPrivate(field.modifiers)
+            assert isStatic(field.modifiers)
+            assert isFinal(field.modifiers)
+        '''
     }
 
+    @Test
     void testLockFieldDefaultsForStaticWriteLock() {
-        def tester = new GroovyClassLoader().parseClass('''
-        class MyClass {
-            @groovy.transform.WithWriteLock
-            public static void readerMethod1() { }
-        }
-''')
-        def field = tester.getDeclaredField('$REENTRANTLOCK')
-        assert Modifier.isPrivate(field.modifiers)
-        assert !Modifier.isTransient(field.modifiers)
-        assert Modifier.isFinal(field.modifiers)
-        assert Modifier.isStatic(field.modifiers)
-
-        assert field.type == ReentrantReadWriteLock
+        assertScript shell, '''
+            class C {
+                @WithWriteLock static void m() { }
+            }
+
+            def field = C.getDeclaredField('$REENTRANTLOCK')
+            assert field.type == ReentrantReadWriteLock
+            assert !isTransient(field.modifiers)
+            assert isPrivate(field.modifiers)
+            assert isStatic(field.modifiers)
+            assert isFinal(field.modifiers)
+        '''
     }
 
+    @Test
     void testLocking() {
-
         def tester = new MyClass()
         tester.readerMethod1()
         tester.readerMethod2()
@@ -111,8 +121,8 @@ class ReadWriteLockTest extends GroovyTestCase {
         tester.readerMethod1()
     }
 
+    @Test
     void testStaticLocking() {
-
         def tester = new MyClass()
         tester.staticReaderMethod1()
         tester.staticReaderMethod2()
@@ -130,10 +140,11 @@ class ReadWriteLockTest extends GroovyTestCase {
         tester.staticReaderMethod1()
     }
 
+    @Test
     void testDeadlockingDoesNotOccur() {
         def tester = new MyClass()
 
-        // this tests for deadlocks from not releaseing in finally block 
+        // this tests for deadlocks from not releaseing in finally block
         shouldFail { tester.namedReaderMethod1() }
         shouldFail { tester.namedReaderMethod2() }
         shouldFail { tester.namedWriterMethod1() }
@@ -145,41 +156,40 @@ class ReadWriteLockTest extends GroovyTestCase {
         shouldFail { tester.namedReaderMethod1() }
     }
 
+    @Test
     void testCompileError_NamingConflict() {
-        shouldFail("lock field with name 'unknown' not found") {
-            '''
+        def err = shouldFail shell, '''
             class MyClass {
                 @groovy.transform.WithWriteLock('unknown')
                 public static void readerMethod1() { }
-            } '''
-        }
+            }
+        '''
+        assert err =~ /lock field with name 'unknown' not found/
 
-        shouldFail("lock field with name 'myLock' should be static") {
-            '''
+        err = shouldFail shell, '''
             class MyClass {
-                def myLock = new java.util.concurrent.locks.ReentrantReadWriteLock()
+                def myLock = new ReentrantReadWriteLock()
 
                 @groovy.transform.WithWriteLock('myLock')
                 public static void readerMethod1() { }
-            } '''
-        }
+            }
+        '''
+        assert err =~ /lock field with name 'myLock' should be static/
 
-        shouldFail("lock field with name 'myLock' should not be static") {
-            '''
+        err = shouldFail shell, '''
             class MyClass {
-                static def myLock = new java.util.concurrent.locks.ReentrantReadWriteLock()
+                static def myLock = new ReentrantReadWriteLock()
 
                 @groovy.transform.WithWriteLock('myLock')
                 public void readerMethod1() { }
-            } '''
-        }
+            }
+        '''
+        assert err =~ /lock field with name 'myLock' should not be static/
     }
 
-    // GROOVY-8758
+    @Test // GROOVY-8758
     void testShouldBeAllowedInInnerClassWithCompileStatic() {
-        assertScript '''
-            import groovy.transform.*
-
+        assertScript shell, '''
             @CompileStatic
             class A {
                 private class B {
@@ -198,77 +208,68 @@ class ReadWriteLockTest extends GroovyTestCase {
         '''
     }
 
-    def shouldFail(String expectedText, Closure c) {
-        String script = c()
-        try {
-            new GroovyClassLoader().parseClass(script)
-            fail('Failure Expected')
-        } catch (Exception e) {
-            assert e.getMessage().contains(expectedText)
+    //--------------------------------------------------------------------------
+
+    static class MyClass {
+        def readerMethod1Called = false
+        def readerMethod2Called = false
+        def writerMethod1Called = false
+        def writerMethod2Called = false
+        def staticReaderMethod1Called = false
+        def staticReaderMethod2Called = false
+        def staticWriterMethod1Called = false
+        def staticWriterMethod2Called = false
+        def myLock = new java.util.concurrent.locks.ReentrantReadWriteLock()
+
+        @WithReadLock
+        void readerMethod1() {
+            readerMethod1Called = true
+        }
+        @WithReadLock
+        void readerMethod2() {
+            readerMethod2Called = true
+        }
+        @WithWriteLock
+        void writerMethod1() {
+            writerMethod1Called = true
+        }
+        @WithWriteLock
+        void writerMethod2() {
+            writerMethod2Called = true
         }
-    }
-}
-
-class MyClass {
-
-    def readerMethod1Called = false
-    def readerMethod2Called = false
-    def writerMethod1Called = false
-    def writerMethod2Called = false
-    def staticReaderMethod1Called = false
-    def staticReaderMethod2Called = false
-    def staticWriterMethod1Called = false
-    def staticWriterMethod2Called = false
-    def myLock = new ReentrantReadWriteLock()
-
-    @WithReadLock
-    void readerMethod1() {
-        readerMethod1Called = true
-    }
-    @WithReadLock
-    void readerMethod2() {
-        readerMethod2Called = true
-    }
-    @WithWriteLock
-    void writerMethod1() {
-        writerMethod1Called = true
-    }
-    @WithWriteLock
-    void writerMethod2() {
-        writerMethod2Called = true
-    }
 
-    @WithReadLock('myLock')
-    void namedReaderMethod1() {
-        throw new Exception()
-    }
-    @WithReadLock('myLock')
-    void namedReaderMethod2() {
-        throw new Exception()
-    }
-    @WithWriteLock('myLock')
-    void namedWriterMethod1() {
-        throw new Exception()
-    }
-    @WithWriteLock('myLock')
-    void namedWriterMethod2() {
-        throw new Exception()
-    }
+        @WithReadLock('myLock')
+        void namedReaderMethod1() {
+            throw new Exception()
+        }
+        @WithReadLock('myLock')
+        void namedReaderMethod2() {
+            throw new Exception()
+        }
+        @WithWriteLock('myLock')
+        void namedWriterMethod1() {
+            throw new Exception()
+        }
+        @WithWriteLock('myLock')
+        void namedWriterMethod2() {
+            throw new Exception()
+        }
 
-    @WithReadLock
-    void staticReaderMethod1() {
-        staticReaderMethod1Called = true
-    }
-    @WithReadLock
-    void staticReaderMethod2() {
-        staticReaderMethod2Called = true
-    }
-    @WithWriteLock
-    void staticWriterMethod1() {
-        staticWriterMethod1Called = true
-    }
-    @WithWriteLock
-    void staticWriterMethod2() {
-        staticWriterMethod2Called = true
+        @WithReadLock
+        void staticReaderMethod1() {
+            staticReaderMethod1Called = true
+        }
+        @WithReadLock
+        void staticReaderMethod2() {
+            staticReaderMethod2Called = true
+        }
+        @WithWriteLock
+        void staticWriterMethod1() {
+            staticWriterMethod1Called = true
+        }
+        @WithWriteLock
+        void staticWriterMethod2() {
+            staticWriterMethod2Called = true
+        }
     }
 }
diff --git a/src/test/groovy/transform/ThreadInterruptTest.groovy b/src/test/groovy/transform/ThreadInterruptTest.groovy
index 4747d2d3c1..bc7f3a2b22 100644
--- a/src/test/groovy/transform/ThreadInterruptTest.groovy
+++ b/src/test/groovy/transform/ThreadInterruptTest.groovy
@@ -20,6 +20,8 @@ package groovy.transform
 
 import groovy.mock.interceptor.StubFor
 import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.customizers.ImportCustomizer
 import org.codehaus.groovy.transform.ThreadInterruptibleASTTransformation
 import org.junit.After
 import org.junit.Before
@@ -27,14 +29,22 @@ import org.junit.Test
 
 import java.lang.reflect.Modifier
 
+import static groovy.test.GroovyAssert.assertScript
 import static groovy.test.GroovyAssert.isAtLeastJdk
 import static groovy.test.GroovyAssert.shouldFail
 import static org.junit.Assume.assumeTrue
 
 /**
- * Test for @ThreadInterrupt.
+ * Tests for the {@link ThreadInterrupt} AST transform.
  */
-class ThreadInterruptTest {
+final class ThreadInterruptTest {
+
+    private final GroovyShell shell = new GroovyShell(new CompilerConfiguration().addCompilationCustomizers(
+        new ImportCustomizer().tap {
+            addStarImports('groovy.transform')
+            addImport('groovy.mock.interceptor.StubFor')
+        }
+    ))
     private static final boolean jdk12plus = isAtLeastJdk('12.0')
     private Map<String, MethodNode> oldValues = [:]
 
@@ -44,7 +54,7 @@ class ThreadInterruptTest {
         Thread.metaClass = null
         ['CURRENTTHREAD_METHOD', 'ISINTERRUPTED_METHOD'].each {
             def ov = ThreadInterruptibleASTTransformation.getDeclaredField(it)
-            def modifiersField = ov.class.getDeclaredField("modifiers")
+            def modifiersField = ov.class.getDeclaredField('modifiers')
             modifiersField.accessible = true
             modifiersField.setInt(ov, ov.modifiers & ~Modifier.FINAL)
             ov.accessible = true
@@ -53,15 +63,15 @@ class ThreadInterruptTest {
     }
 
     @Before
-    void setUp() throws Exception {
+    void setUp() {
         // JDK12+ doesn't allow adjusting static final fields even via reflection, so
         // skip all tests on such JDK versions - it is only test code that's affected
         // and currently we have coverage from builds with lower JDK versions.
-        assumeTrue !jdk12plus
+        assumeTrue(!jdk12plus)
 
         ['CURRENTTHREAD_METHOD', 'ISINTERRUPTED_METHOD'].each {
             def ov = ThreadInterruptibleASTTransformation.getDeclaredField(it)
-            def modifiersField = ov.class.getDeclaredField("modifiers")
+            def modifiersField = ov.class.getDeclaredField('modifiers')
             modifiersField.accessible = true
             modifiersField.setInt(ov, ov.modifiers & ~Modifier.FINAL)
             ov.accessible = true
@@ -72,365 +82,343 @@ class ThreadInterruptTest {
 
     @Test
     void testDefaultParameters_Method() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-              def myMethod() { }
+        assertScript shell, '''
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() { }
             }
-        """)
 
-        def counter = new CountingThread()
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
-        mocker.use {
-            c.newInstance().myMethod()
-        }
-        assert 1 == counter.interruptedCheckCount
+            def mocker = new StubFor(Thread)
+            def counter = new CountingThread()
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
+            mocker.use {
+                new C().m()
+            }
+            assert 1 == counter.interruptedCheckCount
+        '''
     }
 
     @Test
     void testNoMethodCheck_Method() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt(checkOnMethodStart = false)
-            class MyClass {
-              def myMethod() { }
+        assertScript shell, '''
+            @ThreadInterrupt(applyToAllClasses=false, checkOnMethodStart=false)
+            class C {
+                def m() { }
             }
-        """)
 
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
-        mocker.use {
-            c.newInstance().myMethod()
-        }
-        // no exception means success
+            def mocker = new StubFor(Thread)
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
+            mocker.use {
+                new C().m()
+            }
+            // no exception means success
+        '''
     }
 
     @Test
     void testDefaultParameters_ForLoop() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-              def myMethod() {
-                  for (int i in (1..99)) {
-                      // do something
-                  }
-              }
+        assertScript shell, '''
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() {
+                    for (int i in (1..99)) {
+                        // do something
+                    }
+                }
             }
-        """)
 
-        def counter = new CountingThread()
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
-        mocker.use {
-            c.newInstance().myMethod()
-        }
-        assert 100 == counter.interruptedCheckCount
+            def mocker = new StubFor(Thread)
+            def counter = new CountingThread()
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
+            mocker.use {
+                new C().m()
+            }
+            assert 100 == counter.interruptedCheckCount
+        '''
     }
 
     @Test
     void testDefaultParameters_WhileLoop() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-              def myMethod() {
-                  int x = 99
-                  while (x > 0) {
-                      x--
-                  }
-              }
+        assertScript shell, '''
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() {
+                    int x = 99
+                    while (x > 0) {
+                        x--
+                    }
+                }
             }
-        """)
 
-        def counter = new CountingThread()
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
-        mocker.use {
-            c.newInstance().myMethod()
-        }
-        assert 100 == counter.interruptedCheckCount
+            def mocker = new StubFor(Thread)
+            def counter = new CountingThread()
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
+            mocker.use {
+                new C().m()
+            }
+            assert 100 == counter.interruptedCheckCount
+        '''
     }
 
     @Test
     void testDefaultParameters_Closure() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-              def myMethod() {
-                  99.times {
-                    // do something
-                  }
-              }
+        assertScript shell, '''
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() {
+                    99.times {
+                        // do something
+                    }
+                }
             }
-        """)
 
-        def counter = new CountingThread()
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
-        mocker.use {
-            c.newInstance().myMethod()
-        }
-        assert 100 == counter.interruptedCheckCount
+            def mocker = new StubFor(Thread)
+            def counter = new CountingThread()
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
+            mocker.use {
+                new C().m()
+            }
+            assert 100 == counter.interruptedCheckCount
+        '''
     }
 
     @Test
     void testInterrupt_Method_AndTestExceptionMessage() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-              def myMethod() { }
+        def err = shouldFail shell, InterruptedException, '''
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() { }
             }
-        """)
 
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
-        mocker.use {
-            def ex = shouldFail(InterruptedException) { c.newInstance().myMethod() }
-            assert ex.message == 'Execution interrupted. The current thread has been interrupted.'
-        }
+            def mocker = new StubFor(Thread)
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
+            mocker.use {
+                new C().m()
+            }
+        '''
+        assert err.message == 'Execution interrupted. The current thread has been interrupted.'
     }
 
     @Test
     void testInterrupt_ForLoop() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-              def myMethod() {
-                  for (int i in (1..99)) {
-                      // do something
-                  }
-              }
+        shouldFail shell, InterruptedException, '''
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() {
+                    for (int i in (1..99)) {
+                        // do something
+                    }
+                }
             }
-        """)
 
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
-        mocker.use {
-            shouldFail(InterruptedException) { c.newInstance().myMethod() }
-        }
+            def mocker = new StubFor(Thread)
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
+            mocker.use {
+                new C().m()
+            }
+        '''
     }
 
     @Test
     void testInterrupt_WhileLoop() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-              def myMethod() {
-                  int x = 99
-                  while (x > 0) {
-                      x--
-                  }
-              }
+        shouldFail shell, InterruptedException, '''
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() {
+                    int x = 99
+                    while (x > 0) {
+                        x--
+                    }
+                }
             }
-        """)
 
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
-        mocker.use {
-            shouldFail(InterruptedException) { c.newInstance().myMethod() }
-        }
+            def mocker = new StubFor(Thread)
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
+            mocker.use {
+                new C().m()
+            }
+        '''
     }
 
     @Test
     void testInterrupt_Closure() {
-
-        def c = new GroovyClassLoader().parseClass("""
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-              def myMethod() {
-                  99.times {
-                    // do something
-                  }
-              }
+        shouldFail shell, InterruptedException, '''
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() {
+                    99.times {
+                      // do something
+                    }
+                }
             }
-        """)
 
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
-        mocker.use {
-            shouldFail(InterruptedException) { c.newInstance().myMethod() }
-        }
+            def mocker = new StubFor(Thread)
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
+            mocker.use {
+                new C().m()
+            }
+        '''
     }
 
     @Test
     void testInterrupt_ClosureWithCustomExceptionType() {
-
-        def c = new GroovyClassLoader(this.class.classLoader).parseClass("""
-            @groovy.transform.ThreadInterrupt(thrown=groovy.transform.CustomException)
-            class MyClass {
-              def myMethod() {
-                  99.times {
-                    // do something
-                  }
-              }
+        shouldFail shell, CustomException, '''
+            @ThreadInterrupt(applyToAllClasses=false, thrown=CustomException)
+            class C {
+                def m() {
+                    99.times {
+                      // do something
+                    }
+                }
             }
-        """)
 
-        def mocker = new StubFor(Thread.class)
-        mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
-        mocker.use {
-            shouldFail(CustomException) { c.newInstance().myMethod() }
-        }
+            def mocker = new StubFor(Thread)
+            mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
+            mocker.use {
+                new C().m()
+            }
+        '''
     }
 
     @Test
     void testEntireCompileUnitIsAffected() {
-
         def script = '''
             def scriptMethod() {
                 // this method should inherit the checks from the annotation defined later
             }
 
-            @groovy.transform.ThreadInterrupt
-            class MyClass {
-
-              def myMethod() {
-                // this method should also be guarded
-              }
+            @ThreadInterrupt
+            class C {
+                def m() {
+                    // this method should also be guarded
+                }
             }
+
             scriptMethod()
-            new MyClass().myMethod()
-            '''
+            new C().m()
+        '''
+        def mocker = new StubFor(Thread)
         def counter = new CountingThread()
-        def mocker = new StubFor(Thread.class)
         mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
         mocker.use {
-            new GroovyShell().evaluate(script)
+            shell.evaluate(script)
         }
-        // 3 is once for run(), once for scriptMethod() and once for myMethod()
-        assert 3 == counter.interruptedCheckCount
+        assert counter.interruptedCheckCount == 3 // once for run(), once for scriptMethod() and once for m()
     }
 
     @Test
     void testOnlyScriptAffected() {
-
         def script = '''
-            @groovy.transform.ThreadInterrupt(applyToAllClasses = false)
+            @ThreadInterrupt(applyToAllClasses=false)
             def scriptMethod() {
                 // should be affected
             }
 
-            class MyClass {
-              def myMethod() {
-                // should not be affected
-              }
+            class C {
+                def m() {
+                    // should not be affected
+                }
             }
             scriptMethod()
-            new MyClass().myMethod()
-            '''
+            new C().m()
+        '''
+        def mocker = new StubFor(Thread)
         def counter = new CountingThread()
-        def mocker = new StubFor(Thread.class)
         mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
         mocker.use {
-            new GroovyShell().evaluate(script)
+            shell.evaluate(script)
         }
-        // 2 is once for run() and once for scriptMethod()
-        assert 2 == counter.interruptedCheckCount
+        assert counter.interruptedCheckCount == 2 // once for run() and once for scriptMethod()
     }
 
     @Test
     void testAnnotationOnImport() {
-
         def script = '''
-            @groovy.transform.ThreadInterrupt
+            @ThreadInterrupt
             import java.lang.String
 
             3.times {
                 // should be affected
             }
-            '''
+        '''
+        def mocker = new StubFor(Thread)
         def counter = new CountingThread()
-        def mocker = new StubFor(Thread.class)
         mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
         mocker.use {
-            new GroovyShell().evaluate(script)
+            shell.evaluate(script)
         }
-        // 4 is once for run() plus 3 for times loop
-        assert 4 == counter.interruptedCheckCount
+        assert counter.interruptedCheckCount == 4 // once for run() plus 3 for times loop
     }
 
     @Test
     void testOnlyClassAffected() {
-
         def script = '''
             def scriptMethod() {
                 // this should not be affected
             }
 
-            @groovy.transform.ThreadInterrupt(applyToAllClasses = false)
-            class MyClass {
-              def myMethod() {
-                // this should be affected
-              }
+            @ThreadInterrupt(applyToAllClasses=false)
+            class C {
+                def m() {
+                    // this should be affected
+                }
             }
             scriptMethod()
-            new MyClass().myMethod()
-            '''
+            new C().m()
+        '''
+        def mocker = new StubFor(Thread)
         def counter = new CountingThread()
-        def mocker = new StubFor(Thread.class)
         mocker.demand.currentThread(1..Integer.MAX_VALUE) { counter }
         mocker.use {
-            new GroovyShell(ThreadInterruptibleASTTransformation.getClassLoader()).evaluate(script)
+            shell.evaluate(script)
         }
-        // 1 is once for myMethod()
-        assert 1 == counter.interruptedCheckCount
+        assert counter.interruptedCheckCount == 1 // once for m()
     }
 
     @Test
     void testThreadInterruptOnAbstractClass() {
         def script = '''
-            @groovy.transform.ThreadInterrupt
-            abstract class MyAbstractClass {
-                abstract void myMethod()
+            @ThreadInterrupt
+            abstract class A {
+                abstract void m()
             }
 
-            class Concrete extends MyAbstractClass {
-                void myMethod() {
+            class C extends A {
+                void m() {
                     99.times {
                         // do something
                     }
                 }
             }
 
-            new Concrete().myMethod()
+            new C().m()
         '''
-        def mocker = new StubFor(Thread.class)
+        def mocker = new StubFor(Thread)
         mocker.demand.currentThread(1..Integer.MAX_VALUE) { new InterruptingThread() }
         mocker.use {
-            shouldFail(InterruptedException) {
-                new GroovyShell(ThreadInterruptibleASTTransformation.getClassLoader()).evaluate(script)
-            }
+            shouldFail(shell, InterruptedException, script)
         }
-
     }
 }
 
-class InterruptingThread extends Thread {
+//--------------------------------------------------------------------------
+
+class CountingThread extends Thread {
+    int interruptedCheckCount = 0
     @Override
     boolean isInterrupted() {
-        true
+        interruptedCheckCount += 1
+        false
     }
 }
 
-class CountingThread extends Thread {
-    def interruptedCheckCount = 0
-
+class InterruptingThread extends Thread {
     @Override
     boolean isInterrupted() {
-        interruptedCheckCount++
-        false
+        true
     }
 }
 
+@groovy.transform.InheritConstructors
 class CustomException extends Exception {
-    CustomException(final String message) {
-        super(message)
-    }
-}
\ No newline at end of file
+}
diff --git a/src/test/groovy/transform/TimedInterruptTest.groovy b/src/test/groovy/transform/TimedInterruptTest.groovy
index adbc74a02b..b4aadbde3e 100644
--- a/src/test/groovy/transform/TimedInterruptTest.groovy
+++ b/src/test/groovy/transform/TimedInterruptTest.groovy
@@ -19,271 +19,249 @@
 package groovy.transform
 
 import groovy.mock.interceptor.StubFor
-import groovy.test.GroovyTestCase
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.MultipleCompilationErrorsException
+import org.codehaus.groovy.control.customizers.ImportCustomizer
+import org.junit.Test
 
-import java.util.concurrent.TimeUnit
 import java.util.concurrent.TimeoutException
-import org.codehaus.groovy.control.MultipleCompilationErrorsException
-import org.codehaus.groovy.transform.TimedInterruptibleASTTransformation
+
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
 
 /**
- * Test for TimedInterrupt.
+ * Tests for the {@link TimedInterrupt} AST transform.
  */
-class TimedInterruptTest extends GroovyTestCase {
-
-  void testClassMethodIsVisited() {
-    def c = new GroovyClassLoader().parseClass('''
-      import groovy.transform.TimedInterrupt
-
-      @TimedInterrupt(value = 1L)
-      class MyClass {
-        def myMethod() { }
-      }
-    ''')
-    assertPassesNormalFailsSlowExecution(c)
-  }
-
-  void testClassMethodIsVisitedAndCustomExceptionThrown() {
-    def c = new GroovyClassLoader(this.class.classLoader).parseClass('''
-      import groovy.transform.TimedInterrupt
-
-      @TimedInterrupt(thrown=groovy.transform.CustomException,value = 1L)
-      class MyClass {
-        def myMethod() { }
-      }
-    ''')
-    assertPassesNormalFailsSlowExecution(c, 1000000666L, '1', 'myMethod', CustomException)
-  }
-
-  void testScriptMethodIsVisited() {
-    def c = new GroovyClassLoader().parseClass('''
-      import groovy.transform.TimedInterrupt
-
-      @TimedInterrupt(value = 1L)
-      def myMethod() { }
-    ''')
-    assertPassesNormalFailsSlowExecution(c)
-  }
-
-  void testStaticMethodIsNotVisited() {
-    def c = new GroovyClassLoader().parseClass('''
-      import groovy.transform.TimedInterrupt
-
-      @TimedInterrupt(value = 1L)
-      class MyClass {
-        static def myMethod() { }
-      }
-    ''')
-    assertPassesSlowExecution(c)
-  }
-
-  void testClosureFieldIsVisited() {
-    def c = new GroovyClassLoader().parseClass('''
-      import groovy.transform.TimedInterrupt
-
-      @TimedInterrupt(value = 1L)
-      class MyClass {
-        def myMethod = { }
-      }
-    ''')
-    assertPassesNormalFailsSlowExecution(c)
-  }
-
-  void testClosureInScriptIsVisited_CheckOnMethodStartIsFalse() {
-    def c = new GroovyClassLoader().parseClass('''
-      import groovy.transform.TimedInterrupt
-
-      @TimedInterrupt(checkOnMethodStart = false, value = 1L)
-      def myMethod = { }
-      myMethod()
-    ''')
-    assertPassesNormalFailsSlowExecution(c, 1000000666L, '1', 'run')
-  }
-
-  void testWhileInScriptIsVisited_CheckOnMethodStartIsFalse() {
-    def c = new GroovyClassLoader().parseClass('''
-      @TimedInterrupt(checkOnMethodStart = false, value = 1L)
-      import groovy.transform.TimedInterrupt
-      import java.util.concurrent.TimeUnit
-
-      int x = 1
-      while (x < 2) { x = 2 }
-    ''')
-    assertPassesNormalFailsSlowExecution(c, 1000000666L, '1', 'run')
-  }
-
-  void testForInScriptIsVisited_CheckOnMethodStartIsFalse() {
-    def c = new GroovyClassLoader().parseClass('''
-      @TimedInterrupt(checkOnMethodStart = false, value = 1L)
-      import groovy.transform.TimedInterrupt
-
-      def x = [1]
-      for (def o : x) { o++ }
-    ''')
-    assertPassesNormalFailsSlowExecution(c, 1000000666L, '1', 'run')
-  }
-
-  void testStaticClosureFieldNotVisited() {
-    def c = new GroovyClassLoader().parseClass('''
-      import groovy.transform.TimedInterrupt
-
-      @TimedInterrupt(value = 1L)
-      class MyClass {
-        static def myMethod = { }
-      }
-    ''')
-    assertPassesSlowExecution(c)
-  }
-
-  void testAnnotationParameters() {
-    def c = new GroovyClassLoader().parseClass('''
-      import groovy.transform.TimedInterrupt
-      import java.util.concurrent.TimeUnit
-
-      @TimedInterrupt(value = 18000000L, unit = TimeUnit.MILLISECONDS)
-      def myMethod() { }
-    ''')
-    assertPassesNormalFailsSlowExecution(c, 18000000000666, '18000000', 'myMethod', TimeoutException, 'milliseconds') //5 hours in future
-  }
-
-  // TODO not sure all these tests are pulling their weight - testing Groovy annotation type handing not subject
-  void testErrorHandling() {
-    shouldFail(MultipleCompilationErrorsException) {
-      new GroovyClassLoader().parseClass('''
-        import groovy.transform.TimedInterrupt
-        @TimedInterrupt(value = "5")
-        def myMethod() { }
-      ''')
+final class TimedInterruptTest {
+
+    private final GroovyShell shell = new GroovyShell(new CompilerConfiguration().addCompilationCustomizers(
+        new ImportCustomizer().tap {
+            addStarImports('groovy.transform')
+            addStaticStars(TimedInterruptTest.name)
+            addImport('groovy.mock.interceptor.StubFor')
+        }
+    ))
+
+    @Test
+    void testClassMethodIsVisited() {
+        assertScript shell, '''
+            @TimedInterrupt(applyToAllClasses=false, value=1L)
+            class C {
+                def m() { }
+            }
+            assertPassesNormalFailsSlowExecution(C, methodName: 'm')
+        '''
     }
 
-    shouldFail(MultipleCompilationErrorsException) {
-      new GroovyClassLoader().parseClass('''
-        import groovy.transform.TimedInterrupt
-        @TimedInterrupt(value = foo())
-        def myMethod() { }
-      ''')
+    @Test
+    void testClassMethodIsVisitedAndCustomExceptionThrown() {
+        assertScript shell, '''
+            @TimedInterrupt(applyToAllClasses=false, thrown=CustomException, value=1L)
+            class C {
+                def m() { }
+            }
+            assertPassesNormalFailsSlowExecution(C, methodName: 'm', exception: CustomException)
+        '''
     }
 
-    shouldFail(MultipleCompilationErrorsException) {
-      new GroovyClassLoader().parseClass('''
-        import groovy.transform.TimedInterrupt
-        @TimedInterrupt(value = 5L, applyToAllClasses = 5)
-        def myMethod() { }
-      ''')
+    @Test
+    void testScriptMethodIsVisited() {
+        assertScript shell, '''
+            @TimedInterrupt(applyToAllClasses=false, value=1L) def m() { }
+            assertPassesNormalFailsSlowExecution(this.class, methodName: 'm')
+        '''
     }
 
-    shouldFail(MultipleCompilationErrorsException) {
-      new GroovyClassLoader().parseClass('''
-        import groovy.transform.TimedInterrupt
-        @TimedInterrupt(value = 5L, applyToAllClasses = foo())
-        def myMethod() { }
-      ''')
+    @Test
+    void testStaticMethodIsNotVisited() {
+        assertScript shell, '''
+            @TimedInterrupt(applyToAllClasses=false, value=1L)
+            class C {
+                static myMethod() { }
+            }
+            assertPassesSlowExecution(C)
+        '''
     }
 
-    shouldFail(MultipleCompilationErrorsException) {
-      new GroovyClassLoader().parseClass('''
-        import groovy.transform.TimedInterrupt
-        @TimedInterrupt(value = 5L, checkOnMethodStart = 5)
-        def myMethod() { }
-      ''')
+    @Test
+    void testClosureFieldIsVisited() {
+        assertScript shell, '''
+            @TimedInterrupt(applyToAllClasses=false, value=1L)
+            class C {
+                def m = { -> }
+            }
+            assertPassesNormalFailsSlowExecution(C, methodName: 'm')
+        '''
     }
 
-    shouldFail(MultipleCompilationErrorsException) {
-      new GroovyClassLoader().parseClass('''
-        import groovy.transform.TimedInterrupt
-        @TimedInterrupt(value = 5L, checkOnMethodStart = foo())
-        def myMethod() { }
-      ''')
+    @Test
+    void testClosureInScriptIsVisited_CheckOnMethodStartIsFalse() {
+        def script = shell.parse '''
+            @TimedInterrupt(applyToAllClasses=false, applyToAllMembers=false, checkOnMethodStart=false, value=1L)
+            def m = { -> }
+            m()
+        '''
+        assertPassesNormalFailsSlowExecution(script.class, methodName: 'run')
     }
 
-    shouldFail(MultipleCompilationErrorsException) {
-      new GroovyClassLoader().parseClass('''
-        import groovy.transform.TimedInterrupt
-        @TimedInterrupt(value = 5L, unit = 5)
-        def myMethod() { }
-      ''')
+    @Test
+    void testWhileInScriptIsVisited_CheckOnMethodStartIsFalse() {
+        def script = shell.parse '''
+            @TimedInterrupt(applyToAllClasses=false, checkOnMethodStart=false, value=1L)
+            int x = 1
+            while (x < 2) { x = 2 }
+        '''
+        assertPassesNormalFailsSlowExecution(script.class, methodName: 'run')
     }
 
-    shouldFail(MultipleCompilationErrorsException) {
-      new GroovyClassLoader().parseClass('''
-        import groovy.transform.TimedInterrupt
-        @TimedInterrupt(value = 5L, unit = foo())
-        def myMethod() { }
-      ''')
+    @Test
+    void testForInScriptIsVisited_CheckOnMethodStartIsFalse() {
+        def script = shell.parse '''
+            @TimedInterrupt(applyToAllClasses=false, checkOnMethodStart=false, value=1L)
+            def x = [1]
+            for (def o : x) { o++ }
+        '''
+        assertPassesNormalFailsSlowExecution(script.class, methodName: 'run')
     }
-  }
-
-  void testTimedInterruptOnAbstractClass() {
-    def script = '''
-      @groovy.transform.TimedInterrupt(value = 1L)
-      abstract class MyAbstractClass {
-        abstract void myMethod()
-      }
-
-      class Concrete extends MyAbstractClass {
-        void myMethod() {
-          99.times {
-            // do something
-          }
-        }
-      }
-      new Concrete()
-    '''
 
-    def system = new StubFor(System)
+    @Test
+    void testStaticClosureFieldNotVisited() {
+        assertScript shell, '''
+            @TimedInterrupt(applyToAllClasses=false, value=1L)
+            class C {
+                static myMethod = { -> }
+            }
+            assertPassesSlowExecution(C)
+        '''
+    }
 
-    // start time initialized to the Long of the Beast
-    system.demand.nanoTime(4) { 666L } // 2 times to cover full instantiation
-    system.demand.nanoTime() { 1000000667L }
+    @Test
+    void testAnnotationParameters() {
+        assertScript shell, '''
+            import static java.util.concurrent.TimeUnit.*
 
-    system.use {
-      def instance = new GroovyShell(TimedInterruptibleASTTransformation.getClassLoader()).evaluate(script)
-      // may get false positives if multiple annotations with the same expireTime defined in test script
-      assert instance.dump().matches('.*timedInterrupt\\S+\\$expireTime=1000000666 .*')
+            @TimedInterrupt(applyToAllClasses=false, value=18000000L, unit=MILLISECONDS)
+            def myMethod() { }
 
-      shouldFail(TimeoutException) {
-        instance.myMethod()
-      }
+            assertPassesNormalFailsSlowExecution(this.class, expireTime: 18000000000666L, units: '18000000', timeUnitName: 'milliseconds') // 5 hours in future
+        '''
     }
-  }
-
-  private void assertPassesNormalFailsSlowExecution(c, long expireTime=1000000666L, units='1', methodName='myMethod', exception=TimeoutException, timeUnitName='seconds') {
-    def system = new StubFor(System)
-    // start time initialized to the Long of the Beast
-    system.demand.nanoTime() { 666L }
-    def instance
-    system.use {
-      instance = c.newInstance()
-    }
-    // may get false positives if multiple annotations with the same expireTime defined in test script
-    assert instance.dump().matches('.*timedInterrupt\\S+\\$expireTime=' + expireTime + ' .*')
 
-    system.demand.nanoTime() { expireTime }
-    system.use {
-      instance."$methodName"()
+    @Test // TODO: not sure all these tests are pulling their weight - testing Groovy annotation type handing not subject
+    void testErrorHandling() {
+        shouldFail shell, MultipleCompilationErrorsException, '''
+            @TimedInterrupt(value = "5")
+            def myMethod() { }
+        '''
+
+        shouldFail shell, MultipleCompilationErrorsException, '''
+            @TimedInterrupt(value = foo())
+            def myMethod() { }
+        '''
+
+        shouldFail shell, MultipleCompilationErrorsException, '''
+            @TimedInterrupt(value = 5L, applyToAllClasses = 5)
+            def myMethod() { }
+        '''
+
+        shouldFail shell, MultipleCompilationErrorsException, '''
+            @TimedInterrupt(value = 5L, applyToAllClasses = foo())
+            def myMethod() { }
+        '''
+
+        shouldFail shell, MultipleCompilationErrorsException, '''
+            @TimedInterrupt(value = 5L, checkOnMethodStart = 5)
+            def myMethod() { }
+        '''
+
+        shouldFail shell, MultipleCompilationErrorsException, '''
+            @TimedInterrupt(value = 5L, checkOnMethodStart = foo())
+            def myMethod() { }
+        '''
+
+        shouldFail shell, MultipleCompilationErrorsException, '''
+            @TimedInterrupt(value = 5L, unit = 5)
+            def myMethod() { }
+        '''
+
+        shouldFail shell, MultipleCompilationErrorsException, '''
+            @TimedInterrupt(value = 5L, unit = foo())
+            def myMethod() { }
+        '''
     }
 
-    // one nanosecond too slow
-    system.demand.nanoTime() { expireTime + 1 }
-    system.use {
-      def e = shouldFail(exception) {
-        instance."$methodName"()
-      }
-      assert e.contains('Execution timed out after ' + units + ' ' + timeUnitName)
+    @Test
+    void testTimedInterruptOnAbstractClass() {
+        def script = '''
+            @TimedInterrupt(value = 1L)
+            abstract class A {
+                abstract void m()
+            }
+            class C extends A {
+                void m() {
+                    99.times {
+                        // do something
+                    }
+                }
+            }
+            new C()
+        '''
+        def system = new StubFor(System)
+        // start time initialized to the Long of the Beast
+        system.demand.nanoTime(4) { 666L } // 2 times to cover full instantiation
+        system.demand.nanoTime() { 1000000667L }
+        system.use {
+            def instance = shell.evaluate(script)
+            // may get false positives if multiple annotations with the same expireTime defined in test script
+            assert instance.dump().matches('.*timedInterrupt\\S+\\$expireTime=1000000666 .*')
+
+            shouldFail(TimeoutException) {
+                instance.m()
+            }
+        }
     }
-  }
-
-  private void assertPassesSlowExecution(c) {
-    def system = new StubFor(System)
-    // start time initialized to the Long of the Beast
-    system.demand.nanoTime() { 666L }
-    def instance
-    system.use {
-      instance = c.newInstance()
+
+    //--------------------------------------------------------------------------
+
+    static void assertPassesNormalFailsSlowExecution(Map<String,?> args, Class type) {
+        def system = new StubFor(System)
+        // start time initialized to ...
+        system.demand.nanoTime() { 666L }
+        def instance
+        system.use {
+            instance = type.newInstance()
+        }
+        long expireTime = args.getOrDefault('expireTime', 1000000666L)
+        String methodName = args.getOrDefault('methodName', 'myMethod')
+        // may get false positives if multiple annotations with the same expireTime defined
+        assert instance.dump().matches('.*timedInterrupt\\S+\\$expireTime=' + expireTime + ' .*')
+
+        system.demand.nanoTime() { expireTime }
+        system.use {
+            instance.(methodName)()
+        }
+
+        // one nanosecond too slow
+        system.demand.nanoTime() { expireTime + 1 }
+        system.use {
+            def err = shouldFail(args.getOrDefault('exception', java.util.concurrent.TimeoutException)) {
+                instance.(methodName)()
+            }
+            assert err.message.contains('Execution timed out after ' + args.getOrDefault('units', '1') + ' ' + args.getOrDefault('timeUnitName', 'seconds'))
+        }
     }
-    system.demand.nanoTime() { 1000000667L }
-    system.use {
-      instance.myMethod()
+
+    static void assertPassesSlowExecution(Class c) {
+        def system = new StubFor(System)
+        // start time initialized to the Long of the Beast
+        system.demand.nanoTime() { 666L }
+        def instance
+        system.use {
+            instance = c.newInstance()
+        }
+        system.demand.nanoTime() { 1000000667L }
+        system.use {
+            instance.myMethod()
+        }
     }
-  }
 }
diff --git a/src/test/org/codehaus/groovy/classgen/asm/ClosureWriterGeneratedAnnotationTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/ClosureWriterGeneratedAnnotationTest.groovy
index dba3b22467..9fbcabe848 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/ClosureWriterGeneratedAnnotationTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/ClosureWriterGeneratedAnnotationTest.groovy
@@ -19,7 +19,6 @@
 package org.codehaus.groovy.classgen.asm
 
 import groovy.transform.Generated
-import junit.framework.TestCase
 import org.codehaus.groovy.control.CompilationUnit
 import org.codehaus.groovy.control.Phases
 import org.junit.Test
@@ -27,22 +26,21 @@ import org.junit.Test
 /**
  * Verifies if {@link Generated} annotations are added on {@code call} methods of generated closure classes.
  */
-class ClosureWriterGeneratedAnnotationTest extends TestCase {
-    private CompilationUnit compileScript(String scriptText) {
-        CompilationUnit compilationUnit = new CompilationUnit()
-        compilationUnit.addSource("script", scriptText)
-        compilationUnit.compile(Phases.ALL)
+final class ClosureWriterGeneratedAnnotationTest {
 
-        compilationUnit
+    private CompilationUnit compileScript(String script) {
+        new CompilationUnit().tap {
+            addSource('script', script)
+            compile(Phases.CLASS_GENERATION)
+        }
     }
 
     private Collection<Class> findGeneratedClosureClasses(String outerClassName, CompilationUnit compilationUnit) {
-        Collection<Class> generatedClosureClasses = []
+        List<Class> generatedClosureClasses = []
         compilationUnit.classes.each {
             generatedClosureClasses.add(compilationUnit.classLoader.defineClass(it.name, it.bytes))
         }
-
-        return generatedClosureClasses.findAll({ it.name.matches(/.*${ outerClassName }\$\_.*\_closure.*/) })
+        generatedClosureClasses.findAll { it.name =~ /${outerClassName}\$\_.*\_closure/ }
     }
 
     /**
@@ -50,19 +48,18 @@ class ClosureWriterGeneratedAnnotationTest extends TestCase {
      */
     @Test
     void testClosureWithNoParameters() {
-        String scriptText = """    
-        class MyClass {
-            void myMethod() {
-                [1..3].each {
-                    println it
+        String scriptText = '''
+            class MyClass {
+                void myMethod() {
+                    [1..3].each {
+                        println it
+                    }
                 }
             }
-        }
-        """
-
+        '''
         CompilationUnit compilationUnit = compileScript(scriptText)
-        Class myClosureClassCompiled = findGeneratedClosureClasses("MyClass", compilationUnit)[0]
-        Collection callMethods = myClosureClassCompiled.declaredMethods.findAll { it.name == "call" }
+        Class myClosureClassCompiled = findGeneratedClosureClasses('MyClass', compilationUnit)[0]
+        Collection callMethods = myClosureClassCompiled.declaredMethods.findAll { it.name == 'call' }
 
         assert callMethods.size() == 0
     }
@@ -72,19 +69,18 @@ class ClosureWriterGeneratedAnnotationTest extends TestCase {
      */
     @Test
     void testClosureWithSingleParameter() {
-        String scriptText = """    
-        class MyClass {
-            void myMethod() {
-                [1..3].each { Integer myInt ->
-                    println myInt
+        String scriptText = '''
+            class MyClass {
+                void myMethod() {
+                    [1..3].each { Integer myInt ->
+                        println myInt
+                    }
                 }
             }
-        }
-        """
-
+        '''
         CompilationUnit compilationUnit = compileScript(scriptText)
-        Class myClosureClassCompiled = findGeneratedClosureClasses("MyClass", compilationUnit)[0]
-        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == "call" }
+        Class myClosureClassCompiled = findGeneratedClosureClasses('MyClass', compilationUnit)[0]
+        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == 'call' }
 
         assert callMethodCollection.size() == 1
         assert callMethodCollection[0].getAnnotation(Generated)
@@ -96,19 +92,18 @@ class ClosureWriterGeneratedAnnotationTest extends TestCase {
      */
     @Test
     void testClosureWithMultipleParameters() {
-        String scriptText = """    
-        class MyClass {
-            void myMethod() {
-                [1..3].eachWithIndex { IntRange entry, Integer i ->
-                    println entry[i]
+        String scriptText = '''
+            class MyClass {
+                void myMethod() {
+                    [1..3].eachWithIndex { IntRange entry, Integer i ->
+                        println entry[i]
+                    }
                 }
             }
-        }
-        """
-
+        '''
         CompilationUnit compilationUnit = compileScript(scriptText)
-        Class myClosureClassCompiled = findGeneratedClosureClasses("MyClass", compilationUnit)[0]
-        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == "call" }
+        Class myClosureClassCompiled = findGeneratedClosureClasses('MyClass', compilationUnit)[0]
+        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == 'call' }
 
         assert callMethodCollection.size() == 1
         assert callMethodCollection[0].getAnnotation(Generated)
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
index 5576b16354..68181ad0c7 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
@@ -931,8 +931,7 @@ import groovy.transform.TypeCheckingMode
 
     // GROOVY-6095
     void testServletError() {
-        def shell = new GroovyShell()
-        shell.evaluate '''
+        assertScript '''
             @Grab('javax.servlet:javax.servlet-api:3.0.1')
             import groovy.transform.CompileStatic
 
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompileClosureGeneratedAnnotationTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompileClosureGeneratedAnnotationTest.groovy
index e9641a5c0f..634a6b10dc 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompileClosureGeneratedAnnotationTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompileClosureGeneratedAnnotationTest.groovy
@@ -19,7 +19,6 @@
 package org.codehaus.groovy.classgen.asm.sc
 
 import groovy.transform.Generated
-import junit.framework.TestCase
 import org.codehaus.groovy.control.CompilationUnit
 import org.codehaus.groovy.control.Phases
 import org.junit.Test
@@ -29,22 +28,21 @@ import java.lang.reflect.Method
 /**
  * Verifies if {@link Generated} annotations are added on {@code call} methods of generated closure classes when static compilation is used.
  */
-class StaticCompileClosureGeneratedAnnotationTest extends TestCase {
-    private CompilationUnit compileScript(String scriptText) {
-        CompilationUnit compilationUnit = new CompilationUnit()
-        compilationUnit.addSource("script", scriptText)
-        compilationUnit.compile(Phases.ALL)
+final class StaticCompileClosureGeneratedAnnotationTest {
 
-        compilationUnit
+    private CompilationUnit compileScript(String script) {
+        new CompilationUnit().tap {
+            addSource('script', script)
+            compile(Phases.CLASS_GENERATION)
+        }
     }
 
     private Collection<Class> findGeneratedClosureClasses(String outerClassName, CompilationUnit compilationUnit) {
-        Collection<Class> generatedClosureClasses = []
+        List<Class> generatedClosureClasses = []
         compilationUnit.classes.each {
             generatedClosureClasses.add(compilationUnit.classLoader.defineClass(it.name, it.bytes))
         }
-
-        return generatedClosureClasses.findAll({ it.name.matches(/.*${ outerClassName }\$\_.*\_closure.*/) })
+        generatedClosureClasses.findAll { it.name =~ /${outerClassName}\$\_.*\_closure/ }
     }
 
     /**
@@ -52,20 +50,19 @@ class StaticCompileClosureGeneratedAnnotationTest extends TestCase {
      */
     @Test
     void testClosureWithNoParameters() {
-        String scriptText = """
-        @groovy.transform.CompileStatic
-        class MyClass {
-            void myMethod() {
-                [1..3].each {
-                    println it
+        String scriptText = '''
+            @groovy.transform.CompileStatic
+            class MyClass {
+                void myMethod() {
+                    [1..3].each {
+                        println it
+                    }
                 }
             }
-        }
-        """
-
+        '''
         CompilationUnit compilationUnit = compileScript(scriptText)
-        Class myClosureClassCompiled = findGeneratedClosureClasses("MyClass", compilationUnit)[0]
-        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == "call" }
+        Class myClosureClassCompiled = findGeneratedClosureClasses('MyClass', compilationUnit)[0]
+        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == 'call' }
 
         assert callMethodCollection.size() == 2
         callMethodCollection.each { Method method ->
@@ -80,20 +77,19 @@ class StaticCompileClosureGeneratedAnnotationTest extends TestCase {
      */
     @Test
     void testClosureWithSingleParameter() {
-        String scriptText = """
-        @groovy.transform.CompileStatic
-        class MyClass {
-            void myMethod() {
-                [1..3].each { IntRange myIntRange ->
-                  println myIntRange
+        String scriptText = '''
+            @groovy.transform.CompileStatic
+            class MyClass {
+                void myMethod() {
+                    [1..3].each { IntRange myIntRange ->
+                      println myIntRange
+                    }
                 }
             }
-        }
-        """
-
+        '''
         CompilationUnit compilationUnit = compileScript(scriptText)
-        Class myClosureClassCompiled = findGeneratedClosureClasses("MyClass", compilationUnit)[0]
-        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == "call" }
+        Class myClosureClassCompiled = findGeneratedClosureClasses('MyClass', compilationUnit)[0]
+        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == 'call' }
 
         assert callMethodCollection.size() == 1
         assert callMethodCollection[0].getAnnotation(Generated)
@@ -105,20 +101,19 @@ class StaticCompileClosureGeneratedAnnotationTest extends TestCase {
      */
     @Test
     void testClosureWithMultipleParameters() {
-        String scriptText = """
-        @groovy.transform.CompileStatic
-        class MyClass {
-            void myMethod() {
-                [1..3].eachWithIndex { IntRange entry, Integer i ->
-                    println entry[i]
+        String scriptText = '''
+            @groovy.transform.CompileStatic
+            class MyClass {
+                void myMethod() {
+                    [1..3].eachWithIndex { IntRange entry, Integer i ->
+                        println entry[i]
+                    }
                 }
             }
-        }
-        """
-
+        '''
         CompilationUnit compilationUnit = compileScript(scriptText)
-        Class myClosureClassCompiled = findGeneratedClosureClasses("MyClass", compilationUnit)[0]
-        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == "call" }
+        Class myClosureClassCompiled = findGeneratedClosureClasses('MyClass', compilationUnit)[0]
+        Collection callMethodCollection = myClosureClassCompiled.declaredMethods.findAll { it.name == 'call' }
 
         assert callMethodCollection.size() == 1
         assert callMethodCollection[0].getAnnotation(Generated)
diff --git a/src/test/org/codehaus/groovy/transform/classloading/TransformsAndCustomClassLoadersTest.groovy b/src/test/org/codehaus/groovy/transform/classloading/TransformsAndCustomClassLoadersTest.groovy
index e1884bbae1..bc8a0b66c0 100644
--- a/src/test/org/codehaus/groovy/transform/classloading/TransformsAndCustomClassLoadersTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/classloading/TransformsAndCustomClassLoadersTest.groovy
@@ -113,7 +113,7 @@ final class TransformsAndCustomClassLoadersTest {
         try (def loader = new GroovyClassLoader(this.class.classLoader)) {
             def unit = new CompilationUnit(null, null, dependencyLoader, transformLoader)
             unit.addSource('Foo.groovy', source)
-            unit.compile()
+            unit.compile(CompilePhase.CLASS_GENERATION.phaseNumber)
 
             assert unit.classes.size() == 1
             def classInfo = unit.classes[0]