• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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