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