• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005 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.testing;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import com.google.common.base.Converter;
24 import com.google.common.base.Function;
25 import com.google.common.base.Supplier;
26 import com.google.common.collect.ImmutableList;
27 import com.google.common.collect.ImmutableMap;
28 import com.google.common.collect.ImmutableMultimap;
29 import com.google.common.collect.ImmutableMultiset;
30 import com.google.common.collect.ImmutableSet;
31 import com.google.common.collect.ImmutableSortedSet;
32 import com.google.common.collect.ImmutableTable;
33 import com.google.common.collect.Maps;
34 import com.google.common.collect.Multimap;
35 import com.google.common.collect.Multiset;
36 import com.google.common.collect.Table;
37 import com.google.common.reflect.TypeToken;
38 import com.google.common.testing.NullPointerTester.Visibility;
39 import com.google.common.testing.anotherpackage.SomeClassThatDoesNotUseNullable;
40 import java.lang.reflect.Constructor;
41 import java.lang.reflect.Method;
42 import java.util.List;
43 import java.util.Locale;
44 import java.util.Map;
45 import java.util.Set;
46 import java.util.SortedSet;
47 import junit.framework.AssertionFailedError;
48 import junit.framework.TestCase;
49 import org.checkerframework.checker.nullness.qual.Nullable;
50 
51 /**
52  * Unit test for {@link NullPointerTester}.
53  *
54  * @author Kevin Bourrillion
55  * @author Mick Killianey
56  */
57 public class NullPointerTesterTest extends TestCase {
58 
59   /** Non-NPE RuntimeException. */
60   public static class FooException extends RuntimeException {
61     private static final long serialVersionUID = 1L;
62   }
63 
64   /**
65    * Class for testing all permutations of static/non-static one-argument methods using
66    * methodParameter().
67    */
68   @SuppressWarnings("unused") // used by reflection
69   public static class OneArg {
70 
staticOneArgCorrectlyThrowsNpe(String s)71     public static void staticOneArgCorrectlyThrowsNpe(String s) {
72       checkNotNull(s); // expect NPE here on null
73     }
74 
staticOneArgThrowsOtherThanNpe(String s)75     public static void staticOneArgThrowsOtherThanNpe(String s) {
76       throw new FooException(); // should catch as failure
77     }
78 
staticOneArgShouldThrowNpeButDoesnt(String s)79     public static void staticOneArgShouldThrowNpeButDoesnt(String s) {
80       // should catch as failure
81     }
82 
staticOneArgCheckForNullCorrectlyDoesNotThrowNPE( @avax.annotation.CheckForNull String s)83     public static void staticOneArgCheckForNullCorrectlyDoesNotThrowNPE(
84         @javax.annotation.CheckForNull String s) {
85       // null?  no problem
86     }
87 
staticOneArgJsr305NullableCorrectlyDoesNotThrowNPE( @avax.annotation.Nullable String s)88     public static void staticOneArgJsr305NullableCorrectlyDoesNotThrowNPE(
89         @javax.annotation.Nullable String s) {
90       // null?  no problem
91     }
92 
staticOneArgNullableCorrectlyDoesNotThrowNPE(@ullable String s)93     public static void staticOneArgNullableCorrectlyDoesNotThrowNPE(@Nullable String s) {
94       // null?  no problem
95     }
96 
staticOneArgCheckForNullCorrectlyThrowsOtherThanNPE( @avax.annotation.CheckForNull String s)97     public static void staticOneArgCheckForNullCorrectlyThrowsOtherThanNPE(
98         @javax.annotation.CheckForNull String s) {
99       throw new FooException(); // ok, as long as it's not NullPointerException
100     }
101 
staticOneArgNullableCorrectlyThrowsOtherThanNPE(@ullable String s)102     public static void staticOneArgNullableCorrectlyThrowsOtherThanNPE(@Nullable String s) {
103       throw new FooException(); // ok, as long as it's not NullPointerException
104     }
105 
staticOneArgCheckForNullThrowsNPE(@avax.annotation.CheckForNull String s)106     public static void staticOneArgCheckForNullThrowsNPE(@javax.annotation.CheckForNull String s) {
107       checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
108     }
109 
staticOneArgNullableThrowsNPE(@ullable String s)110     public static void staticOneArgNullableThrowsNPE(@Nullable String s) {
111       checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
112     }
113 
oneArgCorrectlyThrowsNpe(String s)114     public void oneArgCorrectlyThrowsNpe(String s) {
115       checkNotNull(s); // expect NPE here on null
116     }
117 
oneArgThrowsOtherThanNpe(String s)118     public void oneArgThrowsOtherThanNpe(String s) {
119       throw new FooException(); // should catch as failure
120     }
121 
oneArgShouldThrowNpeButDoesnt(String s)122     public void oneArgShouldThrowNpeButDoesnt(String s) {
123       // should catch as failure
124     }
125 
oneArgCheckForNullCorrectlyDoesNotThrowNPE( @avax.annotation.CheckForNull String s)126     public void oneArgCheckForNullCorrectlyDoesNotThrowNPE(
127         @javax.annotation.CheckForNull String s) {
128       // null?  no problem
129     }
130 
oneArgNullableCorrectlyDoesNotThrowNPE(@ullable String s)131     public void oneArgNullableCorrectlyDoesNotThrowNPE(@Nullable String s) {
132       // null?  no problem
133     }
134 
oneArgCheckForNullCorrectlyThrowsOtherThanNPE( @avax.annotation.CheckForNull String s)135     public void oneArgCheckForNullCorrectlyThrowsOtherThanNPE(
136         @javax.annotation.CheckForNull String s) {
137       throw new FooException(); // ok, as long as it's not NullPointerException
138     }
139 
oneArgNullableCorrectlyThrowsOtherThanNPE(@ullable String s)140     public void oneArgNullableCorrectlyThrowsOtherThanNPE(@Nullable String s) {
141       throw new FooException(); // ok, as long as it's not NullPointerException
142     }
143 
oneArgCheckForNullThrowsNPE(@avax.annotation.CheckForNull String s)144     public void oneArgCheckForNullThrowsNPE(@javax.annotation.CheckForNull String s) {
145       checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
146     }
147 
oneArgNullableThrowsNPE(@ullable String s)148     public void oneArgNullableThrowsNPE(@Nullable String s) {
149       checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
150     }
151   }
152 
153   private static final String[] STATIC_ONE_ARG_METHODS_SHOULD_PASS = {
154     "staticOneArgCorrectlyThrowsNpe",
155     "staticOneArgCheckForNullCorrectlyDoesNotThrowNPE",
156     "staticOneArgCheckForNullCorrectlyThrowsOtherThanNPE",
157     "staticOneArgCheckForNullThrowsNPE",
158     "staticOneArgNullableCorrectlyDoesNotThrowNPE",
159     "staticOneArgNullableCorrectlyThrowsOtherThanNPE",
160     "staticOneArgNullableThrowsNPE",
161   };
162   private static final String[] STATIC_ONE_ARG_METHODS_SHOULD_FAIL = {
163     "staticOneArgThrowsOtherThanNpe", "staticOneArgShouldThrowNpeButDoesnt",
164   };
165   private static final String[] NONSTATIC_ONE_ARG_METHODS_SHOULD_PASS = {
166     "oneArgCorrectlyThrowsNpe",
167     "oneArgCheckForNullCorrectlyDoesNotThrowNPE",
168     "oneArgCheckForNullCorrectlyThrowsOtherThanNPE",
169     "oneArgCheckForNullThrowsNPE",
170     "oneArgNullableCorrectlyDoesNotThrowNPE",
171     "oneArgNullableCorrectlyThrowsOtherThanNPE",
172     "oneArgNullableThrowsNPE",
173   };
174   private static final String[] NONSTATIC_ONE_ARG_METHODS_SHOULD_FAIL = {
175     "oneArgThrowsOtherThanNpe", "oneArgShouldThrowNpeButDoesnt",
176   };
177 
178   private static class ThrowsIae {
christenPoodle(String name)179     public static void christenPoodle(String name) {
180       checkArgument(name != null);
181     }
182   }
183 
184   private static class ThrowsNpe {
christenPoodle(String name)185     public static void christenPoodle(String name) {
186       checkNotNull(name);
187     }
188   }
189 
190   private static class ThrowsUoe {
christenPoodle(String name)191     public static void christenPoodle(String name) {
192       throw new UnsupportedOperationException();
193     }
194   }
195 
196   private static class ThrowsSomethingElse {
christenPoodle(String name)197     public static void christenPoodle(String name) {
198       throw new RuntimeException();
199     }
200   }
201 
202   private interface InterfaceStaticMethodFailsToCheckNull {
create(String s)203     static String create(String s) {
204       return "I don't check";
205     }
206   }
207 
208   private interface InterfaceStaticMethodChecksNull {
create(String s)209     static String create(String s) {
210       return checkNotNull(s);
211     }
212   }
213 
214   private interface InterfaceDefaultMethodFailsToCheckNull {
create()215     static InterfaceDefaultMethodFailsToCheckNull create() {
216       return new InterfaceDefaultMethodFailsToCheckNull() {};
217     }
218 
doNotCheckNull(String s)219     default void doNotCheckNull(String s) {}
220   }
221 
222   private interface InterfaceDefaultMethodChecksNull {
create()223     static InterfaceDefaultMethodChecksNull create() {
224       return new InterfaceDefaultMethodChecksNull() {};
225     }
226 
checksNull(String s)227     default void checksNull(String s) {
228       checkNotNull(s);
229     }
230   }
231 
testInterfaceStaticMethod()232   public void testInterfaceStaticMethod() {
233     NullPointerTester tester = new NullPointerTester();
234     tester.testAllPublicStaticMethods(InterfaceStaticMethodChecksNull.class);
235     try {
236       tester.testAllPublicStaticMethods(InterfaceStaticMethodFailsToCheckNull.class);
237     } catch (AssertionError expected) {
238       return;
239     }
240     fail();
241   }
242 
testInterfaceDefaultMethod()243   public void testInterfaceDefaultMethod() {
244     NullPointerTester tester = new NullPointerTester();
245     tester.testAllPublicInstanceMethods(InterfaceDefaultMethodChecksNull.create());
246     try {
247       tester.testAllPublicInstanceMethods(InterfaceDefaultMethodFailsToCheckNull.create());
248     } catch (AssertionError expected) {
249       return;
250     }
251     fail();
252   }
253 
testDontAcceptIae()254   public void testDontAcceptIae() {
255     NullPointerTester tester = new NullPointerTester();
256     tester.testAllPublicStaticMethods(ThrowsNpe.class);
257     tester.testAllPublicStaticMethods(ThrowsUoe.class);
258     try {
259       tester.testAllPublicStaticMethods(ThrowsIae.class);
260     } catch (AssertionFailedError expected) {
261       return;
262     }
263     fail();
264   }
265 
testStaticOneArgMethodsThatShouldPass()266   public void testStaticOneArgMethodsThatShouldPass() throws Exception {
267     for (String methodName : STATIC_ONE_ARG_METHODS_SHOULD_PASS) {
268       Method method = OneArg.class.getMethod(methodName, String.class);
269       try {
270         new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
271       } catch (AssertionFailedError unexpected) {
272         fail("Should not have flagged method " + methodName);
273       }
274     }
275   }
276 
testStaticOneArgMethodsThatShouldFail()277   public void testStaticOneArgMethodsThatShouldFail() throws Exception {
278     for (String methodName : STATIC_ONE_ARG_METHODS_SHOULD_FAIL) {
279       Method method = OneArg.class.getMethod(methodName, String.class);
280       boolean foundProblem = false;
281       try {
282         new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
283       } catch (AssertionFailedError expected) {
284         foundProblem = true;
285       }
286       assertTrue("Should report error in method " + methodName, foundProblem);
287     }
288   }
289 
testNonStaticOneArgMethodsThatShouldPass()290   public void testNonStaticOneArgMethodsThatShouldPass() throws Exception {
291     OneArg foo = new OneArg();
292     for (String methodName : NONSTATIC_ONE_ARG_METHODS_SHOULD_PASS) {
293       Method method = OneArg.class.getMethod(methodName, String.class);
294       try {
295         new NullPointerTester().testMethodParameter(foo, method, 0);
296       } catch (AssertionFailedError unexpected) {
297         fail("Should not have flagged method " + methodName);
298       }
299     }
300   }
301 
testNonStaticOneArgMethodsThatShouldFail()302   public void testNonStaticOneArgMethodsThatShouldFail() throws Exception {
303     OneArg foo = new OneArg();
304     for (String methodName : NONSTATIC_ONE_ARG_METHODS_SHOULD_FAIL) {
305       Method method = OneArg.class.getMethod(methodName, String.class);
306       boolean foundProblem = false;
307       try {
308         new NullPointerTester().testMethodParameter(foo, method, 0);
309       } catch (AssertionFailedError expected) {
310         foundProblem = true;
311       }
312       assertTrue("Should report error in method " + methodName, foundProblem);
313     }
314   }
315 
testMessageOtherException()316   public void testMessageOtherException() throws Exception {
317     Method method = OneArg.class.getMethod("staticOneArgThrowsOtherThanNpe", String.class);
318     boolean foundProblem = false;
319     try {
320       new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
321     } catch (AssertionFailedError expected) {
322       assertThat(expected.getMessage()).contains("index 0");
323       assertThat(expected.getMessage()).contains("[null]");
324       foundProblem = true;
325     }
326     assertTrue("Should report error when different exception is thrown", foundProblem);
327   }
328 
testMessageNoException()329   public void testMessageNoException() throws Exception {
330     Method method = OneArg.class.getMethod("staticOneArgShouldThrowNpeButDoesnt", String.class);
331     boolean foundProblem = false;
332     try {
333       new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
334     } catch (AssertionFailedError expected) {
335       assertThat(expected.getMessage()).contains("index 0");
336       assertThat(expected.getMessage()).contains("[null]");
337       foundProblem = true;
338     }
339     assertTrue("Should report error when no exception is thrown", foundProblem);
340   }
341 
342   /**
343    * Class for testing all permutations of nullable/non-nullable two-argument methods using
344    * testMethod().
345    *
346    * <ul>
347    *   <li>normalNormal: two params, neither is Nullable
348    *   <li>nullableNormal: only first param is Nullable
349    *   <li>normalNullable: only second param is Nullable
350    *   <li>nullableNullable: both params are Nullable
351    * </ul>
352    */
353   public static class TwoArg {
354     /** Action to take on a null param. */
355     public enum Action {
356       THROW_A_NPE {
357         @Override
act()358         public void act() {
359           throw new NullPointerException();
360         }
361       },
362       THROW_OTHER {
363         @Override
act()364         public void act() {
365           throw new FooException();
366         }
367       },
368       JUST_RETURN {
369         @Override
act()370         public void act() {}
371       };
372 
act()373       public abstract void act();
374     }
375 
376     Action actionWhenFirstParamIsNull;
377     Action actionWhenSecondParamIsNull;
378 
TwoArg(Action actionWhenFirstParamIsNull, Action actionWhenSecondParamIsNull)379     public TwoArg(Action actionWhenFirstParamIsNull, Action actionWhenSecondParamIsNull) {
380       this.actionWhenFirstParamIsNull = actionWhenFirstParamIsNull;
381       this.actionWhenSecondParamIsNull = actionWhenSecondParamIsNull;
382     }
383 
384     /** Method that decides how to react to parameters. */
reactToNullParameters(Object first, Object second)385     public void reactToNullParameters(Object first, Object second) {
386       if (first == null) {
387         actionWhenFirstParamIsNull.act();
388       }
389       if (second == null) {
390         actionWhenSecondParamIsNull.act();
391       }
392     }
393 
394     /** Two-arg method with no Nullable params. */
normalNormal(String first, Integer second)395     public void normalNormal(String first, Integer second) {
396       reactToNullParameters(first, second);
397     }
398 
399     /** Two-arg method with the second param Nullable. */
normalNullable(String first, @Nullable Integer second)400     public void normalNullable(String first, @Nullable Integer second) {
401       reactToNullParameters(first, second);
402     }
403 
404     /** Two-arg method with the first param Nullable. */
nullableNormal(@ullable String first, Integer second)405     public void nullableNormal(@Nullable String first, Integer second) {
406       reactToNullParameters(first, second);
407     }
408 
409     /** Two-arg method with the both params Nullable. */
nullableNullable(@ullable String first, @Nullable Integer second)410     public void nullableNullable(@Nullable String first, @Nullable Integer second) {
411       reactToNullParameters(first, second);
412     }
413 
414     /** To provide sanity during debugging. */
415     @Override
toString()416     public String toString() {
417       return rootLocaleFormat(
418           "Bar(%s, %s)", actionWhenFirstParamIsNull, actionWhenSecondParamIsNull);
419     }
420   }
421 
verifyBarPass(Method method, TwoArg bar)422   public void verifyBarPass(Method method, TwoArg bar) {
423     try {
424       new NullPointerTester().testMethod(bar, method);
425     } catch (AssertionFailedError incorrectError) {
426       String errorMessage =
427           rootLocaleFormat("Should not have flagged method %s for %s", method.getName(), bar);
428       assertNull(errorMessage, incorrectError);
429     }
430   }
431 
verifyBarFail(Method method, TwoArg bar)432   public void verifyBarFail(Method method, TwoArg bar) {
433     try {
434       new NullPointerTester().testMethod(bar, method);
435     } catch (AssertionFailedError expected) {
436       return; // good...we wanted a failure
437     }
438     String errorMessage =
439         rootLocaleFormat("Should have flagged method %s for %s", method.getName(), bar);
440     fail(errorMessage);
441   }
442 
testTwoArgNormalNormal()443   public void testTwoArgNormalNormal() throws Exception {
444     Method method = TwoArg.class.getMethod("normalNormal", String.class, Integer.class);
445     for (TwoArg.Action first : TwoArg.Action.values()) {
446       for (TwoArg.Action second : TwoArg.Action.values()) {
447         TwoArg bar = new TwoArg(first, second);
448         if (first.equals(TwoArg.Action.THROW_A_NPE) && second.equals(TwoArg.Action.THROW_A_NPE)) {
449           verifyBarPass(method, bar); // require both params to throw NPE
450         } else {
451           verifyBarFail(method, bar);
452         }
453       }
454     }
455   }
456 
testTwoArgNormalNullable()457   public void testTwoArgNormalNullable() throws Exception {
458     Method method = TwoArg.class.getMethod("normalNullable", String.class, Integer.class);
459     for (TwoArg.Action first : TwoArg.Action.values()) {
460       for (TwoArg.Action second : TwoArg.Action.values()) {
461         TwoArg bar = new TwoArg(first, second);
462         if (first.equals(TwoArg.Action.THROW_A_NPE)) {
463           verifyBarPass(method, bar); // only pass if 1st param throws NPE
464         } else {
465           verifyBarFail(method, bar);
466         }
467       }
468     }
469   }
470 
testTwoArgNullableNormal()471   public void testTwoArgNullableNormal() throws Exception {
472     Method method = TwoArg.class.getMethod("nullableNormal", String.class, Integer.class);
473     for (TwoArg.Action first : TwoArg.Action.values()) {
474       for (TwoArg.Action second : TwoArg.Action.values()) {
475         TwoArg bar = new TwoArg(first, second);
476         if (second.equals(TwoArg.Action.THROW_A_NPE)) {
477           verifyBarPass(method, bar); // only pass if 2nd param throws NPE
478         } else {
479           verifyBarFail(method, bar);
480         }
481       }
482     }
483   }
484 
testTwoArgNullableNullable()485   public void testTwoArgNullableNullable() throws Exception {
486     Method method = TwoArg.class.getMethod("nullableNullable", String.class, Integer.class);
487     for (TwoArg.Action first : TwoArg.Action.values()) {
488       for (TwoArg.Action second : TwoArg.Action.values()) {
489         TwoArg bar = new TwoArg(first, second);
490         verifyBarPass(method, bar); // All args nullable:  anything goes!
491       }
492     }
493   }
494 
495   /*
496    * This next part consists of several sample classes that provide
497    * demonstrations of conditions that cause NullPointerTester
498    * to succeed/fail.
499    */
500 
501   /** Lots of well-behaved methods. */
502   @SuppressWarnings("unused") // used by reflection
503   private static class PassObject extends SomeClassThatDoesNotUseNullable {
doThrow(Object arg)504     public static void doThrow(Object arg) {
505       if (arg == null) {
506         throw new FooException();
507       }
508     }
509 
noArg()510     public void noArg() {}
511 
oneArg(String s)512     public void oneArg(String s) {
513       checkNotNull(s);
514     }
515 
packagePrivateOneArg(String s)516     void packagePrivateOneArg(String s) {
517       checkNotNull(s);
518     }
519 
protectedOneArg(String s)520     protected void protectedOneArg(String s) {
521       checkNotNull(s);
522     }
523 
oneNullableArg(@ullable String s)524     public void oneNullableArg(@Nullable String s) {}
525 
oneNullableArgThrows(@ullable String s)526     public void oneNullableArgThrows(@Nullable String s) {
527       doThrow(s);
528     }
529 
twoArg(String s, Integer i)530     public void twoArg(String s, Integer i) {
531       checkNotNull(s);
532       i.intValue();
533     }
534 
twoMixedArgs(String s, @Nullable Integer i)535     public void twoMixedArgs(String s, @Nullable Integer i) {
536       checkNotNull(s);
537     }
538 
twoMixedArgs(@ullable Integer i, String s)539     public void twoMixedArgs(@Nullable Integer i, String s) {
540       checkNotNull(s);
541     }
542 
twoMixedArgsThrows(String s, @Nullable Integer i)543     public void twoMixedArgsThrows(String s, @Nullable Integer i) {
544       checkNotNull(s);
545       doThrow(i);
546     }
547 
twoMixedArgsThrows(@ullable Integer i, String s)548     public void twoMixedArgsThrows(@Nullable Integer i, String s) {
549       checkNotNull(s);
550       doThrow(i);
551     }
552 
twoNullableArgs(@ullable String s, @javax.annotation.Nullable Integer i)553     public void twoNullableArgs(@Nullable String s, @javax.annotation.Nullable Integer i) {}
554 
twoNullableArgsThrowsFirstArg(@ullable String s, @Nullable Integer i)555     public void twoNullableArgsThrowsFirstArg(@Nullable String s, @Nullable Integer i) {
556       doThrow(s);
557     }
558 
twoNullableArgsThrowsSecondArg(@ullable String s, @Nullable Integer i)559     public void twoNullableArgsThrowsSecondArg(@Nullable String s, @Nullable Integer i) {
560       doThrow(i);
561     }
562 
staticOneArg(String s)563     public static void staticOneArg(String s) {
564       checkNotNull(s);
565     }
566 
staticOneNullableArg(@ullable String s)567     public static void staticOneNullableArg(@Nullable String s) {}
568 
staticOneNullableArgThrows(@ullable String s)569     public static void staticOneNullableArgThrows(@Nullable String s) {
570       doThrow(s);
571     }
572   }
573 
testGoodClass()574   public void testGoodClass() {
575     shouldPass(new PassObject());
576   }
577 
578   private static class FailOneArgDoesntThrowNPE extends PassObject {
579     @Override
oneArg(String s)580     public void oneArg(String s) {
581       // Fail:  missing NPE for s
582     }
583   }
584 
testFailOneArgDoesntThrowNpe()585   public void testFailOneArgDoesntThrowNpe() {
586     shouldFail(new FailOneArgDoesntThrowNPE());
587   }
588 
589   private static class FailOneArgThrowsWrongType extends PassObject {
590     @Override
oneArg(String s)591     public void oneArg(String s) {
592       doThrow(s); // Fail:  throwing non-NPE exception for null s
593     }
594   }
595 
testFailOneArgThrowsWrongType()596   public void testFailOneArgThrowsWrongType() {
597     shouldFail(new FailOneArgThrowsWrongType());
598   }
599 
600   private static class PassOneNullableArgThrowsNPE extends PassObject {
601     @Override
oneNullableArg(@ullable String s)602     public void oneNullableArg(@Nullable String s) {
603       checkNotNull(s); // ok to throw NPE
604     }
605   }
606 
testPassOneNullableArgThrowsNPE()607   public void testPassOneNullableArgThrowsNPE() {
608     shouldPass(new PassOneNullableArgThrowsNPE());
609   }
610 
611   private static class FailTwoArgsFirstArgDoesntThrowNPE extends PassObject {
612     @Override
twoArg(String s, Integer i)613     public void twoArg(String s, Integer i) {
614       // Fail: missing NPE for s
615       i.intValue();
616     }
617   }
618 
testFailTwoArgsFirstArgDoesntThrowNPE()619   public void testFailTwoArgsFirstArgDoesntThrowNPE() {
620     shouldFail(new FailTwoArgsFirstArgDoesntThrowNPE());
621   }
622 
623   private static class FailTwoArgsFirstArgThrowsWrongType extends PassObject {
624     @Override
twoArg(String s, Integer i)625     public void twoArg(String s, Integer i) {
626       doThrow(s); // Fail:  throwing non-NPE exception for null s
627       i.intValue();
628     }
629   }
630 
testFailTwoArgsFirstArgThrowsWrongType()631   public void testFailTwoArgsFirstArgThrowsWrongType() {
632     shouldFail(new FailTwoArgsFirstArgThrowsWrongType());
633   }
634 
635   private static class FailTwoArgsSecondArgDoesntThrowNPE extends PassObject {
636     @Override
twoArg(String s, Integer i)637     public void twoArg(String s, Integer i) {
638       checkNotNull(s);
639       // Fail: missing NPE for i
640     }
641   }
642 
testFailTwoArgsSecondArgDoesntThrowNPE()643   public void testFailTwoArgsSecondArgDoesntThrowNPE() {
644     shouldFail(new FailTwoArgsSecondArgDoesntThrowNPE());
645   }
646 
647   private static class FailTwoArgsSecondArgThrowsWrongType extends PassObject {
648     @Override
twoArg(String s, Integer i)649     public void twoArg(String s, Integer i) {
650       checkNotNull(s);
651       doThrow(i); // Fail:  throwing non-NPE exception for null i
652     }
653   }
654 
testFailTwoArgsSecondArgThrowsWrongType()655   public void testFailTwoArgsSecondArgThrowsWrongType() {
656     shouldFail(new FailTwoArgsSecondArgThrowsWrongType());
657   }
658 
659   private static class FailTwoMixedArgsFirstArgDoesntThrowNPE extends PassObject {
660     @Override
twoMixedArgs(String s, @Nullable Integer i)661     public void twoMixedArgs(String s, @Nullable Integer i) {
662       // Fail: missing NPE for s
663     }
664   }
665 
testFailTwoMixedArgsFirstArgDoesntThrowNPE()666   public void testFailTwoMixedArgsFirstArgDoesntThrowNPE() {
667     shouldFail(new FailTwoMixedArgsFirstArgDoesntThrowNPE());
668   }
669 
670   private static class FailTwoMixedArgsFirstArgThrowsWrongType extends PassObject {
671     @Override
twoMixedArgs(String s, @Nullable Integer i)672     public void twoMixedArgs(String s, @Nullable Integer i) {
673       doThrow(s); // Fail:  throwing non-NPE exception for null s
674     }
675   }
676 
testFailTwoMixedArgsFirstArgThrowsWrongType()677   public void testFailTwoMixedArgsFirstArgThrowsWrongType() {
678     shouldFail(new FailTwoMixedArgsFirstArgThrowsWrongType());
679   }
680 
681   private static class PassTwoMixedArgsNullableArgThrowsNPE extends PassObject {
682     @Override
twoMixedArgs(String s, @Nullable Integer i)683     public void twoMixedArgs(String s, @Nullable Integer i) {
684       checkNotNull(s);
685       i.intValue(); // ok to throw NPE?
686     }
687   }
688 
testPassTwoMixedArgsNullableArgThrowsNPE()689   public void testPassTwoMixedArgsNullableArgThrowsNPE() {
690     shouldPass(new PassTwoMixedArgsNullableArgThrowsNPE());
691   }
692 
693   private static class PassTwoMixedArgSecondNullableArgThrowsOther extends PassObject {
694     @Override
twoMixedArgs(String s, @Nullable Integer i)695     public void twoMixedArgs(String s, @Nullable Integer i) {
696       checkNotNull(s);
697       doThrow(i); // ok to throw non-NPE exception for null i
698     }
699   }
700 
testPassTwoMixedArgSecondNullableArgThrowsOther()701   public void testPassTwoMixedArgSecondNullableArgThrowsOther() {
702     shouldPass(new PassTwoMixedArgSecondNullableArgThrowsOther());
703   }
704 
705   private static class FailTwoMixedArgsSecondArgDoesntThrowNPE extends PassObject {
706     @Override
twoMixedArgs(@ullable Integer i, String s)707     public void twoMixedArgs(@Nullable Integer i, String s) {
708       // Fail: missing NPE for null s
709     }
710   }
711 
testFailTwoMixedArgsSecondArgDoesntThrowNPE()712   public void testFailTwoMixedArgsSecondArgDoesntThrowNPE() {
713     shouldFail(new FailTwoMixedArgsSecondArgDoesntThrowNPE());
714   }
715 
716   private static class FailTwoMixedArgsSecondArgThrowsWrongType extends PassObject {
717     @Override
twoMixedArgs(@ullable Integer i, String s)718     public void twoMixedArgs(@Nullable Integer i, String s) {
719       doThrow(s); // Fail:  throwing non-NPE exception for null s
720     }
721   }
722 
testFailTwoMixedArgsSecondArgThrowsWrongType()723   public void testFailTwoMixedArgsSecondArgThrowsWrongType() {
724     shouldFail(new FailTwoMixedArgsSecondArgThrowsWrongType());
725   }
726 
727   private static class PassTwoNullableArgsFirstThrowsNPE extends PassObject {
728     @Override
twoNullableArgs(@ullable String s, @Nullable Integer i)729     public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
730       checkNotNull(s); // ok to throw NPE?
731     }
732   }
733 
testPassTwoNullableArgsFirstThrowsNPE()734   public void testPassTwoNullableArgsFirstThrowsNPE() {
735     shouldPass(new PassTwoNullableArgsFirstThrowsNPE());
736   }
737 
738   private static class PassTwoNullableArgsFirstThrowsOther extends PassObject {
739     @Override
twoNullableArgs(@ullable String s, @Nullable Integer i)740     public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
741       doThrow(s); // ok to throw non-NPE exception for null s
742     }
743   }
744 
testPassTwoNullableArgsFirstThrowsOther()745   public void testPassTwoNullableArgsFirstThrowsOther() {
746     shouldPass(new PassTwoNullableArgsFirstThrowsOther());
747   }
748 
749   private static class PassTwoNullableArgsSecondThrowsNPE extends PassObject {
750     @Override
twoNullableArgs(@ullable String s, @Nullable Integer i)751     public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
752       i.intValue(); // ok to throw NPE?
753     }
754   }
755 
testPassTwoNullableArgsSecondThrowsNPE()756   public void testPassTwoNullableArgsSecondThrowsNPE() {
757     shouldPass(new PassTwoNullableArgsSecondThrowsNPE());
758   }
759 
760   private static class PassTwoNullableArgsSecondThrowsOther extends PassObject {
761     @Override
twoNullableArgs(@ullable String s, @Nullable Integer i)762     public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
763       doThrow(i); // ok to throw non-NPE exception for null i
764     }
765   }
766 
testPassTwoNullableArgsSecondThrowsOther()767   public void testPassTwoNullableArgsSecondThrowsOther() {
768     shouldPass(new PassTwoNullableArgsSecondThrowsOther());
769   }
770 
771   private static class PassTwoNullableArgsNeitherThrowsAnything extends PassObject {
772     @Override
twoNullableArgs(@ullable String s, @Nullable Integer i)773     public void twoNullableArgs(@Nullable String s, @Nullable Integer i) {
774       // ok to do nothing
775     }
776   }
777 
testPassTwoNullableArgsNeitherThrowsAnything()778   public void testPassTwoNullableArgsNeitherThrowsAnything() {
779     shouldPass(new PassTwoNullableArgsNeitherThrowsAnything());
780   }
781 
782   @SuppressWarnings("unused") // for NullPointerTester
783   private abstract static class BaseClassThatFailsToThrow {
oneArg(String s)784     public void oneArg(String s) {}
785   }
786 
787   private static class SubclassWithBadSuperclass extends BaseClassThatFailsToThrow {}
788 
testSubclassWithBadSuperclass()789   public void testSubclassWithBadSuperclass() {
790     shouldFail(new SubclassWithBadSuperclass());
791   }
792 
793   @SuppressWarnings("unused") // for NullPointerTester
794   private abstract static class BaseClassThatFailsToThrowForPackagePrivate {
packagePrivateOneArg(String s)795     void packagePrivateOneArg(String s) {}
796   }
797 
798   private static class SubclassWithBadSuperclassForPackagePrivate
799       extends BaseClassThatFailsToThrowForPackagePrivate {}
800 
testSubclassWithBadSuperclassForPackagePrivateMethod()801   public void testSubclassWithBadSuperclassForPackagePrivateMethod() {
802     shouldFail(new SubclassWithBadSuperclassForPackagePrivate(), Visibility.PACKAGE);
803   }
804 
805   @SuppressWarnings("unused") // for NullPointerTester
806   private abstract static class BaseClassThatFailsToThrowForProtected {
protectedOneArg(String s)807     protected void protectedOneArg(String s) {}
808   }
809 
810   private static class SubclassWithBadSuperclassForProtected
811       extends BaseClassThatFailsToThrowForProtected {}
812 
testSubclassWithBadSuperclassForPackageProtectedMethod()813   public void testSubclassWithBadSuperclassForPackageProtectedMethod() {
814     shouldFail(new SubclassWithBadSuperclassForProtected(), Visibility.PROTECTED);
815   }
816 
817   private static class SubclassThatOverridesBadSuperclassMethod extends BaseClassThatFailsToThrow {
818     @Override
oneArg(@ullable String s)819     public void oneArg(@Nullable String s) {}
820   }
821 
testSubclassThatOverridesBadSuperclassMethod()822   public void testSubclassThatOverridesBadSuperclassMethod() {
823     shouldPass(new SubclassThatOverridesBadSuperclassMethod());
824   }
825 
826   @SuppressWarnings("unused") // for NullPointerTester
827   private static class SubclassOverridesTheWrongMethod extends BaseClassThatFailsToThrow {
oneArg(@ullable CharSequence s)828     public void oneArg(@Nullable CharSequence s) {}
829   }
830 
testSubclassOverridesTheWrongMethod()831   public void testSubclassOverridesTheWrongMethod() {
832     shouldFail(new SubclassOverridesTheWrongMethod());
833   }
834 
835   @SuppressWarnings("unused") // for NullPointerTester
836   private static class ClassThatFailsToThrowForStatic {
staticOneArg(String s)837     static void staticOneArg(String s) {}
838   }
839 
testClassThatFailsToThrowForStatic()840   public void testClassThatFailsToThrowForStatic() {
841     shouldFail(ClassThatFailsToThrowForStatic.class);
842   }
843 
844   private static class SubclassThatFailsToThrowForStatic extends ClassThatFailsToThrowForStatic {}
845 
testSubclassThatFailsToThrowForStatic()846   public void testSubclassThatFailsToThrowForStatic() {
847     shouldFail(SubclassThatFailsToThrowForStatic.class);
848   }
849 
850   private static class SubclassThatTriesToOverrideBadStaticMethod
851       extends ClassThatFailsToThrowForStatic {
staticOneArg(@ullable String s)852     static void staticOneArg(@Nullable String s) {}
853   }
854 
testSubclassThatTriesToOverrideBadStaticMethod()855   public void testSubclassThatTriesToOverrideBadStaticMethod() {
856     shouldFail(SubclassThatTriesToOverrideBadStaticMethod.class);
857   }
858 
859   private static final class HardToCreate {
HardToCreate(HardToCreate x)860     private HardToCreate(HardToCreate x) {}
861   }
862 
863   @SuppressWarnings("unused") // used by reflection
864   private static class CanCreateDefault {
foo(@ullable HardToCreate ignored, String required)865     public void foo(@Nullable HardToCreate ignored, String required) {
866       checkNotNull(required);
867     }
868   }
869 
testCanCreateDefault()870   public void testCanCreateDefault() {
871     shouldPass(new CanCreateDefault());
872   }
873 
874   @SuppressWarnings("unused") // used by reflection
875   private static class CannotCreateDefault {
foo(HardToCreate ignored, String required)876     public void foo(HardToCreate ignored, String required) {
877       checkNotNull(ignored);
878       checkNotNull(required);
879     }
880   }
881 
testCannotCreateDefault()882   public void testCannotCreateDefault() {
883     shouldFail(new CannotCreateDefault());
884   }
885 
shouldPass(Object instance, Visibility visibility)886   private static void shouldPass(Object instance, Visibility visibility) {
887     new NullPointerTester().testInstanceMethods(instance, visibility);
888   }
889 
shouldPass(Object instance)890   private static void shouldPass(Object instance) {
891     shouldPass(instance, Visibility.PACKAGE);
892     shouldPass(instance, Visibility.PROTECTED);
893     shouldPass(instance, Visibility.PUBLIC);
894   }
895 
896   // TODO(cpovirk): eliminate surprising Object/Class overloading of shouldFail
897 
shouldFail(Object instance, Visibility visibility)898   private static void shouldFail(Object instance, Visibility visibility) {
899     try {
900       new NullPointerTester().testInstanceMethods(instance, visibility);
901     } catch (AssertionFailedError expected) {
902       return;
903     }
904     fail("Should detect problem in " + instance.getClass().getSimpleName());
905   }
906 
shouldFail(Object instance)907   private static void shouldFail(Object instance) {
908     shouldFail(instance, Visibility.PACKAGE);
909     shouldFail(instance, Visibility.PROTECTED);
910     shouldFail(instance, Visibility.PUBLIC);
911   }
912 
shouldFail(Class<?> cls, Visibility visibility)913   private static void shouldFail(Class<?> cls, Visibility visibility) {
914     try {
915       new NullPointerTester().testStaticMethods(cls, visibility);
916     } catch (AssertionFailedError expected) {
917       return;
918     }
919     fail("Should detect problem in " + cls.getSimpleName());
920   }
921 
shouldFail(Class<?> cls)922   private static void shouldFail(Class<?> cls) {
923     shouldFail(cls, Visibility.PACKAGE);
924   }
925 
926   @SuppressWarnings("unused") // used by reflection
927   private static class PrivateClassWithPrivateConstructor {
PrivateClassWithPrivateConstructor(@ullable Integer argument)928     private PrivateClassWithPrivateConstructor(@Nullable Integer argument) {}
929   }
930 
testPrivateClass()931   public void testPrivateClass() {
932     NullPointerTester tester = new NullPointerTester();
933     for (Constructor<?> constructor :
934         PrivateClassWithPrivateConstructor.class.getDeclaredConstructors()) {
935       tester.testConstructor(constructor);
936     }
937   }
938 
939   private interface Foo<T> {
doSomething(T bar, Integer baz)940     void doSomething(T bar, Integer baz);
941   }
942 
943   private static class StringFoo implements Foo<String> {
944 
945     @Override
doSomething(String bar, Integer baz)946     public void doSomething(String bar, Integer baz) {
947       checkNotNull(bar);
948       checkNotNull(baz);
949     }
950   }
951 
testBridgeMethodIgnored()952   public void testBridgeMethodIgnored() {
953     new NullPointerTester().testAllPublicInstanceMethods(new StringFoo());
954   }
955 
956   private abstract static class DefaultValueChecker {
957 
958     private final Map<Integer, Object> arguments = Maps.newHashMap();
959 
runTester()960     final DefaultValueChecker runTester() {
961       new NullPointerTester().testInstanceMethods(this, Visibility.PACKAGE);
962       return this;
963     }
964 
assertNonNullValues(Object... expectedValues)965     final void assertNonNullValues(Object... expectedValues) {
966       assertEquals(expectedValues.length, arguments.size());
967       for (int i = 0; i < expectedValues.length; i++) {
968         assertEquals("Default value for parameter #" + i, expectedValues[i], arguments.get(i));
969       }
970     }
971 
getDefaultParameterValue(int position)972     final Object getDefaultParameterValue(int position) {
973       return arguments.get(position);
974     }
975 
calledWith(Object... args)976     final void calledWith(Object... args) {
977       for (int i = 0; i < args.length; i++) {
978         if (args[i] != null) {
979           arguments.put(i, args[i]);
980         }
981       }
982       for (Object arg : args) {
983         checkNotNull(arg); // to fulfill null check
984       }
985     }
986   }
987 
988   private enum Gender {
989     MALE,
990     FEMALE
991   }
992 
993   private static class AllDefaultValuesChecker extends DefaultValueChecker {
994 
995     @SuppressWarnings("unused") // called by NullPointerTester
checkDefaultValuesForTheseTypes( Gender gender, Integer integer, int i, String string, CharSequence charSequence, List<String> list, ImmutableList<Integer> immutableList, Map<String, Integer> map, ImmutableMap<String, String> immutableMap, Set<String> set, ImmutableSet<Integer> immutableSet, SortedSet<Number> sortedSet, ImmutableSortedSet<Number> immutableSortedSet, Multiset<String> multiset, ImmutableMultiset<Integer> immutableMultiset, Multimap<String, Integer> multimap, ImmutableMultimap<String, Integer> immutableMultimap, Table<String, Integer, Exception> table, ImmutableTable<Integer, String, Exception> immutableTable)996     public void checkDefaultValuesForTheseTypes(
997         Gender gender,
998         Integer integer,
999         int i,
1000         String string,
1001         CharSequence charSequence,
1002         List<String> list,
1003         ImmutableList<Integer> immutableList,
1004         Map<String, Integer> map,
1005         ImmutableMap<String, String> immutableMap,
1006         Set<String> set,
1007         ImmutableSet<Integer> immutableSet,
1008         SortedSet<Number> sortedSet,
1009         ImmutableSortedSet<Number> immutableSortedSet,
1010         Multiset<String> multiset,
1011         ImmutableMultiset<Integer> immutableMultiset,
1012         Multimap<String, Integer> multimap,
1013         ImmutableMultimap<String, Integer> immutableMultimap,
1014         Table<String, Integer, Exception> table,
1015         ImmutableTable<Integer, String, Exception> immutableTable) {
1016       calledWith(
1017           gender,
1018           integer,
1019           i,
1020           string,
1021           charSequence,
1022           list,
1023           immutableList,
1024           map,
1025           immutableMap,
1026           set,
1027           immutableSet,
1028           sortedSet,
1029           immutableSortedSet,
1030           multiset,
1031           immutableMultiset,
1032           multimap,
1033           immutableMultimap,
1034           table,
1035           immutableTable);
1036     }
1037 
check()1038     final void check() {
1039       runTester()
1040           .assertNonNullValues(
1041               Gender.MALE,
1042               Integer.valueOf(0),
1043               0,
1044               "",
1045               "",
1046               ImmutableList.of(),
1047               ImmutableList.of(),
1048               ImmutableMap.of(),
1049               ImmutableMap.of(),
1050               ImmutableSet.of(),
1051               ImmutableSet.of(),
1052               ImmutableSortedSet.of(),
1053               ImmutableSortedSet.of(),
1054               ImmutableMultiset.of(),
1055               ImmutableMultiset.of(),
1056               ImmutableMultimap.of(),
1057               ImmutableMultimap.of(),
1058               ImmutableTable.of(),
1059               ImmutableTable.of());
1060     }
1061   }
1062 
testDefaultValues()1063   public void testDefaultValues() {
1064     new AllDefaultValuesChecker().check();
1065   }
1066 
1067   private static class ObjectArrayDefaultValueChecker extends DefaultValueChecker {
1068 
1069     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(Object[] array, String s)1070     public void checkArray(Object[] array, String s) {
1071       calledWith(array, s);
1072     }
1073 
check()1074     void check() {
1075       runTester();
1076       Object[] defaultArray = (Object[]) getDefaultParameterValue(0);
1077       assertThat(defaultArray).isEmpty();
1078     }
1079   }
1080 
testObjectArrayDefaultValue()1081   public void testObjectArrayDefaultValue() {
1082     new ObjectArrayDefaultValueChecker().check();
1083   }
1084 
1085   private static class StringArrayDefaultValueChecker extends DefaultValueChecker {
1086 
1087     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(String[] array, String s)1088     public void checkArray(String[] array, String s) {
1089       calledWith(array, s);
1090     }
1091 
check()1092     void check() {
1093       runTester();
1094       String[] defaultArray = (String[]) getDefaultParameterValue(0);
1095       assertThat(defaultArray).isEmpty();
1096     }
1097   }
1098 
testStringArrayDefaultValue()1099   public void testStringArrayDefaultValue() {
1100     new StringArrayDefaultValueChecker().check();
1101   }
1102 
1103   private static class IntArrayDefaultValueChecker extends DefaultValueChecker {
1104 
1105     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(int[] array, String s)1106     public void checkArray(int[] array, String s) {
1107       calledWith(array, s);
1108     }
1109 
check()1110     void check() {
1111       runTester();
1112       int[] defaultArray = (int[]) getDefaultParameterValue(0);
1113       assertEquals(0, defaultArray.length);
1114     }
1115   }
1116 
testIntArrayDefaultValue()1117   public void testIntArrayDefaultValue() {
1118     new IntArrayDefaultValueChecker().check();
1119   }
1120 
1121   private enum EmptyEnum {}
1122 
1123   private static class EmptyEnumDefaultValueChecker extends DefaultValueChecker {
1124 
1125     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(EmptyEnum object, String s)1126     public void checkArray(EmptyEnum object, String s) {
1127       calledWith(object, s);
1128     }
1129 
check()1130     void check() {
1131       try {
1132         runTester();
1133       } catch (AssertionFailedError expected) {
1134         return;
1135       }
1136       fail("Should have failed because enum has no constant");
1137     }
1138   }
1139 
testEmptyEnumDefaultValue()1140   public void testEmptyEnumDefaultValue() {
1141     new EmptyEnumDefaultValueChecker().check();
1142   }
1143 
1144   private static class GenericClassTypeDefaultValueChecker extends DefaultValueChecker {
1145 
1146     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(Class<? extends List<?>> cls, String s)1147     public void checkArray(Class<? extends List<?>> cls, String s) {
1148       calledWith(cls, s);
1149     }
1150 
check()1151     void check() {
1152       runTester();
1153       Class<?> defaultClass = (Class<?>) getDefaultParameterValue(0);
1154       assertEquals(List.class, defaultClass);
1155     }
1156   }
1157 
testGenericClassDefaultValue()1158   public void testGenericClassDefaultValue() {
1159     new GenericClassTypeDefaultValueChecker().check();
1160   }
1161 
1162   private static class NonGenericClassTypeDefaultValueChecker extends DefaultValueChecker {
1163 
1164     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(@uppressWarnings"rawtypes") Class cls, String s)1165     public void checkArray(@SuppressWarnings("rawtypes") Class cls, String s) {
1166       calledWith(cls, s);
1167     }
1168 
check()1169     void check() {
1170       runTester();
1171       Class<?> defaultClass = (Class<?>) getDefaultParameterValue(0);
1172       assertEquals(Object.class, defaultClass);
1173     }
1174   }
1175 
testNonGenericClassDefaultValue()1176   public void testNonGenericClassDefaultValue() {
1177     new NonGenericClassTypeDefaultValueChecker().check();
1178   }
1179 
1180   private static class GenericTypeTokenDefaultValueChecker extends DefaultValueChecker {
1181 
1182     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(TypeToken<? extends List<? super Number>> type, String s)1183     public void checkArray(TypeToken<? extends List<? super Number>> type, String s) {
1184       calledWith(type, s);
1185     }
1186 
check()1187     void check() {
1188       runTester();
1189       TypeToken<?> defaultType = (TypeToken<?>) getDefaultParameterValue(0);
1190       assertTrue(new TypeToken<List<? super Number>>() {}.isSupertypeOf(defaultType));
1191     }
1192   }
1193 
testGenericTypeTokenDefaultValue()1194   public void testGenericTypeTokenDefaultValue() {
1195     new GenericTypeTokenDefaultValueChecker().check();
1196   }
1197 
1198   private static class NonGenericTypeTokenDefaultValueChecker extends DefaultValueChecker {
1199 
1200     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(@uppressWarnings"rawtypes") TypeToken type, String s)1201     public void checkArray(@SuppressWarnings("rawtypes") TypeToken type, String s) {
1202       calledWith(type, s);
1203     }
1204 
check()1205     void check() {
1206       runTester();
1207       TypeToken<?> defaultType = (TypeToken<?>) getDefaultParameterValue(0);
1208       assertEquals(new TypeToken<Object>() {}, defaultType);
1209     }
1210   }
1211 
testNonGenericTypeTokenDefaultValue()1212   public void testNonGenericTypeTokenDefaultValue() {
1213     new NonGenericTypeTokenDefaultValueChecker().check();
1214   }
1215 
1216   private interface FromTo<F, T> extends Function<F, T> {}
1217 
1218   private static class GenericInterfaceDefaultValueChecker extends DefaultValueChecker {
1219 
1220     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(FromTo<String, Integer> f, String s)1221     public void checkArray(FromTo<String, Integer> f, String s) {
1222       calledWith(f, s);
1223     }
1224 
check()1225     void check() {
1226       runTester();
1227       FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1228       assertEquals(0, defaultFunction.apply(null));
1229     }
1230   }
1231 
testGenericInterfaceDefaultValue()1232   public void testGenericInterfaceDefaultValue() {
1233     new GenericInterfaceDefaultValueChecker().check();
1234   }
1235 
1236   private interface NullRejectingFromTo<F, T> extends Function<F, T> {
1237     @Override
apply(F from)1238     public abstract T apply(F from);
1239   }
1240 
1241   private static class NullRejectingInterfaceDefaultValueChecker extends DefaultValueChecker {
1242 
1243     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(NullRejectingFromTo<String, Integer> f, String s)1244     public void checkArray(NullRejectingFromTo<String, Integer> f, String s) {
1245       calledWith(f, s);
1246     }
1247 
check()1248     void check() {
1249       runTester();
1250       NullRejectingFromTo<?, ?> defaultFunction =
1251           (NullRejectingFromTo<?, ?>) getDefaultParameterValue(0);
1252       assertNotNull(defaultFunction);
1253       try {
1254         defaultFunction.apply(null);
1255         fail("Proxy Should have rejected null");
1256       } catch (NullPointerException expected) {
1257       }
1258     }
1259   }
1260 
testNullRejectingInterfaceDefaultValue()1261   public void testNullRejectingInterfaceDefaultValue() {
1262     new NullRejectingInterfaceDefaultValueChecker().check();
1263   }
1264 
1265   private static class MultipleInterfacesDefaultValueChecker extends DefaultValueChecker {
1266 
1267     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(T f, String s)1268     public <T extends FromTo<String, Integer> & Supplier<Long>> void checkArray(T f, String s) {
1269       calledWith(f, s);
1270     }
1271 
check()1272     void check() {
1273       runTester();
1274       FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1275       assertEquals(0, defaultFunction.apply(null));
1276       Supplier<?> defaultSupplier = (Supplier<?>) defaultFunction;
1277       assertEquals(Long.valueOf(0), defaultSupplier.get());
1278     }
1279   }
1280 
testMultipleInterfacesDefaultValue()1281   public void testMultipleInterfacesDefaultValue() {
1282     new MultipleInterfacesDefaultValueChecker().check();
1283   }
1284 
1285   private static class GenericInterface2DefaultValueChecker extends DefaultValueChecker {
1286 
1287     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(FromTo<String, FromTo<Integer, String>> f, String s)1288     public void checkArray(FromTo<String, FromTo<Integer, String>> f, String s) {
1289       calledWith(f, s);
1290     }
1291 
check()1292     void check() {
1293       runTester();
1294       FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1295       FromTo<?, ?> returnValue = (FromTo<?, ?>) defaultFunction.apply(null);
1296       assertEquals("", returnValue.apply(null));
1297     }
1298   }
1299 
testGenericInterfaceReturnedByGenericMethod()1300   public void testGenericInterfaceReturnedByGenericMethod() {
1301     new GenericInterface2DefaultValueChecker().check();
1302   }
1303 
1304   private abstract static class AbstractGenericDefaultValueChecker<T> extends DefaultValueChecker {
1305 
1306     @SuppressWarnings("unused") // called by NullPointerTester
checkGeneric(T value, String s)1307     public void checkGeneric(T value, String s) {
1308       calledWith(value, s);
1309     }
1310   }
1311 
1312   private static class GenericDefaultValueResolvedToStringChecker
1313       extends AbstractGenericDefaultValueChecker<String> {
check()1314     void check() {
1315       runTester();
1316       assertEquals("", getDefaultParameterValue(0));
1317     }
1318   }
1319 
testGenericTypeResolvedForDefaultValue()1320   public void testGenericTypeResolvedForDefaultValue() {
1321     new GenericDefaultValueResolvedToStringChecker().check();
1322   }
1323 
1324   private abstract static class AbstractGenericDefaultValueForPackagePrivateMethodChecker<T>
1325       extends DefaultValueChecker {
1326 
1327     @SuppressWarnings("unused") // called by NullPointerTester
checkGeneric(T value, String s)1328     void checkGeneric(T value, String s) {
1329       calledWith(value, s);
1330     }
1331   }
1332 
1333   private static class DefaultValueForPackagePrivateMethodResolvedToStringChecker
1334       extends AbstractGenericDefaultValueForPackagePrivateMethodChecker<String> {
check()1335     void check() {
1336       runTester();
1337       assertEquals("", getDefaultParameterValue(0));
1338     }
1339   }
1340 
testDefaultValueResolvedForPackagePrivateMethod()1341   public void testDefaultValueResolvedForPackagePrivateMethod() {
1342     new DefaultValueForPackagePrivateMethodResolvedToStringChecker().check();
1343   }
1344 
1345   private static class ConverterDefaultValueChecker extends DefaultValueChecker {
1346 
1347     @SuppressWarnings("unused") // called by NullPointerTester
checkArray(Converter<String, Integer> c, String s)1348     public void checkArray(Converter<String, Integer> c, String s) {
1349       calledWith(c, s);
1350     }
1351 
check()1352     void check() {
1353       runTester();
1354       @SuppressWarnings("unchecked") // We are checking it anyway
1355       Converter<String, Integer> defaultConverter =
1356           (Converter<String, Integer>) getDefaultParameterValue(0);
1357       assertEquals(Integer.valueOf(0), defaultConverter.convert("anything"));
1358       assertEquals("", defaultConverter.reverse().convert(123));
1359       assertNull(defaultConverter.convert(null));
1360       assertNull(defaultConverter.reverse().convert(null));
1361     }
1362   }
1363 
testConverterDefaultValue()1364   public void testConverterDefaultValue() {
1365     new ConverterDefaultValueChecker().check();
1366   }
1367 
1368   private static class VisibilityMethods {
1369 
1370     @SuppressWarnings("unused") // Called by reflection
privateMethod()1371     private void privateMethod() {}
1372 
1373     @SuppressWarnings("unused") // Called by reflection
packagePrivateMethod()1374     void packagePrivateMethod() {}
1375 
1376     @SuppressWarnings("unused") // Called by reflection
protectedMethod()1377     protected void protectedMethod() {}
1378 
1379     @SuppressWarnings("unused") // Called by reflection
publicMethod()1380     public void publicMethod() {}
1381   }
1382 
testVisibility_public()1383   public void testVisibility_public() throws Exception {
1384     assertFalse(
1385         Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1386     assertFalse(
1387         Visibility.PUBLIC.isVisible(
1388             VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1389     assertFalse(
1390         Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1391     assertTrue(
1392         Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
1393   }
1394 
testVisibility_protected()1395   public void testVisibility_protected() throws Exception {
1396     assertFalse(
1397         Visibility.PROTECTED.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1398     assertFalse(
1399         Visibility.PROTECTED.isVisible(
1400             VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1401     assertTrue(
1402         Visibility.PROTECTED.isVisible(
1403             VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1404     assertTrue(
1405         Visibility.PROTECTED.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
1406   }
1407 
testVisibility_package()1408   public void testVisibility_package() throws Exception {
1409     assertFalse(
1410         Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1411     assertTrue(
1412         Visibility.PACKAGE.isVisible(
1413             VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1414     assertTrue(
1415         Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1416     assertTrue(
1417         Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
1418   }
1419 
1420   private class Inner {
Inner(String s)1421     public Inner(String s) {
1422       checkNotNull(s);
1423     }
1424   }
1425 
testNonStaticInnerClass()1426   public void testNonStaticInnerClass() {
1427     try {
1428       new NullPointerTester().testAllPublicConstructors(Inner.class);
1429       fail();
1430     } catch (IllegalArgumentException expected) {
1431       assertThat(expected.getMessage()).contains("inner class");
1432     }
1433   }
1434 
rootLocaleFormat(String format, Object... args)1435   private static String rootLocaleFormat(String format, Object... args) {
1436     return String.format(Locale.ROOT, format, args);
1437   }
1438 
1439   static class OverridesEquals {
1440     @SuppressWarnings("EqualsHashCode")
1441     @Override
equals(Object o)1442     public boolean equals(Object o) {
1443       return true;
1444     }
1445   }
1446 
1447   static class DoesNotOverrideEquals {
equals(Object a, Object b)1448     public boolean equals(Object a, Object b) {
1449       return true;
1450     }
1451   }
1452 
testEqualsMethod()1453   public void testEqualsMethod() {
1454     shouldPass(new OverridesEquals());
1455     shouldFail(new DoesNotOverrideEquals());
1456   }
1457 
1458   private static final class FailOnOneOfTwoConstructors {
1459     @SuppressWarnings("unused") // Called by reflection
FailOnOneOfTwoConstructors(String s)1460     public FailOnOneOfTwoConstructors(String s) {}
1461 
1462     @SuppressWarnings("unused") // Called by reflection
FailOnOneOfTwoConstructors(Object o)1463     public FailOnOneOfTwoConstructors(Object o) {
1464       checkNotNull(o);
1465     }
1466   }
1467 
testConstructor_Ignored_ShouldPass()1468   public void testConstructor_Ignored_ShouldPass() throws Exception {
1469     new NullPointerTester()
1470         .ignore(FailOnOneOfTwoConstructors.class.getDeclaredConstructor(String.class))
1471         .testAllPublicConstructors(FailOnOneOfTwoConstructors.class);
1472   }
1473 
testConstructor_ShouldFail()1474   public void testConstructor_ShouldFail() throws Exception {
1475     try {
1476       new NullPointerTester().testAllPublicConstructors(FailOnOneOfTwoConstructors.class);
1477     } catch (AssertionFailedError expected) {
1478       return;
1479     }
1480     fail("Should detect problem in " + FailOnOneOfTwoConstructors.class.getSimpleName());
1481   }
1482 }
1483