You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2026/08/23 16:23:50 UTC

(groovy) branch master updated: Fix reliability issues reported by Sonar

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

asf-gitbox-commits 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 e5ea4eb8bf Fix reliability issues reported by Sonar
e5ea4eb8bf is described below

commit e5ea4eb8bf9782e0c121aa29dac79a5f388cc656
Author: Daniel Sun <su...@apache.org>
AuthorDate: Mon Aug 24 01:21:32 2026 +0900

    Fix reliability issues reported by Sonar
---
 .../groovy/concurrent/AwaitableAdapterRegistry.java    |  3 +++
 src/main/java/groovy/io/LineColumnReader.java          |  4 ++--
 src/main/java/groovy/lang/NumberRange.java             |  2 +-
 .../org/apache/groovy/parser/antlr4/AstBuilder.java    |  2 +-
 src/main/java/org/codehaus/groovy/ast/FieldNode.java   |  5 +++++
 .../codehaus/groovy/classgen/asm/ClosureWriter.java    |  2 +-
 .../sc/StaticTypesMethodReferenceExpressionWriter.java |  2 +-
 .../org/codehaus/groovy/runtime/MetaClassHelper.java   | 12 ++++++------
 .../groovy/runtime/memoize/CacheCleanupTest.groovy     |  2 +-
 .../groovy/util/ManagedConcurrentValueMapTest.groovy   |  2 +-
 .../src/main/java/groovy/ant/AntBuilder.java           |  6 +++++-
 .../main/groovy/groovy/console/ui/text/TextEditor.java | 14 +++++++-------
 .../contracts/ast/LoopVariantASTTransformation.java    |  2 +-
 .../ginq/provider/collection/runtime/Null.groovy       |  2 +-
 .../ginq/provider/collection/runtime/WindowImpl.java   |  8 ++++----
 .../groovy/tools/groovydoc/antlr4/GroovyDocParser.java |  5 +++--
 .../tools/groovydoc/antlr4/GroovydocJavaVisitor.java   |  4 ++--
 .../apache/groovy/json/internal/JsonFastParser.java    |  5 ++++-
 .../org/apache/groovy/json/internal/JsonParserLax.java |  3 ++-
 .../src/test/groovy/groovy/xml/FactorySupportTest.java | 18 ++++++++----------
 20 files changed, 59 insertions(+), 44 deletions(-)

diff --git a/src/main/java/groovy/concurrent/AwaitableAdapterRegistry.java b/src/main/java/groovy/concurrent/AwaitableAdapterRegistry.java
index cf24fef402..bc90a901fd 100644
--- a/src/main/java/groovy/concurrent/AwaitableAdapterRegistry.java
+++ b/src/main/java/groovy/concurrent/AwaitableAdapterRegistry.java
@@ -232,6 +232,9 @@ public final class AwaitableAdapterRegistry {
                         cf.complete(future.get());
                     } catch (ExecutionException e) {
                         cf.completeExceptionally(e.getCause());
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                        cf.completeExceptionally(e);
                     } catch (Throwable e) {
                         cf.completeExceptionally(e);
                     }
diff --git a/src/main/java/groovy/io/LineColumnReader.java b/src/main/java/groovy/io/LineColumnReader.java
index f2933e8250..5f8833e2eb 100644
--- a/src/main/java/groovy/io/LineColumnReader.java
+++ b/src/main/java/groovy/io/LineColumnReader.java
@@ -111,10 +111,10 @@ public class LineColumnReader extends BufferedReader {
                 newLineWasRead = true;
                 if (c == '\r') {
                     mark(1);
-                    c = (char)super.read();
+                    int nextChar = super.read();
                     // check if we have \r\n like on Windows
                     // if it's not \r\n we reset, otherwise, the \n is just consumed
-                    if (c != '\n') {
+                    if (nextChar != '\n') {
                         reset();
                     }
                 }
diff --git a/src/main/java/groovy/lang/NumberRange.java b/src/main/java/groovy/lang/NumberRange.java
index 0046cfa80d..4635be8106 100644
--- a/src/main/java/groovy/lang/NumberRange.java
+++ b/src/main/java/groovy/lang/NumberRange.java
@@ -544,7 +544,7 @@ public class NumberRange extends AbstractList<Comparable> implements Range<Compa
 
     private boolean isIntegral(Number stepSize) {
         BigDecimal tempStepSize = NumberMath.toBigDecimal(stepSize);
-        return tempStepSize.equals(new BigDecimal(tempStepSize.toBigInteger()));
+        return tempStepSize.compareTo(new BigDecimal(tempStepSize.toBigInteger())) == 0;
     }
 
     /**
diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 59f0b24bd6..4f32b94144 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -5484,7 +5484,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
     // GROOVY-10355: a cast whose operand is the binary-only keyword identifier "in" or "as"
     private static final String CAST_OF_BINARY_KEYWORD = "_CAST_OF_BINARY_KEYWORD";
 
-    private static final Pattern BARE_NAME_PATTERN = Pattern.compile("[A-Za-z_$][A-Za-z0-9_$]*(\\.[A-Za-z_$][A-Za-z0-9_$]*)*");
+    private static final Pattern BARE_NAME_PATTERN = Pattern.compile("[A-Za-z_$][A-Za-z0-9_$]*(?:\\.[A-Za-z_$][A-Za-z0-9_$]*)*");
 
     private static final String CLASS_NAME = "_CLASS_NAME";
     private static final String INSIDE_PARENTHESES_LEVEL = "_INSIDE_PARENTHESES_LEVEL";
diff --git a/src/main/java/org/codehaus/groovy/ast/FieldNode.java b/src/main/java/org/codehaus/groovy/ast/FieldNode.java
index 3b7605930e..8d9372c9ec 100644
--- a/src/main/java/org/codehaus/groovy/ast/FieldNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/FieldNode.java
@@ -252,6 +252,11 @@ public class FieldNode extends AnnotatedNode implements Variable {
         return super.equals(obj);
     }
 
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
     /**
      * Returns the original declared type of this field before any transformations.
      * Useful for preserving type information through compilation phases that may modify types.
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
index 9f5d742d8e..6523876a09 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
@@ -1557,7 +1557,7 @@ public class ClosureWriter {
         }
         final byte[] hashBytes = md.digest(str.getBytes(StandardCharsets.UTF_8));
         long hash = 0;
-        for (int i = Math.min(hashBytes.length, 7); i >= 0; i--) {
+        for (int i = Math.min(hashBytes.length - 1, 7); i >= 0; i--) {
             hash = (hash << 8) | (hashBytes[i] & 0xFF);
         }
         return hash;
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
index 7b2f4da125..9f83d28b0e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
@@ -561,7 +561,7 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
                 score += 9;
             }
             return score;
-        }).thenComparing(StaticTypesMethodReferenceExpressionWriter::isExtensionMethod)).get();
+        }).thenComparing(StaticTypesMethodReferenceExpressionWriter::isExtensionMethod)).orElse(null);
     }
 
     private List<MethodNode> findVisibleMethods(final String name, final ClassNode type) {
diff --git a/src/main/java/org/codehaus/groovy/runtime/MetaClassHelper.java b/src/main/java/org/codehaus/groovy/runtime/MetaClassHelper.java
index 124c7a2ca6..8fa7179280 100644
--- a/src/main/java/org/codehaus/groovy/runtime/MetaClassHelper.java
+++ b/src/main/java/org/codehaus/groovy/runtime/MetaClassHelper.java
@@ -1024,12 +1024,12 @@ public class MetaClassHelper {
      */
     public static Object normalizeBoxedReturn(final Object value, final Class<?> returnType) {
         if (value == null || !returnType.isPrimitive()) return value; // null includes void
-        if (returnType == int.class) return Integer.valueOf((Integer) value);
-        if (returnType == boolean.class) return Boolean.valueOf((Boolean) value);
-        if (returnType == long.class) return Long.valueOf((Long) value);
-        if (returnType == char.class) return Character.valueOf((Character) value);
-        if (returnType == byte.class) return Byte.valueOf((Byte) value);
-        if (returnType == short.class) return Short.valueOf((Short) value);
+        if (returnType == int.class) return Integer.valueOf(((Integer) value).intValue());
+        if (returnType == boolean.class) return Boolean.valueOf(((Boolean) value).booleanValue());
+        if (returnType == long.class) return Long.valueOf(((Long) value).longValue());
+        if (returnType == char.class) return Character.valueOf(((Character) value).charValue());
+        if (returnType == byte.class) return Byte.valueOf(((Byte) value).byteValue());
+        if (returnType == short.class) return Short.valueOf(((Short) value).shortValue());
         return value; // float/double: valueOf does not cache on any path
     }
 
diff --git a/src/test/groovy/org/codehaus/groovy/runtime/memoize/CacheCleanupTest.groovy b/src/test/groovy/org/codehaus/groovy/runtime/memoize/CacheCleanupTest.groovy
index 4bb89d6777..d3190b6beb 100644
--- a/src/test/groovy/org/codehaus/groovy/runtime/memoize/CacheCleanupTest.groovy
+++ b/src/test/groovy/org/codehaus/groovy/runtime/memoize/CacheCleanupTest.groovy
@@ -57,7 +57,7 @@ public class CacheCleanupTest {
         cache.put('key2', new SoftReference(ANCHOR))
         assert cache.@map.size() == 2
         for (i in (3..1000)) {
-            cache.put("key${i}", new SoftReference(null))  //Simulating evicted objects
+            cache.put('key' + i, new SoftReference(null))  //Simulating evicted objects
             cache.get('key1')  //touch the non-null cache entries to keep them hot to prevent a potential LRU algorithm from evicting them
             cache.get('key2')
         }
diff --git a/src/test/groovy/org/codehaus/groovy/util/ManagedConcurrentValueMapTest.groovy b/src/test/groovy/org/codehaus/groovy/util/ManagedConcurrentValueMapTest.groovy
index 05c0d5df5b..742c6592ab 100644
--- a/src/test/groovy/org/codehaus/groovy/util/ManagedConcurrentValueMapTest.groovy
+++ b/src/test/groovy/org/codehaus/groovy/util/ManagedConcurrentValueMapTest.groovy
@@ -28,7 +28,7 @@ final class ManagedConcurrentValueMapTest {
     @Test
     void testEntriesRemoveSelfFromMapWhenFinalized() {
         for (int i = 0; i < 5; i++) {
-            map.put("Key${i}", new Object())
+            map.put('Key' + i, new Object())
         }
 
         assert map.@internalMap.size() == 5
diff --git a/subprojects/groovy-ant/src/main/java/groovy/ant/AntBuilder.java b/subprojects/groovy-ant/src/main/java/groovy/ant/AntBuilder.java
index 6ec36eb308..cd54e0a067 100644
--- a/subprojects/groovy-ant/src/main/java/groovy/ant/AntBuilder.java
+++ b/subprojects/groovy-ant/src/main/java/groovy/ant/AntBuilder.java
@@ -396,7 +396,11 @@ public class AntBuilder extends BuilderSupport {
             } catch (Exception e) {
                 BuildException be = new BuildException(e);
                 be.setLocation(task.getLocation());
-                throw be;
+                if (reason != null) {
+                    reason.addSuppressed(be);
+                } else {
+                    throw be;
+                }
             }
         }
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextEditor.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextEditor.java
index d9aa201bcb..6972454124 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextEditor.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextEditor.java
@@ -322,21 +322,21 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
             FontMetrics fm = graphics.getFontMetrics(font);
             int width = SwingUtilities.computeStringWidth(fm, header);
             ((Graphics2D) graphics).drawString(header,
-                    (float) (paper.getImageableWidth() / 2 - width / 2),
-                    (float) paper.getImageableY() / 2 + fm.getHeight());
+                    (float) (paper.getImageableWidth() / 2.0 - width / 2.0),
+                    (float) (paper.getImageableY() / 2.0 + fm.getHeight()));
 
             ((Graphics2D) graphics).translate(0, paper.getImageableY() - fm.getHeight());
-            double height = paper.getImageableHeight() + paper.getImageableY() / 2;
+            double height = paper.getImageableHeight() + paper.getImageableY() / 2.0;
             width = SwingUtilities.computeStringWidth(fm, name);
             ((Graphics2D) graphics).drawString(name,
-                    (float) (paper.getImageableWidth() / 2 - width / 2),
-                    (float) height - fm.getHeight() / 2);
+                    (float) (paper.getImageableWidth() / 2.0 - width / 2.0),
+                    (float) (height - fm.getHeight() / 2.0));
 
             ((Graphics2D) graphics).translate(0, fm.getHeight());
             width = SwingUtilities.computeStringWidth(fm, pageStr);
             ((Graphics2D) graphics).drawString(pageStr,
-                    (float) (paper.getImageableWidth() / 2 - width / 2),
-                    (float) height - fm.getHeight() / 2);
+                    (float) (paper.getImageableWidth() / 2.0 - width / 2.0),
+                    (float) (height - fm.getHeight() / 2.0));
 
             return Printable.PAGE_EXISTS;
         }
diff --git a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/LoopVariantASTTransformation.java b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/LoopVariantASTTransformation.java
index 5a279219ec..897dab1da4 100644
--- a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/LoopVariantASTTransformation.java
+++ b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/LoopVariantASTTransformation.java
@@ -142,7 +142,7 @@ public class LoopVariantASTTransformation implements ASTTransformation, Compilat
             Statement declSeen = declS(localVarX(seenVarName, ClassHelper.boolean_TYPE), constX(false, true));
             declSeen.setSourcePosition(annotation);
             List<Statement> siblings = enclosingBlock.getStatements();
-            siblings.addAll(siblings.indexOf(loopStatement), List.of(declPrev, declSeen));
+            siblings.addAll(siblings.indexOf((Statement) loopStatement), List.of(declPrev, declSeen));
 
             Statement saveCurr = declS(localVarX(currVarName, ClassHelper.dynamicType()), variantExpression);
             saveCurr.setSourcePosition(annotation);
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Null.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Null.groovy
index 87fd0db1ae..5474c35803 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Null.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Null.groovy
@@ -26,7 +26,7 @@ import groovy.transform.PackageScope
  * @since 4.0.0
  */
 @PackageScope
-class Null {
+class Null implements Cloneable {
     /** Shared null-object instance. */
     public static final Null INSTANCE = new Null()
 
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
index 27490ffaa8..963133fe33 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
@@ -100,7 +100,7 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
         if (0 == size) {
             return null;
         }
-        return nthValue(extractor, size - 1);
+        return nthValue(extractor, size - 1L);
     }
 
     @Override
@@ -282,7 +282,7 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
         if ((firstIndex < 0 && lastIndex < 0) || (firstIndex >= size && lastIndex >= size)) {
             return null;
         }
-        return new RowBound(Math.max(firstIndex, 0), Math.min(lastIndex, size - 1));
+        return new RowBound(Math.max(firstIndex, 0L), Math.min(lastIndex, size - 1L));
     }
 
     private static <T, U extends Comparable<? super U>> long getIndexByValue(BigDecimal value, boolean isLower, List<U> list) {
@@ -303,7 +303,7 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
         if (isLower) {
             int i = valueIndex - 1;
             for (; i >= 0; i--) {
-                if (!value.equals(toBigDecimal((Number) list.get(i)))) {
+                if (value.compareTo(toBigDecimal((Number) list.get(i))) != 0) {
                     break;
                 }
             }
@@ -311,7 +311,7 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
         } else {
             int i = valueIndex + 1;
             for (int n = list.size(); i < n; i++) {
-                if (!value.equals(toBigDecimal((Number) list.get(i)))) {
+                if (value.compareTo(toBigDecimal((Number) list.get(i))) != 0) {
                     break;
                 }
             }
diff --git a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/antlr4/GroovyDocParser.java b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/antlr4/GroovyDocParser.java
index 7361c0afe7..e57d32a143 100644
--- a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/antlr4/GroovyDocParser.java
+++ b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/antlr4/GroovyDocParser.java
@@ -98,10 +98,11 @@ public class GroovyDocParser implements GroovyDocParserI {
         GroovydocJavaVisitor visitor = new GroovydocJavaVisitor(packagePath, links, properties);
         try {
             ParseResult<com.github.javaparser.ast.CompilationUnit> parseResult = javaParser.parse(src);
-            if (!parseResult.isSuccessful() || parseResult.getResult().isEmpty()) {
+            var cuOpt = parseResult.getResult();
+            if (!parseResult.isSuccessful() || cuOpt.isEmpty()) {
                 throw new ParseProblemException(parseResult.getProblems());
             }
-            visitor.visit(parseResult.getResult().get(), null);
+            visitor.visit(cuOpt.get(), null);
         } catch (Throwable t) {
             LOGGER.log(WARNING, "Attempting to ignore error parsing Java source file: {0}/{1}", packagePath, file);
             LOGGER.log(WARNING, "Consider reporting the error to the Groovy project: https://issues.apache.org/jira/browse/GROOVY");
diff --git a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/antlr4/GroovydocJavaVisitor.java b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/antlr4/GroovydocJavaVisitor.java
index 49e673e65d..402bcfe9be 100644
--- a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/antlr4/GroovydocJavaVisitor.java
+++ b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/antlr4/GroovydocJavaVisitor.java
@@ -360,8 +360,8 @@ public class GroovydocJavaVisitor
     }
 
     private String getAnnotationText(final AnnotationExpr an) {
-        if (an != null && an.getTokenRange().isPresent()) {
-            return an.getTokenRange().get().toString();
+        if (an != null) {
+            return an.getTokenRange().map(Object::toString).orElse("");
         }
         return "";
     }
diff --git a/subprojects/groovy-json/src/main/java/org/apache/groovy/json/internal/JsonFastParser.java b/subprojects/groovy-json/src/main/java/org/apache/groovy/json/internal/JsonFastParser.java
index f8c7f74bc5..860f446a4e 100644
--- a/subprojects/groovy-json/src/main/java/org/apache/groovy/json/internal/JsonFastParser.java
+++ b/subprojects/groovy-json/src/main/java/org/apache/groovy/json/internal/JsonFastParser.java
@@ -163,7 +163,10 @@ public class JsonFastParser extends JsonParserCharArray {
             case '{' -> decodeJsonObjectLazyFinalParse();
             case 't' -> decodeTrue() ? ValueContainer.TRUE : ValueContainer.FALSE;
             case 'f' -> !decodeFalse() ? ValueContainer.FALSE : ValueContainer.TRUE;
-            case 'n' -> decodeNull() == null ? ValueContainer.NULL : ValueContainer.NULL;
+            case 'n' -> {
+                decodeNull();
+                yield ValueContainer.NULL;
+            }
             case '[' -> decodeJsonArrayOverlay();
             case '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' -> decodeNumberOverlay(false);
             case '-' -> decodeNumberOverlay(true);
diff --git a/subprojects/groovy-json/src/main/java/org/apache/groovy/json/internal/JsonParserLax.java b/subprojects/groovy-json/src/main/java/org/apache/groovy/json/internal/JsonParserLax.java
index 45aeffe5a4..4ece265ba0 100644
--- a/subprojects/groovy-json/src/main/java/org/apache/groovy/json/internal/JsonParserLax.java
+++ b/subprojects/groovy-json/src/main/java/org/apache/groovy/json/internal/JsonParserLax.java
@@ -317,7 +317,8 @@ public class JsonParserLax extends JsonParserCharArray {
 
                 case 'n':
                     if (isNull()) {
-                        return decodeNull() == null ? ValueContainer.NULL : ValueContainer.NULL;
+                        decodeNull();
+                        return ValueContainer.NULL;
                     } else {
                         value = decodeStringLax();
                     }
diff --git a/subprojects/groovy-xml/src/test/groovy/groovy/xml/FactorySupportTest.java b/subprojects/groovy-xml/src/test/groovy/groovy/xml/FactorySupportTest.java
index 22216f8c8e..2ad63be11b 100644
--- a/subprojects/groovy-xml/src/test/groovy/groovy/xml/FactorySupportTest.java
+++ b/subprojects/groovy-xml/src/test/groovy/groovy/xml/FactorySupportTest.java
@@ -44,6 +44,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
@@ -73,19 +74,16 @@ public class FactorySupportTest {
     }
 
     @Test
-    public void otherExceptionsWrappedAsUnchecked() throws ParserConfigurationException {
-        try {
-            FactorySupport.createFactory(new PrivilegedExceptionAction() {
+    public void otherExceptionsWrappedAsUnchecked() {
+        RuntimeException re = assertThrows(RuntimeException.class, () ->
+            FactorySupport.createFactory(new PrivilegedExceptionAction<Object>() {
+                @Override
                 public Object run() throws Exception {
                     throw PRIVILEGED_ACTION_EXCEPTION;
                 }
-            });
-            fail("Exception was not caught");
-        } catch (RuntimeException re) {
-            assertSame(PRIVILEGED_ACTION_EXCEPTION, re.getCause());
-        } catch (Throwable t) {
-            fail("Exception was not wrapped as runtime");
-        }
+            })
+        );
+        assertSame(PRIVILEGED_ACTION_EXCEPTION, re.getCause());
     }
 
     @Test