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:14 UTC
[groovy] branch GROOVY_3_0_X updated (73111a7 -> 4075278)
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a change to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.
from 73111a7 GROOVY-9452: Multiple Repeatable Annotations Container generated if an explicit container is present and an implicit one required
new a171464 GROOVY-9492: Relax groovy.test.NotYetImplemented dependency on JUnit 4's AssertionFailedError
new 4075278 GROOVY-9492: Relax groovy.test.NotYetImplemented dependency on JUnit 4's AssertionFailedError (adjustments for Groovy 3)
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../main/java/groovy/test/NotYetImplemented.java | 16 ++++++--
.../java/groovy/transform/NotYetImplemented.java | 2 +-
.../NotYetImplementedASTTransformation.java | 26 ++++++++-----
... NotYetImplementedLegacyASTTransformation.java} | 7 ++--
.../NotYetImplementedTransformTest.groovy | 44 ++++++++++++++++------
5 files changed, 65 insertions(+), 30 deletions(-)
copy subprojects/groovy-test/src/main/java/org/apache/groovy/test/transform/{NotYetImplementedASTTransformation.java => NotYetImplementedLegacyASTTransformation.java} (94%)
[groovy] 01/02: GROOVY-9492: Relax groovy.test.NotYetImplemented
dependency on JUnit 4's AssertionFailedError
Posted by pa...@apache.org.
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 a17146424734e84eaef41a5fa42a28caa75d247b
Author: Paul King <pa...@asert.com.au>
AuthorDate: Tue Mar 31 13:02:49 2020 +1000
GROOVY-9492: Relax groovy.test.NotYetImplemented dependency on JUnit 4's AssertionFailedError
---
.../main/java/groovy/test/NotYetImplemented.java | 15 +++++++++----
.../NotYetImplementedASTTransformation.java | 26 +++++++++++++---------
.../NotYetImplementedTransformTest.groovy | 25 ++++++++++-----------
3 files changed, 39 insertions(+), 27 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 ad21c52..712b852 100644
--- a/subprojects/groovy-test/src/main/java/groovy/test/NotYetImplemented.java
+++ b/subprojects/groovy-test/src/main/java/groovy/test/NotYetImplemented.java
@@ -26,14 +26,14 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Method annotation used to invert test case results. If a JUnit 3/4 test case method is
- * annotated with {@code @NotYetImplemented} the test will fail if no test failure occurs and it will pass
- * if a test failure occurs.
+ * Method annotation used to invert test case results. If a JUnit 3/4/5 test case method is
+ * annotated with {@code @NotYetImplemented}, the test will fail if no test failure occurs
+ * and it will pass if a test failure occurs.
* <p>
* This is helpful for tests that don't currently work but should work one day,
* when the tested functionality has been implemented.
* <p>
- * The idea for this AST transformation originated in {@link groovy.test.GroovyTestCase#notYetImplemented()}.
+ * Note: JUnit 3 users should use the optional {@code exception} attribute, e.g. {@code @NotYetImplemented(exception=junit.framework.AssertionFailedError)}.
*
* @since 3.0.0
*/
@@ -42,4 +42,11 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@GroovyASTTransformationClass("org.apache.groovy.test.transform.NotYetImplementedASTTransformation")
public @interface NotYetImplemented {
+ /**
+ * If defined, tests which unexpectedly pass will throw this exception.
+ * The supplied exception class should have a constructor variant accepting a single String error message.
+ *
+ * @since 3.0.3
+ */
+ Class<? extends AssertionError> exception() default AssertionError.class;
}
diff --git a/subprojects/groovy-test/src/main/java/org/apache/groovy/test/transform/NotYetImplementedASTTransformation.java b/subprojects/groovy-test/src/main/java/org/apache/groovy/test/transform/NotYetImplementedASTTransformation.java
index 7c6250c..c6f7f70 100644
--- a/subprojects/groovy-test/src/main/java/org/apache/groovy/test/transform/NotYetImplementedASTTransformation.java
+++ b/subprojects/groovy-test/src/main/java/org/apache/groovy/test/transform/NotYetImplementedASTTransformation.java
@@ -22,7 +22,9 @@ 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.ConstructorNode;
import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.ThrowStatement;
@@ -32,9 +34,6 @@ 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;
@@ -53,22 +52,29 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.tryCatchS;
public class NotYetImplementedASTTransformation 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
+ private static final ClassNode DEFAULT_THROW_TYPE = ClassHelper.make(AssertionError.class);
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));
- }
-
+ init(nodes, source);
+ AnnotationNode anno = (AnnotationNode) nodes[0];
MethodNode methodNode = (MethodNode) nodes[1];
- if (methodNode.getCode() instanceof BlockStatement && !((BlockStatement) methodNode.getCode()).isEmpty()) {
+ ClassNode exception = getMemberClassValue(anno, "exception");
+ if (exception == null) {
+ exception = DEFAULT_THROW_TYPE;
+ }
+ ConstructorNode cons = exception.getDeclaredConstructor(new Parameter[]{new Parameter(ClassHelper.STRING_TYPE, "dummy")});
+ if (cons == null) {
+ addError("Error during @NotYetImplemented processing: supplied exception " + exception.getNameWithoutPackage() + " doesn't have expected String constructor", methodNode);
+ }
+
+ if (methodNode.getCode() instanceof 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"))));
+ ThrowStatement throwStatement = throwS(ctorX(exception, 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 f6eef26..b4fbad5 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,7 +18,6 @@
*/
package org.apache.groovy.test.transform
-import junit.framework.AssertionFailedError
import org.junit.Test
final class NotYetImplementedTransformTest {
@@ -40,7 +39,7 @@ final class NotYetImplementedTransformTest {
junit.textui.TestRunner.run(new junit.framework.TestSuite(MyTests))
''')
- assert output.wasSuccessful() : 'test method marked with @NotYetImplemented must NOT throw an AssertionFailedError'
+ assert output.wasSuccessful() : 'failing test method marked with @NotYetImplemented must NOT throw an AssertionError'
}
@Test
@@ -58,7 +57,7 @@ final class NotYetImplementedTransformTest {
junit.textui.TestRunner.run(new junit.framework.TestSuite(MyTests))
''')
- assert output.wasSuccessful() : 'test method marked with @NotYetImplemented must NOT throw an AssertionFailedError'
+ assert output.wasSuccessful() : 'test method throwing exception marked with @NotYetImplemented must NOT throw an AssertionError'
}
@Test
@@ -68,7 +67,7 @@ final class NotYetImplementedTransformTest {
import groovy.test.NotYetImplemented
class MyTests extends GroovyTestCase {
- @NotYetImplemented void testThatPasses() {
+ @NotYetImplemented(exception=junit.framework.AssertionFailedError) void testThatPasses() {
assertTrue(true)
}
}
@@ -76,8 +75,8 @@ final class NotYetImplementedTransformTest {
junit.textui.TestRunner.run(new junit.framework.TestSuite(MyTests))
''')
- assert output.failureCount() == 1 : 'test method marked with @NotYetImplemented must throw an AssertionFailedError'
- assert output.failures().nextElement().thrownException() instanceof AssertionFailedError : 'test method marked with @NotYetImplemented must throw an AssertionFailedError'
+ assert output.failureCount() == 1 : 'succeeding test method marked with @NotYetImplemented must throw an AssertionError'
+ assert output.failures().nextElement().thrownException() instanceof AssertionError : 'succeeding test method marked with @NotYetImplemented must throw an AssertionError'
}
@Test
@@ -94,7 +93,7 @@ final class NotYetImplementedTransformTest {
junit.textui.TestRunner.run(new junit.framework.TestSuite(MyTests))
''')
- assert output.wasSuccessful() : 'empty test method must not throw an AssertionFailedError'
+ assert output.wasSuccessful() : 'empty test method must not throw an AssertionError'
}
@Test
@@ -114,7 +113,7 @@ final class NotYetImplementedTransformTest {
new JUnitCore().run(MyTests)
''')
- assert output.wasSuccessful() : '@Test method marked with @NotYetImplemented must NOT throw an AssertionFailedError'
+ assert output.wasSuccessful() : 'failing @Test method marked with @NotYetImplemented must NOT throw an AssertionError'
}
@Test // GROOVY-8457
@@ -135,7 +134,7 @@ final class NotYetImplementedTransformTest {
new JUnitCore().run(MyTests)
''')
- assert output.wasSuccessful() : '@Test method marked with @CompileStatic and @NotYetImplemented must NOT throw an AssertionFailedError'
+ assert output.wasSuccessful() : 'failing @Test method marked with @CompileStatic and @NotYetImplemented must NOT throw an AssertionError'
}
@Test
@@ -155,8 +154,8 @@ final class NotYetImplementedTransformTest {
new JUnitCore().run(MyTests)
''')
- assert output.failureCount == 1 : '@Test method marked with @NotYetImplemented must throw an AssertionFailedError'
- assert output.failures.first().exception instanceof AssertionFailedError : '@Test method marked with @NotYetImplemented must throw an AssertionFailedError'
+ assert output.failureCount == 1 : 'succeeding @Test method marked with @NotYetImplemented must throw an AssertionError'
+ assert output.failures.first().exception instanceof AssertionError : 'succeeding @Test method marked with @NotYetImplemented must throw an AssertionError'
}
@Test // GROOVY-8457
@@ -177,7 +176,7 @@ final class NotYetImplementedTransformTest {
new JUnitCore().run(MyTests)
''')
- assert output.failureCount == 1 : '@Test method marked with @CompileStatic and @NotYetImplemented must throw an AssertionFailedError'
- assert output.failures.first().exception instanceof AssertionFailedError : '@Test method marked with @CompileStatic and @NotYetImplemented must throw an AssertionFailedError'
+ assert output.failureCount == 1 : 'succeeding @Test method marked with @CompileStatic and @NotYetImplemented must throw an AssertionError'
+ assert output.failures.first().exception instanceof AssertionError : 'succeeding @Test method marked with @CompileStatic and @NotYetImplemented must throw an AssertionError'
}
}
[groovy] 02/02: GROOVY-9492: Relax groovy.test.NotYetImplemented
dependency on JUnit 4's AssertionFailedError (adjustments for Groovy 3)
Posted by pa...@apache.org.
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