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