• 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.ReflectionFreeAssertThrows.assertThrows;
20 import static com.google.common.base.StandardSystemProperty.JAVA_SPECIFICATION_VERSION;
21 import static com.google.common.base.Throwables.getCausalChain;
22 import static com.google.common.base.Throwables.getCauseAs;
23 import static com.google.common.base.Throwables.getRootCause;
24 import static com.google.common.base.Throwables.getStackTraceAsString;
25 import static com.google.common.base.Throwables.lazyStackTrace;
26 import static com.google.common.base.Throwables.lazyStackTraceIsLazy;
27 import static com.google.common.base.Throwables.propagate;
28 import static com.google.common.base.Throwables.propagateIfInstanceOf;
29 import static com.google.common.base.Throwables.propagateIfPossible;
30 import static com.google.common.base.Throwables.throwIfInstanceOf;
31 import static com.google.common.base.Throwables.throwIfUnchecked;
32 import static com.google.common.truth.Truth.assertThat;
33 import static java.util.regex.Pattern.quote;
34 
35 import com.google.common.annotations.GwtCompatible;
36 import com.google.common.annotations.GwtIncompatible;
37 import com.google.common.annotations.J2ktIncompatible;
38 import com.google.common.base.TestExceptions.SomeChainingException;
39 import com.google.common.base.TestExceptions.SomeCheckedException;
40 import com.google.common.base.TestExceptions.SomeError;
41 import com.google.common.base.TestExceptions.SomeOtherCheckedException;
42 import com.google.common.base.TestExceptions.SomeUncheckedException;
43 import com.google.common.base.TestExceptions.YetAnotherCheckedException;
44 import com.google.common.collect.Iterables;
45 import com.google.common.primitives.Ints;
46 import com.google.common.testing.NullPointerTester;
47 import java.util.List;
48 import junit.framework.TestCase;
49 
50 /**
51  * Unit test for {@link Throwables}.
52  *
53  * @author Kevin Bourrillion
54  */
55 @GwtCompatible(emulated = true)
56 @SuppressWarnings("deprecation") // tests of numerous deprecated methods
57 public class ThrowablesTest extends TestCase {
testThrowIfUnchecked_unchecked()58   public void testThrowIfUnchecked_unchecked() {
59     assertThrows(
60         SomeUncheckedException.class, () -> throwIfUnchecked(new SomeUncheckedException()));
61   }
62 
testThrowIfUnchecked_error()63   public void testThrowIfUnchecked_error() {
64     assertThrows(SomeError.class, () -> throwIfUnchecked(new SomeError()));
65   }
66 
67   @SuppressWarnings("ThrowIfUncheckedKnownChecked")
testThrowIfUnchecked_checked()68   public void testThrowIfUnchecked_checked() {
69     throwIfUnchecked(new SomeCheckedException());
70   }
71 
72   @J2ktIncompatible
73   @GwtIncompatible // propagateIfPossible
testPropagateIfPossible_noneDeclared_unchecked()74   public void testPropagateIfPossible_noneDeclared_unchecked() {
75     assertThrows(
76         SomeUncheckedException.class, () -> propagateIfPossible(new SomeUncheckedException()));
77   }
78 
79   @J2ktIncompatible
80   @GwtIncompatible // propagateIfPossible
81   @SuppressWarnings("ThrowIfUncheckedKnownChecked")
testPropagateIfPossible_noneDeclared_checked()82   public void testPropagateIfPossible_noneDeclared_checked() {
83     propagateIfPossible(new SomeCheckedException());
84   }
85 
86   @J2ktIncompatible
87   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropagateIfPossible_oneDeclared_unchecked()88   public void testPropagateIfPossible_oneDeclared_unchecked() {
89     assertThrows(
90         SomeUncheckedException.class,
91         () -> propagateIfPossible(new SomeUncheckedException(), SomeCheckedException.class));
92   }
93 
94   @J2ktIncompatible
95   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropagateIfPossible_oneDeclared_checkedSame()96   public void testPropagateIfPossible_oneDeclared_checkedSame() {
97     assertThrows(
98         SomeCheckedException.class,
99         () -> propagateIfPossible(new SomeCheckedException(), SomeCheckedException.class));
100   }
101 
102   @J2ktIncompatible
103   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropagateIfPossible_oneDeclared_checkedDifferent()104   public void testPropagateIfPossible_oneDeclared_checkedDifferent() throws SomeCheckedException {
105     propagateIfPossible(new SomeOtherCheckedException(), SomeCheckedException.class);
106   }
107 
108   @J2ktIncompatible
109   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropagateIfPossible_twoDeclared_unchecked()110   public void testPropagateIfPossible_twoDeclared_unchecked() {
111     assertThrows(
112         SomeUncheckedException.class,
113         () ->
114             propagateIfPossible(
115                 new SomeUncheckedException(),
116                 SomeCheckedException.class,
117                 SomeOtherCheckedException.class));
118   }
119 
120   @J2ktIncompatible
121   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropagateIfPossible_twoDeclared_firstSame()122   public void testPropagateIfPossible_twoDeclared_firstSame() {
123     assertThrows(
124         SomeCheckedException.class,
125         () ->
126             propagateIfPossible(
127                 new SomeCheckedException(),
128                 SomeCheckedException.class,
129                 SomeOtherCheckedException.class));
130   }
131 
132   @J2ktIncompatible
133   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropagateIfPossible_twoDeclared_secondSame()134   public void testPropagateIfPossible_twoDeclared_secondSame() {
135     assertThrows(
136         SomeOtherCheckedException.class,
137         () ->
138             propagateIfPossible(
139                 new SomeOtherCheckedException(),
140                 SomeCheckedException.class,
141                 SomeOtherCheckedException.class));
142   }
143 
144   @J2ktIncompatible
145   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropagateIfPossible_twoDeclared_neitherSame()146   public void testPropagateIfPossible_twoDeclared_neitherSame()
147       throws SomeCheckedException, SomeOtherCheckedException {
148     propagateIfPossible(
149         new YetAnotherCheckedException(),
150         SomeCheckedException.class,
151         SomeOtherCheckedException.class);
152   }
153 
testThrowIfUnchecked_null()154   public void testThrowIfUnchecked_null() {
155     assertThrows(NullPointerException.class, () -> throwIfUnchecked(null));
156   }
157 
158   @J2ktIncompatible
159   @GwtIncompatible // propagateIfPossible
testPropageIfPossible_null()160   public void testPropageIfPossible_null() {
161     propagateIfPossible(null);
162   }
163 
164   @J2ktIncompatible
165   @GwtIncompatible // propagateIfPossible(Throwable, Class)
testPropageIfPossible_oneDeclared_null()166   public void testPropageIfPossible_oneDeclared_null() throws SomeCheckedException {
167     propagateIfPossible(null, SomeCheckedException.class);
168   }
169 
170   @J2ktIncompatible
171   @GwtIncompatible // propagateIfPossible(Throwable, Class, Class)
testPropageIfPossible_twoDeclared_null()172   public void testPropageIfPossible_twoDeclared_null()
173       throws SomeCheckedException, SomeOtherCheckedException {
174     propagateIfPossible(null, SomeCheckedException.class, SomeOtherCheckedException.class);
175   }
176 
177   @J2ktIncompatible
178   @GwtIncompatible // propagate
testPropagate_noneDeclared_unchecked()179   public void testPropagate_noneDeclared_unchecked() {
180     assertThrows(SomeUncheckedException.class, () -> propagate(new SomeUncheckedException()));
181   }
182 
183   @J2ktIncompatible
184   @GwtIncompatible // propagate
testPropagate_noneDeclared_error()185   public void testPropagate_noneDeclared_error() {
186     assertThrows(SomeError.class, () -> propagate(new SomeError()));
187   }
188 
189   @J2ktIncompatible
190   @GwtIncompatible // propagate
testPropagate_noneDeclared_checked()191   public void testPropagate_noneDeclared_checked() {
192     RuntimeException expected =
193         assertThrows(RuntimeException.class, () -> propagate(new SomeCheckedException()));
194     assertThat(expected).hasCauseThat().isInstanceOf(SomeCheckedException.class);
195   }
196 
197   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_unchecked()198   public void testThrowIfInstanceOf_unchecked() throws SomeCheckedException {
199     throwIfInstanceOf(new SomeUncheckedException(), SomeCheckedException.class);
200   }
201 
202   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_checkedDifferent()203   public void testThrowIfInstanceOf_checkedDifferent() throws SomeCheckedException {
204     throwIfInstanceOf(new SomeOtherCheckedException(), SomeCheckedException.class);
205   }
206 
207   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_checkedSame()208   public void testThrowIfInstanceOf_checkedSame() {
209     assertThrows(
210         SomeCheckedException.class,
211         () -> throwIfInstanceOf(new SomeCheckedException(), SomeCheckedException.class));
212   }
213 
214   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_checkedSubclass()215   public void testThrowIfInstanceOf_checkedSubclass() {
216     assertThrows(
217         SomeCheckedException.class,
218         () -> throwIfInstanceOf(new SomeCheckedException() {}, SomeCheckedException.class));
219   }
220 
221   @J2ktIncompatible
222   @GwtIncompatible // propagateIfInstanceOf
testPropagateIfInstanceOf_checkedSame()223   public void testPropagateIfInstanceOf_checkedSame() {
224     assertThrows(
225         SomeCheckedException.class,
226         () -> propagateIfInstanceOf(new SomeCheckedException(), SomeCheckedException.class));
227   }
228 
229   @J2ktIncompatible
230   @GwtIncompatible // propagateIfInstanceOf
testPropagateIfInstanceOf_unchecked()231   public void testPropagateIfInstanceOf_unchecked() throws SomeCheckedException {
232     propagateIfInstanceOf(new SomeUncheckedException(), SomeCheckedException.class);
233   }
234 
235   @J2ktIncompatible
236   @GwtIncompatible // propagateIfInstanceOf
testPropagateIfInstanceOf_checkedDifferent()237   public void testPropagateIfInstanceOf_checkedDifferent() throws SomeCheckedException {
238     propagateIfInstanceOf(new SomeOtherCheckedException(), SomeCheckedException.class);
239   }
240 
241   @GwtIncompatible // throwIfInstanceOf
testThrowIfInstanceOf_null()242   public void testThrowIfInstanceOf_null() {
243     assertThrows(
244         NullPointerException.class, () -> throwIfInstanceOf(null, SomeCheckedException.class));
245   }
246 
247   @J2ktIncompatible
248   @GwtIncompatible // propagateIfInstanceOf
testPropageIfInstanceOf_null()249   public void testPropageIfInstanceOf_null() throws SomeCheckedException {
250     propagateIfInstanceOf(null, SomeCheckedException.class);
251   }
252 
testGetRootCause_noCause()253   public void testGetRootCause_noCause() {
254     SomeCheckedException exception = new SomeCheckedException();
255     assertSame(exception, getRootCause(exception));
256   }
257 
testGetRootCause_singleWrapped()258   public void testGetRootCause_singleWrapped() {
259     SomeCheckedException cause = new SomeCheckedException();
260     SomeChainingException exception = new SomeChainingException(cause);
261     assertSame(cause, getRootCause(exception));
262   }
263 
testGetRootCause_doubleWrapped()264   public void testGetRootCause_doubleWrapped() {
265     SomeCheckedException cause = new SomeCheckedException();
266     SomeChainingException exception = new SomeChainingException(new SomeChainingException(cause));
267     assertSame(cause, getRootCause(exception));
268   }
269 
testGetRootCause_loop()270   public void testGetRootCause_loop() {
271     Exception cause = new Exception();
272     Exception exception = new Exception(cause);
273     cause.initCause(exception);
274     IllegalArgumentException expected =
275         assertThrows(IllegalArgumentException.class, () -> getRootCause(cause));
276     assertThat(expected).hasCauseThat().isSameInstanceAs(cause);
277   }
278 
279   @J2ktIncompatible // Format does not match
280   @GwtIncompatible // getStackTraceAsString(Throwable)
testGetStackTraceAsString()281   public void testGetStackTraceAsString() {
282     class StackTraceException extends Exception {
283       StackTraceException(String message) {
284         super(message);
285       }
286     }
287 
288     StackTraceException e = new StackTraceException("my message");
289 
290     String firstLine = quote(e.getClass().getName() + ": " + e.getMessage());
291     String secondLine = "\\s*at " + ThrowablesTest.class.getName() + "\\..*";
292     String moreLines = "(?:.*" + System.lineSeparator() + "?)*";
293     String expected =
294         firstLine + System.lineSeparator() + secondLine + System.lineSeparator() + moreLines;
295     assertThat(getStackTraceAsString(e)).matches(expected);
296   }
297 
testGetCausalChain()298   public void testGetCausalChain() {
299     SomeUncheckedException sue = new SomeUncheckedException();
300     IllegalArgumentException iae = new IllegalArgumentException(sue);
301     RuntimeException re = new RuntimeException(iae);
302     IllegalStateException ex = new IllegalStateException(re);
303 
304     assertThat(getCausalChain(ex)).containsExactly(ex, re, iae, sue).inOrder();
305     assertSame(sue, Iterables.getOnlyElement(getCausalChain(sue)));
306 
307     List<Throwable> causes = getCausalChain(ex);
308     assertThrows(UnsupportedOperationException.class, () -> causes.add(new RuntimeException()));
309   }
310 
testGetCasualChainNull()311   public void testGetCasualChainNull() {
312     assertThrows(NullPointerException.class, () -> getCausalChain(null));
313   }
314 
testGetCasualChainLoop()315   public void testGetCasualChainLoop() {
316     Exception cause = new Exception();
317     Exception exception = new Exception(cause);
318     cause.initCause(exception);
319     IllegalArgumentException expected =
320         assertThrows(IllegalArgumentException.class, () -> getCausalChain(cause));
321     assertThat(expected).hasCauseThat().isSameInstanceAs(cause);
322   }
323 
324   @GwtIncompatible // getCauseAs(Throwable, Class)
testGetCauseAs()325   public void testGetCauseAs() {
326     SomeCheckedException cause = new SomeCheckedException();
327     SomeChainingException thrown = new SomeChainingException(cause);
328 
329     assertThat(thrown).hasCauseThat().isSameInstanceAs(cause);
330     assertThat(getCauseAs(thrown, SomeCheckedException.class)).isSameInstanceAs(cause);
331     assertThat(getCauseAs(thrown, Exception.class)).isSameInstanceAs(cause);
332 
333     ClassCastException expected =
334         assertThrows(
335             ClassCastException.class, () -> getCauseAs(thrown, IllegalStateException.class));
336     assertThat(expected).hasCauseThat().isSameInstanceAs(thrown);
337   }
338 
339   @AndroidIncompatible // No getJavaLangAccess in Android (at least not in the version we use).
340   @J2ktIncompatible
341   @GwtIncompatible // lazyStackTraceIsLazy()
testLazyStackTraceWorksInProd()342   public void testLazyStackTraceWorksInProd() {
343     // TODO(b/64442212): Remove this guard once lazyStackTrace() works in Java 9+.
344     Integer javaVersion = Ints.tryParse(JAVA_SPECIFICATION_VERSION.value());
345     if (javaVersion != null && javaVersion >= 9) {
346       return;
347     }
348     // Obviously this isn't guaranteed in every environment, but it works well enough for now:
349     assertTrue(lazyStackTraceIsLazy());
350   }
351 
352   @J2ktIncompatible
353   @GwtIncompatible // lazyStackTrace(Throwable)
testLazyStackTrace()354   public void testLazyStackTrace() {
355     Exception e = new Exception();
356     StackTraceElement[] originalStackTrace = e.getStackTrace();
357 
358     assertThat(lazyStackTrace(e)).containsExactly((Object[]) originalStackTrace).inOrder();
359 
360     assertThrows(UnsupportedOperationException.class, () -> lazyStackTrace(e).set(0, null));
361 
362     // Now we test a property that holds only for the lazy implementation.
363 
364     if (!lazyStackTraceIsLazy()) {
365       return;
366     }
367 
368     e.setStackTrace(new StackTraceElement[0]);
369     assertThat(lazyStackTrace(e)).containsExactly((Object[]) originalStackTrace).inOrder();
370   }
371 
372   @J2ktIncompatible
373   @GwtIncompatible // lazyStackTrace
doTestLazyStackTraceFallback()374   private void doTestLazyStackTraceFallback() {
375     assertFalse(lazyStackTraceIsLazy());
376 
377     Exception e = new Exception();
378 
379     assertThat(lazyStackTrace(e)).containsExactly((Object[]) e.getStackTrace()).inOrder();
380 
381     try {
382       lazyStackTrace(e).set(0, null);
383       fail();
384     } catch (UnsupportedOperationException expected) {
385     }
386 
387     e.setStackTrace(new StackTraceElement[0]);
388     assertThat(lazyStackTrace(e)).isEmpty();
389   }
390 
391   @J2ktIncompatible
392   @GwtIncompatible // NullPointerTester
testNullPointers()393   public void testNullPointers() {
394     new NullPointerTester().testAllPublicStaticMethods(Throwables.class);
395   }
396 }
397