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