diff options
Diffstat (limited to 'src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java')
-rw-r--r-- | src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java | 853 |
1 files changed, 853 insertions, 0 deletions
diff --git a/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java b/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java new file mode 100644 index 000000000..b12d66950 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java @@ -0,0 +1,853 @@ +/* + * 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.commons.lang3.exception; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +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.assertNull; +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 java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.AbstractLangTest; +import org.apache.commons.lang3.test.NotVisibleExceptionFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link org.apache.commons.lang3.exception.ExceptionUtils}. + * + * @since 1.0 + */ +public class ExceptionUtilsTest extends AbstractLangTest { + + /** + * Provides a method with a well known chained/nested exception + * name which matches the full signature (e.g. has a return value + * of {@code Throwable}). + */ + private static class ExceptionWithCause extends Exception { + private static final long serialVersionUID = 1L; + + private Throwable cause; + + ExceptionWithCause(final String str, final Throwable cause) { + super(str); + setCause(cause); + } + + ExceptionWithCause(final Throwable cause) { + setCause(cause); + } + + @Override + public synchronized Throwable getCause() { + return cause; + } + + public void setCause(final Throwable cause) { + this.cause = cause; + } + } + + /** + * Provides a method with a well known chained/nested exception + * name which does not match the full signature (e.g. lacks a + * return value of {@code Throwable}). + */ + private static class ExceptionWithoutCause extends Exception { + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + public void getTargetException() { + // noop + } + } + + // Temporary classes to allow the nested exception code to be removed + // prior to a rewrite of this test class. + private static class NestableException extends Exception { + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unused") + NestableException() { + } + + NestableException(final Throwable t) { + super(t); + } + } + + public static class TestThrowable extends Throwable { + private static final long serialVersionUID = 1L; + } + + private static int redeclareCheckedException() { + return throwsCheckedException(); + } + + private static int throwsCheckedException() { + try { + throw new IOException(); + } catch (final Exception e) { + return ExceptionUtils.<Integer>rethrow(e); + } + } + + private NestableException nested; + + + private Throwable withCause; + + private Throwable withoutCause; + + private Throwable jdkNoCause; + + private ExceptionWithCause cyclicCause; + + private Throwable notVisibleException; + + private Throwable createExceptionWithCause() { + try { + try { + throw new ExceptionWithCause(createExceptionWithoutCause()); + } catch (final Throwable t) { + throw new ExceptionWithCause(t); + } + } catch (final Throwable t) { + return t; + } + } + + private Throwable createExceptionWithoutCause() { + try { + throw new ExceptionWithoutCause(); + } catch (final Throwable t) { + return t; + } + } + + @BeforeEach + public void setUp() { + withoutCause = createExceptionWithoutCause(); + nested = new NestableException(withoutCause); + withCause = new ExceptionWithCause(nested); + jdkNoCause = new NullPointerException(); + final ExceptionWithCause a = new ExceptionWithCause(null); + final ExceptionWithCause b = new ExceptionWithCause(a); + a.setCause(b); + cyclicCause = new ExceptionWithCause(a); + notVisibleException = NotVisibleExceptionFactory.createException(withoutCause); + } + + @AfterEach + public void tearDown() { + withoutCause = null; + nested = null; + withCause = null; + jdkNoCause = null; + cyclicCause = null; + notVisibleException = null; + } + + @Test + public void test_getMessage_Throwable() { + Throwable th = null; + assertEquals("", ExceptionUtils.getMessage(th)); + + th = new IllegalArgumentException("Base"); + assertEquals("IllegalArgumentException: Base", ExceptionUtils.getMessage(th)); + + th = new ExceptionWithCause("Wrapper", th); + assertEquals("ExceptionUtilsTest.ExceptionWithCause: Wrapper", ExceptionUtils.getMessage(th)); + } + + @Test + public void test_getRootCauseMessage_Throwable() { + Throwable th = null; + assertEquals("", ExceptionUtils.getRootCauseMessage(th)); + + th = new IllegalArgumentException("Base"); + assertEquals("IllegalArgumentException: Base", ExceptionUtils.getRootCauseMessage(th)); + + th = new ExceptionWithCause("Wrapper", th); + assertEquals("IllegalArgumentException: Base", ExceptionUtils.getRootCauseMessage(th)); + } + + @Test + public void testCatchTechniques() { + IOException ioe = assertThrows(IOException.class, ExceptionUtilsTest::throwsCheckedException); + assertEquals(1, ExceptionUtils.getThrowableCount(ioe)); + + ioe = assertThrows(IOException.class, ExceptionUtilsTest::redeclareCheckedException); + assertEquals(1, ExceptionUtils.getThrowableCount(ioe)); + } + + @Test + public void testConstructor() { + assertNotNull(new ExceptionUtils()); + final Constructor<?>[] cons = ExceptionUtils.class.getDeclaredConstructors(); + assertEquals(1, cons.length); + assertTrue(Modifier.isPublic(cons[0].getModifiers())); + assertTrue(Modifier.isPublic(ExceptionUtils.class.getModifiers())); + assertFalse(Modifier.isFinal(ExceptionUtils.class.getModifiers())); + } + + @Test + public void testForEach_jdkNoCause() { + final List<Throwable> throwables = new ArrayList<>(); + ExceptionUtils.forEach(jdkNoCause, throwables::add); + assertEquals(1, throwables.size()); + assertSame(jdkNoCause, throwables.get(0)); + } + + @Test + public void testForEach_nested() { + final List<Throwable> throwables = new ArrayList<>(); + ExceptionUtils.forEach(nested, throwables::add); + assertEquals(2, throwables.size()); + assertSame(nested, throwables.get(0)); + assertSame(withoutCause, throwables.get(1)); + } + + @Test + public void testForEach_null() { + final List<Throwable> throwables = new ArrayList<>(); + ExceptionUtils.forEach(null, throwables::add); + assertEquals(0, throwables.size()); + } + + @Test + public void testForEach_recursiveCause() { + final List<Throwable> throwables = new ArrayList<>(); + ExceptionUtils.forEach(cyclicCause, throwables::add); + assertEquals(3, throwables.size()); + assertSame(cyclicCause, throwables.get(0)); + assertSame(cyclicCause.getCause(), throwables.get(1)); + assertSame(cyclicCause.getCause().getCause(), throwables.get(2)); + } + + @Test + public void testForEach_withCause() { + final List<Throwable> throwables = new ArrayList<>(); + ExceptionUtils.forEach(withCause, throwables::add); + assertEquals(3, throwables.size()); + assertSame(withCause, throwables.get(0)); + assertSame(nested, throwables.get(1)); + assertSame(withoutCause, throwables.get(2)); + } + + @Test + public void testForEach_withoutCause() { + final List<Throwable> throwables = new ArrayList<>(); + ExceptionUtils.forEach(withoutCause, throwables::add); + assertEquals(1, throwables.size()); + assertSame(withoutCause, throwables.get(0)); + } + + @SuppressWarnings("deprecation") // Specifically tests the deprecated methods + @Test + public void testGetCause_Throwable() { + assertSame(null, ExceptionUtils.getCause(null)); + assertSame(null, ExceptionUtils.getCause(withoutCause)); + assertSame(withoutCause, ExceptionUtils.getCause(nested)); + assertSame(nested, ExceptionUtils.getCause(withCause)); + assertSame(null, ExceptionUtils.getCause(jdkNoCause)); + assertSame(cyclicCause.getCause(), ExceptionUtils.getCause(cyclicCause)); + assertSame(cyclicCause.getCause().getCause(), ExceptionUtils.getCause(cyclicCause.getCause())); + assertSame(cyclicCause.getCause(), ExceptionUtils.getCause(cyclicCause.getCause().getCause())); + assertSame(withoutCause, ExceptionUtils.getCause(notVisibleException)); + } + + @SuppressWarnings("deprecation") // Specifically tests the deprecated methods + @Test + public void testGetCause_ThrowableArray() { + assertSame(null, ExceptionUtils.getCause(null, null)); + assertSame(null, ExceptionUtils.getCause(null, new String[0])); + + // not known type, so match on supplied method names + assertSame(nested, ExceptionUtils.getCause(withCause, null)); // default names + assertSame(null, ExceptionUtils.getCause(withCause, new String[0])); + assertSame(null, ExceptionUtils.getCause(withCause, new String[]{null})); + assertSame(nested, ExceptionUtils.getCause(withCause, new String[]{"getCause"})); + + // not known type, so match on supplied method names + assertSame(null, ExceptionUtils.getCause(withoutCause, null)); + assertSame(null, ExceptionUtils.getCause(withoutCause, new String[0])); + assertSame(null, ExceptionUtils.getCause(withoutCause, new String[]{null})); + assertSame(null, ExceptionUtils.getCause(withoutCause, new String[]{"getCause"})); + assertSame(null, ExceptionUtils.getCause(withoutCause, new String[]{"getTargetException"})); + } + + @Test + public void testGetRootCause_Throwable() { + assertSame(null, ExceptionUtils.getRootCause(null)); + assertSame(withoutCause, ExceptionUtils.getRootCause(withoutCause)); + assertSame(withoutCause, ExceptionUtils.getRootCause(nested)); + assertSame(withoutCause, ExceptionUtils.getRootCause(withCause)); + assertSame(jdkNoCause, ExceptionUtils.getRootCause(jdkNoCause)); + assertSame(cyclicCause.getCause().getCause(), ExceptionUtils.getRootCause(cyclicCause)); + } + + @Test + public void testGetRootCauseStackTrace_Throwable() { + assertEquals(0, ExceptionUtils.getRootCauseStackTrace(null).length); + + final Throwable cause = createExceptionWithCause(); + String[] stackTrace = ExceptionUtils.getRootCauseStackTrace(cause); + boolean match = false; + for (final String element : stackTrace) { + if (element.startsWith(ExceptionUtils.WRAPPED_MARKER)) { + match = true; + break; + } + } + assertTrue(match); + + stackTrace = ExceptionUtils.getRootCauseStackTrace(withoutCause); + match = false; + for (final String element : stackTrace) { + if (element.startsWith(ExceptionUtils.WRAPPED_MARKER)) { + match = true; + break; + } + } + assertFalse(match); + } + + @Test + public void testGetRootCauseStackTraceList_Throwable() { + assertEquals(0, ExceptionUtils.getRootCauseStackTraceList(null).size()); + + final Throwable cause = createExceptionWithCause(); + List<String> stackTrace = ExceptionUtils.getRootCauseStackTraceList(cause); + boolean match = false; + for (final String element : stackTrace) { + if (element.startsWith(ExceptionUtils.WRAPPED_MARKER)) { + match = true; + break; + } + } + assertTrue(match); + + stackTrace = ExceptionUtils.getRootCauseStackTraceList(withoutCause); + match = false; + for (final String element : stackTrace) { + if (element.startsWith(ExceptionUtils.WRAPPED_MARKER)) { + match = true; + break; + } + } + assertFalse(match); + } + + @Test + @DisplayName("getStackFrames returns empty string array when the argument is null") + public void testgetStackFramesHappyPath() { + final String[] actual = ExceptionUtils.getStackFrames(new Throwable() { + private static final long serialVersionUID = 1L; + + // provide static stack trace to make test stable + @Override + public void printStackTrace(final PrintWriter s) { + s.write("org.apache.commons.lang3.exception.ExceptionUtilsTest$1\n" + + "\tat org.apache.commons.lang3.exception.ExceptionUtilsTest.testgetStackFramesGappyPath(ExceptionUtilsTest.java:706)\n" + + "\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + "\tat com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)\n" + + "\tat com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)\n"); + } + }); + + assertArrayEquals(new String[]{ + "org.apache.commons.lang3.exception.ExceptionUtilsTest$1", + "\tat org.apache.commons.lang3.exception.ExceptionUtilsTest.testgetStackFramesGappyPath(ExceptionUtilsTest.java:706)", + "\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)", + "\tat com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)", + "\tat com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)" + }, actual); + } + + @Test + @DisplayName("getStackFrames returns the string array of the stack frames when there is a real exception") + public void testgetStackFramesNullArg() { + final String[] actual = ExceptionUtils.getStackFrames((Throwable) null); + assertEquals(0, actual.length); + } + + @Test + public void testGetThrowableCount_Throwable() { + assertEquals(0, ExceptionUtils.getThrowableCount(null)); + assertEquals(1, ExceptionUtils.getThrowableCount(withoutCause)); + assertEquals(2, ExceptionUtils.getThrowableCount(nested)); + assertEquals(3, ExceptionUtils.getThrowableCount(withCause)); + assertEquals(1, ExceptionUtils.getThrowableCount(jdkNoCause)); + assertEquals(3, ExceptionUtils.getThrowableCount(cyclicCause)); + } + + @Test + public void testGetThrowableList_Throwable_jdkNoCause() { + final List<?> throwables = ExceptionUtils.getThrowableList(jdkNoCause); + assertEquals(1, throwables.size()); + assertSame(jdkNoCause, throwables.get(0)); + } + + @Test + public void testGetThrowableList_Throwable_nested() { + final List<?> throwables = ExceptionUtils.getThrowableList(nested); + assertEquals(2, throwables.size()); + assertSame(nested, throwables.get(0)); + assertSame(withoutCause, throwables.get(1)); + } + + @Test + public void testGetThrowableList_Throwable_null() { + final List<?> throwables = ExceptionUtils.getThrowableList(null); + assertEquals(0, throwables.size()); + } + + @Test + public void testGetThrowableList_Throwable_recursiveCause() { + final List<?> throwables = ExceptionUtils.getThrowableList(cyclicCause); + assertEquals(3, throwables.size()); + assertSame(cyclicCause, throwables.get(0)); + assertSame(cyclicCause.getCause(), throwables.get(1)); + assertSame(cyclicCause.getCause().getCause(), throwables.get(2)); + } + + @Test + public void testGetThrowableList_Throwable_withCause() { + final List<?> throwables = ExceptionUtils.getThrowableList(withCause); + assertEquals(3, throwables.size()); + assertSame(withCause, throwables.get(0)); + assertSame(nested, throwables.get(1)); + assertSame(withoutCause, throwables.get(2)); + } + + @Test + public void testGetThrowableList_Throwable_withoutCause() { + final List<?> throwables = ExceptionUtils.getThrowableList(withoutCause); + assertEquals(1, throwables.size()); + assertSame(withoutCause, throwables.get(0)); + } + + @Test + public void testGetThrowables_Throwable_jdkNoCause() { + final Throwable[] throwables = ExceptionUtils.getThrowables(jdkNoCause); + assertEquals(1, throwables.length); + assertSame(jdkNoCause, throwables[0]); + } + + @Test + public void testGetThrowables_Throwable_nested() { + final Throwable[] throwables = ExceptionUtils.getThrowables(nested); + assertEquals(2, throwables.length); + assertSame(nested, throwables[0]); + assertSame(withoutCause, throwables[1]); + } + + @Test + public void testGetThrowables_Throwable_null() { + assertEquals(0, ExceptionUtils.getThrowables(null).length); + } + + @Test + public void testGetThrowables_Throwable_recursiveCause() { + final Throwable[] throwables = ExceptionUtils.getThrowables(cyclicCause); + assertEquals(3, throwables.length); + assertSame(cyclicCause, throwables[0]); + assertSame(cyclicCause.getCause(), throwables[1]); + assertSame(cyclicCause.getCause().getCause(), throwables[2]); + } + + @Test + public void testGetThrowables_Throwable_withCause() { + final Throwable[] throwables = ExceptionUtils.getThrowables(withCause); + assertEquals(3, throwables.length); + assertSame(withCause, throwables[0]); + assertSame(nested, throwables[1]); + assertSame(withoutCause, throwables[2]); + } + + @Test + public void testGetThrowables_Throwable_withoutCause() { + final Throwable[] throwables = ExceptionUtils.getThrowables(withoutCause); + assertEquals(1, throwables.length); + assertSame(withoutCause, throwables[0]); + } + + @Test + public void testIndexOf_ThrowableClass() { + assertEquals(-1, ExceptionUtils.indexOfThrowable(null, null)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(null, NestableException.class)); + + assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, null)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, ExceptionWithCause.class)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, NestableException.class)); + assertEquals(0, ExceptionUtils.indexOfThrowable(withoutCause, ExceptionWithoutCause.class)); + + assertEquals(-1, ExceptionUtils.indexOfThrowable(nested, null)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(nested, ExceptionWithCause.class)); + assertEquals(0, ExceptionUtils.indexOfThrowable(nested, NestableException.class)); + assertEquals(1, ExceptionUtils.indexOfThrowable(nested, ExceptionWithoutCause.class)); + + assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, null)); + assertEquals(0, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class)); + assertEquals(1, ExceptionUtils.indexOfThrowable(withCause, NestableException.class)); + assertEquals(2, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithoutCause.class)); + + assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Exception.class)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Throwable.class)); + } + + @Test + public void testIndexOf_ThrowableClassInt() { + assertEquals(-1, ExceptionUtils.indexOfThrowable(null, null, 0)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(null, NestableException.class, 0)); + + assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, null)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, ExceptionWithCause.class, 0)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, NestableException.class, 0)); + assertEquals(0, ExceptionUtils.indexOfThrowable(withoutCause, ExceptionWithoutCause.class, 0)); + + assertEquals(-1, ExceptionUtils.indexOfThrowable(nested, null, 0)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(nested, ExceptionWithCause.class, 0)); + assertEquals(0, ExceptionUtils.indexOfThrowable(nested, NestableException.class, 0)); + assertEquals(1, ExceptionUtils.indexOfThrowable(nested, ExceptionWithoutCause.class, 0)); + + assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, null)); + assertEquals(0, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 0)); + assertEquals(1, ExceptionUtils.indexOfThrowable(withCause, NestableException.class, 0)); + assertEquals(2, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithoutCause.class, 0)); + + assertEquals(0, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, -1)); + assertEquals(0, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 0)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 1)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 9)); + + assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Exception.class, 0)); + assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Throwable.class, 0)); + } + + @Test + public void testIndexOfType_ThrowableClass() { + assertEquals(-1, ExceptionUtils.indexOfType(null, null)); + assertEquals(-1, ExceptionUtils.indexOfType(null, NestableException.class)); + + assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, null)); + assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, ExceptionWithCause.class)); + assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, NestableException.class)); + assertEquals(0, ExceptionUtils.indexOfType(withoutCause, ExceptionWithoutCause.class)); + + assertEquals(-1, ExceptionUtils.indexOfType(nested, null)); + assertEquals(-1, ExceptionUtils.indexOfType(nested, ExceptionWithCause.class)); + assertEquals(0, ExceptionUtils.indexOfType(nested, NestableException.class)); + assertEquals(1, ExceptionUtils.indexOfType(nested, ExceptionWithoutCause.class)); + + assertEquals(-1, ExceptionUtils.indexOfType(withCause, null)); + assertEquals(0, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class)); + assertEquals(1, ExceptionUtils.indexOfType(withCause, NestableException.class)); + assertEquals(2, ExceptionUtils.indexOfType(withCause, ExceptionWithoutCause.class)); + + assertEquals(0, ExceptionUtils.indexOfType(withCause, Exception.class)); + assertEquals(0, ExceptionUtils.indexOfType(withCause, Throwable.class)); + } + + @Test + public void testIndexOfType_ThrowableClassInt() { + assertEquals(-1, ExceptionUtils.indexOfType(null, null, 0)); + assertEquals(-1, ExceptionUtils.indexOfType(null, NestableException.class, 0)); + + assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, null)); + assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, ExceptionWithCause.class, 0)); + assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, NestableException.class, 0)); + assertEquals(0, ExceptionUtils.indexOfType(withoutCause, ExceptionWithoutCause.class, 0)); + + assertEquals(-1, ExceptionUtils.indexOfType(nested, null, 0)); + assertEquals(-1, ExceptionUtils.indexOfType(nested, ExceptionWithCause.class, 0)); + assertEquals(0, ExceptionUtils.indexOfType(nested, NestableException.class, 0)); + assertEquals(1, ExceptionUtils.indexOfType(nested, ExceptionWithoutCause.class, 0)); + + assertEquals(-1, ExceptionUtils.indexOfType(withCause, null)); + assertEquals(0, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 0)); + assertEquals(1, ExceptionUtils.indexOfType(withCause, NestableException.class, 0)); + assertEquals(2, ExceptionUtils.indexOfType(withCause, ExceptionWithoutCause.class, 0)); + + assertEquals(0, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, -1)); + assertEquals(0, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 0)); + assertEquals(-1, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 1)); + assertEquals(-1, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 9)); + + assertEquals(0, ExceptionUtils.indexOfType(withCause, Exception.class, 0)); + assertEquals(0, ExceptionUtils.indexOfType(withCause, Throwable.class, 0)); + } + + @Test + public void testPrintRootCauseStackTrace_Throwable() { + ExceptionUtils.printRootCauseStackTrace(null); + // could pipe system.err to a known stream, but not much point as + // internally this method calls stream method anyway + } + + @Test + public void testPrintRootCauseStackTrace_ThrowableStream() { + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + ExceptionUtils.printRootCauseStackTrace(null, (PrintStream) null); + ExceptionUtils.printRootCauseStackTrace(null, new PrintStream(out)); + assertEquals(0, out.toString().length()); + + out = new ByteArrayOutputStream(1024); + assertThrows( + NullPointerException.class, + () -> ExceptionUtils.printRootCauseStackTrace(withCause, (PrintStream) null)); + + out = new ByteArrayOutputStream(1024); + final Throwable cause = createExceptionWithCause(); + ExceptionUtils.printRootCauseStackTrace(cause, new PrintStream(out)); + String stackTrace = out.toString(); + assertTrue(stackTrace.contains(ExceptionUtils.WRAPPED_MARKER)); + + out = new ByteArrayOutputStream(1024); + ExceptionUtils.printRootCauseStackTrace(withoutCause, new PrintStream(out)); + stackTrace = out.toString(); + assertFalse(stackTrace.contains(ExceptionUtils.WRAPPED_MARKER)); + } + + @Test + public void testPrintRootCauseStackTrace_ThrowableWriter() { + StringWriter writer = new StringWriter(1024); + ExceptionUtils.printRootCauseStackTrace(null, (PrintWriter) null); + ExceptionUtils.printRootCauseStackTrace(null, new PrintWriter(writer)); + assertEquals(0, writer.getBuffer().length()); + + writer = new StringWriter(1024); + assertThrows( + NullPointerException.class, + () -> ExceptionUtils.printRootCauseStackTrace(withCause, (PrintWriter) null)); + + writer = new StringWriter(1024); + final Throwable cause = createExceptionWithCause(); + ExceptionUtils.printRootCauseStackTrace(cause, new PrintWriter(writer)); + String stackTrace = writer.toString(); + assertTrue(stackTrace.contains(ExceptionUtils.WRAPPED_MARKER)); + + writer = new StringWriter(1024); + ExceptionUtils.printRootCauseStackTrace(withoutCause, new PrintWriter(writer)); + stackTrace = writer.toString(); + assertFalse(stackTrace.contains(ExceptionUtils.WRAPPED_MARKER)); + } + + @Test + public void testRemoveCommonFrames_ListList() { + assertThrows(NullPointerException.class, () -> ExceptionUtils.removeCommonFrames(null, null)); + } + + @Test + public void testStream_jdkNoCause() { + assertEquals(1, ExceptionUtils.stream(jdkNoCause).count()); + assertSame(jdkNoCause, ExceptionUtils.stream(jdkNoCause).toArray()[0]); + } + + @Test + public void testStream_nested() { + assertEquals(2, ExceptionUtils.stream(nested).count()); + final Object[] array = ExceptionUtils.stream(nested).toArray(); + assertSame(nested, array[0]); + assertSame(withoutCause, array[1]); + } + + @Test + public void testStream_null() { + assertEquals(0, ExceptionUtils.stream(null).count()); + } + + @Test + public void testStream_recursiveCause() { + final List<?> throwables = ExceptionUtils.stream(cyclicCause).collect(Collectors.toList()); + assertEquals(3, throwables.size()); + assertSame(cyclicCause, throwables.get(0)); + assertSame(cyclicCause.getCause(), throwables.get(1)); + assertSame(cyclicCause.getCause().getCause(), throwables.get(2)); + } + + @Test + public void testStream_withCause() { + final List<?> throwables = ExceptionUtils.stream(withCause).collect(Collectors.toList()); + assertEquals(3, throwables.size()); + assertSame(withCause, throwables.get(0)); + assertSame(nested, throwables.get(1)); + assertSame(withoutCause, throwables.get(2)); + } + + @Test + public void testStream_withoutCause() { + final List<?> throwables = ExceptionUtils.stream(withoutCause).collect(Collectors.toList()); + assertEquals(1, throwables.size()); + assertSame(withoutCause, throwables.get(0)); + } + + @Test + public void testThrow() { + final Exception expected = new InterruptedException(); + final Exception actual = assertThrows(Exception.class, () -> ExceptionUtils.rethrow(expected)); + assertSame(expected, actual); + } + + @Test + public void testThrowableOf_ThrowableClass() { + assertNull(ExceptionUtils.throwableOfThrowable(null, null)); + assertNull(ExceptionUtils.throwableOfThrowable(null, NestableException.class)); + + assertNull(ExceptionUtils.throwableOfThrowable(withoutCause, null)); + assertNull(ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithCause.class)); + assertNull(ExceptionUtils.throwableOfThrowable(withoutCause, NestableException.class)); + assertEquals(withoutCause, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithoutCause.class)); + + assertNull(ExceptionUtils.throwableOfThrowable(nested, null)); + assertNull(ExceptionUtils.throwableOfThrowable(nested, ExceptionWithCause.class)); + assertEquals(nested, ExceptionUtils.throwableOfThrowable(nested, NestableException.class)); + assertEquals(nested.getCause(), ExceptionUtils.throwableOfThrowable(nested, ExceptionWithoutCause.class)); + + assertNull(ExceptionUtils.throwableOfThrowable(withCause, null)); + assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class)); + assertEquals(withCause.getCause(), ExceptionUtils.throwableOfThrowable(withCause, NestableException.class)); + assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithoutCause.class)); + + assertNull(ExceptionUtils.throwableOfThrowable(withCause, Exception.class)); + assertNull(ExceptionUtils.throwableOfThrowable(withCause, Throwable.class)); + } + + @Test + public void testThrowableOf_ThrowableClassInt() { + assertNull(ExceptionUtils.throwableOfThrowable(null, null, 0)); + assertNull(ExceptionUtils.throwableOfThrowable(null, NestableException.class, 0)); + + assertNull(ExceptionUtils.throwableOfThrowable(withoutCause, null)); + assertNull(ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithCause.class, 0)); + assertNull(ExceptionUtils.throwableOfThrowable(withoutCause, NestableException.class, 0)); + assertEquals(withoutCause, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithoutCause.class, 0)); + + assertNull(ExceptionUtils.throwableOfThrowable(nested, null, 0)); + assertNull(ExceptionUtils.throwableOfThrowable(nested, ExceptionWithCause.class, 0)); + assertEquals(nested, ExceptionUtils.throwableOfThrowable(nested, NestableException.class, 0)); + assertEquals(nested.getCause(), ExceptionUtils.throwableOfThrowable(nested, ExceptionWithoutCause.class, 0)); + + assertNull(ExceptionUtils.throwableOfThrowable(withCause, null)); + assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 0)); + assertEquals(withCause.getCause(), ExceptionUtils.throwableOfThrowable(withCause, NestableException.class, 0)); + assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithoutCause.class, 0)); + + assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, -1)); + assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 0)); + assertNull(ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 1)); + assertNull(ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 9)); + + assertNull(ExceptionUtils.throwableOfThrowable(withCause, Exception.class, 0)); + assertNull(ExceptionUtils.throwableOfThrowable(withCause, Throwable.class, 0)); + } + + @Test + public void testThrowableOfType_ThrowableClass() { + assertNull(ExceptionUtils.throwableOfType(null, null)); + assertNull(ExceptionUtils.throwableOfType(null, NestableException.class)); + + assertNull(ExceptionUtils.throwableOfType(withoutCause, null)); + assertNull(ExceptionUtils.throwableOfType(withoutCause, ExceptionWithCause.class)); + assertNull(ExceptionUtils.throwableOfType(withoutCause, NestableException.class)); + assertEquals(withoutCause, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithoutCause.class)); + + assertNull(ExceptionUtils.throwableOfType(nested, null)); + assertNull(ExceptionUtils.throwableOfType(nested, ExceptionWithCause.class)); + assertEquals(nested, ExceptionUtils.throwableOfType(nested, NestableException.class)); + assertEquals(nested.getCause(), ExceptionUtils.throwableOfType(nested, ExceptionWithoutCause.class)); + + assertNull(ExceptionUtils.throwableOfType(withCause, null)); + assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class)); + assertEquals(withCause.getCause(), ExceptionUtils.throwableOfType(withCause, NestableException.class)); + assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfType(withCause, ExceptionWithoutCause.class)); + + assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Exception.class)); + assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Throwable.class)); + } + + @Test + public void testThrowableOfType_ThrowableClassInt() { + assertNull(ExceptionUtils.throwableOfType(null, null, 0)); + assertNull(ExceptionUtils.throwableOfType(null, NestableException.class, 0)); + + assertNull(ExceptionUtils.throwableOfType(withoutCause, null)); + assertNull(ExceptionUtils.throwableOfType(withoutCause, ExceptionWithCause.class, 0)); + assertNull(ExceptionUtils.throwableOfType(withoutCause, NestableException.class, 0)); + assertEquals(withoutCause, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithoutCause.class, 0)); + + assertNull(ExceptionUtils.throwableOfType(nested, null, 0)); + assertNull(ExceptionUtils.throwableOfType(nested, ExceptionWithCause.class, 0)); + assertEquals(nested, ExceptionUtils.throwableOfType(nested, NestableException.class, 0)); + assertEquals(nested.getCause(), ExceptionUtils.throwableOfType(nested, ExceptionWithoutCause.class, 0)); + + assertNull(ExceptionUtils.throwableOfType(withCause, null)); + assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 0)); + assertEquals(withCause.getCause(), ExceptionUtils.throwableOfType(withCause, NestableException.class, 0)); + assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfType(withCause, ExceptionWithoutCause.class, 0)); + + assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, -1)); + assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 0)); + assertNull(ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 1)); + assertNull(ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 9)); + + assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Exception.class, 0)); + assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Throwable.class, 0)); + } + + @Test + public void testWrapAndUnwrapCheckedException() { + final Throwable t = assertThrows(Throwable.class, () -> ExceptionUtils.wrapAndThrow(new IOException())); + assertTrue(ExceptionUtils.hasCause(t, IOException.class)); + } + + @Test + public void testWrapAndUnwrapError() { + final Throwable t = assertThrows(Throwable.class, () -> ExceptionUtils.wrapAndThrow(new OutOfMemoryError())); + assertTrue(ExceptionUtils.hasCause(t, Error.class)); + } + + @Test + public void testWrapAndUnwrapRuntimeException() { + final Throwable t = assertThrows(Throwable.class, () -> ExceptionUtils.wrapAndThrow(new IllegalArgumentException())); + assertTrue(ExceptionUtils.hasCause(t, RuntimeException.class)); + } + + @Test + public void testWrapAndUnwrapThrowable() { + final Throwable t = assertThrows(Throwable.class, () -> ExceptionUtils.wrapAndThrow(new TestThrowable())); + assertTrue(ExceptionUtils.hasCause(t, TestThrowable.class)); + } +} |