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