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