You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2020/04/04 06:54:16 UTC

[groovy] 02/02: GROOVY-9492: Relax groovy.test.NotYetImplemented dependency on JUnit 4's AssertionFailedError (adjustments for Groovy 3)

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

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

commit 40752788ffd63343f4a7497131a4f0397cd4bc26
Author: Paul King <pa...@asert.com.au>
AuthorDate: Sat Apr 4 16:52:42 2020 +1000

    GROOVY-9492: Relax groovy.test.NotYetImplemented dependency on JUnit 4's AssertionFailedError (adjustments for Groovy 3)
---
 .../main/java/groovy/test/NotYetImplemented.java   |  3 +-
 .../java/groovy/transform/NotYetImplemented.java   |  2 +-
 .../NotYetImplementedLegacyASTTransformation.java  | 77 ++++++++++++++++++++++
 .../NotYetImplementedTransformTest.groovy          | 21 ++++++
 4 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/subprojects/groovy-test/src/main/java/groovy/test/NotYetImplemented.java b/subprojects/groovy-test/src/main/java/groovy/test/NotYetImplemented.java
index 712b852..2c948a8 100644
--- a/subprojects/groovy-test/src/main/java/groovy/test/NotYetImplemented.java
+++ b/subprojects/groovy-test/src/main/java/groovy/test/NotYetImplemented.java
@@ -33,7 +33,8 @@ import java.lang.annotation.Target;
  * This is helpful for tests that don't currently work but should work one day,
  * when the tested functionality has been implemented.
  * <p>
- * Note: JUnit 3 users should use the optional {@code exception} attribute, e.g. {@code @NotYetImplemented(exception=junit.framework.AssertionFailedError)}.
+ * Note: JUnit 3 users should use the optional {@code exception} attribute, e.g. {@code @NotYetImplemented(exception=junit.framework.AssertionFailedError)}
+ * or the legacy {@code groovy.transform.NotYetImplemented} annotation.
  *
  * @since 3.0.0
  */
diff --git a/subprojects/groovy-test/src/main/java/groovy/transform/NotYetImplemented.java b/subprojects/groovy-test/src/main/java/groovy/transform/NotYetImplemented.java
index 0f9ddf3..cb39797 100644
--- a/subprojects/groovy-test/src/main/java/groovy/transform/NotYetImplemented.java
+++ b/subprojects/groovy-test/src/main/java/groovy/transform/NotYetImplemented.java
@@ -42,6 +42,6 @@ import java.lang.annotation.Target;
 @java.lang.annotation.Documented
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD})
-@GroovyASTTransformationClass("org.apache.groovy.test.transform.NotYetImplementedASTTransformation")
+@GroovyASTTransformationClass("org.apache.groovy.test.transform.NotYetImplementedLegacyASTTransformation")
 public @interface NotYetImplemented {
 }
diff --git a/subprojects/groovy-test/src/main/java/org/apache/groovy/test/transform/NotYetImplementedLegacyASTTransformation.java b/subprojects/groovy-test/src/main/java/org/apache/groovy/test/transform/NotYetImplementedLegacyASTTransformation.java
new file mode 100644
index 0000000..2dcb969
--- /dev/null
+++ b/subprojects/groovy-test/src/main/java/org/apache/groovy/test/transform/NotYetImplementedLegacyASTTransformation.java
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.groovy.test.transform;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.ReturnStatement;
+import org.codehaus.groovy.ast.stmt.ThrowStatement;
+import org.codehaus.groovy.ast.stmt.TryCatchStatement;
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.transform.AbstractASTTransformation;
+import org.codehaus.groovy.transform.GroovyASTTransformation;
+
+import java.util.Arrays;
+import junit.framework.AssertionFailedError;
+
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.catchS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.tryCatchS;
+
+/**
+ * Generates code for the legacy {@code @NotYetImplemented} annotation.
+ *
+ * @see groovy.transform.NotYetImplemented
+ */
+@Deprecated
+@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
+public class NotYetImplementedLegacyASTTransformation extends AbstractASTTransformation {
+
+    private static final ClassNode CATCH_TYPE = ClassHelper.make(Throwable.class);
+    private static final ClassNode THROW_TYPE = ClassHelper.make(AssertionFailedError.class); // TODO: java.lang.AssertionError
+
+    public void visit(ASTNode[] nodes, SourceUnit source) {
+        if (!(nodes.length == 2 && nodes[0] instanceof AnnotationNode && nodes[1] instanceof MethodNode)) {
+            throw new RuntimeException("Internal error: expecting [AnnotationNode, MethodNode] but got: " + Arrays.toString(nodes));
+        }
+
+        MethodNode methodNode = (MethodNode) nodes[1];
+
+        if (methodNode.getCode() instanceof BlockStatement && !((BlockStatement) methodNode.getCode()).isEmpty()) {
+            // wrap code in try/catch with return for failure path followed by throws for success path
+
+            TryCatchStatement tryCatchStatement = tryCatchS(methodNode.getCode());
+            tryCatchStatement.addCatch(catchS(param(CATCH_TYPE, "ignore"), ReturnStatement.RETURN_NULL_OR_VOID));
+
+            ThrowStatement throwStatement = throwS(ctorX(THROW_TYPE, args(constX("Method is marked with @NotYetImplemented but passes unexpectedly"))));
+
+            methodNode.setCode(block(tryCatchStatement, throwStatement));
+        }
+    }
+}
diff --git a/subprojects/groovy-test/src/test/groovy/org/apache/groovy/test/transform/NotYetImplementedTransformTest.groovy b/subprojects/groovy-test/src/test/groovy/org/apache/groovy/test/transform/NotYetImplementedTransformTest.groovy
index b4fbad5..36b4fa5 100644
--- a/subprojects/groovy-test/src/test/groovy/org/apache/groovy/test/transform/NotYetImplementedTransformTest.groovy
+++ b/subprojects/groovy-test/src/test/groovy/org/apache/groovy/test/transform/NotYetImplementedTransformTest.groovy
@@ -18,6 +18,7 @@
  */
 package org.apache.groovy.test.transform
 
+import junit.framework.AssertionFailedError
 import org.junit.Test
 
 final class NotYetImplementedTransformTest {
@@ -61,6 +62,26 @@ final class NotYetImplementedTransformTest {
     }
 
     @Test
+    @Deprecated
+    void testNotYetImplementedLegacyJunit3PassThrough() {
+        def output = shell.evaluate('''
+            import groovy.test.GroovyTestCase
+            import groovy.transform.NotYetImplemented
+
+            class MyTests extends GroovyTestCase {
+                @NotYetImplemented void testThatPasses()  {
+                    assertTrue(true)
+                }
+            }
+
+            junit.textui.TestRunner.run(new junit.framework.TestSuite(MyTests))
+        ''')
+
+        assert output.failureCount() == 1 : 'succeeding test method marked with legacy @NotYetImplemented must throw an AssertionFailedError'
+        assert output.failures().nextElement().thrownException() instanceof AssertionFailedError : 'succeeding test method marked with legacy @NotYetImplemented must throw an AssertionFailedError'
+    }
+
+    @Test
     void testNotYetImplementedJunit3PassThrough() {
         def output = shell.evaluate('''
             import groovy.test.GroovyTestCase