• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Guava Authors
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 
17 package com.google.common.base;
18 
19 import static com.google.common.base.Throwables.getStackTraceAsString;
20 import static java.util.Arrays.asList;
21 import static java.util.regex.Pattern.quote;
22 
23 import com.google.common.collect.Iterables;
24 import com.google.common.testing.NullPointerTester;
25 
26 import junit.framework.TestCase;
27 
28 import java.io.FileNotFoundException;
29 import java.util.List;
30 
31 /**
32  * Unit test for {@link Throwables}.
33  *
34  * @author Kevin Bourrillion
35  */
36 @SuppressWarnings("serial") // this warning is silly for exceptions in tests
37 public class ThrowablesTest extends TestCase {
testPropagateIfPossible_NoneDeclared_NoneThrown()38   public void testPropagateIfPossible_NoneDeclared_NoneThrown() {
39     Sample sample = new Sample() {
40       @Override public void noneDeclared() {
41         try {
42           methodThatDoesntThrowAnything();
43         } catch (Throwable t) {
44           Throwables.propagateIfPossible(t);
45           throw new SomeChainingException(t);
46         }
47       }
48     };
49 
50     // Expect no exception to be thrown
51     sample.noneDeclared();
52   }
53 
testPropagateIfPossible_NoneDeclared_UncheckedThrown()54   public void testPropagateIfPossible_NoneDeclared_UncheckedThrown() {
55     Sample sample = new Sample() {
56       @Override public void noneDeclared() {
57         try {
58           methodThatThrowsUnchecked();
59         } catch (Throwable t) {
60           Throwables.propagateIfPossible(t);
61           throw new SomeChainingException(t);
62         }
63       }
64     };
65 
66     // Expect the unchecked exception to propagate as-is
67     try {
68       sample.noneDeclared();
69       fail();
70     } catch (SomeUncheckedException expected) {
71     }
72   }
73 
testPropagateIfPossible_NoneDeclared_UndeclaredThrown()74   public void testPropagateIfPossible_NoneDeclared_UndeclaredThrown() {
75     Sample sample = new Sample() {
76       @Override public void noneDeclared() {
77         try {
78           methodThatThrowsUndeclaredChecked();
79         } catch (Throwable t) {
80           Throwables.propagateIfPossible(t);
81           throw new SomeChainingException(t);
82         }
83       }
84     };
85 
86     // Expect the undeclared exception to have been chained inside another
87     try {
88       sample.noneDeclared();
89       fail();
90     } catch (SomeChainingException expected) {
91     }
92   }
93 
testPropagateIfPossible_OneDeclared_NoneThrown()94   public void testPropagateIfPossible_OneDeclared_NoneThrown()
95       throws SomeCheckedException {
96     Sample sample = new Sample() {
97       @Override public void oneDeclared() throws SomeCheckedException {
98         try {
99           methodThatDoesntThrowAnything();
100         } catch (Throwable t) {
101           // yes, this block is never reached, but for purposes of illustration
102           // we're keeping it the same in each test
103           Throwables.propagateIfPossible(t, SomeCheckedException.class);
104           throw new SomeChainingException(t);
105         }
106       }
107     };
108 
109     // Expect no exception to be thrown
110     sample.oneDeclared();
111   }
112 
testPropagateIfPossible_OneDeclared_UncheckedThrown()113   public void testPropagateIfPossible_OneDeclared_UncheckedThrown()
114       throws SomeCheckedException {
115     Sample sample = new Sample() {
116       @Override public void oneDeclared() throws SomeCheckedException {
117         try {
118           methodThatThrowsUnchecked();
119         } catch (Throwable t) {
120           Throwables.propagateIfPossible(t, SomeCheckedException.class);
121           throw new SomeChainingException(t);
122         }
123       }
124     };
125 
126     // Expect the unchecked exception to propagate as-is
127     try {
128       sample.oneDeclared();
129       fail();
130     } catch (SomeUncheckedException expected) {
131     }
132   }
133 
testPropagateIfPossible_OneDeclared_CheckedThrown()134   public void testPropagateIfPossible_OneDeclared_CheckedThrown() {
135     Sample sample = new Sample() {
136       @Override public void oneDeclared() throws SomeCheckedException {
137         try {
138           methodThatThrowsChecked();
139         } catch (Throwable t) {
140           Throwables.propagateIfPossible(t, SomeCheckedException.class);
141           throw new SomeChainingException(t);
142         }
143       }
144     };
145 
146     // Expect the checked exception to propagate as-is
147     try {
148       sample.oneDeclared();
149       fail();
150     } catch (SomeCheckedException expected) {
151     }
152   }
153 
testPropagateIfPossible_OneDeclared_UndeclaredThrown()154   public void testPropagateIfPossible_OneDeclared_UndeclaredThrown()
155       throws SomeCheckedException {
156     Sample sample = new Sample() {
157       @Override public void oneDeclared() throws SomeCheckedException {
158         try {
159           methodThatThrowsUndeclaredChecked();
160         } catch (Throwable t) {
161           Throwables.propagateIfPossible(t, SomeCheckedException.class);
162           throw new SomeChainingException(t);
163         }
164       }
165     };
166 
167     // Expect the undeclared exception to have been chained inside another
168     try {
169       sample.oneDeclared();
170       fail();
171     } catch (SomeChainingException expected) {
172     }
173   }
174 
testPropagateIfPossible_TwoDeclared_NoneThrown()175   public void testPropagateIfPossible_TwoDeclared_NoneThrown()
176       throws SomeCheckedException, SomeOtherCheckedException {
177     Sample sample = new Sample() {
178       @Override public void twoDeclared() throws SomeCheckedException,
179           SomeOtherCheckedException {
180         try {
181           methodThatDoesntThrowAnything();
182         } catch (Throwable t) {
183           Throwables.propagateIfPossible(t, SomeCheckedException.class,
184               SomeOtherCheckedException.class);
185           throw new SomeChainingException(t);
186         }
187       }
188     };
189 
190     // Expect no exception to be thrown
191     sample.twoDeclared();
192   }
193 
testPropagateIfPossible_TwoDeclared_UncheckedThrown()194   public void testPropagateIfPossible_TwoDeclared_UncheckedThrown()
195       throws SomeCheckedException, SomeOtherCheckedException {
196     Sample sample = new Sample() {
197       @Override public void twoDeclared() throws SomeCheckedException,
198           SomeOtherCheckedException {
199         try {
200           methodThatThrowsUnchecked();
201         } catch (Throwable t) {
202           Throwables.propagateIfPossible(t, SomeCheckedException.class,
203               SomeOtherCheckedException.class);
204           throw new SomeChainingException(t);
205         }
206       }
207     };
208 
209     // Expect the unchecked exception to propagate as-is
210     try {
211       sample.twoDeclared();
212       fail();
213     } catch (SomeUncheckedException expected) {
214     }
215   }
216 
testPropagateIfPossible_TwoDeclared_CheckedThrown()217   public void testPropagateIfPossible_TwoDeclared_CheckedThrown()
218       throws SomeOtherCheckedException {
219     Sample sample = new Sample() {
220       @Override public void twoDeclared() throws SomeCheckedException,
221           SomeOtherCheckedException {
222         try {
223           methodThatThrowsChecked();
224         } catch (Throwable t) {
225           Throwables.propagateIfPossible(t, SomeCheckedException.class,
226               SomeOtherCheckedException.class);
227           throw new SomeChainingException(t);
228         }
229       }
230     };
231 
232     // Expect the checked exception to propagate as-is
233     try {
234       sample.twoDeclared();
235       fail();
236     } catch (SomeCheckedException expected) {
237     }
238   }
239 
testPropagateIfPossible_TwoDeclared_OtherCheckedThrown()240   public void testPropagateIfPossible_TwoDeclared_OtherCheckedThrown()
241       throws SomeCheckedException {
242     Sample sample = new Sample() {
243       @Override public void twoDeclared() throws SomeCheckedException,
244           SomeOtherCheckedException {
245         try {
246           methodThatThrowsOtherChecked();
247         } catch (Throwable t) {
248           Throwables.propagateIfPossible(t, SomeCheckedException.class,
249               SomeOtherCheckedException.class);
250           throw new SomeChainingException(t);
251         }
252       }
253     };
254 
255     // Expect the checked exception to propagate as-is
256     try {
257       sample.twoDeclared();
258       fail();
259     } catch (SomeOtherCheckedException expected) {
260     }
261   }
262 
testPropageIfPossible_null()263   public void testPropageIfPossible_null() throws SomeCheckedException {
264     Throwables.propagateIfPossible(null);
265     Throwables.propagateIfPossible(null, SomeCheckedException.class);
266     Throwables.propagateIfPossible(null, SomeCheckedException.class,
267         SomeUncheckedException.class);
268   }
269 
testPropagate_NoneDeclared_NoneThrown()270   public void testPropagate_NoneDeclared_NoneThrown() {
271     Sample sample = new Sample() {
272       @Override public void noneDeclared() {
273         try {
274           methodThatDoesntThrowAnything();
275         } catch (Throwable t) {
276           throw Throwables.propagate(t);
277         }
278       }
279     };
280 
281     // Expect no exception to be thrown
282     sample.noneDeclared();
283   }
284 
testPropagate_NoneDeclared_UncheckedThrown()285   public void testPropagate_NoneDeclared_UncheckedThrown() {
286     Sample sample = new Sample() {
287       @Override public void noneDeclared() {
288         try {
289           methodThatThrowsUnchecked();
290         } catch (Throwable t) {
291           throw Throwables.propagate(t);
292         }
293       }
294     };
295 
296     // Expect the unchecked exception to propagate as-is
297     try {
298       sample.noneDeclared();
299       fail();
300     } catch (SomeUncheckedException expected) {
301     }
302   }
303 
testPropagate_NoneDeclared_ErrorThrown()304   public void testPropagate_NoneDeclared_ErrorThrown() {
305     Sample sample = new Sample() {
306       @Override public void noneDeclared() {
307         try {
308           methodThatThrowsError();
309         } catch (Throwable t) {
310           throw Throwables.propagate(t);
311         }
312       }
313     };
314 
315     // Expect the error to propagate as-is
316     try {
317       sample.noneDeclared();
318       fail();
319     } catch (SomeError expected) {
320     }
321   }
322 
testPropagate_NoneDeclared_CheckedThrown()323   public void testPropagate_NoneDeclared_CheckedThrown() {
324     Sample sample = new Sample() {
325       @Override public void noneDeclared() {
326         try {
327           methodThatThrowsChecked();
328         } catch (Throwable t) {
329           throw Throwables.propagate(t);
330         }
331       }
332     };
333 
334     // Expect the undeclared exception to have been chained inside another
335     try {
336       sample.noneDeclared();
337       fail();
338     } catch (RuntimeException expected) {
339       assertTrue(expected.getCause() instanceof SomeCheckedException);
340     }
341   }
342 
testPropagateIfInstanceOf_NoneThrown()343   public void testPropagateIfInstanceOf_NoneThrown()
344       throws SomeCheckedException {
345     Sample sample = new Sample() {
346       @Override public void oneDeclared() throws SomeCheckedException {
347         try {
348           methodThatDoesntThrowAnything();
349         } catch (Throwable t) {
350           Throwables.propagateIfInstanceOf(t, SomeCheckedException.class);
351           throw Throwables.propagate(t);
352         }
353       }
354     };
355 
356     // Expect no exception to be thrown
357     sample.oneDeclared();
358   }
359 
testPropagateIfInstanceOf_DeclaredThrown()360   public void testPropagateIfInstanceOf_DeclaredThrown() {
361     Sample sample = new Sample() {
362       @Override public void oneDeclared() throws SomeCheckedException {
363         try {
364           methodThatThrowsChecked();
365         } catch (Throwable t) {
366           Throwables.propagateIfInstanceOf(t, SomeCheckedException.class);
367           throw Throwables.propagate(t);
368         }
369       }
370     };
371 
372     // Expect declared exception to be thrown as-is
373     try {
374       sample.oneDeclared();
375       fail();
376     } catch (SomeCheckedException e) {
377     }
378   }
379 
testPropagateIfInstanceOf_UncheckedThrown()380   public void testPropagateIfInstanceOf_UncheckedThrown()
381       throws SomeCheckedException {
382     Sample sample = new Sample() {
383       @Override public void oneDeclared() throws SomeCheckedException {
384         try {
385           methodThatThrowsUnchecked();
386         } catch (Throwable t) {
387           Throwables.propagateIfInstanceOf(t, SomeCheckedException.class);
388           throw Throwables.propagate(t);
389         }
390       }
391     };
392 
393     // Expect unchecked exception to be thrown as-is
394     try {
395       sample.oneDeclared();
396       fail();
397     } catch (SomeUncheckedException e) {
398     }
399   }
400 
testPropagateIfInstanceOf_UndeclaredThrown()401   public void testPropagateIfInstanceOf_UndeclaredThrown()
402       throws SomeCheckedException {
403     Sample sample = new Sample() {
404       @Override public void oneDeclared() throws SomeCheckedException {
405         try {
406           methodThatThrowsOtherChecked();
407         } catch (Throwable t) {
408           Throwables.propagateIfInstanceOf(t, SomeCheckedException.class);
409           throw Throwables.propagate(t);
410         }
411       }
412     };
413 
414     // Expect undeclared exception wrapped by RuntimeException to be thrown
415     try {
416       sample.oneDeclared();
417       fail();
418     } catch (RuntimeException e) {
419       assertTrue(e.getCause() instanceof SomeOtherCheckedException);
420     }
421   }
422 
testPropageIfInstanceOf_null()423   public void testPropageIfInstanceOf_null() throws SomeCheckedException {
424     Throwables.propagateIfInstanceOf(null, SomeCheckedException.class);
425   }
426 
testGetRootCause_NoCause()427   public void testGetRootCause_NoCause() {
428     SomeCheckedException exception = new SomeCheckedException();
429     assertSame(exception, Throwables.getRootCause(exception));
430   }
431 
testGetRootCause_SingleWrapped()432   public void testGetRootCause_SingleWrapped() {
433     SomeCheckedException cause = new SomeCheckedException();
434     SomeChainingException exception = new SomeChainingException(cause);
435     assertSame(cause, Throwables.getRootCause(exception));
436   }
437 
testGetRootCause_DoubleWrapped()438   public void testGetRootCause_DoubleWrapped() {
439     SomeCheckedException cause = new SomeCheckedException();
440     SomeChainingException exception =
441         new SomeChainingException(new SomeChainingException(cause));
442     assertSame(cause, Throwables.getRootCause(exception));
443   }
444 
445   private static class SomeThrowable extends Throwable {}
446   private static class SomeError extends Error {}
447   private static class SomeCheckedException extends Exception {}
448   private static class SomeOtherCheckedException extends Exception {}
449   private static class SomeUncheckedException extends RuntimeException {}
450   private static class SomeUndeclaredCheckedException extends Exception {}
451   private static class SomeChainingException extends RuntimeException {
SomeChainingException(Throwable cause)452     public SomeChainingException(Throwable cause) {
453       super(cause);
454     }
455   }
456 
457   static class Sample {
noneDeclared()458     void noneDeclared() {}
459     /*
460      * Subclasses of Sample will define methods with these signatures that throw
461      * these exceptions, so we must declare them in the throws clause here.
462      * Eclipse doesn't think being thrown from a subclass's non-public,
463      * non-protected method with the same signature counts as being "used."
464      */
465     @SuppressWarnings("unused")
oneDeclared()466     void oneDeclared() throws SomeCheckedException {}
467     @SuppressWarnings("unused")
twoDeclared()468     void twoDeclared() throws SomeCheckedException, SomeOtherCheckedException {}
469   }
470 
methodThatDoesntThrowAnything()471   static void methodThatDoesntThrowAnything() {}
methodThatThrowsError()472   static void methodThatThrowsError() {
473     throw new SomeError();
474   }
methodThatThrowsUnchecked()475   static void methodThatThrowsUnchecked() {
476     throw new SomeUncheckedException();
477   }
methodThatThrowsChecked()478   static void methodThatThrowsChecked() throws SomeCheckedException {
479     throw new SomeCheckedException();
480   }
methodThatThrowsOtherChecked()481   static void methodThatThrowsOtherChecked() throws SomeOtherCheckedException {
482     throw new SomeOtherCheckedException();
483   }
methodThatThrowsUndeclaredChecked()484   static void methodThatThrowsUndeclaredChecked()
485       throws SomeUndeclaredCheckedException {
486     throw new SomeUndeclaredCheckedException();
487   }
488 
testGetStackTraceAsString()489   public void testGetStackTraceAsString() {
490     class StackTraceException extends Exception {
491       StackTraceException(String message) {
492         super(message);
493       }
494     }
495 
496     StackTraceException e = new StackTraceException("my message");
497 
498     String firstLine = quote(e.getClass().getName() + ": " + e.getMessage());
499     String secondLine = "\\s*at " + ThrowablesTest.class.getName() + "\\..*";
500     String moreLines = "(?:.*\n?)*";
501     String expected = firstLine + "\n" + secondLine + "\n" + moreLines;
502     assertTrue(getStackTraceAsString(e).matches(expected));
503   }
504 
testGetCausalChain()505   public void testGetCausalChain() {
506     FileNotFoundException fnfe = new FileNotFoundException();
507     IllegalArgumentException iae = new IllegalArgumentException(fnfe);
508     RuntimeException re = new RuntimeException(iae);
509     IllegalStateException ex = new IllegalStateException(re);
510 
511     assertEquals(asList(ex, re, iae, fnfe), Throwables.getCausalChain(ex));
512     assertSame(fnfe, Iterables.getOnlyElement(Throwables.getCausalChain(fnfe)));
513     try {
514       Throwables.getCausalChain(null);
515       fail("Should have throw NPE");
516     } catch (NullPointerException expected) {
517     }
518 
519     List<Throwable> causes = Throwables.getCausalChain(ex);
520     try {
521       causes.add(new RuntimeException());
522       fail("List should be unmodifiable");
523     } catch (UnsupportedOperationException expected) {
524     }
525   }
526 
testNullPointers()527   public void testNullPointers() throws Exception {
528     NullPointerTester tester = new NullPointerTester();
529     tester.setDefault(Throwable.class, new SomeCheckedException());
530     tester.setDefault(Class.class, SomeCheckedException.class);
531     tester.testAllPublicStaticMethods(Throwables.class);
532   }
533 }
534