blob: c8d363444d1581f7f897c35337c9154c2f3da315 [file] [log] [blame]
zhenghua9b94fb32017-04-20 14:33:38 -07001/*
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
17package com.google.common.testing;
18
19import static com.google.common.base.Preconditions.checkArgument;
20import static com.google.common.base.Preconditions.checkNotNull;
21import static com.google.common.truth.Truth.assertThat;
22
23import com.google.common.base.Converter;
24import com.google.common.base.Function;
25import com.google.common.base.Supplier;
26import com.google.common.collect.ImmutableList;
27import com.google.common.collect.ImmutableMap;
28import com.google.common.collect.ImmutableMultimap;
29import com.google.common.collect.ImmutableMultiset;
30import com.google.common.collect.ImmutableSet;
31import com.google.common.collect.ImmutableSortedSet;
32import com.google.common.collect.ImmutableTable;
33import com.google.common.collect.Maps;
34import com.google.common.collect.Multimap;
35import com.google.common.collect.Multiset;
36import com.google.common.collect.Table;
37import com.google.common.reflect.TypeToken;
38import com.google.common.testing.NullPointerTester.Visibility;
39import com.google.common.testing.anotherpackage.SomeClassThatDoesNotUseNullable;
40import java.lang.reflect.Constructor;
41import java.lang.reflect.Method;
42import java.util.List;
43import java.util.Locale;
44import java.util.Map;
45import java.util.Set;
46import java.util.SortedSet;
zhenghua9b94fb32017-04-20 14:33:38 -070047import junit.framework.AssertionFailedError;
48import junit.framework.TestCase;
cpovirk2d0957c2017-12-04 18:48:08 -080049import org.checkerframework.checker.nullness.compatqual.NullableDecl;
zhenghua9b94fb32017-04-20 14:33:38 -070050
51/**
52 * Unit test for {@link NullPointerTester}.
53 *
54 * @author Kevin Bourrillion
55 * @author Mick Killianey
56 */
57public class NullPointerTesterTest extends TestCase {
58
59 /** Non-NPE RuntimeException. */
60 public static class FooException extends RuntimeException {
61 private static final long serialVersionUID = 1L;
62 }
63
64 /**
cpovirkfd919e52017-12-04 08:51:35 -080065 * Class for testing all permutations of static/non-static one-argument methods using
66 * methodParameter().
zhenghua9b94fb32017-04-20 14:33:38 -070067 */
68 @SuppressWarnings("unused") // used by reflection
69 public static class OneArg {
70
71 public static void staticOneArgCorrectlyThrowsNpe(String s) {
72 checkNotNull(s); // expect NPE here on null
73 }
cpovirkfd919e52017-12-04 08:51:35 -080074
zhenghua9b94fb32017-04-20 14:33:38 -070075 public static void staticOneArgThrowsOtherThanNpe(String s) {
cpovirkfd919e52017-12-04 08:51:35 -080076 throw new FooException(); // should catch as failure
zhenghua9b94fb32017-04-20 14:33:38 -070077 }
cpovirkfd919e52017-12-04 08:51:35 -080078
zhenghua9b94fb32017-04-20 14:33:38 -070079 public static void staticOneArgShouldThrowNpeButDoesnt(String s) {
80 // should catch as failure
81 }
cpovirkfd919e52017-12-04 08:51:35 -080082
cpovirk2d0957c2017-12-04 18:48:08 -080083 public static void staticOneArgCheckForNullCorrectlyDoesNotThrowNPE(
84 @javax.annotation.CheckForNull String s) {
zhenghua9b94fb32017-04-20 14:33:38 -070085 // null? no problem
86 }
cpovirkfd919e52017-12-04 08:51:35 -080087
cushon0a2258e2018-05-08 10:48:52 -070088 public static void staticOneArgJsr305NullableCorrectlyDoesNotThrowNPE(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -070089 // null? no problem
90 }
cpovirkfd919e52017-12-04 08:51:35 -080091
cpovirk2d0957c2017-12-04 18:48:08 -080092 public static void staticOneArgNullableCorrectlyDoesNotThrowNPE(@NullableDecl String s) {
93 // null? no problem
94 }
95
96 public static void staticOneArgCheckForNullCorrectlyThrowsOtherThanNPE(
97 @javax.annotation.CheckForNull String s) {
zhenghua9b94fb32017-04-20 14:33:38 -070098 throw new FooException(); // ok, as long as it's not NullPointerException
99 }
cpovirkfd919e52017-12-04 08:51:35 -0800100
cpovirk2d0957c2017-12-04 18:48:08 -0800101 public static void staticOneArgNullableCorrectlyThrowsOtherThanNPE(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700102 throw new FooException(); // ok, as long as it's not NullPointerException
103 }
cpovirkfd919e52017-12-04 08:51:35 -0800104
cpovirk2d0957c2017-12-04 18:48:08 -0800105 public static void staticOneArgCheckForNullThrowsNPE(@javax.annotation.CheckForNull String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700106 checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
107 }
cpovirkfd919e52017-12-04 08:51:35 -0800108
cpovirk2d0957c2017-12-04 18:48:08 -0800109 public static void staticOneArgNullableThrowsNPE(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700110 checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
111 }
112
113 public void oneArgCorrectlyThrowsNpe(String s) {
114 checkNotNull(s); // expect NPE here on null
115 }
cpovirkfd919e52017-12-04 08:51:35 -0800116
zhenghua9b94fb32017-04-20 14:33:38 -0700117 public void oneArgThrowsOtherThanNpe(String s) {
cpovirkfd919e52017-12-04 08:51:35 -0800118 throw new FooException(); // should catch as failure
zhenghua9b94fb32017-04-20 14:33:38 -0700119 }
cpovirkfd919e52017-12-04 08:51:35 -0800120
zhenghua9b94fb32017-04-20 14:33:38 -0700121 public void oneArgShouldThrowNpeButDoesnt(String s) {
122 // should catch as failure
123 }
cpovirkfd919e52017-12-04 08:51:35 -0800124
cpovirk2d0957c2017-12-04 18:48:08 -0800125 public void oneArgCheckForNullCorrectlyDoesNotThrowNPE(
126 @javax.annotation.CheckForNull String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700127 // null? no problem
128 }
cpovirkfd919e52017-12-04 08:51:35 -0800129
cpovirk2d0957c2017-12-04 18:48:08 -0800130 public void oneArgNullableCorrectlyDoesNotThrowNPE(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700131 // null? no problem
132 }
cpovirkfd919e52017-12-04 08:51:35 -0800133
cpovirk2d0957c2017-12-04 18:48:08 -0800134 public void oneArgCheckForNullCorrectlyThrowsOtherThanNPE(
135 @javax.annotation.CheckForNull String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700136 throw new FooException(); // ok, as long as it's not NullPointerException
137 }
cpovirkfd919e52017-12-04 08:51:35 -0800138
cpovirk2d0957c2017-12-04 18:48:08 -0800139 public void oneArgNullableCorrectlyThrowsOtherThanNPE(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700140 throw new FooException(); // ok, as long as it's not NullPointerException
141 }
cpovirkfd919e52017-12-04 08:51:35 -0800142
cpovirk2d0957c2017-12-04 18:48:08 -0800143 public void oneArgCheckForNullThrowsNPE(@javax.annotation.CheckForNull String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700144 checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
145 }
cpovirkfd919e52017-12-04 08:51:35 -0800146
cpovirk2d0957c2017-12-04 18:48:08 -0800147 public void oneArgNullableThrowsNPE(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700148 checkNotNull(s); // doesn't check if you said you'd accept null, but you don't
149 }
150 }
151
152 private static final String[] STATIC_ONE_ARG_METHODS_SHOULD_PASS = {
153 "staticOneArgCorrectlyThrowsNpe",
154 "staticOneArgCheckForNullCorrectlyDoesNotThrowNPE",
155 "staticOneArgCheckForNullCorrectlyThrowsOtherThanNPE",
156 "staticOneArgCheckForNullThrowsNPE",
157 "staticOneArgNullableCorrectlyDoesNotThrowNPE",
158 "staticOneArgNullableCorrectlyThrowsOtherThanNPE",
159 "staticOneArgNullableThrowsNPE",
160 };
161 private static final String[] STATIC_ONE_ARG_METHODS_SHOULD_FAIL = {
cpovirkfd919e52017-12-04 08:51:35 -0800162 "staticOneArgThrowsOtherThanNpe", "staticOneArgShouldThrowNpeButDoesnt",
zhenghua9b94fb32017-04-20 14:33:38 -0700163 };
164 private static final String[] NONSTATIC_ONE_ARG_METHODS_SHOULD_PASS = {
165 "oneArgCorrectlyThrowsNpe",
166 "oneArgCheckForNullCorrectlyDoesNotThrowNPE",
167 "oneArgCheckForNullCorrectlyThrowsOtherThanNPE",
168 "oneArgCheckForNullThrowsNPE",
169 "oneArgNullableCorrectlyDoesNotThrowNPE",
170 "oneArgNullableCorrectlyThrowsOtherThanNPE",
171 "oneArgNullableThrowsNPE",
172 };
173 private static final String[] NONSTATIC_ONE_ARG_METHODS_SHOULD_FAIL = {
cpovirkfd919e52017-12-04 08:51:35 -0800174 "oneArgThrowsOtherThanNpe", "oneArgShouldThrowNpeButDoesnt",
zhenghua9b94fb32017-04-20 14:33:38 -0700175 };
176
177 private static class ThrowsIae {
178 public static void christenPoodle(String name) {
179 checkArgument(name != null);
180 }
181 }
182
183 private static class ThrowsNpe {
184 public static void christenPoodle(String name) {
185 checkNotNull(name);
186 }
187 }
188
189 private static class ThrowsUoe {
190 public static void christenPoodle(String name) {
191 throw new UnsupportedOperationException();
192 }
193 }
194
195 private static class ThrowsSomethingElse {
196 public static void christenPoodle(String name) {
197 throw new RuntimeException();
198 }
199 }
200
201 public void testDontAcceptIae() {
202 NullPointerTester tester = new NullPointerTester();
203 tester.testAllPublicStaticMethods(ThrowsNpe.class);
204 tester.testAllPublicStaticMethods(ThrowsUoe.class);
205 try {
206 tester.testAllPublicStaticMethods(ThrowsIae.class);
207 } catch (AssertionFailedError expected) {
208 return;
209 }
210 fail();
211 }
212
213 public void testStaticOneArgMethodsThatShouldPass() throws Exception {
214 for (String methodName : STATIC_ONE_ARG_METHODS_SHOULD_PASS) {
215 Method method = OneArg.class.getMethod(methodName, String.class);
216 try {
217 new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
218 } catch (AssertionFailedError unexpected) {
219 fail("Should not have flagged method " + methodName);
220 }
221 }
222 }
223
224 public void testStaticOneArgMethodsThatShouldFail() throws Exception {
225 for (String methodName : STATIC_ONE_ARG_METHODS_SHOULD_FAIL) {
226 Method method = OneArg.class.getMethod(methodName, String.class);
227 boolean foundProblem = false;
228 try {
229 new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
230 } catch (AssertionFailedError expected) {
231 foundProblem = true;
232 }
233 assertTrue("Should report error in method " + methodName, foundProblem);
234 }
235 }
236
237 public void testNonStaticOneArgMethodsThatShouldPass() throws Exception {
238 OneArg foo = new OneArg();
239 for (String methodName : NONSTATIC_ONE_ARG_METHODS_SHOULD_PASS) {
240 Method method = OneArg.class.getMethod(methodName, String.class);
241 try {
242 new NullPointerTester().testMethodParameter(foo, method, 0);
243 } catch (AssertionFailedError unexpected) {
244 fail("Should not have flagged method " + methodName);
245 }
246 }
247 }
248
249 public void testNonStaticOneArgMethodsThatShouldFail() throws Exception {
250 OneArg foo = new OneArg();
251 for (String methodName : NONSTATIC_ONE_ARG_METHODS_SHOULD_FAIL) {
252 Method method = OneArg.class.getMethod(methodName, String.class);
253 boolean foundProblem = false;
254 try {
255 new NullPointerTester().testMethodParameter(foo, method, 0);
256 } catch (AssertionFailedError expected) {
257 foundProblem = true;
258 }
259 assertTrue("Should report error in method " + methodName, foundProblem);
260 }
261 }
262
263 public void testMessageOtherException() throws Exception {
264 Method method = OneArg.class.getMethod("staticOneArgThrowsOtherThanNpe", String.class);
265 boolean foundProblem = false;
266 try {
267 new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
268 } catch (AssertionFailedError expected) {
269 assertThat(expected.getMessage()).contains("index 0");
270 assertThat(expected.getMessage()).contains("[null]");
271 foundProblem = true;
272 }
273 assertTrue("Should report error when different exception is thrown", foundProblem);
274 }
275
276 public void testMessageNoException() throws Exception {
277 Method method = OneArg.class.getMethod("staticOneArgShouldThrowNpeButDoesnt", String.class);
278 boolean foundProblem = false;
279 try {
280 new NullPointerTester().testMethodParameter(new OneArg(), method, 0);
281 } catch (AssertionFailedError expected) {
282 assertThat(expected.getMessage()).contains("index 0");
283 assertThat(expected.getMessage()).contains("[null]");
284 foundProblem = true;
285 }
286 assertTrue("Should report error when no exception is thrown", foundProblem);
287 }
288
289 /**
cpovirkfd919e52017-12-04 08:51:35 -0800290 * Class for testing all permutations of nullable/non-nullable two-argument methods using
291 * testMethod().
zhenghua9b94fb32017-04-20 14:33:38 -0700292 *
cpovirkfd919e52017-12-04 08:51:35 -0800293 * <ul>
294 * <li>normalNormal: two params, neither is Nullable
295 * <li>nullableNormal: only first param is Nullable
296 * <li>normalNullable: only second param is Nullable
297 * <li>nullableNullable: both params are Nullable
298 * </ul>
zhenghua9b94fb32017-04-20 14:33:38 -0700299 */
300 public static class TwoArg {
301 /** Action to take on a null param. */
302 public enum Action {
303 THROW_A_NPE {
cpovirkfd919e52017-12-04 08:51:35 -0800304 @Override
305 public void act() {
zhenghua9b94fb32017-04-20 14:33:38 -0700306 throw new NullPointerException();
307 }
308 },
309 THROW_OTHER {
cpovirkfd919e52017-12-04 08:51:35 -0800310 @Override
311 public void act() {
zhenghua9b94fb32017-04-20 14:33:38 -0700312 throw new FooException();
313 }
314 },
315 JUST_RETURN {
cpovirkfd919e52017-12-04 08:51:35 -0800316 @Override
317 public void act() {}
zhenghua9b94fb32017-04-20 14:33:38 -0700318 };
319
320 public abstract void act();
321 }
cpovirkfd919e52017-12-04 08:51:35 -0800322
zhenghua9b94fb32017-04-20 14:33:38 -0700323 Action actionWhenFirstParamIsNull;
324 Action actionWhenSecondParamIsNull;
325
cpovirkfd919e52017-12-04 08:51:35 -0800326 public TwoArg(Action actionWhenFirstParamIsNull, Action actionWhenSecondParamIsNull) {
zhenghua9b94fb32017-04-20 14:33:38 -0700327 this.actionWhenFirstParamIsNull = actionWhenFirstParamIsNull;
328 this.actionWhenSecondParamIsNull = actionWhenSecondParamIsNull;
329 }
330
331 /** Method that decides how to react to parameters. */
332 public void reactToNullParameters(Object first, Object second) {
333 if (first == null) {
334 actionWhenFirstParamIsNull.act();
335 }
336 if (second == null) {
337 actionWhenSecondParamIsNull.act();
338 }
339 }
340
341 /** Two-arg method with no Nullable params. */
342 public void normalNormal(String first, Integer second) {
343 reactToNullParameters(first, second);
344 }
345
346 /** Two-arg method with the second param Nullable. */
cpovirk2d0957c2017-12-04 18:48:08 -0800347 public void normalNullable(String first, @NullableDecl Integer second) {
zhenghua9b94fb32017-04-20 14:33:38 -0700348 reactToNullParameters(first, second);
349 }
350
351 /** Two-arg method with the first param Nullable. */
cpovirk2d0957c2017-12-04 18:48:08 -0800352 public void nullableNormal(@NullableDecl String first, Integer second) {
zhenghua9b94fb32017-04-20 14:33:38 -0700353 reactToNullParameters(first, second);
354 }
355
356 /** Two-arg method with the both params Nullable. */
cpovirk2d0957c2017-12-04 18:48:08 -0800357 public void nullableNullable(@NullableDecl String first, @NullableDecl Integer second) {
zhenghua9b94fb32017-04-20 14:33:38 -0700358 reactToNullParameters(first, second);
359 }
360
361 /** To provide sanity during debugging. */
cpovirkfd919e52017-12-04 08:51:35 -0800362 @Override
363 public String toString() {
364 return rootLocaleFormat(
365 "Bar(%s, %s)", actionWhenFirstParamIsNull, actionWhenSecondParamIsNull);
zhenghua9b94fb32017-04-20 14:33:38 -0700366 }
367 }
368
369 public void verifyBarPass(Method method, TwoArg bar) {
370 try {
371 new NullPointerTester().testMethod(bar, method);
372 } catch (AssertionFailedError incorrectError) {
cpovirkfd919e52017-12-04 08:51:35 -0800373 String errorMessage =
374 rootLocaleFormat("Should not have flagged method %s for %s", method.getName(), bar);
zhenghua9b94fb32017-04-20 14:33:38 -0700375 assertNull(errorMessage, incorrectError);
376 }
377 }
378
379 public void verifyBarFail(Method method, TwoArg bar) {
380 try {
381 new NullPointerTester().testMethod(bar, method);
382 } catch (AssertionFailedError expected) {
383 return; // good...we wanted a failure
384 }
cpovirkfd919e52017-12-04 08:51:35 -0800385 String errorMessage =
386 rootLocaleFormat("Should have flagged method %s for %s", method.getName(), bar);
zhenghua9b94fb32017-04-20 14:33:38 -0700387 fail(errorMessage);
388 }
389
390 public void testTwoArgNormalNormal() throws Exception {
cpovirkfd919e52017-12-04 08:51:35 -0800391 Method method = TwoArg.class.getMethod("normalNormal", String.class, Integer.class);
zhenghua9b94fb32017-04-20 14:33:38 -0700392 for (TwoArg.Action first : TwoArg.Action.values()) {
393 for (TwoArg.Action second : TwoArg.Action.values()) {
394 TwoArg bar = new TwoArg(first, second);
cpovirkfd919e52017-12-04 08:51:35 -0800395 if (first.equals(TwoArg.Action.THROW_A_NPE) && second.equals(TwoArg.Action.THROW_A_NPE)) {
zhenghua9b94fb32017-04-20 14:33:38 -0700396 verifyBarPass(method, bar); // require both params to throw NPE
397 } else {
398 verifyBarFail(method, bar);
399 }
400 }
401 }
402 }
403
404 public void testTwoArgNormalNullable() throws Exception {
cpovirkfd919e52017-12-04 08:51:35 -0800405 Method method = TwoArg.class.getMethod("normalNullable", String.class, Integer.class);
zhenghua9b94fb32017-04-20 14:33:38 -0700406 for (TwoArg.Action first : TwoArg.Action.values()) {
407 for (TwoArg.Action second : TwoArg.Action.values()) {
408 TwoArg bar = new TwoArg(first, second);
409 if (first.equals(TwoArg.Action.THROW_A_NPE)) {
410 verifyBarPass(method, bar); // only pass if 1st param throws NPE
411 } else {
412 verifyBarFail(method, bar);
413 }
414 }
415 }
416 }
417
418 public void testTwoArgNullableNormal() throws Exception {
cpovirkfd919e52017-12-04 08:51:35 -0800419 Method method = TwoArg.class.getMethod("nullableNormal", String.class, Integer.class);
zhenghua9b94fb32017-04-20 14:33:38 -0700420 for (TwoArg.Action first : TwoArg.Action.values()) {
421 for (TwoArg.Action second : TwoArg.Action.values()) {
422 TwoArg bar = new TwoArg(first, second);
423 if (second.equals(TwoArg.Action.THROW_A_NPE)) {
424 verifyBarPass(method, bar); // only pass if 2nd param throws NPE
425 } else {
426 verifyBarFail(method, bar);
427 }
428 }
429 }
430 }
431
432 public void testTwoArgNullableNullable() throws Exception {
cpovirkfd919e52017-12-04 08:51:35 -0800433 Method method = TwoArg.class.getMethod("nullableNullable", String.class, Integer.class);
zhenghua9b94fb32017-04-20 14:33:38 -0700434 for (TwoArg.Action first : TwoArg.Action.values()) {
435 for (TwoArg.Action second : TwoArg.Action.values()) {
436 TwoArg bar = new TwoArg(first, second);
437 verifyBarPass(method, bar); // All args nullable: anything goes!
438 }
439 }
440 }
441
442 /*
443 * This next part consists of several sample classes that provide
444 * demonstrations of conditions that cause NullPointerTester
445 * to succeed/fail.
446 */
447
448 /** Lots of well-behaved methods. */
449 @SuppressWarnings("unused") // used by reflection
450 private static class PassObject extends SomeClassThatDoesNotUseNullable {
451 public static void doThrow(Object arg) {
452 if (arg == null) {
453 throw new FooException();
454 }
455 }
zhenghua9b94fb32017-04-20 14:33:38 -0700456
cpovirkfd919e52017-12-04 08:51:35 -0800457 public void noArg() {}
458
459 public void oneArg(String s) {
460 checkNotNull(s);
zhenghua9b94fb32017-04-20 14:33:38 -0700461 }
cpovirkfd919e52017-12-04 08:51:35 -0800462
463 void packagePrivateOneArg(String s) {
464 checkNotNull(s);
zhenghua9b94fb32017-04-20 14:33:38 -0700465 }
cpovirkfd919e52017-12-04 08:51:35 -0800466
467 protected void protectedOneArg(String s) {
468 checkNotNull(s);
469 }
470
cpovirk2d0957c2017-12-04 18:48:08 -0800471 public void oneNullableArg(@NullableDecl String s) {}
cpovirkfd919e52017-12-04 08:51:35 -0800472
cpovirk2d0957c2017-12-04 18:48:08 -0800473 public void oneNullableArgThrows(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700474 doThrow(s);
475 }
cpovirkfd919e52017-12-04 08:51:35 -0800476
477 public void twoArg(String s, Integer i) {
478 checkNotNull(s);
479 i.intValue();
480 }
481
cpovirk2d0957c2017-12-04 18:48:08 -0800482 public void twoMixedArgs(String s, @NullableDecl Integer i) {
cpovirkfd919e52017-12-04 08:51:35 -0800483 checkNotNull(s);
484 }
485
cpovirk7abf5992018-02-08 11:41:03 -0800486 public void twoMixedArgs(@NullableDecl Integer i, String s) {
487 checkNotNull(s);
488 }
489
cpovirk2d0957c2017-12-04 18:48:08 -0800490 public void twoMixedArgsThrows(String s, @NullableDecl Integer i) {
cpovirkfd919e52017-12-04 08:51:35 -0800491 checkNotNull(s);
zhenghua9b94fb32017-04-20 14:33:38 -0700492 doThrow(i);
493 }
cpovirkfd919e52017-12-04 08:51:35 -0800494
cpovirk2d0957c2017-12-04 18:48:08 -0800495 public void twoMixedArgsThrows(@NullableDecl Integer i, String s) {
cpovirkfd919e52017-12-04 08:51:35 -0800496 checkNotNull(s);
497 doThrow(i);
498 }
499
cushon0a2258e2018-05-08 10:48:52 -0700500 public void twoNullableArgs(@NullableDecl String s, @NullableDecl Integer i) {}
cpovirkfd919e52017-12-04 08:51:35 -0800501
cpovirk2d0957c2017-12-04 18:48:08 -0800502 public void twoNullableArgsThrowsFirstArg(@NullableDecl String s, @NullableDecl Integer i) {
cpovirkfd919e52017-12-04 08:51:35 -0800503 doThrow(s);
504 }
505
cpovirk2d0957c2017-12-04 18:48:08 -0800506 public void twoNullableArgsThrowsSecondArg(@NullableDecl String s, @NullableDecl Integer i) {
cpovirkfd919e52017-12-04 08:51:35 -0800507 doThrow(i);
508 }
509
510 public static void staticOneArg(String s) {
511 checkNotNull(s);
512 }
513
cpovirk2d0957c2017-12-04 18:48:08 -0800514 public static void staticOneNullableArg(@NullableDecl String s) {}
cpovirkfd919e52017-12-04 08:51:35 -0800515
cpovirk2d0957c2017-12-04 18:48:08 -0800516 public static void staticOneNullableArgThrows(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700517 doThrow(s);
518 }
519 }
520
521 public void testGoodClass() {
522 shouldPass(new PassObject());
523 }
524
525 private static class FailOneArgDoesntThrowNPE extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800526 @Override
527 public void oneArg(String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700528 // Fail: missing NPE for s
529 }
530 }
531
532 public void testFailOneArgDoesntThrowNpe() {
533 shouldFail(new FailOneArgDoesntThrowNPE());
534 }
535
536 private static class FailOneArgThrowsWrongType extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800537 @Override
538 public void oneArg(String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700539 doThrow(s); // Fail: throwing non-NPE exception for null s
540 }
541 }
542
543 public void testFailOneArgThrowsWrongType() {
544 shouldFail(new FailOneArgThrowsWrongType());
545 }
546
547 private static class PassOneNullableArgThrowsNPE extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800548 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800549 public void oneNullableArg(@NullableDecl String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700550 checkNotNull(s); // ok to throw NPE
551 }
552 }
553
554 public void testPassOneNullableArgThrowsNPE() {
555 shouldPass(new PassOneNullableArgThrowsNPE());
556 }
557
558 private static class FailTwoArgsFirstArgDoesntThrowNPE extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800559 @Override
560 public void twoArg(String s, Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700561 // Fail: missing NPE for s
562 i.intValue();
563 }
564 }
565
566 public void testFailTwoArgsFirstArgDoesntThrowNPE() {
567 shouldFail(new FailTwoArgsFirstArgDoesntThrowNPE());
568 }
569
570 private static class FailTwoArgsFirstArgThrowsWrongType extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800571 @Override
572 public void twoArg(String s, Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700573 doThrow(s); // Fail: throwing non-NPE exception for null s
574 i.intValue();
575 }
576 }
577
578 public void testFailTwoArgsFirstArgThrowsWrongType() {
579 shouldFail(new FailTwoArgsFirstArgThrowsWrongType());
580 }
581
582 private static class FailTwoArgsSecondArgDoesntThrowNPE extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800583 @Override
584 public void twoArg(String s, Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700585 checkNotNull(s);
586 // Fail: missing NPE for i
587 }
588 }
589
590 public void testFailTwoArgsSecondArgDoesntThrowNPE() {
591 shouldFail(new FailTwoArgsSecondArgDoesntThrowNPE());
592 }
593
594 private static class FailTwoArgsSecondArgThrowsWrongType extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800595 @Override
596 public void twoArg(String s, Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700597 checkNotNull(s);
598 doThrow(i); // Fail: throwing non-NPE exception for null i
599 }
600 }
601
602 public void testFailTwoArgsSecondArgThrowsWrongType() {
603 shouldFail(new FailTwoArgsSecondArgThrowsWrongType());
604 }
605
cpovirkfd919e52017-12-04 08:51:35 -0800606 private static class FailTwoMixedArgsFirstArgDoesntThrowNPE extends PassObject {
607 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800608 public void twoMixedArgs(String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700609 // Fail: missing NPE for s
610 }
611 }
612
613 public void testFailTwoMixedArgsFirstArgDoesntThrowNPE() {
614 shouldFail(new FailTwoMixedArgsFirstArgDoesntThrowNPE());
615 }
616
cpovirkfd919e52017-12-04 08:51:35 -0800617 private static class FailTwoMixedArgsFirstArgThrowsWrongType extends PassObject {
618 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800619 public void twoMixedArgs(String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700620 doThrow(s); // Fail: throwing non-NPE exception for null s
621 }
622 }
623
624 public void testFailTwoMixedArgsFirstArgThrowsWrongType() {
625 shouldFail(new FailTwoMixedArgsFirstArgThrowsWrongType());
626 }
627
628 private static class PassTwoMixedArgsNullableArgThrowsNPE extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800629 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800630 public void twoMixedArgs(String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700631 checkNotNull(s);
632 i.intValue(); // ok to throw NPE?
633 }
634 }
635
636 public void testPassTwoMixedArgsNullableArgThrowsNPE() {
637 shouldPass(new PassTwoMixedArgsNullableArgThrowsNPE());
638 }
639
cpovirkfd919e52017-12-04 08:51:35 -0800640 private static class PassTwoMixedArgSecondNullableArgThrowsOther extends PassObject {
641 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800642 public void twoMixedArgs(String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700643 checkNotNull(s);
644 doThrow(i); // ok to throw non-NPE exception for null i
645 }
646 }
647
648 public void testPassTwoMixedArgSecondNullableArgThrowsOther() {
649 shouldPass(new PassTwoMixedArgSecondNullableArgThrowsOther());
650 }
651
cpovirkfd919e52017-12-04 08:51:35 -0800652 private static class FailTwoMixedArgsSecondArgDoesntThrowNPE extends PassObject {
653 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800654 public void twoMixedArgs(@NullableDecl Integer i, String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700655 // Fail: missing NPE for null s
656 }
657 }
658
659 public void testFailTwoMixedArgsSecondArgDoesntThrowNPE() {
660 shouldFail(new FailTwoMixedArgsSecondArgDoesntThrowNPE());
661 }
662
cpovirkfd919e52017-12-04 08:51:35 -0800663 private static class FailTwoMixedArgsSecondArgThrowsWrongType extends PassObject {
664 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800665 public void twoMixedArgs(@NullableDecl Integer i, String s) {
zhenghua9b94fb32017-04-20 14:33:38 -0700666 doThrow(s); // Fail: throwing non-NPE exception for null s
667 }
668 }
669
670 public void testFailTwoMixedArgsSecondArgThrowsWrongType() {
671 shouldFail(new FailTwoMixedArgsSecondArgThrowsWrongType());
672 }
673
674 private static class PassTwoNullableArgsFirstThrowsNPE extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800675 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800676 public void twoNullableArgs(@NullableDecl String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700677 checkNotNull(s); // ok to throw NPE?
678 }
679 }
680
681 public void testPassTwoNullableArgsFirstThrowsNPE() {
682 shouldPass(new PassTwoNullableArgsFirstThrowsNPE());
683 }
684
685 private static class PassTwoNullableArgsFirstThrowsOther extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800686 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800687 public void twoNullableArgs(@NullableDecl String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700688 doThrow(s); // ok to throw non-NPE exception for null s
689 }
690 }
691
692 public void testPassTwoNullableArgsFirstThrowsOther() {
693 shouldPass(new PassTwoNullableArgsFirstThrowsOther());
694 }
695
696 private static class PassTwoNullableArgsSecondThrowsNPE extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800697 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800698 public void twoNullableArgs(@NullableDecl String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700699 i.intValue(); // ok to throw NPE?
700 }
701 }
702
703 public void testPassTwoNullableArgsSecondThrowsNPE() {
704 shouldPass(new PassTwoNullableArgsSecondThrowsNPE());
705 }
706
707 private static class PassTwoNullableArgsSecondThrowsOther extends PassObject {
cpovirkfd919e52017-12-04 08:51:35 -0800708 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800709 public void twoNullableArgs(@NullableDecl String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700710 doThrow(i); // ok to throw non-NPE exception for null i
711 }
712 }
713
714 public void testPassTwoNullableArgsSecondThrowsOther() {
715 shouldPass(new PassTwoNullableArgsSecondThrowsOther());
716 }
717
cpovirkfd919e52017-12-04 08:51:35 -0800718 private static class PassTwoNullableArgsNeitherThrowsAnything extends PassObject {
719 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800720 public void twoNullableArgs(@NullableDecl String s, @NullableDecl Integer i) {
zhenghua9b94fb32017-04-20 14:33:38 -0700721 // ok to do nothing
722 }
723 }
724
725 public void testPassTwoNullableArgsNeitherThrowsAnything() {
726 shouldPass(new PassTwoNullableArgsNeitherThrowsAnything());
727 }
728
729 @SuppressWarnings("unused") // for NullPointerTester
730 private abstract static class BaseClassThatFailsToThrow {
731 public void oneArg(String s) {}
732 }
733
cpovirkfd919e52017-12-04 08:51:35 -0800734 private static class SubclassWithBadSuperclass extends BaseClassThatFailsToThrow {}
zhenghua9b94fb32017-04-20 14:33:38 -0700735
736 public void testSubclassWithBadSuperclass() {
737 shouldFail(new SubclassWithBadSuperclass());
738 }
739
740 @SuppressWarnings("unused") // for NullPointerTester
741 private abstract static class BaseClassThatFailsToThrowForPackagePrivate {
742 void packagePrivateOneArg(String s) {}
743 }
744
745 private static class SubclassWithBadSuperclassForPackagePrivate
746 extends BaseClassThatFailsToThrowForPackagePrivate {}
747
748 public void testSubclassWithBadSuperclassForPackagePrivateMethod() {
cpovirkfd919e52017-12-04 08:51:35 -0800749 shouldFail(new SubclassWithBadSuperclassForPackagePrivate(), Visibility.PACKAGE);
zhenghua9b94fb32017-04-20 14:33:38 -0700750 }
751
752 @SuppressWarnings("unused") // for NullPointerTester
753 private abstract static class BaseClassThatFailsToThrowForProtected {
754 protected void protectedOneArg(String s) {}
755 }
756
757 private static class SubclassWithBadSuperclassForProtected
758 extends BaseClassThatFailsToThrowForProtected {}
759
760 public void testSubclassWithBadSuperclassForPackageProtectedMethod() {
cpovirkfd919e52017-12-04 08:51:35 -0800761 shouldFail(new SubclassWithBadSuperclassForProtected(), Visibility.PROTECTED);
zhenghua9b94fb32017-04-20 14:33:38 -0700762 }
763
cpovirkfd919e52017-12-04 08:51:35 -0800764 private static class SubclassThatOverridesBadSuperclassMethod extends BaseClassThatFailsToThrow {
765 @Override
cpovirk2d0957c2017-12-04 18:48:08 -0800766 public void oneArg(@NullableDecl String s) {}
zhenghua9b94fb32017-04-20 14:33:38 -0700767 }
768
769 public void testSubclassThatOverridesBadSuperclassMethod() {
770 shouldPass(new SubclassThatOverridesBadSuperclassMethod());
771 }
772
773 @SuppressWarnings("unused") // for NullPointerTester
cpovirkfd919e52017-12-04 08:51:35 -0800774 private static class SubclassOverridesTheWrongMethod extends BaseClassThatFailsToThrow {
cpovirk2d0957c2017-12-04 18:48:08 -0800775 public void oneArg(@NullableDecl CharSequence s) {}
zhenghua9b94fb32017-04-20 14:33:38 -0700776 }
777
778 public void testSubclassOverridesTheWrongMethod() {
779 shouldFail(new SubclassOverridesTheWrongMethod());
780 }
781
782 @SuppressWarnings("unused") // for NullPointerTester
783 private static class ClassThatFailsToThrowForStatic {
784 static void staticOneArg(String s) {}
785 }
786
787 public void testClassThatFailsToThrowForStatic() {
788 shouldFail(ClassThatFailsToThrowForStatic.class);
789 }
790
cpovirkfd919e52017-12-04 08:51:35 -0800791 private static class SubclassThatFailsToThrowForStatic extends ClassThatFailsToThrowForStatic {}
zhenghua9b94fb32017-04-20 14:33:38 -0700792
793 public void testSubclassThatFailsToThrowForStatic() {
794 shouldFail(SubclassThatFailsToThrowForStatic.class);
795 }
796
797 private static class SubclassThatTriesToOverrideBadStaticMethod
798 extends ClassThatFailsToThrowForStatic {
cpovirk2d0957c2017-12-04 18:48:08 -0800799 static void staticOneArg(@NullableDecl String s) {}
zhenghua9b94fb32017-04-20 14:33:38 -0700800 }
801
802 public void testSubclassThatTriesToOverrideBadStaticMethod() {
803 shouldFail(SubclassThatTriesToOverrideBadStaticMethod.class);
804 }
805
806 private static final class HardToCreate {
807 private HardToCreate(HardToCreate x) {}
808 }
809
810 @SuppressWarnings("unused") // used by reflection
811 private static class CanCreateDefault {
cpovirk2d0957c2017-12-04 18:48:08 -0800812 public void foo(@NullableDecl HardToCreate ignored, String required) {
zhenghua9b94fb32017-04-20 14:33:38 -0700813 checkNotNull(required);
814 }
815 }
816
817 public void testCanCreateDefault() {
818 shouldPass(new CanCreateDefault());
819 }
820
821 @SuppressWarnings("unused") // used by reflection
822 private static class CannotCreateDefault {
823 public void foo(HardToCreate ignored, String required) {
824 checkNotNull(ignored);
825 checkNotNull(required);
826 }
827 }
828
829 public void testCannotCreateDefault() {
830 shouldFail(new CannotCreateDefault());
831 }
832
833 private static void shouldPass(Object instance, Visibility visibility) {
834 new NullPointerTester().testInstanceMethods(instance, visibility);
835 }
836
837 private static void shouldPass(Object instance) {
838 shouldPass(instance, Visibility.PACKAGE);
839 shouldPass(instance, Visibility.PROTECTED);
840 shouldPass(instance, Visibility.PUBLIC);
841 }
842
843 // TODO(cpovirk): eliminate surprising Object/Class overloading of shouldFail
844
845 private static void shouldFail(Object instance, Visibility visibility) {
846 try {
847 new NullPointerTester().testInstanceMethods(instance, visibility);
848 } catch (AssertionFailedError expected) {
849 return;
850 }
851 fail("Should detect problem in " + instance.getClass().getSimpleName());
852 }
853
854 private static void shouldFail(Object instance) {
855 shouldFail(instance, Visibility.PACKAGE);
856 shouldFail(instance, Visibility.PROTECTED);
857 shouldFail(instance, Visibility.PUBLIC);
858 }
859
860 private static void shouldFail(Class<?> cls, Visibility visibility) {
861 try {
862 new NullPointerTester().testStaticMethods(cls, visibility);
863 } catch (AssertionFailedError expected) {
864 return;
865 }
866 fail("Should detect problem in " + cls.getSimpleName());
867 }
868
869 private static void shouldFail(Class<?> cls) {
870 shouldFail(cls, Visibility.PACKAGE);
871 }
872
873 @SuppressWarnings("unused") // used by reflection
874 private static class PrivateClassWithPrivateConstructor {
cpovirk2d0957c2017-12-04 18:48:08 -0800875 private PrivateClassWithPrivateConstructor(@NullableDecl Integer argument) {}
zhenghua9b94fb32017-04-20 14:33:38 -0700876 }
877
878 public void testPrivateClass() {
879 NullPointerTester tester = new NullPointerTester();
cpovirkfd919e52017-12-04 08:51:35 -0800880 for (Constructor<?> constructor :
881 PrivateClassWithPrivateConstructor.class.getDeclaredConstructors()) {
zhenghua9b94fb32017-04-20 14:33:38 -0700882 tester.testConstructor(constructor);
883 }
884 }
885
886 private interface Foo<T> {
887 void doSomething(T bar, Integer baz);
888 }
889
890 private static class StringFoo implements Foo<String> {
891
cpovirkfd919e52017-12-04 08:51:35 -0800892 @Override
893 public void doSomething(String bar, Integer baz) {
zhenghua9b94fb32017-04-20 14:33:38 -0700894 checkNotNull(bar);
895 checkNotNull(baz);
896 }
897 }
898
899 public void testBridgeMethodIgnored() {
900 new NullPointerTester().testAllPublicInstanceMethods(new StringFoo());
901 }
902
903 private abstract static class DefaultValueChecker {
904
905 private final Map<Integer, Object> arguments = Maps.newHashMap();
906
907 final DefaultValueChecker runTester() {
cpovirkfd919e52017-12-04 08:51:35 -0800908 new NullPointerTester().testInstanceMethods(this, Visibility.PACKAGE);
zhenghua9b94fb32017-04-20 14:33:38 -0700909 return this;
910 }
911
912 final void assertNonNullValues(Object... expectedValues) {
913 assertEquals(expectedValues.length, arguments.size());
914 for (int i = 0; i < expectedValues.length; i++) {
cpovirkfd919e52017-12-04 08:51:35 -0800915 assertEquals("Default value for parameter #" + i, expectedValues[i], arguments.get(i));
zhenghua9b94fb32017-04-20 14:33:38 -0700916 }
917 }
918
919 final Object getDefaultParameterValue(int position) {
920 return arguments.get(position);
921 }
922
923 final void calledWith(Object... args) {
924 for (int i = 0; i < args.length; i++) {
925 if (args[i] != null) {
926 arguments.put(i, args[i]);
927 }
928 }
929 for (Object arg : args) {
930 checkNotNull(arg); // to fulfill null check
931 }
932 }
933 }
934
935 private enum Gender {
cpovirkfd919e52017-12-04 08:51:35 -0800936 MALE,
937 FEMALE
zhenghua9b94fb32017-04-20 14:33:38 -0700938 }
939
940 private static class AllDefaultValuesChecker extends DefaultValueChecker {
941
942 @SuppressWarnings("unused") // called by NullPointerTester
943 public void checkDefaultValuesForTheseTypes(
944 Gender gender,
cpovirkfd919e52017-12-04 08:51:35 -0800945 Integer integer,
946 int i,
947 String string,
948 CharSequence charSequence,
zhenghua9b94fb32017-04-20 14:33:38 -0700949 List<String> list,
950 ImmutableList<Integer> immutableList,
951 Map<String, Integer> map,
952 ImmutableMap<String, String> immutableMap,
953 Set<String> set,
954 ImmutableSet<Integer> immutableSet,
955 SortedSet<Number> sortedSet,
956 ImmutableSortedSet<Number> immutableSortedSet,
957 Multiset<String> multiset,
958 ImmutableMultiset<Integer> immutableMultiset,
959 Multimap<String, Integer> multimap,
960 ImmutableMultimap<String, Integer> immutableMultimap,
961 Table<String, Integer, Exception> table,
962 ImmutableTable<Integer, String, Exception> immutableTable) {
963 calledWith(
964 gender,
cpovirkfd919e52017-12-04 08:51:35 -0800965 integer,
966 i,
967 string,
968 charSequence,
969 list,
970 immutableList,
971 map,
972 immutableMap,
973 set,
974 immutableSet,
975 sortedSet,
976 immutableSortedSet,
977 multiset,
978 immutableMultiset,
979 multimap,
980 immutableMultimap,
981 table,
982 immutableTable);
zhenghua9b94fb32017-04-20 14:33:38 -0700983 }
984
985 final void check() {
cpovirkfd919e52017-12-04 08:51:35 -0800986 runTester()
987 .assertNonNullValues(
988 Gender.MALE,
989 Integer.valueOf(0),
990 0,
991 "",
992 "",
993 ImmutableList.of(),
994 ImmutableList.of(),
995 ImmutableMap.of(),
996 ImmutableMap.of(),
997 ImmutableSet.of(),
998 ImmutableSet.of(),
999 ImmutableSortedSet.of(),
1000 ImmutableSortedSet.of(),
1001 ImmutableMultiset.of(),
1002 ImmutableMultiset.of(),
1003 ImmutableMultimap.of(),
1004 ImmutableMultimap.of(),
1005 ImmutableTable.of(),
1006 ImmutableTable.of());
zhenghua9b94fb32017-04-20 14:33:38 -07001007 }
1008 }
1009
1010 public void testDefaultValues() {
1011 new AllDefaultValuesChecker().check();
1012 }
1013
cpovirkfd919e52017-12-04 08:51:35 -08001014 private static class ObjectArrayDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001015
1016 @SuppressWarnings("unused") // called by NullPointerTester
1017 public void checkArray(Object[] array, String s) {
1018 calledWith(array, s);
1019 }
1020
1021 void check() {
1022 runTester();
1023 Object[] defaultArray = (Object[]) getDefaultParameterValue(0);
1024 assertThat(defaultArray).isEmpty();
1025 }
1026 }
1027
1028 public void testObjectArrayDefaultValue() {
1029 new ObjectArrayDefaultValueChecker().check();
1030 }
1031
cpovirkfd919e52017-12-04 08:51:35 -08001032 private static class StringArrayDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001033
1034 @SuppressWarnings("unused") // called by NullPointerTester
1035 public void checkArray(String[] array, String s) {
1036 calledWith(array, s);
1037 }
1038
1039 void check() {
1040 runTester();
1041 String[] defaultArray = (String[]) getDefaultParameterValue(0);
1042 assertThat(defaultArray).isEmpty();
1043 }
1044 }
1045
1046 public void testStringArrayDefaultValue() {
1047 new StringArrayDefaultValueChecker().check();
1048 }
1049
cpovirkfd919e52017-12-04 08:51:35 -08001050 private static class IntArrayDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001051
1052 @SuppressWarnings("unused") // called by NullPointerTester
1053 public void checkArray(int[] array, String s) {
1054 calledWith(array, s);
1055 }
1056
1057 void check() {
1058 runTester();
1059 int[] defaultArray = (int[]) getDefaultParameterValue(0);
1060 assertEquals(0, defaultArray.length);
1061 }
1062 }
1063
1064 public void testIntArrayDefaultValue() {
1065 new IntArrayDefaultValueChecker().check();
1066 }
1067
1068 private enum EmptyEnum {}
1069
cpovirkfd919e52017-12-04 08:51:35 -08001070 private static class EmptyEnumDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001071
1072 @SuppressWarnings("unused") // called by NullPointerTester
1073 public void checkArray(EmptyEnum object, String s) {
1074 calledWith(object, s);
1075 }
1076
1077 void check() {
1078 try {
1079 runTester();
1080 } catch (AssertionFailedError expected) {
1081 return;
1082 }
1083 fail("Should have failed because enum has no constant");
1084 }
1085 }
1086
1087 public void testEmptyEnumDefaultValue() {
1088 new EmptyEnumDefaultValueChecker().check();
1089 }
1090
cpovirkfd919e52017-12-04 08:51:35 -08001091 private static class GenericClassTypeDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001092
1093 @SuppressWarnings("unused") // called by NullPointerTester
1094 public void checkArray(Class<? extends List<?>> cls, String s) {
1095 calledWith(cls, s);
1096 }
1097
1098 void check() {
1099 runTester();
1100 Class<?> defaultClass = (Class<?>) getDefaultParameterValue(0);
1101 assertEquals(List.class, defaultClass);
1102 }
1103 }
1104
1105 public void testGenericClassDefaultValue() {
1106 new GenericClassTypeDefaultValueChecker().check();
1107 }
1108
cpovirkfd919e52017-12-04 08:51:35 -08001109 private static class NonGenericClassTypeDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001110
1111 @SuppressWarnings("unused") // called by NullPointerTester
1112 public void checkArray(@SuppressWarnings("rawtypes") Class cls, String s) {
1113 calledWith(cls, s);
1114 }
1115
1116 void check() {
1117 runTester();
1118 Class<?> defaultClass = (Class<?>) getDefaultParameterValue(0);
1119 assertEquals(Object.class, defaultClass);
1120 }
1121 }
1122
1123 public void testNonGenericClassDefaultValue() {
1124 new NonGenericClassTypeDefaultValueChecker().check();
1125 }
1126
cpovirkfd919e52017-12-04 08:51:35 -08001127 private static class GenericTypeTokenDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001128
1129 @SuppressWarnings("unused") // called by NullPointerTester
cpovirkfd919e52017-12-04 08:51:35 -08001130 public void checkArray(TypeToken<? extends List<? super Number>> type, String s) {
zhenghua9b94fb32017-04-20 14:33:38 -07001131 calledWith(type, s);
1132 }
1133
1134 void check() {
1135 runTester();
1136 TypeToken<?> defaultType = (TypeToken<?>) getDefaultParameterValue(0);
cpovirkfd919e52017-12-04 08:51:35 -08001137 assertTrue(new TypeToken<List<? super Number>>() {}.isSupertypeOf(defaultType));
zhenghua9b94fb32017-04-20 14:33:38 -07001138 }
1139 }
1140
1141 public void testGenericTypeTokenDefaultValue() {
1142 new GenericTypeTokenDefaultValueChecker().check();
1143 }
1144
cpovirkfd919e52017-12-04 08:51:35 -08001145 private static class NonGenericTypeTokenDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001146
1147 @SuppressWarnings("unused") // called by NullPointerTester
cpovirkfd919e52017-12-04 08:51:35 -08001148 public void checkArray(@SuppressWarnings("rawtypes") TypeToken type, String s) {
zhenghua9b94fb32017-04-20 14:33:38 -07001149 calledWith(type, s);
1150 }
1151
1152 void check() {
1153 runTester();
1154 TypeToken<?> defaultType = (TypeToken<?>) getDefaultParameterValue(0);
1155 assertEquals(new TypeToken<Object>() {}, defaultType);
1156 }
1157 }
1158
1159 public void testNonGenericTypeTokenDefaultValue() {
1160 new NonGenericTypeTokenDefaultValueChecker().check();
1161 }
1162
1163 private interface FromTo<F, T> extends Function<F, T> {}
1164
cpovirkfd919e52017-12-04 08:51:35 -08001165 private static class GenericInterfaceDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001166
1167 @SuppressWarnings("unused") // called by NullPointerTester
1168 public void checkArray(FromTo<String, Integer> f, String s) {
1169 calledWith(f, s);
1170 }
1171
1172 void check() {
1173 runTester();
1174 FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1175 assertEquals(0, defaultFunction.apply(null));
1176 }
1177 }
1178
1179 public void testGenericInterfaceDefaultValue() {
1180 new GenericInterfaceDefaultValueChecker().check();
1181 }
1182
1183 private interface NullRejectingFromTo<F, T> extends Function<F, T> {
cpovirkfd919e52017-12-04 08:51:35 -08001184 @Override
1185 public abstract T apply(F from);
zhenghua9b94fb32017-04-20 14:33:38 -07001186 }
1187
cpovirkfd919e52017-12-04 08:51:35 -08001188 private static class NullRejectingInterfaceDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001189
1190 @SuppressWarnings("unused") // called by NullPointerTester
1191 public void checkArray(NullRejectingFromTo<String, Integer> f, String s) {
1192 calledWith(f, s);
1193 }
1194
1195 void check() {
1196 runTester();
cpovirkfd919e52017-12-04 08:51:35 -08001197 NullRejectingFromTo<?, ?> defaultFunction =
1198 (NullRejectingFromTo<?, ?>) getDefaultParameterValue(0);
zhenghua9b94fb32017-04-20 14:33:38 -07001199 assertNotNull(defaultFunction);
1200 try {
1201 defaultFunction.apply(null);
1202 fail("Proxy Should have rejected null");
cpovirkfd919e52017-12-04 08:51:35 -08001203 } catch (NullPointerException expected) {
1204 }
zhenghua9b94fb32017-04-20 14:33:38 -07001205 }
1206 }
1207
1208 public void testNullRejectingInterfaceDefaultValue() {
1209 new NullRejectingInterfaceDefaultValueChecker().check();
1210 }
1211
cpovirkfd919e52017-12-04 08:51:35 -08001212 private static class MultipleInterfacesDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001213
1214 @SuppressWarnings("unused") // called by NullPointerTester
cpovirkfd919e52017-12-04 08:51:35 -08001215 public <T extends FromTo<String, Integer> & Supplier<Long>> void checkArray(T f, String s) {
zhenghua9b94fb32017-04-20 14:33:38 -07001216 calledWith(f, s);
1217 }
1218
1219 void check() {
1220 runTester();
1221 FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1222 assertEquals(0, defaultFunction.apply(null));
1223 Supplier<?> defaultSupplier = (Supplier<?>) defaultFunction;
1224 assertEquals(Long.valueOf(0), defaultSupplier.get());
1225 }
1226 }
1227
1228 public void testMultipleInterfacesDefaultValue() {
1229 new MultipleInterfacesDefaultValueChecker().check();
1230 }
1231
cpovirkfd919e52017-12-04 08:51:35 -08001232 private static class GenericInterface2DefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001233
1234 @SuppressWarnings("unused") // called by NullPointerTester
1235 public void checkArray(FromTo<String, FromTo<Integer, String>> f, String s) {
1236 calledWith(f, s);
1237 }
1238
1239 void check() {
1240 runTester();
1241 FromTo<?, ?> defaultFunction = (FromTo<?, ?>) getDefaultParameterValue(0);
1242 FromTo<?, ?> returnValue = (FromTo<?, ?>) defaultFunction.apply(null);
1243 assertEquals("", returnValue.apply(null));
1244 }
1245 }
1246
1247 public void testGenericInterfaceReturnedByGenericMethod() {
1248 new GenericInterface2DefaultValueChecker().check();
1249 }
1250
cpovirkfd919e52017-12-04 08:51:35 -08001251 private abstract static class AbstractGenericDefaultValueChecker<T> extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001252
1253 @SuppressWarnings("unused") // called by NullPointerTester
1254 public void checkGeneric(T value, String s) {
1255 calledWith(value, s);
1256 }
1257 }
1258
1259 private static class GenericDefaultValueResolvedToStringChecker
1260 extends AbstractGenericDefaultValueChecker<String> {
1261 void check() {
1262 runTester();
1263 assertEquals("", getDefaultParameterValue(0));
1264 }
1265 }
1266
1267 public void testGenericTypeResolvedForDefaultValue() {
1268 new GenericDefaultValueResolvedToStringChecker().check();
1269 }
1270
cpovirkfd919e52017-12-04 08:51:35 -08001271 private abstract static class AbstractGenericDefaultValueForPackagePrivateMethodChecker<T>
zhenghua9b94fb32017-04-20 14:33:38 -07001272 extends DefaultValueChecker {
1273
1274 @SuppressWarnings("unused") // called by NullPointerTester
1275 void checkGeneric(T value, String s) {
1276 calledWith(value, s);
1277 }
1278 }
1279
cpovirkfd919e52017-12-04 08:51:35 -08001280 private static class DefaultValueForPackagePrivateMethodResolvedToStringChecker
1281 extends AbstractGenericDefaultValueForPackagePrivateMethodChecker<String> {
zhenghua9b94fb32017-04-20 14:33:38 -07001282 void check() {
1283 runTester();
1284 assertEquals("", getDefaultParameterValue(0));
1285 }
1286 }
1287
1288 public void testDefaultValueResolvedForPackagePrivateMethod() {
1289 new DefaultValueForPackagePrivateMethodResolvedToStringChecker().check();
1290 }
1291
cpovirkfd919e52017-12-04 08:51:35 -08001292 private static class ConverterDefaultValueChecker extends DefaultValueChecker {
zhenghua9b94fb32017-04-20 14:33:38 -07001293
1294 @SuppressWarnings("unused") // called by NullPointerTester
1295 public void checkArray(Converter<String, Integer> c, String s) {
1296 calledWith(c, s);
1297 }
1298
1299 void check() {
1300 runTester();
1301 @SuppressWarnings("unchecked") // We are checking it anyway
cpovirkfd919e52017-12-04 08:51:35 -08001302 Converter<String, Integer> defaultConverter =
1303 (Converter<String, Integer>) getDefaultParameterValue(0);
zhenghua9b94fb32017-04-20 14:33:38 -07001304 assertEquals(Integer.valueOf(0), defaultConverter.convert("anything"));
1305 assertEquals("", defaultConverter.reverse().convert(123));
1306 assertNull(defaultConverter.convert(null));
1307 assertNull(defaultConverter.reverse().convert(null));
1308 }
1309 }
1310
1311 public void testConverterDefaultValue() {
1312 new ConverterDefaultValueChecker().check();
1313 }
1314
1315 private static class VisibilityMethods {
1316
1317 @SuppressWarnings("unused") // Called by reflection
1318 private void privateMethod() {}
1319
1320 @SuppressWarnings("unused") // Called by reflection
1321 void packagePrivateMethod() {}
1322
1323 @SuppressWarnings("unused") // Called by reflection
1324 protected void protectedMethod() {}
1325
1326 @SuppressWarnings("unused") // Called by reflection
1327 public void publicMethod() {}
1328 }
1329
1330 public void testVisibility_public() throws Exception {
cpovirkfd919e52017-12-04 08:51:35 -08001331 assertFalse(
1332 Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1333 assertFalse(
1334 Visibility.PUBLIC.isVisible(
1335 VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1336 assertFalse(
1337 Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1338 assertTrue(
1339 Visibility.PUBLIC.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
zhenghua9b94fb32017-04-20 14:33:38 -07001340 }
1341
1342 public void testVisibility_protected() throws Exception {
cpovirkfd919e52017-12-04 08:51:35 -08001343 assertFalse(
1344 Visibility.PROTECTED.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1345 assertFalse(
1346 Visibility.PROTECTED.isVisible(
1347 VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1348 assertTrue(
1349 Visibility.PROTECTED.isVisible(
1350 VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1351 assertTrue(
1352 Visibility.PROTECTED.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
zhenghua9b94fb32017-04-20 14:33:38 -07001353 }
1354
1355 public void testVisibility_package() throws Exception {
cpovirkfd919e52017-12-04 08:51:35 -08001356 assertFalse(
1357 Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("privateMethod")));
1358 assertTrue(
1359 Visibility.PACKAGE.isVisible(
1360 VisibilityMethods.class.getDeclaredMethod("packagePrivateMethod")));
1361 assertTrue(
1362 Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("protectedMethod")));
1363 assertTrue(
1364 Visibility.PACKAGE.isVisible(VisibilityMethods.class.getDeclaredMethod("publicMethod")));
zhenghua9b94fb32017-04-20 14:33:38 -07001365 }
1366
1367 private class Inner {
1368 public Inner(String s) {
1369 checkNotNull(s);
1370 }
1371 }
1372
1373 public void testNonStaticInnerClass() {
1374 try {
1375 new NullPointerTester().testAllPublicConstructors(Inner.class);
1376 fail();
1377 } catch (IllegalArgumentException expected) {
1378 assertThat(expected.getMessage()).contains("inner class");
1379 }
1380 }
1381
1382 private static String rootLocaleFormat(String format, Object... args) {
1383 return String.format(Locale.ROOT, format, args);
1384 }
1385
1386 static class OverridesEquals {
1387 @Override
1388 public boolean equals(Object o) {
1389 return true;
1390 }
1391 }
1392
1393 static class DoesNotOverrideEquals {
1394 public boolean equals(Object a, Object b) {
1395 return true;
1396 }
1397 }
1398
1399 public void testEqualsMethod() {
1400 shouldPass(new OverridesEquals());
1401 shouldFail(new DoesNotOverrideEquals());
1402 }
1403
1404 private static final class FailOnOneOfTwoConstructors {
1405 @SuppressWarnings("unused") // Called by reflection
1406 public FailOnOneOfTwoConstructors(String s) {}
1407
1408 @SuppressWarnings("unused") // Called by reflection
1409 public FailOnOneOfTwoConstructors(Object o) {
1410 checkNotNull(o);
1411 }
1412 }
1413
1414 public void testConstructor_Ignored_ShouldPass() throws Exception {
1415 new NullPointerTester()
1416 .ignore(FailOnOneOfTwoConstructors.class.getDeclaredConstructor(String.class))
1417 .testAllPublicConstructors(FailOnOneOfTwoConstructors.class);
1418 }
1419
1420 public void testConstructor_ShouldFail() throws Exception {
1421 try {
1422 new NullPointerTester().testAllPublicConstructors(FailOnOneOfTwoConstructors.class);
1423 } catch (AssertionFailedError expected) {
1424 return;
1425 }
1426 fail("Should detect problem in " + FailOnOneOfTwoConstructors.class.getSimpleName());
1427 }
1428}