1 /* 2 * Copyright (C) 2012 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.checkNotNull; 20 import static com.google.common.truth.Truth.assertThat; 21 22 import com.google.common.base.Functions; 23 import com.google.common.base.Optional; 24 import com.google.common.collect.ImmutableList; 25 import com.google.common.testing.ClassSanityTester.FactoryMethodReturnsNullException; 26 import com.google.common.testing.ClassSanityTester.ParameterHasNoDistinctValueException; 27 import com.google.common.testing.ClassSanityTester.ParameterNotInstantiableException; 28 import com.google.common.testing.NullPointerTester.Visibility; 29 import java.io.Serializable; 30 import java.lang.reflect.InvocationTargetException; 31 import java.util.AbstractList; 32 import java.util.ArrayList; 33 import java.util.List; 34 import java.util.Map; 35 import java.util.Set; 36 import java.util.concurrent.TimeUnit; 37 import java.util.stream.Collectors; 38 import java.util.stream.Stream; 39 import junit.framework.AssertionFailedError; 40 import junit.framework.TestCase; 41 import org.checkerframework.checker.nullness.qual.Nullable; 42 43 /** 44 * Unit tests for {@link ClassSanityTester}. 45 * 46 * @author Ben Yu 47 */ 48 public class ClassSanityTesterTest extends TestCase { 49 50 private final ClassSanityTester tester = new ClassSanityTester(); 51 testEqualsOnReturnValues_good()52 public void testEqualsOnReturnValues_good() throws Exception { 53 tester.forAllPublicStaticMethods(GoodEqualsFactory.class).testEquals(); 54 } 55 56 public static class GoodEqualsFactory { good( String a, int b, @SuppressWarnings("unused") OneConstantEnum oneConstantOnly, @SuppressWarnings("unused") @Nullable NoConstantEnum noConstant)57 public static Object good( 58 String a, 59 int b, 60 // oneConstantOnly doesn't matter since it's not nullable and can be only 1 value. 61 @SuppressWarnings("unused") OneConstantEnum oneConstantOnly, 62 // noConstant doesn't matter since it can only be null 63 @SuppressWarnings("unused") @Nullable NoConstantEnum noConstant) { 64 return new GoodEquals(a, b); 65 } 66 // instance method ignored badIgnored()67 public Object badIgnored() { 68 return new BadEquals(); 69 } 70 // primitive ignored returnsInt()71 public int returnsInt() { 72 throw new UnsupportedOperationException(); 73 } 74 // void ignored voidMethod()75 public void voidMethod() { 76 throw new UnsupportedOperationException(); 77 } 78 // non-public method ignored badButNotPublic()79 static Object badButNotPublic() { 80 return new BadEquals(); 81 } 82 } 83 testForAllPublicStaticMethods_noPublicStaticMethods()84 public void testForAllPublicStaticMethods_noPublicStaticMethods() throws Exception { 85 try { 86 tester.forAllPublicStaticMethods(NoPublicStaticMethods.class).testEquals(); 87 } catch (AssertionFailedError expected) { 88 assertThat(expected) 89 .hasMessageThat() 90 .isEqualTo( 91 "No public static methods that return java.lang.Object or subtype are found in " 92 + NoPublicStaticMethods.class 93 + "."); 94 return; 95 } 96 fail(); 97 } 98 testEqualsOnReturnValues_bad()99 public void testEqualsOnReturnValues_bad() throws Exception { 100 try { 101 tester.forAllPublicStaticMethods(BadEqualsFactory.class).testEquals(); 102 } catch (AssertionFailedError expected) { 103 return; 104 } 105 fail(); 106 } 107 108 private static class BadEqualsFactory { 109 /** oneConstantOnly matters now since it can be either null or the constant. */ 110 @SuppressWarnings("unused") // Called by reflection bad(String a, int b, @Nullable OneConstantEnum oneConstantOnly)111 public static Object bad(String a, int b, @Nullable OneConstantEnum oneConstantOnly) { 112 return new GoodEquals(a, b); 113 } 114 } 115 testNullsOnReturnValues_good()116 public void testNullsOnReturnValues_good() throws Exception { 117 tester.forAllPublicStaticMethods(GoodNullsFactory.class).testNulls(); 118 } 119 120 private static class GoodNullsFactory { 121 @SuppressWarnings("unused") // Called by reflection good(String s)122 public static Object good(String s) { 123 return new GoodNulls(s); 124 } 125 } 126 testNullsOnReturnValues_bad()127 public void testNullsOnReturnValues_bad() throws Exception { 128 try { 129 tester.forAllPublicStaticMethods(BadNullsFactory.class).thatReturn(Object.class).testNulls(); 130 } catch (AssertionFailedError expected) { 131 return; 132 } 133 fail(); 134 } 135 testNullsOnReturnValues_returnTypeFiltered()136 public void testNullsOnReturnValues_returnTypeFiltered() throws Exception { 137 try { 138 tester 139 .forAllPublicStaticMethods(BadNullsFactory.class) 140 .thatReturn(Iterable.class) 141 .testNulls(); 142 } catch (AssertionFailedError expected) { 143 assertThat(expected) 144 .hasMessageThat() 145 .isEqualTo( 146 "No public static methods that return java.lang.Iterable or subtype are found in " 147 + BadNullsFactory.class 148 + "."); 149 return; 150 } 151 fail(); 152 } 153 154 public static class BadNullsFactory { bad(@uppressWarnings"unused") String a)155 public static Object bad(@SuppressWarnings("unused") String a) { 156 return new BadNulls(); 157 } 158 } 159 160 @AndroidIncompatible // TODO(cpovirk): ClassNotFoundException... ClassSanityTesterTest$AnInterface testSerializableOnReturnValues_good()161 public void testSerializableOnReturnValues_good() throws Exception { 162 tester.forAllPublicStaticMethods(GoodSerializableFactory.class).testSerializable(); 163 } 164 165 public static class GoodSerializableFactory { good(Runnable r)166 public static Object good(Runnable r) { 167 return r; 168 } 169 good(AnInterface i)170 public static Object good(AnInterface i) { 171 return i; 172 } 173 } 174 testSerializableOnReturnValues_bad()175 public void testSerializableOnReturnValues_bad() throws Exception { 176 try { 177 tester.forAllPublicStaticMethods(BadSerializableFactory.class).testSerializable(); 178 } catch (AssertionFailedError expected) { 179 return; 180 } 181 fail(); 182 } 183 184 public static class BadSerializableFactory { bad()185 public static Object bad() { 186 return new Serializable() { 187 @SuppressWarnings("unused") 188 private final Object notSerializable = new Object(); 189 }; 190 } 191 } 192 testEqualsAndSerializableOnReturnValues_equalsIsGoodButNotSerializable()193 public void testEqualsAndSerializableOnReturnValues_equalsIsGoodButNotSerializable() 194 throws Exception { 195 try { 196 tester.forAllPublicStaticMethods(GoodEqualsFactory.class).testEqualsAndSerializable(); 197 } catch (AssertionFailedError expected) { 198 return; 199 } 200 fail("should have failed"); 201 } 202 testEqualsAndSerializableOnReturnValues_serializableButNotEquals()203 public void testEqualsAndSerializableOnReturnValues_serializableButNotEquals() throws Exception { 204 try { 205 tester.forAllPublicStaticMethods(GoodSerializableFactory.class).testEqualsAndSerializable(); 206 } catch (AssertionFailedError expected) { 207 return; 208 } 209 fail("should have failed"); 210 } 211 212 @AndroidIncompatible // TODO(cpovirk): ClassNotFoundException... ClassSanityTesterTest$AnInterface testEqualsAndSerializableOnReturnValues_good()213 public void testEqualsAndSerializableOnReturnValues_good() throws Exception { 214 tester 215 .forAllPublicStaticMethods(GoodEqualsAndSerialiableFactory.class) 216 .testEqualsAndSerializable(); 217 } 218 219 public static class GoodEqualsAndSerialiableFactory { good(AnInterface s)220 public static Object good(AnInterface s) { 221 return Functions.constant(s); 222 } 223 } 224 testEqualsForReturnValues_factoryReturnsNullButNotAnnotated()225 public void testEqualsForReturnValues_factoryReturnsNullButNotAnnotated() throws Exception { 226 try { 227 tester.forAllPublicStaticMethods(FactoryThatReturnsNullButNotAnnotated.class).testEquals(); 228 } catch (AssertionFailedError expected) { 229 return; 230 } 231 fail(); 232 } 233 testNullsForReturnValues_factoryReturnsNullButNotAnnotated()234 public void testNullsForReturnValues_factoryReturnsNullButNotAnnotated() throws Exception { 235 try { 236 tester.forAllPublicStaticMethods(FactoryThatReturnsNullButNotAnnotated.class).testNulls(); 237 } catch (AssertionFailedError expected) { 238 return; 239 } 240 fail(); 241 } 242 testSerializableForReturnValues_factoryReturnsNullButNotAnnotated()243 public void testSerializableForReturnValues_factoryReturnsNullButNotAnnotated() throws Exception { 244 try { 245 tester 246 .forAllPublicStaticMethods(FactoryThatReturnsNullButNotAnnotated.class) 247 .testSerializable(); 248 } catch (AssertionFailedError expected) { 249 return; 250 } 251 fail(); 252 } 253 testEqualsAndSerializableForReturnValues_factoryReturnsNullButNotAnnotated()254 public void testEqualsAndSerializableForReturnValues_factoryReturnsNullButNotAnnotated() 255 throws Exception { 256 try { 257 tester 258 .forAllPublicStaticMethods(FactoryThatReturnsNullButNotAnnotated.class) 259 .testEqualsAndSerializable(); 260 } catch (AssertionFailedError expected) { 261 return; 262 } 263 fail(); 264 } 265 266 public static class FactoryThatReturnsNullButNotAnnotated { bad()267 public static Object bad() { 268 return null; 269 } 270 } 271 testEqualsForReturnValues_factoryReturnsNullAndAnnotated()272 public void testEqualsForReturnValues_factoryReturnsNullAndAnnotated() throws Exception { 273 tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class).testEquals(); 274 } 275 testNullsForReturnValues_factoryReturnsNullAndAnnotated()276 public void testNullsForReturnValues_factoryReturnsNullAndAnnotated() throws Exception { 277 tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class).testNulls(); 278 } 279 testSerializableForReturnValues_factoryReturnsNullAndAnnotated()280 public void testSerializableForReturnValues_factoryReturnsNullAndAnnotated() throws Exception { 281 tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class).testSerializable(); 282 } 283 testEqualsAndSerializableForReturnValues_factoryReturnsNullAndAnnotated()284 public void testEqualsAndSerializableForReturnValues_factoryReturnsNullAndAnnotated() 285 throws Exception { 286 tester 287 .forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class) 288 .testEqualsAndSerializable(); 289 } 290 291 public static class FactoryThatReturnsNullAndAnnotated { bad()292 public static @Nullable Object bad() { 293 return null; 294 } 295 } 296 testGoodEquals()297 public void testGoodEquals() throws Exception { 298 tester.testEquals(GoodEquals.class); 299 } 300 testEquals_interface()301 public void testEquals_interface() { 302 tester.testEquals(AnInterface.class); 303 } 304 testEquals_abstractClass()305 public void testEquals_abstractClass() { 306 tester.testEquals(AnAbstractClass.class); 307 } 308 testEquals_enum()309 public void testEquals_enum() { 310 tester.testEquals(OneConstantEnum.class); 311 } 312 testBadEquals()313 public void testBadEquals() throws Exception { 314 try { 315 tester.testEquals(BadEquals.class); 316 } catch (AssertionFailedError expected) { 317 assertThat(expected.getMessage()).contains("create(null)"); 318 return; 319 } 320 fail("should have failed"); 321 } 322 testBadEquals_withParameterizedType()323 public void testBadEquals_withParameterizedType() throws Exception { 324 try { 325 tester.testEquals(BadEqualsWithParameterizedType.class); 326 } catch (AssertionFailedError expected) { 327 assertThat(expected.getMessage()).contains("create([[1]])"); 328 return; 329 } 330 fail("should have failed"); 331 } 332 testBadEquals_withSingleParameterValue()333 public void testBadEquals_withSingleParameterValue() throws Exception { 334 try { 335 tester.doTestEquals(ConstructorParameterWithOptionalNotInstantiable.class); 336 fail(); 337 } catch (ParameterHasNoDistinctValueException expected) { 338 } 339 } 340 testGoodReferentialEqualityComparison()341 public void testGoodReferentialEqualityComparison() throws Exception { 342 tester.testEquals(UsesEnum.class); 343 tester.testEquals(UsesReferentialEquality.class); 344 tester.testEquals(SameListInstance.class); 345 } 346 testStreamParameterSkippedForNullTesting()347 public void testStreamParameterSkippedForNullTesting() throws Exception { 348 tester.testNulls(WithStreamParameter.class); 349 } 350 351 @AndroidIncompatible // problem with equality of Type objects? testEqualsUsingReferentialEquality()352 public void testEqualsUsingReferentialEquality() throws Exception { 353 assertBadUseOfReferentialEquality(SameIntegerInstance.class); 354 assertBadUseOfReferentialEquality(SameLongInstance.class); 355 assertBadUseOfReferentialEquality(SameFloatInstance.class); 356 assertBadUseOfReferentialEquality(SameDoubleInstance.class); 357 assertBadUseOfReferentialEquality(SameShortInstance.class); 358 assertBadUseOfReferentialEquality(SameByteInstance.class); 359 assertBadUseOfReferentialEquality(SameCharacterInstance.class); 360 assertBadUseOfReferentialEquality(SameBooleanInstance.class); 361 assertBadUseOfReferentialEquality(SameObjectInstance.class); 362 assertBadUseOfReferentialEquality(SameStringInstance.class); 363 assertBadUseOfReferentialEquality(SameInterfaceInstance.class); 364 } 365 assertBadUseOfReferentialEquality(Class<?> cls)366 private void assertBadUseOfReferentialEquality(Class<?> cls) throws Exception { 367 try { 368 tester.testEquals(cls); 369 } catch (AssertionFailedError expected) { 370 assertThat(expected.getMessage()).contains(cls.getSimpleName() + "("); 371 return; 372 } 373 fail("should have failed for " + cls); 374 } 375 testParameterNotInstantiableForEqualsTest()376 public void testParameterNotInstantiableForEqualsTest() throws Exception { 377 try { 378 tester.doTestEquals(ConstructorParameterNotInstantiable.class); 379 fail("should have failed"); 380 } catch (ParameterNotInstantiableException expected) { 381 } 382 } 383 testNoDistinctValueForEqualsTest()384 public void testNoDistinctValueForEqualsTest() throws Exception { 385 try { 386 tester.doTestEquals(ConstructorParameterSingleValue.class); 387 fail("should have failed"); 388 } catch (ParameterHasNoDistinctValueException expected) { 389 } 390 } 391 testConstructorThrowsForEqualsTest()392 public void testConstructorThrowsForEqualsTest() throws Exception { 393 try { 394 tester.doTestEquals(ConstructorThrows.class); 395 fail("should have failed"); 396 } catch (InvocationTargetException expected) { 397 } 398 } 399 testFactoryMethodReturnsNullForEqualsTest()400 public void testFactoryMethodReturnsNullForEqualsTest() throws Exception { 401 try { 402 tester.doTestEquals(FactoryMethodReturnsNullAndAnnotated.class); 403 fail("should have failed"); 404 } catch (FactoryMethodReturnsNullException expected) { 405 } 406 } 407 testFactoryMethodReturnsNullButNotAnnotatedInEqualsTest()408 public void testFactoryMethodReturnsNullButNotAnnotatedInEqualsTest() throws Exception { 409 try { 410 tester.testEquals(FactoryMethodReturnsNullButNotAnnotated.class); 411 } catch (AssertionFailedError expected) { 412 return; 413 } 414 fail("should have failed"); 415 } 416 testNoEqualsChecksOnEnum()417 public void testNoEqualsChecksOnEnum() throws Exception { 418 tester.testEquals(OneConstantEnum.class); 419 tester.testEquals(NoConstantEnum.class); 420 tester.testEquals(TimeUnit.class); 421 } 422 testNoEqualsChecksOnInterface()423 public void testNoEqualsChecksOnInterface() throws Exception { 424 tester.testEquals(Runnable.class); 425 } 426 testNoEqualsChecksOnAnnotation()427 public void testNoEqualsChecksOnAnnotation() throws Exception { 428 tester.testEquals(MyAnnotation.class); 429 } 430 testGoodNulls()431 public void testGoodNulls() throws Exception { 432 tester.testNulls(GoodNulls.class); 433 } 434 testNoNullCheckNeededDespitNotInstantiable()435 public void testNoNullCheckNeededDespitNotInstantiable() throws Exception { 436 tester.doTestNulls(NoNullCheckNeededDespitNotInstantiable.class, Visibility.PACKAGE); 437 } 438 testNulls_interface()439 public void testNulls_interface() { 440 tester.testNulls(AnInterface.class); 441 } 442 testNulls_abstractClass()443 public void testNulls_abstractClass() { 444 tester.testNulls(AnAbstractClass.class); 445 } 446 testNulls_enum()447 public void testNulls_enum() throws Exception { 448 tester.testNulls(OneConstantEnum.class); 449 tester.testNulls(NoConstantEnum.class); 450 tester.testNulls(TimeUnit.class); 451 } 452 testNulls_parameterOptionalNotInstantiable()453 public void testNulls_parameterOptionalNotInstantiable() throws Exception { 454 tester.testNulls(ConstructorParameterWithOptionalNotInstantiable.class); 455 } 456 testEnumFailsToCheckNull()457 public void testEnumFailsToCheckNull() throws Exception { 458 try { 459 tester.testNulls(EnumFailsToCheckNull.class); 460 } catch (AssertionFailedError expected) { 461 return; 462 } 463 fail("should have failed"); 464 } 465 testNoNullChecksOnInterface()466 public void testNoNullChecksOnInterface() throws Exception { 467 tester.testNulls(Runnable.class); 468 } 469 testNoNullChecksOnAnnotation()470 public void testNoNullChecksOnAnnotation() throws Exception { 471 tester.testNulls(MyAnnotation.class); 472 } 473 testBadNulls()474 public void testBadNulls() throws Exception { 475 try { 476 tester.testNulls(BadNulls.class); 477 } catch (AssertionFailedError expected) { 478 return; 479 } 480 fail("should have failed"); 481 } 482 testInstantiate_factoryMethodReturnsNullButNotAnnotated()483 public void testInstantiate_factoryMethodReturnsNullButNotAnnotated() throws Exception { 484 try { 485 tester.instantiate(FactoryMethodReturnsNullButNotAnnotated.class); 486 } catch (AssertionFailedError expected) { 487 assertThat(expected.getMessage()).contains("@Nullable"); 488 return; 489 } 490 fail("should have failed"); 491 } 492 testInstantiate_factoryMethodReturnsNullAndAnnotated()493 public void testInstantiate_factoryMethodReturnsNullAndAnnotated() throws Exception { 494 try { 495 tester.instantiate(FactoryMethodReturnsNullAndAnnotated.class); 496 fail("should have failed"); 497 } catch (FactoryMethodReturnsNullException expected) { 498 } 499 } 500 testInstantiate_factoryMethodAcceptsNull()501 public void testInstantiate_factoryMethodAcceptsNull() throws Exception { 502 assertNull(tester.instantiate(FactoryMethodAcceptsNull.class).name); 503 } 504 testInstantiate_factoryMethodDoesNotAcceptNull()505 public void testInstantiate_factoryMethodDoesNotAcceptNull() throws Exception { 506 assertNotNull(tester.instantiate(FactoryMethodDoesNotAcceptNull.class).name); 507 } 508 testInstantiate_constructorAcceptsNull()509 public void testInstantiate_constructorAcceptsNull() throws Exception { 510 assertNull(tester.instantiate(ConstructorAcceptsNull.class).name); 511 } 512 testInstantiate_constructorDoesNotAcceptNull()513 public void testInstantiate_constructorDoesNotAcceptNull() throws Exception { 514 assertNotNull(tester.instantiate(ConstructorDoesNotAcceptNull.class).name); 515 } 516 testInstantiate_notInstantiable()517 public void testInstantiate_notInstantiable() throws Exception { 518 assertNull(tester.instantiate(NotInstantiable.class)); 519 } 520 testInstantiate_noConstantEnum()521 public void testInstantiate_noConstantEnum() throws Exception { 522 assertNull(tester.instantiate(NoConstantEnum.class)); 523 } 524 testInstantiate_oneConstantEnum()525 public void testInstantiate_oneConstantEnum() throws Exception { 526 assertEquals(OneConstantEnum.A, tester.instantiate(OneConstantEnum.class)); 527 } 528 testInstantiate_interface()529 public void testInstantiate_interface() throws Exception { 530 assertNull(tester.instantiate(Runnable.class)); 531 } 532 testInstantiate_abstractClass()533 public void testInstantiate_abstractClass() throws Exception { 534 assertNull(tester.instantiate(AbstractList.class)); 535 } 536 testInstantiate_annotation()537 public void testInstantiate_annotation() throws Exception { 538 assertNull(tester.instantiate(MyAnnotation.class)); 539 } 540 testInstantiate_setDefault()541 public void testInstantiate_setDefault() throws Exception { 542 NotInstantiable x = new NotInstantiable(); 543 tester.setDefault(NotInstantiable.class, x); 544 assertNotNull(tester.instantiate(ConstructorParameterNotInstantiable.class)); 545 } 546 testSetDistinctValues_equalInstances()547 public void testSetDistinctValues_equalInstances() { 548 try { 549 tester.setDistinctValues(String.class, "", ""); 550 fail(); 551 } catch (IllegalArgumentException expected) { 552 } 553 } 554 testInstantiate_setDistinctValues()555 public void testInstantiate_setDistinctValues() throws Exception { 556 NotInstantiable x = new NotInstantiable(); 557 NotInstantiable y = new NotInstantiable(); 558 tester.setDistinctValues(NotInstantiable.class, x, y); 559 assertNotNull(tester.instantiate(ConstructorParameterNotInstantiable.class)); 560 tester.testEquals(ConstructorParameterMapOfNotInstantiable.class); 561 } 562 testInstantiate_constructorThrows()563 public void testInstantiate_constructorThrows() throws Exception { 564 try { 565 tester.instantiate(ConstructorThrows.class); 566 fail(); 567 } catch (InvocationTargetException expected) { 568 } 569 } 570 testInstantiate_factoryMethodThrows()571 public void testInstantiate_factoryMethodThrows() throws Exception { 572 try { 573 tester.instantiate(FactoryMethodThrows.class); 574 fail(); 575 } catch (InvocationTargetException expected) { 576 } 577 } 578 testInstantiate_constructorParameterNotInstantiable()579 public void testInstantiate_constructorParameterNotInstantiable() throws Exception { 580 try { 581 tester.instantiate(ConstructorParameterNotInstantiable.class); 582 fail(); 583 } catch (ParameterNotInstantiableException expected) { 584 } 585 } 586 testInstantiate_factoryMethodParameterNotInstantiable()587 public void testInstantiate_factoryMethodParameterNotInstantiable() throws Exception { 588 try { 589 tester.instantiate(FactoryMethodParameterNotInstantiable.class); 590 fail(); 591 } catch (ParameterNotInstantiableException expected) { 592 } 593 } 594 testInstantiate_instantiableFactoryMethodChosen()595 public void testInstantiate_instantiableFactoryMethodChosen() throws Exception { 596 assertEquals("good", tester.instantiate(InstantiableFactoryMethodChosen.class).name); 597 } 598 599 @AndroidIncompatible // TODO(cpovirk): ClassNotFoundException... ClassSanityTesterTest$AnInterface testInterfaceProxySerializable()600 public void testInterfaceProxySerializable() throws Exception { 601 SerializableTester.reserializeAndAssert(tester.instantiate(HasAnInterface.class)); 602 } 603 testReturnValuesFromAnotherPackageIgnoredForNullTests()604 public void testReturnValuesFromAnotherPackageIgnoredForNullTests() throws Exception { 605 new ClassSanityTester().forAllPublicStaticMethods(JdkObjectFactory.class).testNulls(); 606 } 607 608 /** String doesn't check nulls as we expect. But the framework should ignore. */ 609 private static class JdkObjectFactory { 610 @SuppressWarnings("unused") // Called by reflection create()611 public static Object create() { 612 return new ArrayList<>(); 613 } 614 } 615 616 static class HasAnInterface implements Serializable { 617 private final AnInterface i; 618 HasAnInterface(AnInterface i)619 public HasAnInterface(AnInterface i) { 620 this.i = i; 621 } 622 623 @Override equals(@ullable Object obj)624 public boolean equals(@Nullable Object obj) { 625 if (obj instanceof HasAnInterface) { 626 HasAnInterface that = (HasAnInterface) obj; 627 return i.equals(that.i); 628 } else { 629 return false; 630 } 631 } 632 633 @Override hashCode()634 public int hashCode() { 635 return i.hashCode(); 636 } 637 } 638 639 static class InstantiableFactoryMethodChosen { 640 final String name; 641 InstantiableFactoryMethodChosen(String name)642 private InstantiableFactoryMethodChosen(String name) { 643 this.name = name; 644 } 645 InstantiableFactoryMethodChosen(NotInstantiable x)646 public InstantiableFactoryMethodChosen(NotInstantiable x) { 647 checkNotNull(x); 648 this.name = "x1"; 649 } 650 create(NotInstantiable x)651 public static InstantiableFactoryMethodChosen create(NotInstantiable x) { 652 return new InstantiableFactoryMethodChosen(x); 653 } 654 create(String s)655 public static InstantiableFactoryMethodChosen create(String s) { 656 checkNotNull(s); 657 return new InstantiableFactoryMethodChosen("good"); 658 } 659 } 660 testInstantiate_instantiableConstructorChosen()661 public void testInstantiate_instantiableConstructorChosen() throws Exception { 662 assertEquals("good", tester.instantiate(InstantiableConstructorChosen.class).name); 663 } 664 testEquals_setOfNonInstantiable()665 public void testEquals_setOfNonInstantiable() throws Exception { 666 try { 667 new ClassSanityTester().doTestEquals(SetWrapper.class); 668 fail(); 669 } catch (ParameterNotInstantiableException expected) { 670 } 671 } 672 673 private abstract static class Wrapper { 674 private final Object wrapped; 675 Wrapper(Object wrapped)676 Wrapper(Object wrapped) { 677 this.wrapped = checkNotNull(wrapped); 678 } 679 680 @Override equals(@ullable Object obj)681 public boolean equals(@Nullable Object obj) { 682 // In general getClass().isInstance() is bad for equals. 683 // But here we fully control the subclasses to ensure symmetry. 684 if (getClass().isInstance(obj)) { 685 Wrapper that = (Wrapper) obj; 686 return wrapped.equals(that.wrapped); 687 } 688 return false; 689 } 690 691 @Override hashCode()692 public int hashCode() { 693 return wrapped.hashCode(); 694 } 695 696 @Override toString()697 public String toString() { 698 return wrapped.toString(); 699 } 700 } 701 702 private static class SetWrapper extends Wrapper { SetWrapper(Set<NotInstantiable> wrapped)703 public SetWrapper(Set<NotInstantiable> wrapped) { 704 super(wrapped); 705 } 706 } 707 708 static class InstantiableConstructorChosen { 709 final String name; 710 InstantiableConstructorChosen(String name)711 public InstantiableConstructorChosen(String name) { 712 checkNotNull(name); 713 this.name = "good"; 714 } 715 InstantiableConstructorChosen(NotInstantiable x)716 public InstantiableConstructorChosen(NotInstantiable x) { 717 checkNotNull(x); 718 this.name = "x1"; 719 } 720 create(NotInstantiable x)721 public static InstantiableFactoryMethodChosen create(NotInstantiable x) { 722 return new InstantiableFactoryMethodChosen(x); 723 } 724 } 725 726 static class GoodEquals { 727 728 private final String a; 729 private final int b; 730 GoodEquals(String a, int b)731 private GoodEquals(String a, int b) { 732 this.a = checkNotNull(a); 733 this.b = b; 734 } 735 736 // ignored by testEquals() GoodEquals(@uppressWarnings"unused") NotInstantiable x)737 GoodEquals(@SuppressWarnings("unused") NotInstantiable x) { 738 this.a = "x"; 739 this.b = -1; 740 } 741 742 // will keep trying GoodEquals(@uppressWarnings"unused") NotInstantiable x, int b)743 public GoodEquals(@SuppressWarnings("unused") NotInstantiable x, int b) { 744 this.a = "x"; 745 this.b = b; 746 } 747 748 // keep trying 749 @SuppressWarnings("unused") create(int a, int b)750 static GoodEquals create(int a, int b) { 751 throw new RuntimeException(); 752 } 753 754 // Good! create(String a, int b)755 static GoodEquals create(String a, int b) { 756 return new GoodEquals(a, b); 757 } 758 759 // keep trying 760 @SuppressWarnings("unused") createMayReturnNull(int a, int b)761 public static @Nullable GoodEquals createMayReturnNull(int a, int b) { 762 return null; 763 } 764 765 @Override equals(@ullable Object obj)766 public boolean equals(@Nullable Object obj) { 767 if (obj instanceof GoodEquals) { 768 GoodEquals that = (GoodEquals) obj; 769 return a.equals(that.a) && b == that.b; 770 } else { 771 return false; 772 } 773 } 774 775 @Override hashCode()776 public int hashCode() { 777 return 0; 778 } 779 } 780 781 static class BadEquals { 782 BadEquals()783 public BadEquals() {} // ignored by testEquals() since it has less parameters. 784 create(@uppressWarnings"unused") @ullable String s)785 public static BadEquals create(@SuppressWarnings("unused") @Nullable String s) { 786 return new BadEquals(); 787 } 788 789 @Override equals(@ullable Object obj)790 public boolean equals(@Nullable Object obj) { 791 return obj instanceof BadEquals; 792 } 793 794 @Override hashCode()795 public int hashCode() { 796 return 0; 797 } 798 } 799 800 static class SameIntegerInstance { 801 private final Integer i; 802 SameIntegerInstance(Integer i)803 public SameIntegerInstance(Integer i) { 804 this.i = checkNotNull(i); 805 } 806 807 @Override hashCode()808 public int hashCode() { 809 return i.hashCode(); 810 } 811 812 @Override 813 @SuppressWarnings("NumericEquality") equals(Object obj)814 public boolean equals(Object obj) { 815 if (obj instanceof SameIntegerInstance) { 816 SameIntegerInstance that = (SameIntegerInstance) obj; 817 return i == that.i; 818 } 819 return false; 820 } 821 } 822 823 static class SameLongInstance { 824 private final Long i; 825 SameLongInstance(Long i)826 public SameLongInstance(Long i) { 827 this.i = checkNotNull(i); 828 } 829 830 @Override hashCode()831 public int hashCode() { 832 return i.hashCode(); 833 } 834 835 @Override 836 @SuppressWarnings("NumericEquality") equals(Object obj)837 public boolean equals(Object obj) { 838 if (obj instanceof SameLongInstance) { 839 SameLongInstance that = (SameLongInstance) obj; 840 return i == that.i; 841 } 842 return false; 843 } 844 } 845 846 static class SameFloatInstance { 847 private final Float i; 848 SameFloatInstance(Float i)849 public SameFloatInstance(Float i) { 850 this.i = checkNotNull(i); 851 } 852 853 @Override hashCode()854 public int hashCode() { 855 return i.hashCode(); 856 } 857 858 @Override 859 @SuppressWarnings("NumericEquality") equals(Object obj)860 public boolean equals(Object obj) { 861 if (obj instanceof SameFloatInstance) { 862 SameFloatInstance that = (SameFloatInstance) obj; 863 return i == that.i; 864 } 865 return false; 866 } 867 } 868 869 static class SameDoubleInstance { 870 private final Double i; 871 SameDoubleInstance(Double i)872 public SameDoubleInstance(Double i) { 873 this.i = checkNotNull(i); 874 } 875 876 @Override hashCode()877 public int hashCode() { 878 return i.hashCode(); 879 } 880 881 @Override 882 @SuppressWarnings("NumericEquality") equals(Object obj)883 public boolean equals(Object obj) { 884 if (obj instanceof SameDoubleInstance) { 885 SameDoubleInstance that = (SameDoubleInstance) obj; 886 return i == that.i; 887 } 888 return false; 889 } 890 } 891 892 static class SameShortInstance { 893 private final Short i; 894 SameShortInstance(Short i)895 public SameShortInstance(Short i) { 896 this.i = checkNotNull(i); 897 } 898 899 @Override hashCode()900 public int hashCode() { 901 return i.hashCode(); 902 } 903 904 @Override 905 @SuppressWarnings("NumericEquality") equals(Object obj)906 public boolean equals(Object obj) { 907 if (obj instanceof SameShortInstance) { 908 SameShortInstance that = (SameShortInstance) obj; 909 return i == that.i; 910 } 911 return false; 912 } 913 } 914 915 static class SameByteInstance { 916 private final Byte i; 917 SameByteInstance(Byte i)918 public SameByteInstance(Byte i) { 919 this.i = checkNotNull(i); 920 } 921 922 @Override hashCode()923 public int hashCode() { 924 return i.hashCode(); 925 } 926 927 @Override 928 @SuppressWarnings("NumericEquality") equals(Object obj)929 public boolean equals(Object obj) { 930 if (obj instanceof SameByteInstance) { 931 SameByteInstance that = (SameByteInstance) obj; 932 return i == that.i; 933 } 934 return false; 935 } 936 } 937 938 static class SameCharacterInstance { 939 private final Character i; 940 SameCharacterInstance(Character i)941 public SameCharacterInstance(Character i) { 942 this.i = checkNotNull(i); 943 } 944 945 @Override hashCode()946 public int hashCode() { 947 return i.hashCode(); 948 } 949 950 @Override equals(Object obj)951 public boolean equals(Object obj) { 952 if (obj instanceof SameCharacterInstance) { 953 SameCharacterInstance that = (SameCharacterInstance) obj; 954 return i == that.i; 955 } 956 return false; 957 } 958 } 959 960 static class SameBooleanInstance { 961 private final Boolean i; 962 SameBooleanInstance(Boolean i)963 public SameBooleanInstance(Boolean i) { 964 this.i = checkNotNull(i); 965 } 966 967 @Override hashCode()968 public int hashCode() { 969 return i.hashCode(); 970 } 971 972 @Override equals(Object obj)973 public boolean equals(Object obj) { 974 if (obj instanceof SameBooleanInstance) { 975 SameBooleanInstance that = (SameBooleanInstance) obj; 976 return i == that.i; 977 } 978 return false; 979 } 980 } 981 982 static class SameStringInstance { 983 private final String s; 984 SameStringInstance(String s)985 public SameStringInstance(String s) { 986 this.s = checkNotNull(s); 987 } 988 989 @Override hashCode()990 public int hashCode() { 991 return s.hashCode(); 992 } 993 994 @Override equals(Object obj)995 public boolean equals(Object obj) { 996 if (obj instanceof SameStringInstance) { 997 SameStringInstance that = (SameStringInstance) obj; 998 return s == that.s; 999 } 1000 return false; 1001 } 1002 } 1003 1004 static class SameObjectInstance { 1005 private final Object s; 1006 SameObjectInstance(Object s)1007 public SameObjectInstance(Object s) { 1008 this.s = checkNotNull(s); 1009 } 1010 1011 @Override hashCode()1012 public int hashCode() { 1013 return s.hashCode(); 1014 } 1015 1016 @Override equals(Object obj)1017 public boolean equals(Object obj) { 1018 if (obj instanceof SameObjectInstance) { 1019 SameObjectInstance that = (SameObjectInstance) obj; 1020 return s == that.s; 1021 } 1022 return false; 1023 } 1024 } 1025 1026 static class SameInterfaceInstance { 1027 private final Runnable s; 1028 SameInterfaceInstance(Runnable s)1029 public SameInterfaceInstance(Runnable s) { 1030 this.s = checkNotNull(s); 1031 } 1032 1033 @Override hashCode()1034 public int hashCode() { 1035 return s.hashCode(); 1036 } 1037 1038 @Override equals(Object obj)1039 public boolean equals(Object obj) { 1040 if (obj instanceof SameInterfaceInstance) { 1041 SameInterfaceInstance that = (SameInterfaceInstance) obj; 1042 return s == that.s; 1043 } 1044 return false; 1045 } 1046 } 1047 1048 static class SameListInstance { 1049 private final List<?> s; 1050 SameListInstance(List<?> s)1051 public SameListInstance(List<?> s) { 1052 this.s = checkNotNull(s); 1053 } 1054 1055 @Override hashCode()1056 public int hashCode() { 1057 return System.identityHashCode(s); 1058 } 1059 1060 @Override equals(Object obj)1061 public boolean equals(Object obj) { 1062 if (obj instanceof SameListInstance) { 1063 SameListInstance that = (SameListInstance) obj; 1064 return s == that.s; 1065 } 1066 return false; 1067 } 1068 } 1069 1070 static class WithStreamParameter { 1071 private final List<?> list; 1072 1073 // This should be ignored. WithStreamParameter(Stream<?> s, String str)1074 public WithStreamParameter(Stream<?> s, String str) { 1075 this.list = s.collect(Collectors.toList()); 1076 checkNotNull(str); 1077 } 1078 } 1079 1080 static class UsesReferentialEquality { 1081 private final ReferentialEquality s; 1082 UsesReferentialEquality(ReferentialEquality s)1083 public UsesReferentialEquality(ReferentialEquality s) { 1084 this.s = checkNotNull(s); 1085 } 1086 1087 @Override hashCode()1088 public int hashCode() { 1089 return s.hashCode(); 1090 } 1091 1092 @Override equals(Object obj)1093 public boolean equals(Object obj) { 1094 if (obj instanceof UsesReferentialEquality) { 1095 UsesReferentialEquality that = (UsesReferentialEquality) obj; 1096 return s == that.s; 1097 } 1098 return false; 1099 } 1100 } 1101 1102 static class UsesEnum { 1103 private final TimeUnit s; 1104 UsesEnum(TimeUnit s)1105 public UsesEnum(TimeUnit s) { 1106 this.s = checkNotNull(s); 1107 } 1108 1109 @Override hashCode()1110 public int hashCode() { 1111 return s.hashCode(); 1112 } 1113 1114 @Override equals(Object obj)1115 public boolean equals(Object obj) { 1116 if (obj instanceof UsesEnum) { 1117 UsesEnum that = (UsesEnum) obj; 1118 return s == that.s; 1119 } 1120 return false; 1121 } 1122 } 1123 1124 public static class ReferentialEquality { ReferentialEquality()1125 public ReferentialEquality() {} 1126 } 1127 1128 static class BadEqualsWithParameterizedType { 1129 1130 // ignored by testEquals() since it has less parameters. BadEqualsWithParameterizedType()1131 public BadEqualsWithParameterizedType() {} 1132 create( @uppressWarnings"unused") ImmutableList<Iterable<? extends String>> s)1133 public static BadEqualsWithParameterizedType create( 1134 @SuppressWarnings("unused") ImmutableList<Iterable<? extends String>> s) { 1135 return new BadEqualsWithParameterizedType(); 1136 } 1137 1138 @Override equals(@ullable Object obj)1139 public boolean equals(@Nullable Object obj) { 1140 return obj instanceof BadEqualsWithParameterizedType; 1141 } 1142 1143 @Override hashCode()1144 public int hashCode() { 1145 return 0; 1146 } 1147 } 1148 1149 static class GoodNulls { GoodNulls(String s)1150 public GoodNulls(String s) { 1151 checkNotNull(s); 1152 } 1153 rejectNull(String s)1154 public void rejectNull(String s) { 1155 checkNotNull(s); 1156 } 1157 } 1158 1159 public static class BadNulls { failsToRejectNull(@uppressWarnings"unused") String s)1160 public void failsToRejectNull(@SuppressWarnings("unused") String s) {} 1161 } 1162 1163 public static class NoNullCheckNeededDespitNotInstantiable { 1164 NoNullCheckNeededDespitNotInstantiable(NotInstantiable x)1165 public NoNullCheckNeededDespitNotInstantiable(NotInstantiable x) { 1166 checkNotNull(x); 1167 } 1168 1169 @SuppressWarnings("unused") // reflected primitiveOnly(int i)1170 void primitiveOnly(int i) {} 1171 1172 @SuppressWarnings("unused") // reflected nullableOnly(@ullable String s)1173 void nullableOnly(@Nullable String s) {} 1174 noParameter()1175 public void noParameter() {} 1176 1177 @SuppressWarnings("unused") // reflected primitiveAndNullable(@ullable String s, int i)1178 void primitiveAndNullable(@Nullable String s, int i) {} 1179 } 1180 1181 static class FactoryMethodReturnsNullButNotAnnotated { FactoryMethodReturnsNullButNotAnnotated()1182 private FactoryMethodReturnsNullButNotAnnotated() {} 1183 returnsNull()1184 static FactoryMethodReturnsNullButNotAnnotated returnsNull() { 1185 return null; 1186 } 1187 } 1188 1189 static class FactoryMethodReturnsNullAndAnnotated { FactoryMethodReturnsNullAndAnnotated()1190 private FactoryMethodReturnsNullAndAnnotated() {} 1191 returnsNull()1192 public static @Nullable FactoryMethodReturnsNullAndAnnotated returnsNull() { 1193 return null; 1194 } 1195 } 1196 1197 static class FactoryMethodAcceptsNull { 1198 1199 final String name; 1200 FactoryMethodAcceptsNull(String name)1201 private FactoryMethodAcceptsNull(String name) { 1202 this.name = name; 1203 } 1204 create(@ullable String name)1205 static FactoryMethodAcceptsNull create(@Nullable String name) { 1206 return new FactoryMethodAcceptsNull(name); 1207 } 1208 } 1209 1210 static class FactoryMethodDoesNotAcceptNull { 1211 1212 final String name; 1213 FactoryMethodDoesNotAcceptNull(String name)1214 private FactoryMethodDoesNotAcceptNull(String name) { 1215 this.name = checkNotNull(name); 1216 } 1217 create(String name)1218 public static FactoryMethodDoesNotAcceptNull create(String name) { 1219 return new FactoryMethodDoesNotAcceptNull(name); 1220 } 1221 } 1222 1223 static class ConstructorAcceptsNull { 1224 1225 final String name; 1226 ConstructorAcceptsNull(@ullable String name)1227 public ConstructorAcceptsNull(@Nullable String name) { 1228 this.name = name; 1229 } 1230 } 1231 1232 static class ConstructorDoesNotAcceptNull { 1233 1234 final String name; 1235 ConstructorDoesNotAcceptNull(String name)1236 ConstructorDoesNotAcceptNull(String name) { 1237 this.name = checkNotNull(name); 1238 } 1239 } 1240 1241 static class ConstructorParameterNotInstantiable { ConstructorParameterNotInstantiable(@uppressWarnings"unused") NotInstantiable x)1242 public ConstructorParameterNotInstantiable(@SuppressWarnings("unused") NotInstantiable x) {} 1243 } 1244 1245 static class ConstructorParameterMapOfNotInstantiable { 1246 private final Map<NotInstantiable, NotInstantiable> m; 1247 ConstructorParameterMapOfNotInstantiable(Map<NotInstantiable, NotInstantiable> m)1248 public ConstructorParameterMapOfNotInstantiable(Map<NotInstantiable, NotInstantiable> m) { 1249 this.m = checkNotNull(m); 1250 } 1251 1252 @Override equals(@ullable Object obj)1253 public boolean equals(@Nullable Object obj) { 1254 if (obj instanceof ConstructorParameterMapOfNotInstantiable) { 1255 return m.equals(((ConstructorParameterMapOfNotInstantiable) obj).m); 1256 } else { 1257 return false; 1258 } 1259 } 1260 1261 @Override hashCode()1262 public int hashCode() { 1263 return m.hashCode(); 1264 } 1265 } 1266 1267 // Test that we should get a distinct parameter error when doing equals test. 1268 static class ConstructorParameterWithOptionalNotInstantiable { ConstructorParameterWithOptionalNotInstantiable(Optional<NotInstantiable> x)1269 public ConstructorParameterWithOptionalNotInstantiable(Optional<NotInstantiable> x) { 1270 checkNotNull(x); 1271 } 1272 1273 @Override equals(@ullable Object obj)1274 public boolean equals(@Nullable Object obj) { 1275 throw new UnsupportedOperationException(); 1276 } 1277 1278 @Override hashCode()1279 public int hashCode() { 1280 throw new UnsupportedOperationException(); 1281 } 1282 } 1283 1284 static class ConstructorParameterSingleValue { ConstructorParameterSingleValue(@uppressWarnings"unused") Singleton s)1285 public ConstructorParameterSingleValue(@SuppressWarnings("unused") Singleton s) {} 1286 1287 @Override equals(Object obj)1288 public boolean equals(Object obj) { 1289 return obj instanceof ConstructorParameterSingleValue; 1290 } 1291 1292 @Override hashCode()1293 public int hashCode() { 1294 return 1; 1295 } 1296 1297 public static class Singleton { 1298 public static final Singleton INSTANCE = new Singleton(); 1299 Singleton()1300 private Singleton() {} 1301 } 1302 } 1303 1304 static class FactoryMethodParameterNotInstantiable { 1305 FactoryMethodParameterNotInstantiable()1306 private FactoryMethodParameterNotInstantiable() {} 1307 create( @uppressWarnings"unused") NotInstantiable x)1308 static FactoryMethodParameterNotInstantiable create( 1309 @SuppressWarnings("unused") NotInstantiable x) { 1310 return new FactoryMethodParameterNotInstantiable(); 1311 } 1312 } 1313 1314 static class ConstructorThrows { ConstructorThrows()1315 public ConstructorThrows() { 1316 throw new RuntimeException(); 1317 } 1318 } 1319 1320 static class FactoryMethodThrows { FactoryMethodThrows()1321 private FactoryMethodThrows() {} 1322 create()1323 public static FactoryMethodThrows create() { 1324 throw new RuntimeException(); 1325 } 1326 } 1327 1328 static class NotInstantiable { NotInstantiable()1329 private NotInstantiable() {} 1330 } 1331 1332 private enum NoConstantEnum {} 1333 1334 private enum OneConstantEnum { 1335 A 1336 } 1337 1338 private enum EnumFailsToCheckNull { 1339 A; 1340 1341 @SuppressWarnings("unused") failToCheckNull(String s)1342 public void failToCheckNull(String s) {} 1343 } 1344 1345 private interface AnInterface {} 1346 1347 private abstract static class AnAbstractClass { 1348 @SuppressWarnings("unused") AnAbstractClass(String s)1349 public AnAbstractClass(String s) {} 1350 1351 @SuppressWarnings("unused") failsToCheckNull(String s)1352 public void failsToCheckNull(String s) {} 1353 } 1354 1355 private static class NoPublicStaticMethods { 1356 @SuppressWarnings("unused") // To test non-public factory isn't used. notPublic()1357 static String notPublic() { 1358 return ""; 1359 } 1360 } 1361 1362 @interface MyAnnotation {} 1363 } 1364