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