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