diff options
Diffstat (limited to 'src/test/java/org/apache/commons/lang3/exception')
13 files changed, 1654 insertions, 0 deletions
diff --git a/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionContextTest.java b/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionContextTest.java new file mode 100644 index 000000000..3fbe50da5 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionContextTest.java @@ -0,0 +1,190 @@ +/* + * 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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import org.apache.commons.lang3.AbstractLangTest; +import org.apache.commons.lang3.SerializationUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + + +/** + * Abstract test of an ExceptionContext implementation. + */ +public abstract class AbstractExceptionContextTest<T extends ExceptionContext & Serializable> extends AbstractLangTest { + + protected static final String TEST_MESSAGE_2 = "This is monotonous"; + protected static final String TEST_MESSAGE = "Test Message"; + protected T exceptionContext; + + protected static class ObjectWithFaultyToString { + @Override + public String toString() { + throw new RuntimeException("Crap"); + } + } + + + @BeforeEach + public void setUp() throws Exception { + exceptionContext + .addContextValue("test1", null) + .addContextValue("test2", "some value") + .addContextValue("test Date", new Date()) + .addContextValue("test Nbr", Integer.valueOf(5)) + .addContextValue("test Poorly written obj", new ObjectWithFaultyToString()); + } + + @Test + public void testAddContextValue() { + final String message = exceptionContext.getFormattedExceptionMessage(TEST_MESSAGE); + assertTrue(message.contains(TEST_MESSAGE)); + assertTrue(message.contains("test1")); + assertTrue(message.contains("test2")); + assertTrue(message.contains("test Date")); + assertTrue(message.contains("test Nbr")); + assertTrue(message.contains("some value")); + assertTrue(message.contains("5")); + + assertNull(exceptionContext.getFirstContextValue("test1")); + assertEquals("some value", exceptionContext.getFirstContextValue("test2")); + + assertEquals(5, exceptionContext.getContextLabels().size()); + assertTrue(exceptionContext.getContextLabels().contains("test1")); + assertTrue(exceptionContext.getContextLabels().contains("test2")); + assertTrue(exceptionContext.getContextLabels().contains("test Date")); + assertTrue(exceptionContext.getContextLabels().contains("test Nbr")); + + exceptionContext.addContextValue("test2", "different value"); + assertEquals(5, exceptionContext.getContextLabels().size()); + assertTrue(exceptionContext.getContextLabels().contains("test2")); + + final String contextMessage = exceptionContext.getFormattedExceptionMessage(null); + assertFalse(contextMessage.contains(TEST_MESSAGE)); + } + + @Test + public void testSetContextValue() { + exceptionContext.addContextValue("test2", "different value"); + exceptionContext.setContextValue("test3", "3"); + + final String message = exceptionContext.getFormattedExceptionMessage(TEST_MESSAGE); + assertTrue(message.contains(TEST_MESSAGE)); + assertTrue(message.contains("test Poorly written obj")); + assertTrue(message.contains("Crap")); + + assertNull(exceptionContext.getFirstContextValue("crap")); + assertTrue(exceptionContext.getFirstContextValue("test Poorly written obj") instanceof ObjectWithFaultyToString); + + assertEquals(7, exceptionContext.getContextEntries().size()); + assertEquals(6, exceptionContext.getContextLabels().size()); + + assertTrue(exceptionContext.getContextLabels().contains("test Poorly written obj")); + assertFalse(exceptionContext.getContextLabels().contains("crap")); + + exceptionContext.setContextValue("test Poorly written obj", "replacement"); + + assertEquals(7, exceptionContext.getContextEntries().size()); + assertEquals(6, exceptionContext.getContextLabels().size()); + + exceptionContext.setContextValue("test2", "another"); + + assertEquals(6, exceptionContext.getContextEntries().size()); + assertEquals(6, exceptionContext.getContextLabels().size()); + + final String contextMessage = exceptionContext.getFormattedExceptionMessage(null); + assertFalse(contextMessage.contains(TEST_MESSAGE)); + } + + @Test + public void testGetFirstContextValue() { + exceptionContext.addContextValue("test2", "different value"); + + assertNull(exceptionContext.getFirstContextValue("test1")); + assertEquals("some value", exceptionContext.getFirstContextValue("test2")); + assertNull(exceptionContext.getFirstContextValue("crap")); + + exceptionContext.setContextValue("test2", "another"); + + assertEquals("another", exceptionContext.getFirstContextValue("test2")); + } + + @Test + public void testGetContextValues() { + exceptionContext.addContextValue("test2", "different value"); + + assertEquals(exceptionContext.getContextValues("test1"), Collections.singletonList(null)); + assertEquals(exceptionContext.getContextValues("test2"), Arrays.asList("some value", "different value")); + + exceptionContext.setContextValue("test2", "another"); + + assertEquals("another", exceptionContext.getFirstContextValue("test2")); + } + + @Test + public void testGetContextLabels() { + assertEquals(5, exceptionContext.getContextEntries().size()); + + exceptionContext.addContextValue("test2", "different value"); + + final Set<String> labels = exceptionContext.getContextLabels(); + assertEquals(6, exceptionContext.getContextEntries().size()); + assertEquals(5, labels.size()); + assertTrue(labels.contains("test1")); + assertTrue(labels.contains("test2")); + assertTrue(labels.contains("test Date")); + assertTrue(labels.contains("test Nbr")); + } + + @Test + public void testGetContextEntries() { + assertEquals(5, exceptionContext.getContextEntries().size()); + + exceptionContext.addContextValue("test2", "different value"); + + final List<Pair<String, Object>> entries = exceptionContext.getContextEntries(); + assertEquals(6, entries.size()); + assertEquals("test1", entries.get(0).getKey()); + assertEquals("test2", entries.get(1).getKey()); + assertEquals("test Date", entries.get(2).getKey()); + assertEquals("test Nbr", entries.get(3).getKey()); + assertEquals("test Poorly written obj", entries.get(4).getKey()); + assertEquals("test2", entries.get(5).getKey()); + } + + @Test + public void testJavaSerialization() { + exceptionContext.setContextValue("test Poorly written obj", "serializable replacement"); + + final T clone = SerializationUtils.deserialize(SerializationUtils.serialize(exceptionContext)); + + assertEquals(exceptionContext.getFormattedExceptionMessage(null), clone.getFormattedExceptionMessage(null)); + } +} diff --git a/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionTest.java b/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionTest.java new file mode 100644 index 000000000..3be21f2fc --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionTest.java @@ -0,0 +1,35 @@ +/* + * 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.apache.commons.lang3.AbstractLangTest; + +/** + * Base class for testing {@link Exception} descendants + */ +public abstract class AbstractExceptionTest extends AbstractLangTest { + + protected static final String CAUSE_MESSAGE = "Cause message"; + protected static final String EXCEPTION_MESSAGE = "Exception message"; + + protected static final String WRONG_EXCEPTION_MESSAGE = "Wrong exception message"; + protected static final String WRONG_CAUSE_MESSAGE = "Wrong cause message"; + + protected Exception generateCause() { + return new Exception(CAUSE_MESSAGE); + } +} diff --git a/src/test/java/org/apache/commons/lang3/exception/CloneFailedExceptionTest.java b/src/test/java/org/apache/commons/lang3/exception/CloneFailedExceptionTest.java new file mode 100644 index 000000000..5123fe174 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/CloneFailedExceptionTest.java @@ -0,0 +1,83 @@ +/* + * 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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +/** + * JUnit tests for {@link CloneFailedExceptionTest}. + */ +public class CloneFailedExceptionTest extends AbstractExceptionTest { + + @Test + public void testThrowingInformativeException() { + assertThrows(CloneFailedException.class, () -> { + throw new CloneFailedException(EXCEPTION_MESSAGE, generateCause()); + }); + } + + @Test + public void testThrowingExceptionWithMessage() { + assertThrows(CloneFailedException.class, () -> { + throw new CloneFailedException(EXCEPTION_MESSAGE); + }); + } + + @Test + public void testThrowingExceptionWithCause() { + assertThrows(CloneFailedException.class, () -> { + throw new CloneFailedException(generateCause()); + }); + } + + @Test + public void testWithCauseAndMessage() { + final Exception exception = new CloneFailedException(EXCEPTION_MESSAGE, generateCause()); + assertNotNull(exception); + assertEquals(EXCEPTION_MESSAGE, exception.getMessage(), WRONG_EXCEPTION_MESSAGE); + + final Throwable cause = exception.getCause(); + assertNotNull(cause); + assertEquals(CAUSE_MESSAGE, cause.getMessage(), WRONG_CAUSE_MESSAGE); + } + + @Test + public void testWithoutCause() { + final Exception exception = new CloneFailedException(EXCEPTION_MESSAGE); + assertNotNull(exception); + assertEquals(EXCEPTION_MESSAGE, exception.getMessage(), WRONG_EXCEPTION_MESSAGE); + + final Throwable cause = exception.getCause(); + assertNull(cause); + } + + @Test + public void testWithoutMessage() { + final Exception exception = new CloneFailedException(generateCause()); + assertNotNull(exception); + assertNotNull(exception.getMessage()); + + final Throwable cause = exception.getCause(); + assertNotNull(cause); + assertEquals(CAUSE_MESSAGE, cause.getMessage(), WRONG_CAUSE_MESSAGE); + } +} diff --git a/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java b/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java new file mode 100644 index 000000000..131ec937c --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java @@ -0,0 +1,118 @@ +/* + * 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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Date; + +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * JUnit tests for ContextedException. + */ +public class ContextedExceptionTest extends AbstractExceptionContextTest<ContextedException> { + + @BeforeEach + @Override + public void setUp() throws Exception { + exceptionContext = new ContextedException(new Exception(TEST_MESSAGE)); + super.setUp(); + } + + @Test + public void testContextedException() { + exceptionContext = new ContextedException(); + final String message = exceptionContext.getMessage(); + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains("ContextedException")); + assertTrue(StringUtils.isEmpty(message)); + } + + @Test + public void testNullException() { + assertEquals("", ExceptionUtils.getStackTrace(null), "Empty response."); + } + + @Test + public void testContextedExceptionString() { + exceptionContext = new ContextedException(TEST_MESSAGE); + assertEquals(TEST_MESSAGE, exceptionContext.getMessage()); + + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains(TEST_MESSAGE)); + } + + @Test + public void testContextedExceptionThrowable() { + exceptionContext = new ContextedException(new Exception(TEST_MESSAGE)); + final String message = exceptionContext.getMessage(); + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains("ContextedException")); + assertTrue(trace.contains(TEST_MESSAGE)); + assertTrue(message.contains(TEST_MESSAGE)); + } + + @Test + public void testContextedExceptionStringThrowable() { + exceptionContext = new ContextedException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE)); + final String message = exceptionContext.getMessage(); + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains("ContextedException")); + assertTrue(trace.contains(TEST_MESSAGE)); + assertTrue(trace.contains(TEST_MESSAGE_2)); + assertTrue(message.contains(TEST_MESSAGE_2)); + } + + @Test + public void testContextedExceptionStringThrowableContext() { + exceptionContext = new ContextedException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), new DefaultExceptionContext()); + final String message = exceptionContext.getMessage(); + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains("ContextedException")); + assertTrue(trace.contains(TEST_MESSAGE)); + assertTrue(trace.contains(TEST_MESSAGE_2)); + assertTrue(message.contains(TEST_MESSAGE_2)); + } + + @Test + public void testNullExceptionPassing() { + exceptionContext = new ContextedException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), null) + .addContextValue("test1", null) + .addContextValue("test2", "some value") + .addContextValue("test Date", new Date()) + .addContextValue("test Nbr", Integer.valueOf(5)) + .addContextValue("test Poorly written obj", new ObjectWithFaultyToString()); + + final String message = exceptionContext.getMessage(); + assertNotNull(message); + } + + @Test + public void testRawMessage() { + assertEquals(Exception.class.getName() + ": " + TEST_MESSAGE, exceptionContext.getRawMessage()); + exceptionContext = new ContextedException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), new DefaultExceptionContext()); + assertEquals(TEST_MESSAGE_2, exceptionContext.getRawMessage()); + exceptionContext = new ContextedException(null, new Exception(TEST_MESSAGE), new DefaultExceptionContext()); + assertNull(exceptionContext.getRawMessage()); + } +} diff --git a/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java b/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java new file mode 100644 index 000000000..76f718c36 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java @@ -0,0 +1,117 @@ +/* + * 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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Date; + +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * JUnit tests for ContextedRuntimeException. + */ +public class ContextedRuntimeExceptionTest extends AbstractExceptionContextTest<ContextedRuntimeException> { + + @BeforeEach + @Override + public void setUp() throws Exception { + exceptionContext = new ContextedRuntimeException(new Exception(TEST_MESSAGE)); + super.setUp(); + } + + @Test + public void testContextedException() { + exceptionContext = new ContextedRuntimeException(); + final String message = exceptionContext.getMessage(); + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains("ContextedException")); + assertTrue(StringUtils.isEmpty(message)); + } + + @Test + public void testContextedExceptionString() { + exceptionContext = new ContextedRuntimeException(TEST_MESSAGE); + assertEquals(TEST_MESSAGE, exceptionContext.getMessage()); + + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains(TEST_MESSAGE)); + } + + @Test + public void testContextedExceptionThrowable() { + exceptionContext = new ContextedRuntimeException(new Exception(TEST_MESSAGE)); + final String message = exceptionContext.getMessage(); + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains("ContextedException")); + assertTrue(trace.contains(TEST_MESSAGE)); + assertTrue(message.contains(TEST_MESSAGE)); + } + + @Test + public void testContextedExceptionStringThrowable() { + exceptionContext = new ContextedRuntimeException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE)); + final String message = exceptionContext.getMessage(); + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains("ContextedException")); + assertTrue(trace.contains(TEST_MESSAGE)); + assertTrue(trace.contains(TEST_MESSAGE_2)); + assertTrue(message.contains(TEST_MESSAGE_2)); + } + + @Test + public void testContextedExceptionStringThrowableContext() { + // Use an anonymous subclass to make sure users can provide custom implementations + exceptionContext = new ContextedRuntimeException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), + new DefaultExceptionContext() { + private static final long serialVersionUID = 1L; + }); + final String message = exceptionContext.getMessage(); + final String trace = ExceptionUtils.getStackTrace(exceptionContext); + assertTrue(trace.contains("ContextedException")); + assertTrue(trace.contains(TEST_MESSAGE)); + assertTrue(trace.contains(TEST_MESSAGE_2)); + assertTrue(message.contains(TEST_MESSAGE_2)); + } + + @Test + public void testNullExceptionPassing() { + exceptionContext = new ContextedRuntimeException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), null) + .addContextValue("test1", null) + .addContextValue("test2", "some value") + .addContextValue("test Date", new Date()) + .addContextValue("test Nbr", Integer.valueOf(5)) + .addContextValue("test Poorly written obj", new ObjectWithFaultyToString()); + + final String message = exceptionContext.getMessage(); + assertNotNull(message); + } + + @Test + public void testRawMessage() { + assertEquals(Exception.class.getName() + ": " + TEST_MESSAGE, exceptionContext.getRawMessage()); + exceptionContext = new ContextedRuntimeException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), new DefaultExceptionContext()); + assertEquals(TEST_MESSAGE_2, exceptionContext.getRawMessage()); + exceptionContext = new ContextedRuntimeException(null, new Exception(TEST_MESSAGE), new DefaultExceptionContext()); + assertNull(exceptionContext.getRawMessage()); + } +} diff --git a/src/test/java/org/apache/commons/lang3/exception/CustomCheckedException.java b/src/test/java/org/apache/commons/lang3/exception/CustomCheckedException.java new file mode 100644 index 000000000..fe8b1e67e --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/CustomCheckedException.java @@ -0,0 +1,39 @@ +/* + * 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; + +public class CustomCheckedException extends Exception { + + private static final long serialVersionUID = 1L; + + public CustomCheckedException() { + } + + public CustomCheckedException(final String message) { + super(message); + } + + public CustomCheckedException(final String message, final Throwable cause) { + super(message, cause); + } + + public CustomCheckedException(final Throwable cause) { + super(cause); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/exception/CustomUncheckedException.java b/src/test/java/org/apache/commons/lang3/exception/CustomUncheckedException.java new file mode 100644 index 000000000..f6029f907 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/CustomUncheckedException.java @@ -0,0 +1,39 @@ +/* + * 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; + +public class CustomUncheckedException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public CustomUncheckedException() { + } + + public CustomUncheckedException(final String message) { + super(message); + } + + public CustomUncheckedException(final String message, final Throwable cause) { + super(message, cause); + } + + public CustomUncheckedException(final Throwable cause) { + super(cause); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java b/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java new file mode 100644 index 000000000..00aa50ba8 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java @@ -0,0 +1,40 @@ +/* + * 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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * JUnit tests for DefaultExceptionContext. + */ +public class DefaultExceptionContextTest extends AbstractExceptionContextTest<DefaultExceptionContext> { + + @Override + @BeforeEach + public void setUp() throws Exception { + exceptionContext = new DefaultExceptionContext(); + super.setUp(); + } + + @Test + public void testFormattedExceptionMessageNull() { + exceptionContext = new DefaultExceptionContext(); + exceptionContext.getFormattedExceptionMessage(null); + } + +} 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)); + } +} diff --git a/src/test/java/org/apache/commons/lang3/exception/UncheckedExceptionTest.java b/src/test/java/org/apache/commons/lang3/exception/UncheckedExceptionTest.java new file mode 100644 index 000000000..72c38cdd0 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/UncheckedExceptionTest.java @@ -0,0 +1,35 @@ +/* + * 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.assertSame; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link UncheckedException}. + */ +public class UncheckedExceptionTest extends AbstractLangTest { + + @Test + public void testConstructWithCause() { + final Exception e = new Exception(); + assertSame(e, new UncheckedException(e).getCause()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/exception/UncheckedIllegalAccessExceptionTest.java b/src/test/java/org/apache/commons/lang3/exception/UncheckedIllegalAccessExceptionTest.java new file mode 100644 index 000000000..bef674a97 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/UncheckedIllegalAccessExceptionTest.java @@ -0,0 +1,35 @@ +/* + * 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.assertSame; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link UncheckedIllegalAccessException}. + */ +public class UncheckedIllegalAccessExceptionTest extends AbstractLangTest { + + @Test + public void testConstructWithCause() { + final Exception e = new Exception(); + assertSame(e, new UncheckedIllegalAccessException(e).getCause()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/exception/UncheckedInterruptedExceptionTest.java b/src/test/java/org/apache/commons/lang3/exception/UncheckedInterruptedExceptionTest.java new file mode 100644 index 000000000..422996268 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/UncheckedInterruptedExceptionTest.java @@ -0,0 +1,35 @@ +/* + * 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.assertSame; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link UncheckedInterruptedException}. + */ +public class UncheckedInterruptedExceptionTest extends AbstractLangTest { + + @Test + public void testConstructWithCause() { + final Exception e = new Exception(); + assertSame(e, new UncheckedInterruptedException(e).getCause()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/exception/UncheckedReflectiveOperationExceptionTest.java b/src/test/java/org/apache/commons/lang3/exception/UncheckedReflectiveOperationExceptionTest.java new file mode 100644 index 000000000..a9012f222 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/exception/UncheckedReflectiveOperationExceptionTest.java @@ -0,0 +1,35 @@ +/* + * 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.assertSame; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link UncheckedReflectiveOperationException}. + */ +public class UncheckedReflectiveOperationExceptionTest extends AbstractLangTest { + + @Test + public void testConstructWithCause() { + final Exception e = new Exception(); + assertSame(e, new UncheckedReflectiveOperationException(e).getCause()); + } + +} |