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