1 /*
2 * Copyright 2002-2005 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.apache.commons.lang.exception;
17
18 import java.io.ByteArrayOutputStream;
19 import java.io.PrintStream;
20 import java.io.PrintWriter;
21 import java.io.StringWriter;
22 import java.lang.reflect.InvocationTargetException;
23 import java.sql.SQLException;
24
25 import junit.framework.Assert;
26 import junit.framework.Test;
27 import junit.framework.TestSuite;
28 import org.apache.commons.lang.SystemUtils;
29
30 /**
31 * Tests {@link org.apache.commons.lang.exception.ExceptionUtils}.
32 *
33 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
34 * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
35 * @author Stephen Colebourne
36 * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
37 * @since 1.0
38 */
39 public class ExceptionUtilsTestCase extends junit.framework.TestCase {
40
41 private NestableException nested;
42 private Throwable withCause;
43 private Throwable withoutCause;
44
45 public ExceptionUtilsTestCase(String name) {
46 super(name);
47 }
48
49 public static Test suite() {
50 return new TestSuite(ExceptionUtilsTestCase.class);
51 }
52
53 public void setUp() {
54 withoutCause = createExceptionWithoutCause();
55 nested = new NestableException(withoutCause);
56 withCause = new ExceptionWithCause(nested);
57 }
58
59 //-----------------------------------------------------------------------
60 private Throwable createExceptionWithoutCause() {
61 try {
62 throw new ExceptionWithoutCause();
63 } catch (Throwable t) {
64 return t;
65 }
66 }
67
68 private Throwable createExceptionWithCause() {
69 try {
70 try {
71 throw new ExceptionWithCause(createExceptionWithoutCause());
72 } catch (Throwable t) {
73 throw new ExceptionWithCause(t);
74 }
75 } catch (Throwable t) {
76 return t;
77 }
78 }
79
80 //-----------------------------------------------------------------------
81
82 public void testCauseMethodNameOps() {
83 this.testCauseMethodNameOps(null);
84 this.testCauseMethodNameOps("");
85 this.testCauseMethodNameOps(" ");
86 this.testCauseMethodNameOps("\t\r\n\t");
87 this.testCauseMethodNameOps("testMethodName");
88 }
89
90 void testCauseMethodNameOps(String name) {
91 String methodName = "testMethodName";
92 try {
93 Assert.assertFalse(ExceptionUtils.isCauseMethodName(methodName));
94 ExceptionUtils.addCauseMethodName(methodName);
95 ExceptionUtils.addCauseMethodName(methodName);
96 Assert.assertTrue(ExceptionUtils.isCauseMethodName(methodName));
97 } finally {
98 ExceptionUtils.removeCauseMethodName(methodName);
99 Assert.assertFalse(
100 "The method name " + methodName + " should not be in the array",
101 ExceptionUtils.isCauseMethodName(methodName));
102 }
103 }
104
105 public void testGetCause_Throwable() {
106 assertSame(null, ExceptionUtils.getCause(null));
107 assertSame(null, ExceptionUtils.getCause(withoutCause));
108 assertSame(withoutCause, ExceptionUtils.getCause(nested));
109 assertSame(nested, ExceptionUtils.getCause(withCause));
110 }
111
112 public void testGetCause_ThrowableArray() {
113 assertSame(null, ExceptionUtils.getCause(null, null));
114 assertSame(null, ExceptionUtils.getCause(null, new String[0]));
115
116 // match because known type
117 assertSame(withoutCause, ExceptionUtils.getCause(nested, null));
118 assertSame(withoutCause, ExceptionUtils.getCause(nested, new String[0]));
119 assertSame(withoutCause, ExceptionUtils.getCause(nested, new String[] {"getCause"}));
120
121 // not known type, so match on supplied method names
122 assertSame(nested, ExceptionUtils.getCause(withCause, null)); // default names
123 assertSame(null, ExceptionUtils.getCause(withCause, new String[0]));
124 assertSame(null, ExceptionUtils.getCause(withCause, new String[] {null}));
125 assertSame(nested, ExceptionUtils.getCause(withCause, new String[] {"getCause"}));
126
127 // not known type, so match on supplied method names
128 assertSame(null, ExceptionUtils.getCause(withoutCause, null));
129 assertSame(null, ExceptionUtils.getCause(withoutCause, new String[0]));
130 assertSame(null, ExceptionUtils.getCause(withoutCause, new String[] {null}));
131 assertSame(null, ExceptionUtils.getCause(withoutCause, new String[] {"getCause"}));
132 assertSame(null, ExceptionUtils.getCause(withoutCause, new String[] {"getTargetException"}));
133 }
134
135 public void testGetRootCause_Throwable() {
136 assertSame(null, ExceptionUtils.getRootCause(null));
137 assertSame(null, ExceptionUtils.getRootCause(withoutCause));
138 assertSame(withoutCause, ExceptionUtils.getRootCause(nested));
139 assertSame(withoutCause, ExceptionUtils.getRootCause(withCause));
140 }
141
142 //-----------------------------------------------------------------------
143 public void testIsThrowableNested() {
144 if (SystemUtils.isJavaVersionAtLeast(140)) {
145 assertEquals(true, ExceptionUtils.isThrowableNested());
146 } else {
147 assertEquals(false, ExceptionUtils.isThrowableNested());
148 }
149 }
150
151 public void testIsNestedThrowable_Throwable() {
152 assertEquals(true, ExceptionUtils.isNestedThrowable(new SQLException()));
153 assertEquals(true, ExceptionUtils.isNestedThrowable(new InvocationTargetException(new Exception())));
154 assertEquals(true, ExceptionUtils.isNestedThrowable(new NestableRuntimeException()));
155 assertEquals(true, ExceptionUtils.isNestedThrowable(withCause));
156 assertEquals(true, ExceptionUtils.isNestedThrowable(nested));
157 if (SystemUtils.isJavaVersionAtLeast(140)) {
158 assertEquals(true, ExceptionUtils.isNestedThrowable(withoutCause));
159 assertEquals(true, ExceptionUtils.isNestedThrowable(new Throwable()));
160 } else {
161 assertEquals(false, ExceptionUtils.isNestedThrowable(withoutCause));
162 assertEquals(false, ExceptionUtils.isNestedThrowable(new Throwable()));
163 }
164 }
165
166 //-----------------------------------------------------------------------
167 public void testGetThrowableCount_Throwable() {
168 assertEquals(0, ExceptionUtils.getThrowableCount(null));
169 assertEquals(1, ExceptionUtils.getThrowableCount(withoutCause));
170 assertEquals(2, ExceptionUtils.getThrowableCount(nested));
171 assertEquals(3, ExceptionUtils.getThrowableCount(withCause));
172 }
173
174 public void testGetThrowables_Throwable() {
175 assertEquals(0, ExceptionUtils.getThrowables(null).length);
176 assertEquals(1, ExceptionUtils.getThrowables(withoutCause).length);
177 assertSame(withoutCause, ExceptionUtils.getThrowables(withoutCause)[0]);
178
179 assertEquals(2, ExceptionUtils.getThrowables(nested).length);
180 assertSame(nested, ExceptionUtils.getThrowables(nested)[0]);
181 assertSame(withoutCause, ExceptionUtils.getThrowables(nested)[1]);
182
183 assertEquals(3, ExceptionUtils.getThrowables(withCause).length);
184 assertSame(withCause, ExceptionUtils.getThrowables(withCause)[0]);
185 assertSame(nested, ExceptionUtils.getThrowables(withCause)[1]);
186 assertSame(withoutCause, ExceptionUtils.getThrowables(withCause)[2]);
187 }
188
189 //-----------------------------------------------------------------------
190 public void testIndexOf_ThrowableClass() {
191 assertEquals(-1, ExceptionUtils.indexOfThrowable(null, null));
192 assertEquals(-1, ExceptionUtils.indexOfThrowable(null, NestableException.class));
193
194 assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, null));
195 assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, ExceptionWithCause.class));
196 assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, NestableException.class));
197 assertEquals(0, ExceptionUtils.indexOfThrowable(withoutCause, ExceptionWithoutCause.class));
198
199 assertEquals(-1, ExceptionUtils.indexOfThrowable(nested, null));
200 assertEquals(-1, ExceptionUtils.indexOfThrowable(nested, ExceptionWithCause.class));
201 assertEquals(0, ExceptionUtils.indexOfThrowable(nested, NestableException.class));
202 assertEquals(1, ExceptionUtils.indexOfThrowable(nested, ExceptionWithoutCause.class));
203
204 assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, null));
205 assertEquals(0, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class));
206 assertEquals(1, ExceptionUtils.indexOfThrowable(withCause, NestableException.class));
207 assertEquals(2, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithoutCause.class));
208
209 assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Exception.class));
210 }
211
212 public void testIndexOf_ThrowableClassInt() {
213 assertEquals(-1, ExceptionUtils.indexOfThrowable(null, null, 0));
214 assertEquals(-1, ExceptionUtils.indexOfThrowable(null, NestableException.class, 0));
215
216 assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, null));
217 assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, ExceptionWithCause.class, 0));
218 assertEquals(-1, ExceptionUtils.indexOfThrowable(withoutCause, NestableException.class, 0));
219 assertEquals(0, ExceptionUtils.indexOfThrowable(withoutCause, ExceptionWithoutCause.class, 0));
220
221 assertEquals(-1, ExceptionUtils.indexOfThrowable(nested, null, 0));
222 assertEquals(-1, ExceptionUtils.indexOfThrowable(nested, ExceptionWithCause.class, 0));
223 assertEquals(0, ExceptionUtils.indexOfThrowable(nested, NestableException.class, 0));
224 assertEquals(1, ExceptionUtils.indexOfThrowable(nested, ExceptionWithoutCause.class, 0));
225
226 assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, null));
227 assertEquals(0, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 0));
228 assertEquals(1, ExceptionUtils.indexOfThrowable(withCause, NestableException.class, 0));
229 assertEquals(2, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithoutCause.class, 0));
230
231 assertEquals(0, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, -1));
232 assertEquals(0, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 0));
233 assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 1));
234 assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 9));
235
236 assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Exception.class, 0));
237 }
238
239 //-----------------------------------------------------------------------
240 public void testIndexOfType_ThrowableClass() {
241 assertEquals(-1, ExceptionUtils.indexOfType(null, null));
242 assertEquals(-1, ExceptionUtils.indexOfType(null, NestableException.class));
243
244 assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, null));
245 assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, ExceptionWithCause.class));
246 assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, NestableException.class));
247 assertEquals(0, ExceptionUtils.indexOfType(withoutCause, ExceptionWithoutCause.class));
248
249 assertEquals(-1, ExceptionUtils.indexOfType(nested, null));
250 assertEquals(-1, ExceptionUtils.indexOfType(nested, ExceptionWithCause.class));
251 assertEquals(0, ExceptionUtils.indexOfType(nested, NestableException.class));
252 assertEquals(1, ExceptionUtils.indexOfType(nested, ExceptionWithoutCause.class));
253
254 assertEquals(-1, ExceptionUtils.indexOfType(withCause, null));
255 assertEquals(0, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class));
256 assertEquals(1, ExceptionUtils.indexOfType(withCause, NestableException.class));
257 assertEquals(2, ExceptionUtils.indexOfType(withCause, ExceptionWithoutCause.class));
258
259 assertEquals(0, ExceptionUtils.indexOfType(withCause, Exception.class));
260 }
261
262 public void testIndexOfType_ThrowableClassInt() {
263 assertEquals(-1, ExceptionUtils.indexOfType(null, null, 0));
264 assertEquals(-1, ExceptionUtils.indexOfType(null, NestableException.class, 0));
265
266 assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, null));
267 assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, ExceptionWithCause.class, 0));
268 assertEquals(-1, ExceptionUtils.indexOfType(withoutCause, NestableException.class, 0));
269 assertEquals(0, ExceptionUtils.indexOfType(withoutCause, ExceptionWithoutCause.class, 0));
270
271 assertEquals(-1, ExceptionUtils.indexOfType(nested, null, 0));
272 assertEquals(-1, ExceptionUtils.indexOfType(nested, ExceptionWithCause.class, 0));
273 assertEquals(0, ExceptionUtils.indexOfType(nested, NestableException.class, 0));
274 assertEquals(1, ExceptionUtils.indexOfType(nested, ExceptionWithoutCause.class, 0));
275
276 assertEquals(-1, ExceptionUtils.indexOfType(withCause, null));
277 assertEquals(0, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 0));
278 assertEquals(1, ExceptionUtils.indexOfType(withCause, NestableException.class, 0));
279 assertEquals(2, ExceptionUtils.indexOfType(withCause, ExceptionWithoutCause.class, 0));
280
281 assertEquals(0, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, -1));
282 assertEquals(0, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 0));
283 assertEquals(-1, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 1));
284 assertEquals(-1, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 9));
285
286 assertEquals(0, ExceptionUtils.indexOfType(withCause, Exception.class, 0));
287 }
288
289 //-----------------------------------------------------------------------
290 public void testPrintRootCauseStackTrace_Throwable() throws Exception {
291 ExceptionUtils.printRootCauseStackTrace(null);
292 // could pipe system.err to a known stream, but not much point as
293 // internally this method calls stram method anyway
294 }
295
296 public void testPrintRootCauseStackTrace_ThrowableStream() throws Exception {
297 ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
298 ExceptionUtils.printRootCauseStackTrace(null, (PrintStream) null);
299 ExceptionUtils.printRootCauseStackTrace(null, new PrintStream(out));
300 assertEquals(0, out.toString().length());
301
302 out = new ByteArrayOutputStream(1024);
303 try {
304 ExceptionUtils.printRootCauseStackTrace(withCause, (PrintStream) null);
305 fail();
306 } catch (IllegalArgumentException ex) {
307 }
308
309 out = new ByteArrayOutputStream(1024);
310 Throwable withCause = createExceptionWithCause();
311 ExceptionUtils.printRootCauseStackTrace(withCause, new PrintStream(out));
312 String stackTrace = out.toString();
313 assertTrue(stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) != -1);
314
315 out = new ByteArrayOutputStream(1024);
316 ExceptionUtils.printRootCauseStackTrace(withoutCause, new PrintStream(out));
317 stackTrace = out.toString();
318 assertTrue(stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) == -1);
319 }
320
321 public void testPrintRootCauseStackTrace_ThrowableWriter() throws Exception {
322 StringWriter writer = new StringWriter(1024);
323 ExceptionUtils.printRootCauseStackTrace(null, (PrintWriter) null);
324 ExceptionUtils.printRootCauseStackTrace(null, new PrintWriter(writer));
325 assertEquals(0, writer.getBuffer().length());
326
327 writer = new StringWriter(1024);
328 try {
329 ExceptionUtils.printRootCauseStackTrace(withCause, (PrintWriter) null);
330 fail();
331 } catch (IllegalArgumentException ex) {
332 }
333
334 writer = new StringWriter(1024);
335 Throwable withCause = createExceptionWithCause();
336 ExceptionUtils.printRootCauseStackTrace(withCause, new PrintWriter(writer));
337 String stackTrace = writer.toString();
338 assertTrue(stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) != -1);
339
340 writer = new StringWriter(1024);
341 ExceptionUtils.printRootCauseStackTrace(withoutCause, new PrintWriter(writer));
342 stackTrace = writer.toString();
343 assertTrue(stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) == -1);
344 }
345
346 //-----------------------------------------------------------------------
347 public void testGetRootCauseStackTrace_Throwable() throws Exception {
348 assertEquals(0, ExceptionUtils.getRootCauseStackTrace(null).length);
349
350 Throwable withCause = createExceptionWithCause();
351 String[] stackTrace = ExceptionUtils.getRootCauseStackTrace(withCause);
352 boolean match = false;
353 for (int i = 0; i < stackTrace.length; i++) {
354 if (stackTrace[i].startsWith(ExceptionUtils.WRAPPED_MARKER)) {
355 match = true;
356 break;
357 }
358 }
359 assertEquals(true, match);
360
361 stackTrace = ExceptionUtils.getRootCauseStackTrace(withoutCause);
362 match = false;
363 for (int i = 0; i < stackTrace.length; i++) {
364 if (stackTrace[i].startsWith(ExceptionUtils.WRAPPED_MARKER)) {
365 match = true;
366 break;
367 }
368 }
369 assertEquals(false, match);
370 }
371
372 public void testRemoveCommonFrames_ListList() throws Exception {
373 try {
374 ExceptionUtils.removeCommonFrames(null, null);
375 fail();
376 } catch (IllegalArgumentException ex) {
377 }
378 }
379
380 //-----------------------------------------------------------------------
381 /**
382 * Provides a method with a well known chained/nested exception
383 * name which matches the full signature (e.g. has a return value
384 * of <code>Throwable</code>.
385 */
386 private static class ExceptionWithCause extends Exception {
387 private Throwable cause;
388
389 public ExceptionWithCause(Throwable cause) {
390 this.cause = cause;
391 }
392
393 public Throwable getCause() {
394 return cause;
395 }
396 }
397
398 /**
399 * Provides a method with a well known chained/nested exception
400 * name which does not match the full signature (e.g. lacks a
401 * return value of <code>Throwable</code>.
402 */
403 private static class ExceptionWithoutCause extends Exception {
404 public void getTargetException() {
405 }
406 }
407
408 }