• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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.truth.Truth.assertThat;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.common.collect.ImmutableList;
24 import com.google.common.collect.ImmutableSet;
25 import com.google.common.collect.Lists;
26 import com.google.common.testing.ArbitraryInstances;
27 import java.lang.reflect.InvocationTargetException;
28 import java.lang.reflect.Method;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.List;
32 import junit.framework.AssertionFailedError;
33 import junit.framework.TestCase;
34 
35 /**
36  * Unit test for {@link Preconditions}.
37  *
38  * @author Kevin Bourrillion
39  * @author Jared Levy
40  */
41 @GwtCompatible(emulated = true)
42 public class PreconditionsTest extends TestCase {
testCheckArgument_simple_success()43   public void testCheckArgument_simple_success() {
44     Preconditions.checkArgument(true);
45   }
46 
testCheckArgument_simple_failure()47   public void testCheckArgument_simple_failure() {
48     try {
49       Preconditions.checkArgument(false);
50       fail("no exception thrown");
51     } catch (IllegalArgumentException expected) {
52     }
53   }
54 
testCheckArgument_simpleMessage_success()55   public void testCheckArgument_simpleMessage_success() {
56     Preconditions.checkArgument(true, IGNORE_ME);
57   }
58 
testCheckArgument_simpleMessage_failure()59   public void testCheckArgument_simpleMessage_failure() {
60     try {
61       Preconditions.checkArgument(false, new Message());
62       fail("no exception thrown");
63     } catch (IllegalArgumentException expected) {
64       verifySimpleMessage(expected);
65     }
66   }
67 
testCheckArgument_nullMessage_failure()68   public void testCheckArgument_nullMessage_failure() {
69     try {
70       Preconditions.checkArgument(false, null);
71       fail("no exception thrown");
72     } catch (IllegalArgumentException expected) {
73       assertThat(expected).hasMessageThat().isEqualTo("null");
74     }
75   }
76 
testCheckArgument_nullMessageWithArgs_failure()77   public void testCheckArgument_nullMessageWithArgs_failure() {
78     try {
79       Preconditions.checkArgument(false, null, "b", "d");
80       fail("no exception thrown");
81     } catch (IllegalArgumentException e) {
82       assertThat(e).hasMessageThat().isEqualTo("null [b, d]");
83     }
84   }
85 
testCheckArgument_nullArgs_failure()86   public void testCheckArgument_nullArgs_failure() {
87     try {
88       Preconditions.checkArgument(false, "A %s C %s E", null, null);
89       fail("no exception thrown");
90     } catch (IllegalArgumentException e) {
91       assertThat(e).hasMessageThat().isEqualTo("A null C null E");
92     }
93   }
94 
testCheckArgument_notEnoughArgs_failure()95   public void testCheckArgument_notEnoughArgs_failure() {
96     try {
97       Preconditions.checkArgument(false, "A %s C %s E", "b");
98       fail("no exception thrown");
99     } catch (IllegalArgumentException e) {
100       assertThat(e).hasMessageThat().isEqualTo("A b C %s E");
101     }
102   }
103 
testCheckArgument_tooManyArgs_failure()104   public void testCheckArgument_tooManyArgs_failure() {
105     try {
106       Preconditions.checkArgument(false, "A %s C %s E", "b", "d", "f");
107       fail("no exception thrown");
108     } catch (IllegalArgumentException e) {
109       assertThat(e).hasMessageThat().isEqualTo("A b C d E [f]");
110     }
111   }
112 
testCheckArgument_singleNullArg_failure()113   public void testCheckArgument_singleNullArg_failure() {
114     try {
115       Preconditions.checkArgument(false, "A %s C", (Object) null);
116       fail("no exception thrown");
117     } catch (IllegalArgumentException e) {
118       assertThat(e).hasMessageThat().isEqualTo("A null C");
119     }
120   }
121 
testCheckArgument_singleNullArray_failure()122   public void testCheckArgument_singleNullArray_failure() {
123     try {
124       Preconditions.checkArgument(false, "A %s C", (Object[]) null);
125       fail("no exception thrown");
126     } catch (IllegalArgumentException e) {
127       assertThat(e).hasMessageThat().isEqualTo("A (Object[])null C");
128     }
129   }
130 
testCheckArgument_complexMessage_success()131   public void testCheckArgument_complexMessage_success() {
132     Preconditions.checkArgument(true, "%s", IGNORE_ME);
133   }
134 
testCheckArgument_complexMessage_failure()135   public void testCheckArgument_complexMessage_failure() {
136     try {
137       Preconditions.checkArgument(false, FORMAT, 5);
138       fail("no exception thrown");
139     } catch (IllegalArgumentException expected) {
140       verifyComplexMessage(expected);
141     }
142   }
143 
testCheckState_simple_success()144   public void testCheckState_simple_success() {
145     Preconditions.checkState(true);
146   }
147 
testCheckState_simple_failure()148   public void testCheckState_simple_failure() {
149     try {
150       Preconditions.checkState(false);
151       fail("no exception thrown");
152     } catch (IllegalStateException expected) {
153     }
154   }
155 
testCheckState_simpleMessage_success()156   public void testCheckState_simpleMessage_success() {
157     Preconditions.checkState(true, IGNORE_ME);
158   }
159 
testCheckState_simpleMessage_failure()160   public void testCheckState_simpleMessage_failure() {
161     try {
162       Preconditions.checkState(false, new Message());
163       fail("no exception thrown");
164     } catch (IllegalStateException expected) {
165       verifySimpleMessage(expected);
166     }
167   }
168 
testCheckState_nullMessage_failure()169   public void testCheckState_nullMessage_failure() {
170     try {
171       Preconditions.checkState(false, null);
172       fail("no exception thrown");
173     } catch (IllegalStateException expected) {
174       assertThat(expected).hasMessageThat().isEqualTo("null");
175     }
176   }
177 
testCheckState_complexMessage_success()178   public void testCheckState_complexMessage_success() {
179     Preconditions.checkState(true, "%s", IGNORE_ME);
180   }
181 
testCheckState_complexMessage_failure()182   public void testCheckState_complexMessage_failure() {
183     try {
184       Preconditions.checkState(false, FORMAT, 5);
185       fail("no exception thrown");
186     } catch (IllegalStateException expected) {
187       verifyComplexMessage(expected);
188     }
189   }
190 
191   private static final String NON_NULL_STRING = "foo";
192 
testCheckNotNull_simple_success()193   public void testCheckNotNull_simple_success() {
194     String result = Preconditions.checkNotNull(NON_NULL_STRING);
195     assertSame(NON_NULL_STRING, result);
196   }
197 
testCheckNotNull_simple_failure()198   public void testCheckNotNull_simple_failure() {
199     try {
200       Preconditions.checkNotNull(null);
201       fail("no exception thrown");
202     } catch (NullPointerException expected) {
203     }
204   }
205 
testCheckNotNull_simpleMessage_success()206   public void testCheckNotNull_simpleMessage_success() {
207     String result = Preconditions.checkNotNull(NON_NULL_STRING, IGNORE_ME);
208     assertSame(NON_NULL_STRING, result);
209   }
210 
testCheckNotNull_simpleMessage_failure()211   public void testCheckNotNull_simpleMessage_failure() {
212     try {
213       Preconditions.checkNotNull(null, new Message());
214       fail("no exception thrown");
215     } catch (NullPointerException expected) {
216       verifySimpleMessage(expected);
217     }
218   }
219 
testCheckNotNull_complexMessage_success()220   public void testCheckNotNull_complexMessage_success() {
221     String result = Preconditions.checkNotNull(NON_NULL_STRING, "%s", IGNORE_ME);
222     assertSame(NON_NULL_STRING, result);
223   }
224 
testCheckNotNull_complexMessage_failure()225   public void testCheckNotNull_complexMessage_failure() {
226     try {
227       Preconditions.checkNotNull(null, FORMAT, 5);
228       fail("no exception thrown");
229     } catch (NullPointerException expected) {
230       verifyComplexMessage(expected);
231     }
232   }
233 
testCheckElementIndex_ok()234   public void testCheckElementIndex_ok() {
235     assertEquals(0, Preconditions.checkElementIndex(0, 1));
236     assertEquals(0, Preconditions.checkElementIndex(0, 2));
237     assertEquals(1, Preconditions.checkElementIndex(1, 2));
238   }
239 
testCheckElementIndex_badSize()240   public void testCheckElementIndex_badSize() {
241     try {
242       Preconditions.checkElementIndex(1, -1);
243       fail();
244     } catch (IllegalArgumentException expected) {
245       // don't care what the message text is, as this is an invalid usage of
246       // the Preconditions class, unlike all the other exceptions it throws
247     }
248   }
249 
testCheckElementIndex_negative()250   public void testCheckElementIndex_negative() {
251     try {
252       Preconditions.checkElementIndex(-1, 1);
253       fail();
254     } catch (IndexOutOfBoundsException expected) {
255       assertThat(expected).hasMessageThat().isEqualTo("index (-1) must not be negative");
256     }
257   }
258 
testCheckElementIndex_tooHigh()259   public void testCheckElementIndex_tooHigh() {
260     try {
261       Preconditions.checkElementIndex(1, 1);
262       fail();
263     } catch (IndexOutOfBoundsException expected) {
264       assertThat(expected).hasMessageThat().isEqualTo("index (1) must be less than size (1)");
265     }
266   }
267 
testCheckElementIndex_withDesc_negative()268   public void testCheckElementIndex_withDesc_negative() {
269     try {
270       Preconditions.checkElementIndex(-1, 1, "foo");
271       fail();
272     } catch (IndexOutOfBoundsException expected) {
273       assertThat(expected).hasMessageThat().isEqualTo("foo (-1) must not be negative");
274     }
275   }
276 
testCheckElementIndex_withDesc_tooHigh()277   public void testCheckElementIndex_withDesc_tooHigh() {
278     try {
279       Preconditions.checkElementIndex(1, 1, "foo");
280       fail();
281     } catch (IndexOutOfBoundsException expected) {
282       assertThat(expected).hasMessageThat().isEqualTo("foo (1) must be less than size (1)");
283     }
284   }
285 
testCheckPositionIndex_ok()286   public void testCheckPositionIndex_ok() {
287     assertEquals(0, Preconditions.checkPositionIndex(0, 0));
288     assertEquals(0, Preconditions.checkPositionIndex(0, 1));
289     assertEquals(1, Preconditions.checkPositionIndex(1, 1));
290   }
291 
testCheckPositionIndex_badSize()292   public void testCheckPositionIndex_badSize() {
293     try {
294       Preconditions.checkPositionIndex(1, -1);
295       fail();
296     } catch (IllegalArgumentException expected) {
297       // don't care what the message text is, as this is an invalid usage of
298       // the Preconditions class, unlike all the other exceptions it throws
299     }
300   }
301 
testCheckPositionIndex_negative()302   public void testCheckPositionIndex_negative() {
303     try {
304       Preconditions.checkPositionIndex(-1, 1);
305       fail();
306     } catch (IndexOutOfBoundsException expected) {
307       assertThat(expected).hasMessageThat().isEqualTo("index (-1) must not be negative");
308     }
309   }
310 
testCheckPositionIndex_tooHigh()311   public void testCheckPositionIndex_tooHigh() {
312     try {
313       Preconditions.checkPositionIndex(2, 1);
314       fail();
315     } catch (IndexOutOfBoundsException expected) {
316       assertThat(expected)
317           .hasMessageThat()
318           .isEqualTo("index (2) must not be greater than size (1)");
319     }
320   }
321 
testCheckPositionIndex_withDesc_negative()322   public void testCheckPositionIndex_withDesc_negative() {
323     try {
324       Preconditions.checkPositionIndex(-1, 1, "foo");
325       fail();
326     } catch (IndexOutOfBoundsException expected) {
327       assertThat(expected).hasMessageThat().isEqualTo("foo (-1) must not be negative");
328     }
329   }
330 
testCheckPositionIndex_withDesc_tooHigh()331   public void testCheckPositionIndex_withDesc_tooHigh() {
332     try {
333       Preconditions.checkPositionIndex(2, 1, "foo");
334       fail();
335     } catch (IndexOutOfBoundsException expected) {
336       assertThat(expected).hasMessageThat().isEqualTo("foo (2) must not be greater than size (1)");
337     }
338   }
339 
testCheckPositionIndexes_ok()340   public void testCheckPositionIndexes_ok() {
341     Preconditions.checkPositionIndexes(0, 0, 0);
342     Preconditions.checkPositionIndexes(0, 0, 1);
343     Preconditions.checkPositionIndexes(0, 1, 1);
344     Preconditions.checkPositionIndexes(1, 1, 1);
345   }
346 
testCheckPositionIndexes_badSize()347   public void testCheckPositionIndexes_badSize() {
348     try {
349       Preconditions.checkPositionIndexes(1, 1, -1);
350       fail();
351     } catch (IllegalArgumentException expected) {
352     }
353   }
354 
testCheckPositionIndex_startNegative()355   public void testCheckPositionIndex_startNegative() {
356     try {
357       Preconditions.checkPositionIndexes(-1, 1, 1);
358       fail();
359     } catch (IndexOutOfBoundsException expected) {
360       assertThat(expected).hasMessageThat().isEqualTo("start index (-1) must not be negative");
361     }
362   }
363 
testCheckPositionIndexes_endTooHigh()364   public void testCheckPositionIndexes_endTooHigh() {
365     try {
366       Preconditions.checkPositionIndexes(0, 2, 1);
367       fail();
368     } catch (IndexOutOfBoundsException expected) {
369       assertThat(expected)
370           .hasMessageThat()
371           .isEqualTo("end index (2) must not be greater than size (1)");
372     }
373   }
374 
testCheckPositionIndexes_reversed()375   public void testCheckPositionIndexes_reversed() {
376     try {
377       Preconditions.checkPositionIndexes(1, 0, 1);
378       fail();
379     } catch (IndexOutOfBoundsException expected) {
380       assertThat(expected)
381           .hasMessageThat()
382           .isEqualTo("end index (0) must not be less than start index (1)");
383     }
384   }
385 
386   @GwtIncompatible("Reflection")
testAllOverloads_checkArgument()387   public void testAllOverloads_checkArgument() throws Exception {
388     for (ImmutableList<Class<?>> sig : allSignatures(boolean.class)) {
389       Method checkArgumentMethod =
390           Preconditions.class.getMethod("checkArgument", sig.toArray(new Class<?>[] {}));
391       checkArgumentMethod.invoke(null /* static method */, getParametersForSignature(true, sig));
392 
393       Object[] failingParams = getParametersForSignature(false, sig);
394       try {
395         checkArgumentMethod.invoke(null /* static method */, failingParams);
396         fail();
397       } catch (InvocationTargetException ite) {
398         assertFailureCause(ite.getCause(), IllegalArgumentException.class, failingParams);
399       }
400     }
401   }
402 
403   @GwtIncompatible("Reflection")
testAllOverloads_checkState()404   public void testAllOverloads_checkState() throws Exception {
405     for (ImmutableList<Class<?>> sig : allSignatures(boolean.class)) {
406       Method checkArgumentMethod =
407           Preconditions.class.getMethod("checkState", sig.toArray(new Class<?>[] {}));
408       checkArgumentMethod.invoke(null /* static method */, getParametersForSignature(true, sig));
409 
410       Object[] failingParams = getParametersForSignature(false, sig);
411       try {
412         checkArgumentMethod.invoke(null /* static method */, failingParams);
413         fail();
414       } catch (InvocationTargetException ite) {
415         assertFailureCause(ite.getCause(), IllegalStateException.class, failingParams);
416       }
417     }
418   }
419 
420   @GwtIncompatible("Reflection")
testAllOverloads_checkNotNull()421   public void testAllOverloads_checkNotNull() throws Exception {
422     for (ImmutableList<Class<?>> sig : allSignatures(Object.class)) {
423       Method checkArgumentMethod =
424           Preconditions.class.getMethod("checkNotNull", sig.toArray(new Class<?>[] {}));
425       checkArgumentMethod.invoke(
426           null /* static method */, getParametersForSignature(new Object(), sig));
427 
428       Object[] failingParams = getParametersForSignature(null, sig);
429       try {
430         checkArgumentMethod.invoke(null /* static method */, failingParams);
431         fail();
432       } catch (InvocationTargetException ite) {
433         assertFailureCause(ite.getCause(), NullPointerException.class, failingParams);
434       }
435     }
436   }
437 
438   /**
439    * Asserts that the given throwable has the given class and then asserts on the message as using
440    * the full set of method parameters.
441    */
assertFailureCause( Throwable throwable, Class<? extends Throwable> clazz, Object[] params)442   private void assertFailureCause(
443       Throwable throwable, Class<? extends Throwable> clazz, Object[] params) {
444     assertThat(throwable).isInstanceOf(clazz);
445     if (params.length == 1) {
446       assertThat(throwable).hasMessageThat().isNull();
447     } else if (params.length == 2) {
448       assertThat(throwable).hasMessageThat().isEmpty();
449     } else {
450       assertThat(throwable)
451           .hasMessageThat()
452           .isEqualTo(Strings.lenientFormat("", Arrays.copyOfRange(params, 2, params.length)));
453     }
454   }
455 
456   /**
457    * Returns an array containing parameters for invoking a checkArgument, checkNotNull or checkState
458    * method reflectively
459    *
460    * @param firstParam The first parameter
461    * @param sig The method signature
462    */
463   @GwtIncompatible("ArbitraryInstances")
getParametersForSignature(Object firstParam, ImmutableList<Class<?>> sig)464   private Object[] getParametersForSignature(Object firstParam, ImmutableList<Class<?>> sig) {
465     Object[] params = new Object[sig.size()];
466     params[0] = firstParam;
467     if (params.length > 1) {
468       params[1] = "";
469       if (params.length > 2) {
470         // fill in the rest of the array with arbitrary instances
471         for (int i = 2; i < params.length; i++) {
472           params[i] = ArbitraryInstances.get(sig.get(i));
473         }
474       }
475     }
476     return params;
477   }
478 
479   private static final ImmutableList<Class<?>> possibleParamTypes =
480       ImmutableList.of(char.class, int.class, long.class, Object.class);
481 
482   /**
483    * Returns a list of parameters for invoking an overload of checkState, checkArgument or
484    * checkNotNull
485    *
486    * @param predicateType The first parameter to the method (boolean or Object)
487    */
allSignatures(Class<?> predicateType)488   private static ImmutableList<ImmutableList<Class<?>>> allSignatures(Class<?> predicateType) {
489     ImmutableSet.Builder<ImmutableList<Class<?>>> allOverloads = ImmutableSet.builder();
490     // The first two are for the overloads that don't take formatting args, e.g.
491     // checkArgument(boolean) and checkArgument(boolean, Object)
492     allOverloads.add(ImmutableList.<Class<?>>of(predicateType));
493     allOverloads.add(ImmutableList.<Class<?>>of(predicateType, Object.class));
494 
495     List<List<Class<?>>> typesLists = new ArrayList<>();
496     for (int i = 0; i < 2; i++) {
497       typesLists.add(possibleParamTypes);
498       for (List<Class<?>> curr : Lists.cartesianProduct(typesLists)) {
499         allOverloads.add(
500             ImmutableList.<Class<?>>builder()
501                 .add(predicateType)
502                 .add(String.class) // the format string
503                 .addAll(curr)
504                 .build());
505       }
506     }
507     return allOverloads.build().asList();
508   }
509 
510   // 'test' to demonstrate some potentially ambiguous overloads.  This 'test' is kind of strange,
511   // but essentially each line will be a call to a Preconditions method that, but for a documented
512   // change would be a compiler error.
513   // See http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2 for the spec on
514   // how javac selects overloads
515   @SuppressWarnings("null")
overloadSelection()516   public void overloadSelection() {
517     Boolean boxedBoolean = null;
518     boolean aBoolean = true;
519     Long boxedLong = null;
520     int anInt = 1;
521     // With a boxed predicate, no overloads can be selected in phase 1
522     // ambiguous without the call to .booleanValue to unbox the Boolean
523     Preconditions.checkState(boxedBoolean.booleanValue(), "", 1);
524     // ambiguous without the cast to Object because the boxed predicate prevents any overload from
525     // being selected in phase 1
526     Preconditions.checkState(boxedBoolean, "", (Object) boxedLong);
527 
528     // ternaries introduce their own problems. because of the ternary (which requires a boxing
529     // operation) no overload can be selected in phase 1.  and in phase 2 it is ambiguous since it
530     // matches with the second parameter being boxed and without it being boxed.  The cast to Object
531     // avoids this.
532     Preconditions.checkState(aBoolean, "", aBoolean ? "" : anInt, (Object) anInt);
533 
534     // ambiguous without the .booleanValue() call since the boxing forces us into phase 2 resolution
535     short s = 2;
536     Preconditions.checkState(boxedBoolean.booleanValue(), "", s);
537   }
538 
539   @GwtIncompatible // NullPointerTester
testNullPointers()540   public void testNullPointers() {
541     /*
542      * Don't bother testing: Preconditions defines a bunch of methods that accept a template (or
543      * even entire message) that simultaneously:
544      *
545      * - _shouldn't_ be null, so we don't annotate it with @Nullable
546      *
547      * - _can_ be null without causing a runtime failure (because we don't want the interesting
548      *   details of precondition failure to be hidden by an exception we throw about an unexpectedly
549      *   null _failure message_)
550      *
551      * That combination upsets NullPointerTester, which wants any call that passes null for a
552      * non-@Nullable parameter to trigger a NullPointerException.
553      *
554      * (We still define this empty method to keep PackageSanityTests from generating its own
555      * automated nullness tests, which would fail.)
556      */
557   }
558 
559   private static final Object IGNORE_ME =
560       new Object() {
561         @Override
562         public String toString() {
563           throw new AssertionFailedError();
564         }
565       };
566 
567   private static class Message {
568     boolean invoked;
569 
570     @Override
toString()571     public String toString() {
572       assertFalse(invoked);
573       invoked = true;
574       return "A message";
575     }
576   }
577 
578   private static final String FORMAT = "I ate %s pies.";
579 
verifySimpleMessage(Exception e)580   private static void verifySimpleMessage(Exception e) {
581     assertThat(e).hasMessageThat().isEqualTo("A message");
582   }
583 
verifyComplexMessage(Exception e)584   private static void verifyComplexMessage(Exception e) {
585     assertThat(e).hasMessageThat().isEqualTo("I ate 5 pies.");
586   }
587 }
588