/*
* 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 org.junit.After;
import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
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.List;
/**
* Tests {@link org.apache.commons.lang3.exception.ExceptionUtils}.
*
* <h3>Notes</h3>
* <p>
* Make sure this exception code does not depend on Java 1.4 nested exceptions. SVN revision 38990 does not compile with
* Java 1.3.1.
* </p>
* <ul>
* <li>Compiled with Sun Java 1.3.1_15</li>
* <li>Tested with Sun Java 1.3.1_15</li>
* <li>Tested with Sun Java 1.4.2_12</li>
* <li>Tested with Sun Java 1.5.0_08</li>
* <li>All of the above on Windows XP SP2 + patches.</li>
* </ul>
* <p>
* Gary Gregory; August 16, 2006.
* </p>
*
* @since 1.0
*/
public class ExceptionUtilsTest {
private NestableException nested;
private Throwable withCause;
private Throwable withoutCause;
private Throwable jdkNoCause;
private ExceptionWithCause cyclicCause;
@Before
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);
}
@After
public void tearDown() throws Exception {
withoutCause = null;
nested = null;
withCause = null;
jdkNoCause = null;
cyclicCause = null;
}
//-----------------------------------------------------------------------
private Throwable createExceptionWithoutCause() {
try {
throw new ExceptionWithoutCause();
} catch (final Throwable t) {
return t;
}
}
private Throwable createExceptionWithCause() {
try {
try {
throw new ExceptionWithCause(createExceptionWithoutCause());
} catch (final Throwable t) {
throw new ExceptionWithCause(t);
}
} catch (final Throwable t) {
return t;
}
}
//-----------------------------------------------------------------------
@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()));
}
//-----------------------------------------------------------------------
@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(((ExceptionWithCause) cyclicCause.getCause()).getCause(), ExceptionUtils.getCause(cyclicCause.getCause()));
assertSame(cyclicCause.getCause(), ExceptionUtils.getCause(((ExceptionWithCause) cyclicCause.getCause()).getCause()));
}
@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(null, ExceptionUtils.getRootCause(withoutCause));
assertSame(withoutCause, ExceptionUtils.getRootCause(nested));
assertSame(withoutCause, ExceptionUtils.getRootCause(withCause));
assertSame(null, ExceptionUtils.getRootCause(jdkNoCause));
assertSame(((ExceptionWithCause) cyclicCause.getCause()).getCause(), ExceptionUtils.getRootCause(cyclicCause));
}
//-----------------------------------------------------------------------
@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 testGetThrowables_Throwable_null() {
assertEquals(0, ExceptionUtils.getThrowables(null).length);
}
@Test
public void testGetThrowables_Throwable_withoutCause() {
final Throwable[] throwables = ExceptionUtils.getThrowables(withoutCause);
assertEquals(1, throwables.length);
assertSame(withoutCause, 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_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_jdkNoCause() {
final Throwable[] throwables = ExceptionUtils.getThrowables(jdkNoCause);
assertEquals(1, throwables.length);
assertSame(jdkNoCause, throwables[0]);
}
@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(((ExceptionWithCause) cyclicCause.getCause()).getCause(), throwables[2]);
}
//-----------------------------------------------------------------------
@Test
public void testGetThrowableList_Throwable_null() {
final List<?> throwables = ExceptionUtils.getThrowableList(null);
assertEquals(0, throwables.size());
}
@Test
public void testGetThrowableList_Throwable_withoutCause() {
final List<?> throwables = ExceptionUtils.getThrowableList(withoutCause);
assertEquals(1, throwables.size());
assertSame(withoutCause, 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_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_jdkNoCause() {
final List<?> throwables = ExceptionUtils.getThrowableList(jdkNoCause);
assertEquals(1, throwables.size());
assertSame(jdkNoCause, throwables.get(0));
}
@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(((ExceptionWithCause) cyclicCause.getCause()).getCause(), throwables.get(2));
}
//-----------------------------------------------------------------------
@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));
}
@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));
}
//-----------------------------------------------------------------------
@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));
}
@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));
}
//-----------------------------------------------------------------------
@Test
public void testPrintRootCauseStackTrace_Throwable() throws Exception {
ExceptionUtils.printRootCauseStackTrace(null);
// could pipe system.err to a known stream, but not much point as
// internally this method calls stram method anyway
}
@Test
public void testPrintRootCauseStackTrace_ThrowableStream() throws Exception {
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);
try {
ExceptionUtils.printRootCauseStackTrace(withCause, (PrintStream) null);
fail();
} catch (final IllegalArgumentException ex) {
}
out = new ByteArrayOutputStream(1024);
final Throwable cause = createExceptionWithCause();
ExceptionUtils.printRootCauseStackTrace(cause, new PrintStream(out));
String stackTrace = out.toString();
assertTrue(stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) != -1);
out = new ByteArrayOutputStream(1024);
ExceptionUtils.printRootCauseStackTrace(withoutCause, new PrintStream(out));
stackTrace = out.toString();
assertTrue(stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) == -1);
}
@Test
public void testPrintRootCauseStackTrace_ThrowableWriter() throws Exception {
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);
try {
ExceptionUtils.printRootCauseStackTrace(withCause, (PrintWriter) null);
fail();
} catch (final IllegalArgumentException ex) {
}
writer = new StringWriter(1024);
final Throwable cause = createExceptionWithCause();
ExceptionUtils.printRootCauseStackTrace(cause, new PrintWriter(writer));
String stackTrace = writer.toString();
assertTrue(stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) != -1);
writer = new StringWriter(1024);
ExceptionUtils.printRootCauseStackTrace(withoutCause, new PrintWriter(writer));
stackTrace = writer.toString();
assertTrue(stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) == -1);
}
//-----------------------------------------------------------------------
@Test
public void testGetRootCauseStackTrace_Throwable() throws Exception {
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(expected=IllegalArgumentException.class)
public void testRemoveCommonFrames_ListList() throws Exception {
ExceptionUtils.removeCommonFrames(null, 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));
}
//-----------------------------------------------------------------------
/**
* 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</code>.
*/
private static class ExceptionWithCause extends Exception {
private static final long serialVersionUID = 1L;
private Throwable cause;
public ExceptionWithCause(final String str, final Throwable cause) {
super(str);
setCause(cause);
}
public ExceptionWithCause(final Throwable cause) {
super();
setCause(cause);
}
@Override
public 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</code>.
*/
private static class ExceptionWithoutCause extends Exception {
private static final long serialVersionUID = 1L;
@SuppressWarnings("unused")
public void getTargetException() {
}
}
// 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")
public NestableException() { super(); }
public NestableException(final Throwable t) { super(t); }
}
}