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