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