• 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.StandardSystemProperty.JAVA_SPECIFICATION_VERSION;
20 import static com.google.common.base.Throwables.getStackTraceAsString;
21 import static com.google.common.base.Throwables.lazyStackTrace;
22 import static com.google.common.base.Throwables.lazyStackTraceIsLazy;
23 import static com.google.common.base.Throwables.throwIfInstanceOf;
24 import static com.google.common.base.Throwables.throwIfUnchecked;
25 import static com.google.common.truth.Truth.assertThat;
26 import static java.util.Arrays.asList;
27 import static java.util.regex.Pattern.quote;
28 
29 import com.google.common.annotations.GwtCompatible;
30 import com.google.common.annotations.GwtIncompatible;
31 import com.google.common.collect.Iterables;
32 import com.google.common.primitives.Ints;
33 import com.google.common.testing.NullPointerTester;
34 import java.util.List;
35 import junit.framework.TestCase;
36 
37 /**
38  * Unit test for {@link Throwables}.
39  *
40  * @author Kevin Bourrillion
41  */
42 @GwtCompatible(emulated = true)
43 public class ThrowablesTest extends TestCase {
testThrowIfUnchecked_Unchecked()44   public void testThrowIfUnchecked_Unchecked() {
45     try {
46       throwIfUnchecked(new SomeUncheckedException());
47       fail();
48     } catch (SomeUncheckedException expected) {
49     }
50   }
51 
testThrowIfUnchecked_Error()52   public void testThrowIfUnchecked_Error() {
53     try {
54       throwIfUnchecked(new SomeError());
55       fail();
56     } catch (SomeError expected) {
57     }
58   }
59 
60   @SuppressWarnings("ThrowIfUncheckedKnownChecked")
testThrowIfUnchecked_Checked()61   public void testThrowIfUnchecked_Checked() {
62     throwIfUnchecked(new SomeCheckedException());
63   }
64 
65   @GwtIncompatible // propagateIfPossible
testPropagateIfPossible_NoneDeclared_NoneThrown()66   public void testPropagateIfPossible_NoneDeclared_NoneThrown() {
67     Sample sample =
68         new Sample() {
69           @Override
70           public void noneDeclared() {
71             try {
72               methodThatDoesntThrowAnything();
73             } catch (Throwable t) {
74               Throwables.propagateIfPossible(t);
75               throw new SomeChainingException(t);
76             }
77           }
78         };
79 
80     // Expect no exception to be thrown
81     sample.noneDeclared();
82   }
83 
84   @GwtIncompatible // propagateIfPossible
testPropagateIfPossible_NoneDeclared_UncheckedThrown()85   public void testPropagateIfPossible_NoneDeclared_UncheckedThrown() {
86     Sample sample =
87         new Sample() {
88           @Override
89           public void noneDeclared() {
90             try {
91               methodThatThrowsUnchecked();
92             } catch (Throwable t) {
93               Throwables.propagateIfPossible(t);
94               throw new SomeChainingException(t);
95             }
96           }
97         };
98 
99     // Expect the unchecked exception to propagate as-is
100     try {
101       sample.noneDeclared();
102       fail();
103     } catch (SomeUncheckedException expected) {
104     }
105   }
106 
107   @GwtIncompatible // propagateIfPossible
testPropagateIfPossible_NoneDeclared_UndeclaredThrown()108   public void testPropagateIfPossible_NoneDeclared_UndeclaredThrown() {
109     Sample sample =
110         new Sample() {
111           @Override
112           public void noneDeclared() {
113             try {
114               methodThatThrowsUndeclaredChecked();
115             } catch (Throwable t) {
116               Throwables.propagateIfPossible(t);
117               throw new SomeChainingException(t);
118             }
119           }
120         };
121 
122     // Expect the undeclared exception to have been chained inside another
123     try {
124       sample.noneDeclared();
125       fail();
126     } catch (SomeChainingException expected) {
127     }
128   }
129 
130   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropagateIfPossible_OneDeclared_NoneThrown()131   public void testPropagateIfPossible_OneDeclared_NoneThrown() throws SomeCheckedException {
132     Sample sample =
133         new Sample() {
134           @Override
135           public void oneDeclared() throws SomeCheckedException {
136             try {
137               methodThatDoesntThrowAnything();
138             } catch (Throwable t) {
139               // yes, this block is never reached, but for purposes of illustration
140               // we're keeping it the same in each test
141               Throwables.propagateIfPossible(t, SomeCheckedException.class);
142               throw new SomeChainingException(t);
143             }
144           }
145         };
146 
147     // Expect no exception to be thrown
148     sample.oneDeclared();
149   }
150 
151   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropagateIfPossible_OneDeclared_UncheckedThrown()152   public void testPropagateIfPossible_OneDeclared_UncheckedThrown() throws SomeCheckedException {
153     Sample sample =
154         new Sample() {
155           @Override
156           public void oneDeclared() throws SomeCheckedException {
157             try {
158               methodThatThrowsUnchecked();
159             } catch (Throwable t) {
160               Throwables.propagateIfPossible(t, SomeCheckedException.class);
161               throw new SomeChainingException(t);
162             }
163           }
164         };
165 
166     // Expect the unchecked exception to propagate as-is
167     try {
168       sample.oneDeclared();
169       fail();
170     } catch (SomeUncheckedException expected) {
171     }
172   }
173 
174   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropagateIfPossible_OneDeclared_CheckedThrown()175   public void testPropagateIfPossible_OneDeclared_CheckedThrown() {
176     Sample sample =
177         new Sample() {
178           @Override
179           public void oneDeclared() throws SomeCheckedException {
180             try {
181               methodThatThrowsChecked();
182             } catch (Throwable t) {
183               Throwables.propagateIfPossible(t, SomeCheckedException.class);
184               throw new SomeChainingException(t);
185             }
186           }
187         };
188 
189     // Expect the checked exception to propagate as-is
190     try {
191       sample.oneDeclared();
192       fail();
193     } catch (SomeCheckedException expected) {
194     }
195   }
196 
197   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropagateIfPossible_OneDeclared_UndeclaredThrown()198   public void testPropagateIfPossible_OneDeclared_UndeclaredThrown() throws SomeCheckedException {
199     Sample sample =
200         new Sample() {
201           @Override
202           public void oneDeclared() throws SomeCheckedException {
203             try {
204               methodThatThrowsUndeclaredChecked();
205             } catch (Throwable t) {
206               Throwables.propagateIfPossible(t, SomeCheckedException.class);
207               throw new SomeChainingException(t);
208             }
209           }
210         };
211 
212     // Expect the undeclared exception to have been chained inside another
213     try {
214       sample.oneDeclared();
215       fail();
216     } catch (SomeChainingException expected) {
217     }
218   }
219 
220   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropagateIfPossible_TwoDeclared_NoneThrown()221   public void testPropagateIfPossible_TwoDeclared_NoneThrown()
222       throws SomeCheckedException, SomeOtherCheckedException {
223     Sample sample =
224         new Sample() {
225           @Override
226           public void twoDeclared() throws SomeCheckedException, SomeOtherCheckedException {
227             try {
228               methodThatDoesntThrowAnything();
229             } catch (Throwable t) {
230               Throwables.propagateIfPossible(
231                   t, SomeCheckedException.class, SomeOtherCheckedException.class);
232               throw new SomeChainingException(t);
233             }
234           }
235         };
236 
237     // Expect no exception to be thrown
238     sample.twoDeclared();
239   }
240 
241   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropagateIfPossible_TwoDeclared_UncheckedThrown()242   public void testPropagateIfPossible_TwoDeclared_UncheckedThrown()
243       throws SomeCheckedException, SomeOtherCheckedException {
244     Sample sample =
245         new Sample() {
246           @Override
247           public void twoDeclared() throws SomeCheckedException, SomeOtherCheckedException {
248             try {
249               methodThatThrowsUnchecked();
250             } catch (Throwable t) {
251               Throwables.propagateIfPossible(
252                   t, SomeCheckedException.class, SomeOtherCheckedException.class);
253               throw new SomeChainingException(t);
254             }
255           }
256         };
257 
258     // Expect the unchecked exception to propagate as-is
259     try {
260       sample.twoDeclared();
261       fail();
262     } catch (SomeUncheckedException expected) {
263     }
264   }
265 
266   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropagateIfPossible_TwoDeclared_CheckedThrown()267   public void testPropagateIfPossible_TwoDeclared_CheckedThrown() throws SomeOtherCheckedException {
268     Sample sample =
269         new Sample() {
270           @Override
271           public void twoDeclared() throws SomeCheckedException, SomeOtherCheckedException {
272             try {
273               methodThatThrowsChecked();
274             } catch (Throwable t) {
275               Throwables.propagateIfPossible(
276                   t, SomeCheckedException.class, SomeOtherCheckedException.class);
277               throw new SomeChainingException(t);
278             }
279           }
280         };
281 
282     // Expect the checked exception to propagate as-is
283     try {
284       sample.twoDeclared();
285       fail();
286     } catch (SomeCheckedException expected) {
287     }
288   }
289 
290   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropagateIfPossible_TwoDeclared_OtherCheckedThrown()291   public void testPropagateIfPossible_TwoDeclared_OtherCheckedThrown() throws SomeCheckedException {
292     Sample sample =
293         new Sample() {
294           @Override
295           public void twoDeclared() throws SomeCheckedException, SomeOtherCheckedException {
296             try {
297               methodThatThrowsOtherChecked();
298             } catch (Throwable t) {
299               Throwables.propagateIfPossible(
300                   t, SomeCheckedException.class, SomeOtherCheckedException.class);
301               throw new SomeChainingException(t);
302             }
303           }
304         };
305 
306     // Expect the checked exception to propagate as-is
307     try {
308       sample.twoDeclared();
309       fail();
310     } catch (SomeOtherCheckedException expected) {
311     }
312   }
313 
testThrowIfUnchecked_null()314   public void testThrowIfUnchecked_null() throws SomeCheckedException {
315     try {
316       throwIfUnchecked(null);
317       fail();
318     } catch (NullPointerException expected) {
319     }
320   }
321 
322   @GwtIncompatible // propagateIfPossible
testPropageIfPossible_null()323   public void testPropageIfPossible_null() throws SomeCheckedException {
324     Throwables.propagateIfPossible(null);
325   }
326 
327   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropageIfPossible_OneDeclared_null()328   public void testPropageIfPossible_OneDeclared_null() throws SomeCheckedException {
329     Throwables.propagateIfPossible(null, SomeCheckedException.class);
330   }
331 
332   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropageIfPossible_TwoDeclared_null()333   public void testPropageIfPossible_TwoDeclared_null() throws SomeCheckedException {
334     Throwables.propagateIfPossible(null, SomeCheckedException.class, SomeUncheckedException.class);
335   }
336 
337   @GwtIncompatible // propagate
testPropagate_NoneDeclared_NoneThrown()338   public void testPropagate_NoneDeclared_NoneThrown() {
339     Sample sample =
340         new Sample() {
341           @Override
342           public void noneDeclared() {
343             try {
344               methodThatDoesntThrowAnything();
345             } catch (Throwable t) {
346               throw Throwables.propagate(t);
347             }
348           }
349         };
350 
351     // Expect no exception to be thrown
352     sample.noneDeclared();
353   }
354 
355   @GwtIncompatible // propagate
testPropagate_NoneDeclared_UncheckedThrown()356   public void testPropagate_NoneDeclared_UncheckedThrown() {
357     Sample sample =
358         new Sample() {
359           @Override
360           public void noneDeclared() {
361             try {
362               methodThatThrowsUnchecked();
363             } catch (Throwable t) {
364               throw Throwables.propagate(t);
365             }
366           }
367         };
368 
369     // Expect the unchecked exception to propagate as-is
370     try {
371       sample.noneDeclared();
372       fail();
373     } catch (SomeUncheckedException expected) {
374     }
375   }
376 
377   @GwtIncompatible // propagate
testPropagate_NoneDeclared_ErrorThrown()378   public void testPropagate_NoneDeclared_ErrorThrown() {
379     Sample sample =
380         new Sample() {
381           @Override
382           public void noneDeclared() {
383             try {
384               methodThatThrowsError();
385             } catch (Throwable t) {
386               throw Throwables.propagate(t);
387             }
388           }
389         };
390 
391     // Expect the error to propagate as-is
392     try {
393       sample.noneDeclared();
394       fail();
395     } catch (SomeError expected) {
396     }
397   }
398 
399   @GwtIncompatible // propagate
testPropagate_NoneDeclared_CheckedThrown()400   public void testPropagate_NoneDeclared_CheckedThrown() {
401     Sample sample =
402         new Sample() {
403           @Override
404           public void noneDeclared() {
405             try {
406               methodThatThrowsChecked();
407             } catch (Throwable t) {
408               throw Throwables.propagate(t);
409             }
410           }
411         };
412 
413     // Expect the undeclared exception to have been chained inside another
414     try {
415       sample.noneDeclared();
416       fail();
417     } catch (RuntimeException expected) {
418       assertThat(expected).hasCauseThat().isInstanceOf(SomeCheckedException.class);
419     }
420   }
421 
422   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_Unchecked()423   public void testThrowIfInstanceOf_Unchecked() throws SomeCheckedException {
424     throwIfInstanceOf(new SomeUncheckedException(), SomeCheckedException.class);
425   }
426 
427   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_CheckedDifferent()428   public void testThrowIfInstanceOf_CheckedDifferent() throws SomeCheckedException {
429     throwIfInstanceOf(new SomeOtherCheckedException(), SomeCheckedException.class);
430   }
431 
432   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_CheckedSame()433   public void testThrowIfInstanceOf_CheckedSame() {
434     try {
435       throwIfInstanceOf(new SomeCheckedException(), SomeCheckedException.class);
436       fail();
437     } catch (SomeCheckedException expected) {
438     }
439   }
440 
441   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_CheckedSubclass()442   public void testThrowIfInstanceOf_CheckedSubclass() {
443     try {
444       throwIfInstanceOf(new SomeCheckedException() {}, SomeCheckedException.class);
445       fail();
446     } catch (SomeCheckedException expected) {
447     }
448   }
449 
450   @GwtIncompatible // throwIfInstanceOf
testPropagateIfInstanceOf_NoneThrown()451   public void testPropagateIfInstanceOf_NoneThrown() throws SomeCheckedException {
452     Sample sample =
453         new Sample() {
454           @Override
455           public void oneDeclared() throws SomeCheckedException {
456             try {
457               methodThatDoesntThrowAnything();
458             } catch (Throwable t) {
459               Throwables.propagateIfInstanceOf(t, SomeCheckedException.class);
460               throw Throwables.propagate(t);
461             }
462           }
463         };
464 
465     // Expect no exception to be thrown
466     sample.oneDeclared();
467   }
468 
469   @GwtIncompatible // throwIfInstanceOf
testPropagateIfInstanceOf_DeclaredThrown()470   public void testPropagateIfInstanceOf_DeclaredThrown() {
471     Sample sample =
472         new Sample() {
473           @Override
474           public void oneDeclared() throws SomeCheckedException {
475             try {
476               methodThatThrowsChecked();
477             } catch (Throwable t) {
478               Throwables.propagateIfInstanceOf(t, SomeCheckedException.class);
479               throw Throwables.propagate(t);
480             }
481           }
482         };
483 
484     // Expect declared exception to be thrown as-is
485     try {
486       sample.oneDeclared();
487       fail();
488     } catch (SomeCheckedException expected) {
489     }
490   }
491 
492   @GwtIncompatible // throwIfInstanceOf
testPropagateIfInstanceOf_UncheckedThrown()493   public void testPropagateIfInstanceOf_UncheckedThrown() throws SomeCheckedException {
494     Sample sample =
495         new Sample() {
496           @Override
497           public void oneDeclared() throws SomeCheckedException {
498             try {
499               methodThatThrowsUnchecked();
500             } catch (Throwable t) {
501               Throwables.propagateIfInstanceOf(t, SomeCheckedException.class);
502               throw Throwables.propagate(t);
503             }
504           }
505         };
506 
507     // Expect unchecked exception to be thrown as-is
508     try {
509       sample.oneDeclared();
510       fail();
511     } catch (SomeUncheckedException expected) {
512     }
513   }
514 
515   @GwtIncompatible // throwIfInstanceOf
testPropagateIfInstanceOf_UndeclaredThrown()516   public void testPropagateIfInstanceOf_UndeclaredThrown() throws SomeCheckedException {
517     Sample sample =
518         new Sample() {
519           @Override
520           public void oneDeclared() throws SomeCheckedException {
521             try {
522               methodThatThrowsOtherChecked();
523             } catch (Throwable t) {
524               Throwables.propagateIfInstanceOf(t, SomeCheckedException.class);
525               throw Throwables.propagate(t);
526             }
527           }
528         };
529 
530     // Expect undeclared exception wrapped by RuntimeException to be thrown
531     try {
532       sample.oneDeclared();
533       fail();
534     } catch (RuntimeException expected) {
535       assertThat(expected).hasCauseThat().isInstanceOf(SomeOtherCheckedException.class);
536     }
537   }
538 
539   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_null()540   public void testThrowIfInstanceOf_null() throws SomeCheckedException {
541     try {
542       throwIfInstanceOf(null, SomeCheckedException.class);
543       fail();
544     } catch (NullPointerException expected) {
545     }
546   }
547 
548   @GwtIncompatible // throwIfInstanceOf
testPropageIfInstanceOf_null()549   public void testPropageIfInstanceOf_null() throws SomeCheckedException {
550     Throwables.propagateIfInstanceOf(null, SomeCheckedException.class);
551   }
552 
testGetRootCause_NoCause()553   public void testGetRootCause_NoCause() {
554     SomeCheckedException exception = new SomeCheckedException();
555     assertSame(exception, Throwables.getRootCause(exception));
556   }
557 
testGetRootCause_SingleWrapped()558   public void testGetRootCause_SingleWrapped() {
559     SomeCheckedException cause = new SomeCheckedException();
560     SomeChainingException exception = new SomeChainingException(cause);
561     assertSame(cause, Throwables.getRootCause(exception));
562   }
563 
testGetRootCause_DoubleWrapped()564   public void testGetRootCause_DoubleWrapped() {
565     SomeCheckedException cause = new SomeCheckedException();
566     SomeChainingException exception = new SomeChainingException(new SomeChainingException(cause));
567     assertSame(cause, Throwables.getRootCause(exception));
568   }
569 
testGetRootCause_Loop()570   public void testGetRootCause_Loop() {
571     Exception cause = new Exception();
572     Exception exception = new Exception(cause);
573     cause.initCause(exception);
574     try {
575       Throwables.getRootCause(cause);
576       fail("Should have throw IAE");
577     } catch (IllegalArgumentException expected) {
578       assertThat(expected).hasCauseThat().isSameAs(cause);
579     }
580   }
581 
582   private static class SomeError extends Error {}
583 
584   private static class SomeCheckedException extends Exception {}
585 
586   private static class SomeOtherCheckedException extends Exception {}
587 
588   private static class SomeUncheckedException extends RuntimeException {}
589 
590   private static class SomeUndeclaredCheckedException extends Exception {}
591 
592   private static class SomeChainingException extends RuntimeException {
SomeChainingException(Throwable cause)593     public SomeChainingException(Throwable cause) {
594       super(cause);
595     }
596   }
597 
598   static class Sample {
noneDeclared()599     void noneDeclared() {}
600 
oneDeclared()601     void oneDeclared() throws SomeCheckedException {}
602 
twoDeclared()603     void twoDeclared() throws SomeCheckedException, SomeOtherCheckedException {}
604   }
605 
methodThatDoesntThrowAnything()606   static void methodThatDoesntThrowAnything() {}
607 
methodThatThrowsError()608   static void methodThatThrowsError() {
609     throw new SomeError();
610   }
611 
methodThatThrowsUnchecked()612   static void methodThatThrowsUnchecked() {
613     throw new SomeUncheckedException();
614   }
615 
methodThatThrowsChecked()616   static void methodThatThrowsChecked() throws SomeCheckedException {
617     throw new SomeCheckedException();
618   }
619 
methodThatThrowsOtherChecked()620   static void methodThatThrowsOtherChecked() throws SomeOtherCheckedException {
621     throw new SomeOtherCheckedException();
622   }
623 
methodThatThrowsUndeclaredChecked()624   static void methodThatThrowsUndeclaredChecked() throws SomeUndeclaredCheckedException {
625     throw new SomeUndeclaredCheckedException();
626   }
627 
628   @GwtIncompatible // getStackTraceAsString(Throwable)
testGetStackTraceAsString()629   public void testGetStackTraceAsString() {
630     class StackTraceException extends Exception {
631       StackTraceException(String message) {
632         super(message);
633       }
634     }
635 
636     StackTraceException e = new StackTraceException("my message");
637 
638     String firstLine = quote(e.getClass().getName() + ": " + e.getMessage());
639     String secondLine = "\\s*at " + ThrowablesTest.class.getName() + "\\..*";
640     String moreLines = "(?:.*\n?)*";
641     String expected = firstLine + "\n" + secondLine + "\n" + moreLines;
642     assertThat(getStackTraceAsString(e)).matches(expected);
643   }
644 
testGetCausalChain()645   public void testGetCausalChain() {
646     SomeUncheckedException sue = new SomeUncheckedException();
647     IllegalArgumentException iae = new IllegalArgumentException(sue);
648     RuntimeException re = new RuntimeException(iae);
649     IllegalStateException ex = new IllegalStateException(re);
650 
651     assertEquals(asList(ex, re, iae, sue), Throwables.getCausalChain(ex));
652     assertSame(sue, Iterables.getOnlyElement(Throwables.getCausalChain(sue)));
653 
654     List<Throwable> causes = Throwables.getCausalChain(ex);
655     try {
656       causes.add(new RuntimeException());
657       fail("List should be unmodifiable");
658     } catch (UnsupportedOperationException expected) {
659     }
660   }
661 
testGetCasualChainNull()662   public void testGetCasualChainNull() {
663     try {
664       Throwables.getCausalChain(null);
665       fail("Should have throw NPE");
666     } catch (NullPointerException expected) {
667     }
668   }
669 
testGetCasualChainLoop()670   public void testGetCasualChainLoop() {
671     Exception cause = new Exception();
672     Exception exception = new Exception(cause);
673     cause.initCause(exception);
674     try {
675       Throwables.getCausalChain(cause);
676       fail("Should have throw IAE");
677     } catch (IllegalArgumentException expected) {
678       assertThat(expected).hasCauseThat().isSameAs(cause);
679     }
680   }
681 
682   @GwtIncompatible // Throwables.getCauseAs(Throwable, Class)
testGetCauseAs()683   public void testGetCauseAs() {
684     SomeCheckedException cause = new SomeCheckedException();
685     SomeChainingException thrown = new SomeChainingException(cause);
686 
687     assertThat(thrown).hasCauseThat().isSameAs(cause);
688     assertThat(Throwables.getCauseAs(thrown, SomeCheckedException.class)).isSameAs(cause);
689     assertThat(Throwables.getCauseAs(thrown, Exception.class)).isSameAs(cause);
690 
691     try {
692       Throwables.getCauseAs(thrown, IllegalStateException.class);
693       fail("Should have thrown CCE");
694     } catch (ClassCastException expected) {
695       assertThat(expected).hasCauseThat().isSameAs(thrown);
696     }
697   }
698 
699   @AndroidIncompatible // No getJavaLangAccess in Android (at least not in the version we use).
700   @GwtIncompatible // lazyStackTraceIsLazy()
testLazyStackTraceWorksInProd()701   public void testLazyStackTraceWorksInProd() {
702     // TODO(b/64442212): Remove this guard once lazyStackTrace() works in Java 9+.
703     Integer javaVersion = Ints.tryParse(JAVA_SPECIFICATION_VERSION.value());
704     if (javaVersion != null && javaVersion >= 9) {
705       return;
706     }
707     // Obviously this isn't guaranteed in every environment, but it works well enough for now:
708     assertTrue(lazyStackTraceIsLazy());
709   }
710 
711   @GwtIncompatible // lazyStackTrace(Throwable)
testLazyStackTrace()712   public void testLazyStackTrace() {
713     Exception e = new Exception();
714     StackTraceElement[] originalStackTrace = e.getStackTrace();
715 
716     assertThat(lazyStackTrace(e)).containsExactly((Object[]) originalStackTrace).inOrder();
717 
718     try {
719       lazyStackTrace(e).set(0, null);
720       fail();
721     } catch (UnsupportedOperationException expected) {
722     }
723 
724     // Now we test a property that holds only for the lazy implementation.
725 
726     if (!lazyStackTraceIsLazy()) {
727       return;
728     }
729 
730     e.setStackTrace(new StackTraceElement[0]);
731     assertThat(lazyStackTrace(e)).containsExactly((Object[]) originalStackTrace).inOrder();
732   }
733 
734   @GwtIncompatible // lazyStackTrace
doTestLazyStackTraceFallback()735   private void doTestLazyStackTraceFallback() {
736     assertFalse(lazyStackTraceIsLazy());
737 
738     Exception e = new Exception();
739 
740     assertThat(lazyStackTrace(e)).containsExactly((Object[]) e.getStackTrace()).inOrder();
741 
742     try {
743       lazyStackTrace(e).set(0, null);
744       fail();
745     } catch (UnsupportedOperationException expected) {
746     }
747 
748     e.setStackTrace(new StackTraceElement[0]);
749     assertThat(lazyStackTrace(e)).isEmpty();
750   }
751 
752   @GwtIncompatible // NullPointerTester
testNullPointers()753   public void testNullPointers() {
754     new NullPointerTester().testAllPublicStaticMethods(Throwables.class);
755   }
756 }
757