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