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 52 public void testEqualsOnReturnValues_good() throws Exception { 53 tester.forAllPublicStaticMethods(GoodEqualsFactory.class).testEquals(); 54 } 55 56 public static class GoodEqualsFactory { 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 65 public Object badIgnored() { 66 return new BadEquals(); 67 } 68 // primitive ignored 69 public int returnsInt() { 70 throw new UnsupportedOperationException(); 71 } 72 // void ignored 73 public void voidMethod() { 74 throw new UnsupportedOperationException(); 75 } 76 // non-public method ignored 77 static Object badButNotPublic() { 78 return new BadEquals(); 79 } 80 } 81 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 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 107 public static Object bad(String a, int b, 108 @Nullable OneConstantEnum oneConstantOnly) { 109 return new GoodEquals(a, b); 110 } 111 } 112 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 119 public static Object good(String s) { 120 return new GoodNulls(s); 121 } 122 } 123 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 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 { 153 public static Object bad(@SuppressWarnings("unused") String a) { 154 return new BadNulls(); 155 } 156 } 157 158 public void testSerializableOnReturnValues_good() throws Exception { 159 tester.forAllPublicStaticMethods(GoodSerializableFactory.class).testSerializable(); 160 } 161 162 public static class GoodSerializableFactory { 163 public static Object good(Runnable r) { 164 return r; 165 } 166 public static Object good(AnInterface i) { 167 return i; 168 } 169 } 170 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 { 181 public static Object bad() { 182 return new Serializable() { 183 @SuppressWarnings("unused") 184 private final Object notSerializable = new Object(); 185 }; 186 } 187 } 188 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 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 209 public void testEqualsAndSerializableOnReturnValues_good() 210 throws Exception { 211 tester.forAllPublicStaticMethods(GoodEqualsAndSerialiableFactory.class) 212 .testEqualsAndSerializable(); 213 } 214 215 public static class GoodEqualsAndSerialiableFactory { 216 public static Object good(AnInterface s) { 217 return Functions.constant(s); 218 } 219 } 220 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 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 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 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 { 263 public static Object bad() { 264 return null; 265 } 266 } 267 268 public void testEqualsForReturnValues_factoryReturnsNullAndAnnotated() throws Exception { 269 tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class) 270 .testEquals(); 271 } 272 273 public void testNullsForReturnValues_factoryReturnsNullAndAnnotated() throws Exception { 274 tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class) 275 .testNulls(); 276 } 277 278 public void testSerializableForReturnValues_factoryReturnsNullAndAnnotated() throws Exception { 279 tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class) 280 .testSerializable(); 281 } 282 283 public void testEqualsAndSerializableForReturnValues_factoryReturnsNullAndAnnotated() 284 throws Exception { 285 tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class) 286 .testEqualsAndSerializable(); 287 } 288 289 public static class FactoryThatReturnsNullAndAnnotated { 290 @Nullable public static Object bad() { 291 return null; 292 } 293 } 294 295 public void testGoodEquals() throws Exception { 296 tester.testEquals(GoodEquals.class); 297 } 298 299 public void testEquals_interface() { 300 tester.testEquals(AnInterface.class); 301 } 302 303 public void testEquals_abstractClass() { 304 tester.testEquals(AnAbstractClass.class); 305 } 306 307 public void testEquals_enum() { 308 tester.testEquals(OneConstantEnum.class); 309 } 310 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 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 331 public void testBadEquals_withSingleParameterValue() throws Exception { 332 try { 333 tester.doTestEquals(ConstructorParameterWithOptionalNotInstantiable.class); 334 fail(); 335 } catch (ParameterHasNoDistinctValueException expected) {} 336 } 337 338 public void testGoodReferentialEqualityComparison() throws Exception { 339 tester.testEquals(UsesEnum.class); 340 tester.testEquals(UsesReferentialEquality.class); 341 tester.testEquals(SameListInstance.class); 342 } 343 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 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 368 public void testParameterNotInstantiableForEqualsTest() throws Exception { 369 try { 370 tester.doTestEquals(ConstructorParameterNotInstantiable.class); 371 fail("should have failed"); 372 } catch (ParameterNotInstantiableException expected) {} 373 } 374 375 public void testNoDistinctValueForEqualsTest() throws Exception { 376 try { 377 tester.doTestEquals(ConstructorParameterSingleValue.class); 378 fail("should have failed"); 379 } catch (ParameterHasNoDistinctValueException expected) {} 380 } 381 382 public void testConstructorThrowsForEqualsTest() throws Exception { 383 try { 384 tester.doTestEquals(ConstructorThrows.class); 385 fail("should have failed"); 386 } catch (InvocationTargetException expected) {} 387 } 388 389 public void testFactoryMethodReturnsNullForEqualsTest() throws Exception { 390 try { 391 tester.doTestEquals(FactoryMethodReturnsNullAndAnnotated.class); 392 fail("should have failed"); 393 } catch (FactoryMethodReturnsNullException expected) {} 394 } 395 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 405 public void testNoEqualsChecksOnEnum() throws Exception { 406 tester.testEquals(OneConstantEnum.class); 407 tester.testEquals(NoConstantEnum.class); 408 tester.testEquals(TimeUnit.class); 409 } 410 411 public void testNoEqualsChecksOnInterface() throws Exception { 412 tester.testEquals(Runnable.class); 413 } 414 415 public void testNoEqualsChecksOnAnnotation() throws Exception { 416 tester.testEquals(Nullable.class); 417 } 418 419 public void testGoodNulls() throws Exception { 420 tester.testNulls(GoodNulls.class); 421 } 422 423 public void testNoNullCheckNeededDespitNotInstantiable() throws Exception { 424 tester.doTestNulls(NoNullCheckNeededDespitNotInstantiable.class, Visibility.PACKAGE); 425 } 426 427 public void testNulls_interface() { 428 tester.testNulls(AnInterface.class); 429 } 430 431 public void testNulls_abstractClass() { 432 tester.testNulls(AnAbstractClass.class); 433 } 434 435 public void testNulls_enum() throws Exception { 436 tester.testNulls(OneConstantEnum.class); 437 tester.testNulls(NoConstantEnum.class); 438 tester.testNulls(TimeUnit.class); 439 } 440 441 public void testNulls_parameterOptionalNotInstantiable() throws Exception { 442 tester.testNulls(ConstructorParameterWithOptionalNotInstantiable.class); 443 } 444 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 454 public void testNoNullChecksOnInterface() throws Exception { 455 tester.testNulls(Runnable.class); 456 } 457 458 public void testNoNullChecksOnAnnotation() throws Exception { 459 tester.testNulls(Nullable.class); 460 } 461 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 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 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 488 public void testInstantiate_factoryMethodAcceptsNull() throws Exception { 489 assertNull(tester.instantiate(FactoryMethodAcceptsNull.class).name); 490 } 491 492 public void testInstantiate_factoryMethodDoesNotAcceptNull() throws Exception { 493 assertNotNull(tester.instantiate(FactoryMethodDoesNotAcceptNull.class).name); 494 } 495 496 public void testInstantiate_constructorAcceptsNull() throws Exception { 497 assertNull(tester.instantiate(ConstructorAcceptsNull.class).name); 498 } 499 500 public void testInstantiate_constructorDoesNotAcceptNull() throws Exception { 501 assertNotNull(tester.instantiate(ConstructorDoesNotAcceptNull.class).name); 502 } 503 504 public void testInstantiate_notInstantiable() throws Exception { 505 assertNull(tester.instantiate(NotInstantiable.class)); 506 } 507 508 public void testInstantiate_noConstantEnum() throws Exception { 509 assertNull(tester.instantiate(NoConstantEnum.class)); 510 } 511 512 public void testInstantiate_oneConstantEnum() throws Exception { 513 assertEquals(OneConstantEnum.A, tester.instantiate(OneConstantEnum.class)); 514 } 515 516 public void testInstantiate_interface() throws Exception { 517 assertNull(tester.instantiate(Runnable.class)); 518 } 519 520 public void testInstantiate_abstractClass() throws Exception { 521 assertNull(tester.instantiate(AbstractList.class)); 522 } 523 524 public void testInstantiate_annotation() throws Exception { 525 assertNull(tester.instantiate(Nullable.class)); 526 } 527 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 534 public void testSetDistinctValues_equalInstances() { 535 try { 536 tester.setDistinctValues(String.class, "", ""); 537 fail(); 538 } catch (IllegalArgumentException expected) {} 539 } 540 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 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 556 public void testInstantiate_constructorThrows() throws Exception { 557 try { 558 tester.instantiate(ConstructorThrows.class); 559 fail(); 560 } catch (InvocationTargetException expected) {} 561 } 562 563 public void testInstantiate_factoryMethodThrows() throws Exception { 564 try { 565 tester.instantiate(FactoryMethodThrows.class); 566 fail(); 567 } catch (InvocationTargetException expected) {} 568 } 569 570 public void testInstantiate_constructorParameterNotInstantiable() throws Exception { 571 try { 572 tester.instantiate(ConstructorParameterNotInstantiable.class); 573 fail(); 574 } catch (ParameterNotInstantiableException expected) {} 575 } 576 577 public void testInstantiate_factoryMethodParameterNotInstantiable() throws Exception { 578 try { 579 tester.instantiate(FactoryMethodParameterNotInstantiable.class); 580 fail(); 581 } catch (ParameterNotInstantiableException expected) {} 582 } 583 584 public void testInstantiate_instantiableFactoryMethodChosen() throws Exception { 585 assertEquals("good", tester.instantiate(InstantiableFactoryMethodChosen.class).name); 586 } 587 588 public void testInterfaceProxySerializable() throws Exception { 589 SerializableTester.reserializeAndAssert(tester.instantiate(HasAnInterface.class)); 590 } 591 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 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 607 public HasAnInterface(AnInterface i) { 608 this.i = i; 609 } 610 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 620 @Override public int hashCode() { 621 return i.hashCode(); 622 } 623 } 624 625 static class InstantiableFactoryMethodChosen { 626 final String name; 627 628 private InstantiableFactoryMethodChosen(String name) { 629 this.name = name; 630 } 631 632 public InstantiableFactoryMethodChosen(NotInstantiable x) { 633 checkNotNull(x); 634 this.name = "x1"; 635 } 636 637 public static InstantiableFactoryMethodChosen create(NotInstantiable x) { 638 return new InstantiableFactoryMethodChosen(x); 639 } 640 641 public static InstantiableFactoryMethodChosen create(String s) { 642 checkNotNull(s); 643 return new InstantiableFactoryMethodChosen("good"); 644 } 645 } 646 647 public void testInstantiate_instantiableConstructorChosen() throws Exception { 648 assertEquals("good", tester.instantiate(InstantiableConstructorChosen.class).name); 649 } 650 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 661 Wrapper(Object wrapped) { 662 this.wrapped = checkNotNull(wrapped); 663 } 664 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 675 @Override public int hashCode() { 676 return wrapped.hashCode(); 677 } 678 679 @Override public String toString() { 680 return wrapped.toString(); 681 } 682 } 683 684 private static class SetWrapper extends Wrapper { 685 public SetWrapper(Set<NotInstantiable> wrapped) { 686 super(wrapped); 687 } 688 } 689 690 static class InstantiableConstructorChosen { 691 final String name; 692 693 public InstantiableConstructorChosen(String name) { 694 checkNotNull(name); 695 this.name = "good"; 696 } 697 698 public InstantiableConstructorChosen(NotInstantiable x) { 699 checkNotNull(x); 700 this.name = "x1"; 701 } 702 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 713 private GoodEquals(String a, int b) { 714 this.a = checkNotNull(a); 715 this.b = b; 716 } 717 718 // ignored by testEquals() 719 GoodEquals(@SuppressWarnings("unused") NotInstantiable x) { 720 this.a = "x"; 721 this.b = -1; 722 } 723 724 // will keep trying 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") 732 static GoodEquals create(int a, int b) { 733 throw new RuntimeException(); 734 } 735 736 // keep trying 737 @SuppressWarnings("unused") 738 @Nullable public static GoodEquals createMayReturnNull(int a, int b) { 739 return null; 740 } 741 742 // Good! 743 static GoodEquals create(String a, int b) { 744 return new GoodEquals(a, b); 745 } 746 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 756 @Override public int hashCode() { 757 return 0; 758 } 759 } 760 761 static class BadEquals { 762 763 public BadEquals() {} // ignored by testEquals() since it has less parameters. 764 765 public static BadEquals create(@SuppressWarnings("unused") @Nullable String s) { 766 return new BadEquals(); 767 } 768 769 @Override public boolean equals(@Nullable Object obj) { 770 return obj instanceof BadEquals; 771 } 772 773 @Override public int hashCode() { 774 return 0; 775 } 776 } 777 778 static class SameIntegerInstance { 779 private final Integer i; 780 781 public SameIntegerInstance(Integer i) { 782 this.i = checkNotNull(i); 783 } 784 785 @Override public int hashCode() { 786 return i.hashCode(); 787 } 788 789 @Override 790 @SuppressWarnings("NumericEquality") 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 803 public SameLongInstance(Long i) { 804 this.i = checkNotNull(i); 805 } 806 807 @Override public int hashCode() { 808 return i.hashCode(); 809 } 810 811 @Override 812 @SuppressWarnings("NumericEquality") 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 825 public SameFloatInstance(Float i) { 826 this.i = checkNotNull(i); 827 } 828 829 @Override public int hashCode() { 830 return i.hashCode(); 831 } 832 833 @Override 834 @SuppressWarnings("NumericEquality") 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 847 public SameDoubleInstance(Double i) { 848 this.i = checkNotNull(i); 849 } 850 851 @Override public int hashCode() { 852 return i.hashCode(); 853 } 854 855 @Override 856 @SuppressWarnings("NumericEquality") 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 869 public SameShortInstance(Short i) { 870 this.i = checkNotNull(i); 871 } 872 873 @Override public int hashCode() { 874 return i.hashCode(); 875 } 876 877 @Override 878 @SuppressWarnings("NumericEquality") 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 891 public SameByteInstance(Byte i) { 892 this.i = checkNotNull(i); 893 } 894 895 @Override public int hashCode() { 896 return i.hashCode(); 897 } 898 899 @Override 900 @SuppressWarnings("NumericEquality") 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 913 public SameCharacterInstance(Character i) { 914 this.i = checkNotNull(i); 915 } 916 917 @Override public int hashCode() { 918 return i.hashCode(); 919 } 920 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 933 public SameBooleanInstance(Boolean i) { 934 this.i = checkNotNull(i); 935 } 936 937 @Override public int hashCode() { 938 return i.hashCode(); 939 } 940 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 953 public SameStringInstance(String s) { 954 this.s = checkNotNull(s); 955 } 956 957 @Override public int hashCode() { 958 return s.hashCode(); 959 } 960 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 973 public SameObjectInstance(Object s) { 974 this.s = checkNotNull(s); 975 } 976 977 @Override public int hashCode() { 978 return s.hashCode(); 979 } 980 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 993 public SameInterfaceInstance(Runnable s) { 994 this.s = checkNotNull(s); 995 } 996 997 @Override public int hashCode() { 998 return s.hashCode(); 999 } 1000 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 1013 public SameListInstance(List<?> s) { 1014 this.s = checkNotNull(s); 1015 } 1016 1017 @Override public int hashCode() { 1018 return System.identityHashCode(s); 1019 } 1020 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 1033 public UsesReferentialEquality(ReferentialEquality s) { 1034 this.s = checkNotNull(s); 1035 } 1036 1037 @Override public int hashCode() { 1038 return s.hashCode(); 1039 } 1040 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 1053 public UsesEnum(TimeUnit s) { 1054 this.s = checkNotNull(s); 1055 } 1056 1057 @Override public int hashCode() { 1058 return s.hashCode(); 1059 } 1060 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 { 1071 public ReferentialEquality() {} 1072 } 1073 1074 static class BadEqualsWithParameterizedType { 1075 1076 // ignored by testEquals() since it has less parameters. 1077 public BadEqualsWithParameterizedType() {} 1078 1079 public static BadEqualsWithParameterizedType create( 1080 @SuppressWarnings("unused") ImmutableList<Iterable<? extends String>> s) { 1081 return new BadEqualsWithParameterizedType(); 1082 } 1083 1084 @Override public boolean equals(@Nullable Object obj) { 1085 return obj instanceof BadEqualsWithParameterizedType; 1086 } 1087 1088 @Override public int hashCode() { 1089 return 0; 1090 } 1091 } 1092 1093 static class GoodNulls { 1094 public GoodNulls(String s) { 1095 checkNotNull(s); 1096 } 1097 1098 public void rejectNull(String s) { 1099 checkNotNull(s); 1100 } 1101 } 1102 1103 public static class BadNulls { 1104 public void failsToRejectNull(@SuppressWarnings("unused") String s) {} 1105 } 1106 1107 public static class NoNullCheckNeededDespitNotInstantiable { 1108 1109 public NoNullCheckNeededDespitNotInstantiable(NotInstantiable x) { 1110 checkNotNull(x); 1111 } 1112 1113 @SuppressWarnings("unused") // reflected 1114 void primitiveOnly(int i) {} 1115 1116 @SuppressWarnings("unused") //reflected 1117 void nullableOnly(@Nullable String s) {} 1118 public void noParameter() {} 1119 1120 @SuppressWarnings("unused") //reflected 1121 void primitiveAndNullable(@Nullable String s, int i) {} 1122 } 1123 1124 static class FactoryMethodReturnsNullButNotAnnotated { 1125 private FactoryMethodReturnsNullButNotAnnotated() {} 1126 1127 static FactoryMethodReturnsNullButNotAnnotated returnsNull() { 1128 return null; 1129 } 1130 } 1131 1132 static class FactoryMethodReturnsNullAndAnnotated { 1133 private FactoryMethodReturnsNullAndAnnotated() {} 1134 1135 @Nullable public static FactoryMethodReturnsNullAndAnnotated returnsNull() { 1136 return null; 1137 } 1138 } 1139 1140 static class FactoryMethodAcceptsNull { 1141 1142 final String name; 1143 1144 private FactoryMethodAcceptsNull(String name) { 1145 this.name = name; 1146 } 1147 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 1157 private FactoryMethodDoesNotAcceptNull(String name) { 1158 this.name = checkNotNull(name); 1159 } 1160 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 1170 public ConstructorAcceptsNull(@Nullable String name) { 1171 this.name = name; 1172 } 1173 } 1174 1175 static class ConstructorDoesNotAcceptNull { 1176 1177 final String name; 1178 1179 ConstructorDoesNotAcceptNull(String name) { 1180 this.name = checkNotNull(name); 1181 } 1182 } 1183 1184 static class ConstructorParameterNotInstantiable { 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 { 1190 public ConstructorParameterWithOptionalNotInstantiable(Optional<NotInstantiable> x) { 1191 checkNotNull(x); 1192 } 1193 @Override public boolean equals(@Nullable Object obj) { 1194 throw new UnsupportedOperationException(); 1195 } 1196 @Override public int hashCode() { 1197 throw new UnsupportedOperationException(); 1198 } 1199 } 1200 1201 static class ConstructorParameterSingleValue { 1202 public ConstructorParameterSingleValue(@SuppressWarnings("unused") Singleton s) {} 1203 @Override public boolean equals(Object obj) { 1204 return obj instanceof ConstructorParameterSingleValue; 1205 } 1206 @Override public int hashCode() { 1207 return 1; 1208 } 1209 1210 public static class Singleton { 1211 public static final Singleton INSTANCE = new Singleton(); 1212 private Singleton() {} 1213 } 1214 } 1215 1216 static class FactoryMethodParameterNotInstantiable { 1217 1218 private FactoryMethodParameterNotInstantiable() {} 1219 1220 static FactoryMethodParameterNotInstantiable create( 1221 @SuppressWarnings("unused") NotInstantiable x) { 1222 return new FactoryMethodParameterNotInstantiable(); 1223 } 1224 } 1225 1226 static class ConstructorThrows { 1227 public ConstructorThrows() { 1228 throw new RuntimeException(); 1229 } 1230 } 1231 1232 static class FactoryMethodThrows { 1233 private FactoryMethodThrows() {} 1234 1235 public static FactoryMethodThrows create() { 1236 throw new RuntimeException(); 1237 } 1238 } 1239 1240 static class 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") 1254 public void failToCheckNull(String s) {} 1255 } 1256 1257 private interface AnInterface {} 1258 1259 private static abstract class AnAbstractClass { 1260 @SuppressWarnings("unused") 1261 public AnAbstractClass(String s) {} 1262 1263 @SuppressWarnings("unused") 1264 public void failsToCheckNull(String s) {} 1265 } 1266 1267 private static class NoPublicStaticMethods { 1268 @SuppressWarnings("unused") // To test non-public factory isn't used. 1269 static String notPublic() { 1270 return ""; 1271 } 1272 } 1273 } 1274