/* * 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); } } }