blob: 586eb284eb91c6e5dc2953757e397110951a440e [file] [log] [blame]
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.testing;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.testing.ClassSanityTester.FactoryMethodReturnsNullException;
import com.google.common.testing.ClassSanityTester.ParameterHasNoDistinctValueException;
import com.google.common.testing.ClassSanityTester.ParameterNotInstantiableException;
import com.google.common.testing.NullPointerTester.Visibility;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
/**
* Unit tests for {@link ClassSanityTester}.
*
* @author Ben Yu
*/
public class ClassSanityTesterTest extends TestCase {
private final ClassSanityTester tester = new ClassSanityTester();
public void testEqualsOnReturnValues_good() throws Exception {
tester.forAllPublicStaticMethods(GoodEqualsFactory.class).testEquals();
}
public static class GoodEqualsFactory {
public static Object good(
String a,
int b,
// oneConstantOnly doesn't matter since it's not nullable and can be only 1 value.
@SuppressWarnings("unused") OneConstantEnum oneConstantOnly,
// noConstant doesn't matter since it can only be null
@SuppressWarnings("unused") @NullableDecl NoConstantEnum noConstant) {
return new GoodEquals(a, b);
}
// instance method ignored
public Object badIgnored() {
return new BadEquals();
}
// primitive ignored
public int returnsInt() {
throw new UnsupportedOperationException();
}
// void ignored
public void voidMethod() {
throw new UnsupportedOperationException();
}
// non-public method ignored
static Object badButNotPublic() {
return new BadEquals();
}
}
public void testForAllPublicStaticMethods_noPublicStaticMethods() throws Exception {
try {
tester.forAllPublicStaticMethods(NoPublicStaticMethods.class).testEquals();
} catch (AssertionFailedError expected) {
assertThat(expected)
.hasMessageThat()
.isEqualTo(
"No public static methods that return java.lang.Object or subtype are found in "
+ NoPublicStaticMethods.class
+ ".");
return;
}
fail();
}
public void testEqualsOnReturnValues_bad() throws Exception {
try {
tester.forAllPublicStaticMethods(BadEqualsFactory.class).testEquals();
} catch (AssertionFailedError expected) {
return;
}
fail();
}
private static class BadEqualsFactory {
/** oneConstantOnly matters now since it can be either null or the constant. */
@SuppressWarnings("unused") // Called by reflection
public static Object bad(String a, int b, @NullableDecl OneConstantEnum oneConstantOnly) {
return new GoodEquals(a, b);
}
}
public void testNullsOnReturnValues_good() throws Exception {
tester.forAllPublicStaticMethods(GoodNullsFactory.class).testNulls();
}
private static class GoodNullsFactory {
@SuppressWarnings("unused") // Called by reflection
public static Object good(String s) {
return new GoodNulls(s);
}
}
public void testNullsOnReturnValues_bad() throws Exception {
try {
tester.forAllPublicStaticMethods(BadNullsFactory.class).thatReturn(Object.class).testNulls();
} catch (AssertionFailedError expected) {
return;
}
fail();
}
public void testNullsOnReturnValues_returnTypeFiltered() throws Exception {
try {
tester
.forAllPublicStaticMethods(BadNullsFactory.class)
.thatReturn(Iterable.class)
.testNulls();
} catch (AssertionFailedError expected) {
assertThat(expected)
.hasMessageThat()
.isEqualTo(
"No public static methods that return java.lang.Iterable or subtype are found in "
+ BadNullsFactory.class
+ ".");
return;
}
fail();
}
public static class BadNullsFactory {
public static Object bad(@SuppressWarnings("unused") String a) {
return new BadNulls();
}
}
@AndroidIncompatible // TODO(cpovirk): ClassNotFoundException... ClassSanityTesterTest$AnInterface
public void testSerializableOnReturnValues_good() throws Exception {
tester.forAllPublicStaticMethods(GoodSerializableFactory.class).testSerializable();
}
public static class GoodSerializableFactory {
public static Object good(Runnable r) {
return r;
}
public static Object good(AnInterface i) {
return i;
}
}
public void testSerializableOnReturnValues_bad() throws Exception {
try {
tester.forAllPublicStaticMethods(BadSerializableFactory.class).testSerializable();
} catch (AssertionFailedError expected) {
return;
}
fail();
}
public static class BadSerializableFactory {
public static Object bad() {
return new Serializable() {
@SuppressWarnings("unused")
private final Object notSerializable = new Object();
};
}
}
public void testEqualsAndSerializableOnReturnValues_equalsIsGoodButNotSerializable()
throws Exception {
try {
tester.forAllPublicStaticMethods(GoodEqualsFactory.class).testEqualsAndSerializable();
} catch (AssertionFailedError expected) {
return;
}
fail("should have failed");
}
public void testEqualsAndSerializableOnReturnValues_serializableButNotEquals() throws Exception {
try {
tester.forAllPublicStaticMethods(GoodSerializableFactory.class).testEqualsAndSerializable();
} catch (AssertionFailedError expected) {
return;
}
fail("should have failed");
}
@AndroidIncompatible // TODO(cpovirk): ClassNotFoundException... ClassSanityTesterTest$AnInterface
public void testEqualsAndSerializableOnReturnValues_good() throws Exception {
tester
.forAllPublicStaticMethods(GoodEqualsAndSerialiableFactory.class)
.testEqualsAndSerializable();
}
public static class GoodEqualsAndSerialiableFactory {
public static Object good(AnInterface s) {
return Functions.constant(s);
}
}
public void testEqualsForReturnValues_factoryReturnsNullButNotAnnotated() throws Exception {
try {
tester.forAllPublicStaticMethods(FactoryThatReturnsNullButNotAnnotated.class).testEquals();
} catch (AssertionFailedError expected) {
return;
}
fail();
}
public void testNullsForReturnValues_factoryReturnsNullButNotAnnotated() throws Exception {
try {
tester.forAllPublicStaticMethods(FactoryThatReturnsNullButNotAnnotated.class).testNulls();
} catch (AssertionFailedError expected) {
return;
}
fail();
}
public void testSerializableForReturnValues_factoryReturnsNullButNotAnnotated() throws Exception {
try {
tester
.forAllPublicStaticMethods(FactoryThatReturnsNullButNotAnnotated.class)
.testSerializable();
} catch (AssertionFailedError expected) {
return;
}
fail();
}
public void testEqualsAndSerializableForReturnValues_factoryReturnsNullButNotAnnotated()
throws Exception {
try {
tester
.forAllPublicStaticMethods(FactoryThatReturnsNullButNotAnnotated.class)
.testEqualsAndSerializable();
} catch (AssertionFailedError expected) {
return;
}
fail();
}
public static class FactoryThatReturnsNullButNotAnnotated {
public static Object bad() {
return null;
}
}
public void testEqualsForReturnValues_factoryReturnsNullAndAnnotated() throws Exception {
tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class).testEquals();
}
public void testNullsForReturnValues_factoryReturnsNullAndAnnotated() throws Exception {
tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class).testNulls();
}
public void testSerializableForReturnValues_factoryReturnsNullAndAnnotated() throws Exception {
tester.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class).testSerializable();
}
public void testEqualsAndSerializableForReturnValues_factoryReturnsNullAndAnnotated()
throws Exception {
tester
.forAllPublicStaticMethods(FactoryThatReturnsNullAndAnnotated.class)
.testEqualsAndSerializable();
}
public static class FactoryThatReturnsNullAndAnnotated {
@NullableDecl
public static Object bad() {
return null;
}
}
public void testGoodEquals() throws Exception {
tester.testEquals(GoodEquals.class);
}
public void testEquals_interface() {
tester.testEquals(AnInterface.class);
}
public void testEquals_abstractClass() {
tester.testEquals(AnAbstractClass.class);
}
public void testEquals_enum() {
tester.testEquals(OneConstantEnum.class);
}
public void testBadEquals() throws Exception {
try {
tester.testEquals(BadEquals.class);
} catch (AssertionFailedError expected) {
assertThat(expected.getMessage()).contains("create(null)");
return;
}
fail("should have failed");
}
public void testBadEquals_withParameterizedType() throws Exception {
try {
tester.testEquals(BadEqualsWithParameterizedType.class);
} catch (AssertionFailedError expected) {
assertThat(expected.getMessage()).contains("create([[1]])");
return;
}
fail("should have failed");
}
public void testBadEquals_withSingleParameterValue() throws Exception {
try {
tester.doTestEquals(ConstructorParameterWithOptionalNotInstantiable.class);
fail();
} catch (ParameterHasNoDistinctValueException expected) {
}
}
public void testGoodReferentialEqualityComparison() throws Exception {
tester.testEquals(UsesEnum.class);
tester.testEquals(UsesReferentialEquality.class);
tester.testEquals(SameListInstance.class);
}
@AndroidIncompatible // problem with equality of Type objects?
public void testEqualsUsingReferentialEquality() throws Exception {
assertBadUseOfReferentialEquality(SameIntegerInstance.class);
assertBadUseOfReferentialEquality(SameLongInstance.class);
assertBadUseOfReferentialEquality(SameFloatInstance.class);
assertBadUseOfReferentialEquality(SameDoubleInstance.class);
assertBadUseOfReferentialEquality(SameShortInstance.class);
assertBadUseOfReferentialEquality(SameByteInstance.class);
assertBadUseOfReferentialEquality(SameCharacterInstance.class);
assertBadUseOfReferentialEquality(SameBooleanInstance.class);
assertBadUseOfReferentialEquality(SameObjectInstance.class);
assertBadUseOfReferentialEquality(SameStringInstance.class);
assertBadUseOfReferentialEquality(SameInterfaceInstance.class);
}
private void assertBadUseOfReferentialEquality(Class<?> cls) throws Exception {
try {
tester.testEquals(cls);
} catch (AssertionFailedError expected) {
assertThat(expected.getMessage()).contains(cls.getSimpleName() + "(");
return;
}
fail("should have failed for " + cls);
}
public void testParameterNotInstantiableForEqualsTest() throws Exception {
try {
tester.doTestEquals(ConstructorParameterNotInstantiable.class);
fail("should have failed");
} catch (ParameterNotInstantiableException expected) {
}
}
public void testNoDistinctValueForEqualsTest() throws Exception {
try {
tester.doTestEquals(ConstructorParameterSingleValue.class);
fail("should have failed");
} catch (ParameterHasNoDistinctValueException expected) {
}
}
public void testConstructorThrowsForEqualsTest() throws Exception {
try {
tester.doTestEquals(ConstructorThrows.class);
fail("should have failed");
} catch (InvocationTargetException expected) {
}
}
public void testFactoryMethodReturnsNullForEqualsTest() throws Exception {
try {
tester.doTestEquals(FactoryMethodReturnsNullAndAnnotated.class);
fail("should have failed");
} catch (FactoryMethodReturnsNullException expected) {
}
}
public void testFactoryMethodReturnsNullButNotAnnotatedInEqualsTest() throws Exception {
try {
tester.testEquals(FactoryMethodReturnsNullButNotAnnotated.class);
} catch (AssertionFailedError expected) {
return;
}
fail("should have failed");
}
public void testNoEqualsChecksOnEnum() throws Exception {
tester.testEquals(OneConstantEnum.class);
tester.testEquals(NoConstantEnum.class);
tester.testEquals(TimeUnit.class);
}
public void testNoEqualsChecksOnInterface() throws Exception {
tester.testEquals(Runnable.class);
}
public void testNoEqualsChecksOnAnnotation() throws Exception {
tester.testEquals(MyAnnotation.class);
}
public void testGoodNulls() throws Exception {
tester.testNulls(GoodNulls.class);
}
public void testNoNullCheckNeededDespitNotInstantiable() throws Exception {
tester.doTestNulls(NoNullCheckNeededDespitNotInstantiable.class, Visibility.PACKAGE);
}
public void testNulls_interface() {
tester.testNulls(AnInterface.class);
}
public void testNulls_abstractClass() {
tester.testNulls(AnAbstractClass.class);
}
public void testNulls_enum() throws Exception {
tester.testNulls(OneConstantEnum.class);
tester.testNulls(NoConstantEnum.class);
tester.testNulls(TimeUnit.class);
}
public void testNulls_parameterOptionalNotInstantiable() throws Exception {
tester.testNulls(ConstructorParameterWithOptionalNotInstantiable.class);
}
public void testEnumFailsToCheckNull() throws Exception {
try {
tester.testNulls(EnumFailsToCheckNull.class);
} catch (AssertionFailedError expected) {
return;
}
fail("should have failed");
}
public void testNoNullChecksOnInterface() throws Exception {
tester.testNulls(Runnable.class);
}
public void testNoNullChecksOnAnnotation() throws Exception {
tester.testNulls(MyAnnotation.class);
}
public void testBadNulls() throws Exception {
try {
tester.testNulls(BadNulls.class);
} catch (AssertionFailedError expected) {
return;
}
fail("should have failed");
}
public void testInstantiate_factoryMethodReturnsNullButNotAnnotated() throws Exception {
try {
tester.instantiate(FactoryMethodReturnsNullButNotAnnotated.class);
} catch (AssertionFailedError expected) {
assertThat(expected.getMessage()).contains("@Nullable");
return;
}
fail("should have failed");
}
public void testInstantiate_factoryMethodReturnsNullAndAnnotated() throws Exception {
try {
tester.instantiate(FactoryMethodReturnsNullAndAnnotated.class);
fail("should have failed");
} catch (FactoryMethodReturnsNullException expected) {
}
}
public void testInstantiate_factoryMethodAcceptsNull() throws Exception {
assertNull(tester.instantiate(FactoryMethodAcceptsNull.class).name);
}
public void testInstantiate_factoryMethodDoesNotAcceptNull() throws Exception {
assertNotNull(tester.instantiate(FactoryMethodDoesNotAcceptNull.class).name);
}
public void testInstantiate_constructorAcceptsNull() throws Exception {
assertNull(tester.instantiate(ConstructorAcceptsNull.class).name);
}
public void testInstantiate_constructorDoesNotAcceptNull() throws Exception {
assertNotNull(tester.instantiate(ConstructorDoesNotAcceptNull.class).name);
}
public void testInstantiate_notInstantiable() throws Exception {
assertNull(tester.instantiate(NotInstantiable.class));
}
public void testInstantiate_noConstantEnum() throws Exception {
assertNull(tester.instantiate(NoConstantEnum.class));
}
public void testInstantiate_oneConstantEnum() throws Exception {
assertEquals(OneConstantEnum.A, tester.instantiate(OneConstantEnum.class));
}
public void testInstantiate_interface() throws Exception {
assertNull(tester.instantiate(Runnable.class));
}
public void testInstantiate_abstractClass() throws Exception {
assertNull(tester.instantiate(AbstractList.class));
}
public void testInstantiate_annotation() throws Exception {
assertNull(tester.instantiate(MyAnnotation.class));
}
public void testInstantiate_setDefault() throws Exception {
NotInstantiable x = new NotInstantiable();
tester.setDefault(NotInstantiable.class, x);
assertNotNull(tester.instantiate(ConstructorParameterNotInstantiable.class));
}
public void testSetDistinctValues_equalInstances() {
try {
tester.setDistinctValues(String.class, "", "");
fail();
} catch (IllegalArgumentException expected) {
}
}
public void testInstantiate_setDistinctValues() throws Exception {
NotInstantiable x = new NotInstantiable();
NotInstantiable y = new NotInstantiable();
tester.setDistinctValues(NotInstantiable.class, x, y);
assertNotNull(tester.instantiate(ConstructorParameterNotInstantiable.class));
tester.testEquals(ConstructorParameterMapOfNotInstantiable.class);
}
public void testInstantiate_constructorThrows() throws Exception {
try {
tester.instantiate(ConstructorThrows.class);
fail();
} catch (InvocationTargetException expected) {
}
}
public void testInstantiate_factoryMethodThrows() throws Exception {
try {
tester.instantiate(FactoryMethodThrows.class);
fail();
} catch (InvocationTargetException expected) {
}
}
public void testInstantiate_constructorParameterNotInstantiable() throws Exception {
try {
tester.instantiate(ConstructorParameterNotInstantiable.class);
fail();
} catch (ParameterNotInstantiableException expected) {
}
}
public void testInstantiate_factoryMethodParameterNotInstantiable() throws Exception {
try {
tester.instantiate(FactoryMethodParameterNotInstantiable.class);
fail();
} catch (ParameterNotInstantiableException expected) {
}
}
public void testInstantiate_instantiableFactoryMethodChosen() throws Exception {
assertEquals("good", tester.instantiate(InstantiableFactoryMethodChosen.class).name);
}
@AndroidIncompatible // TODO(cpovirk): ClassNotFoundException... ClassSanityTesterTest$AnInterface
public void testInterfaceProxySerializable() throws Exception {
SerializableTester.reserializeAndAssert(tester.instantiate(HasAnInterface.class));
}
public void testReturnValuesFromAnotherPackageIgnoredForNullTests() throws Exception {
new ClassSanityTester().forAllPublicStaticMethods(JdkObjectFactory.class).testNulls();
}
/** String doesn't check nulls as we expect. But the framework should ignore. */
private static class JdkObjectFactory {
@SuppressWarnings("unused") // Called by reflection
public static Object create() {
return new ArrayList<>();
}
}
static class HasAnInterface implements Serializable {
private final AnInterface i;
public HasAnInterface(AnInterface i) {
this.i = i;
}
@Override
public boolean equals(@NullableDecl Object obj) {
if (obj instanceof HasAnInterface) {
HasAnInterface that = (HasAnInterface) obj;
return i.equals(that.i);
} else {
return false;
}
}
@Override
public int hashCode() {
return i.hashCode();
}
}
static class InstantiableFactoryMethodChosen {
final String name;
private InstantiableFactoryMethodChosen(String name) {
this.name = name;
}
public InstantiableFactoryMethodChosen(NotInstantiable x) {
checkNotNull(x);
this.name = "x1";
}
public static InstantiableFactoryMethodChosen create(NotInstantiable x) {
return new InstantiableFactoryMethodChosen(x);
}
public static InstantiableFactoryMethodChosen create(String s) {
checkNotNull(s);
return new InstantiableFactoryMethodChosen("good");
}
}
public void testInstantiate_instantiableConstructorChosen() throws Exception {
assertEquals("good", tester.instantiate(InstantiableConstructorChosen.class).name);
}
public void testEquals_setOfNonInstantiable() throws Exception {
try {
new ClassSanityTester().doTestEquals(SetWrapper.class);
fail();
} catch (ParameterNotInstantiableException expected) {
}
}
private abstract static class Wrapper {
private final Object wrapped;
Wrapper(Object wrapped) {
this.wrapped = checkNotNull(wrapped);
}
@Override
public boolean equals(@NullableDecl Object obj) {
// In general getClass().isInstance() is bad for equals.
// But here we fully control the subclasses to ensure symmetry.
if (getClass().isInstance(obj)) {
Wrapper that = (Wrapper) obj;
return wrapped.equals(that.wrapped);
}
return false;
}
@Override
public int hashCode() {
return wrapped.hashCode();
}
@Override
public String toString() {
return wrapped.toString();
}
}
private static class SetWrapper extends Wrapper {
public SetWrapper(Set<NotInstantiable> wrapped) {
super(wrapped);
}
}
static class InstantiableConstructorChosen {
final String name;
public InstantiableConstructorChosen(String name) {
checkNotNull(name);
this.name = "good";
}
public InstantiableConstructorChosen(NotInstantiable x) {
checkNotNull(x);
this.name = "x1";
}
public static InstantiableFactoryMethodChosen create(NotInstantiable x) {
return new InstantiableFactoryMethodChosen(x);
}
}
static class GoodEquals {
private final String a;
private final int b;
private GoodEquals(String a, int b) {
this.a = checkNotNull(a);
this.b = b;
}
// ignored by testEquals()
GoodEquals(@SuppressWarnings("unused") NotInstantiable x) {
this.a = "x";
this.b = -1;
}
// will keep trying
public GoodEquals(@SuppressWarnings("unused") NotInstantiable x, int b) {
this.a = "x";
this.b = b;
}
// keep trying
@SuppressWarnings("unused")
static GoodEquals create(int a, int b) {
throw new RuntimeException();
}
// Good!
static GoodEquals create(String a, int b) {
return new GoodEquals(a, b);
}
// keep trying
@SuppressWarnings("unused")
@NullableDecl
public static GoodEquals createMayReturnNull(int a, int b) {
return null;
}
@Override
public boolean equals(@NullableDecl Object obj) {
if (obj instanceof GoodEquals) {
GoodEquals that = (GoodEquals) obj;
return a.equals(that.a) && b == that.b;
} else {
return false;
}
}
@Override
public int hashCode() {
return 0;
}
}
static class BadEquals {
public BadEquals() {} // ignored by testEquals() since it has less parameters.
public static BadEquals create(@SuppressWarnings("unused") @NullableDecl String s) {
return new BadEquals();
}
@Override
public boolean equals(@NullableDecl Object obj) {
return obj instanceof BadEquals;
}
@Override
public int hashCode() {
return 0;
}
}
static class SameIntegerInstance {
private final Integer i;
public SameIntegerInstance(Integer i) {
this.i = checkNotNull(i);
}
@Override
public int hashCode() {
return i.hashCode();
}
@Override
@SuppressWarnings("NumericEquality")
public boolean equals(Object obj) {
if (obj instanceof SameIntegerInstance) {
SameIntegerInstance that = (SameIntegerInstance) obj;
return i == that.i;
}
return false;
}
}
static class SameLongInstance {
private final Long i;
public SameLongInstance(Long i) {
this.i = checkNotNull(i);
}
@Override
public int hashCode() {
return i.hashCode();
}
@Override
@SuppressWarnings("NumericEquality")
public boolean equals(Object obj) {
if (obj instanceof SameLongInstance) {
SameLongInstance that = (SameLongInstance) obj;
return i == that.i;
}
return false;
}
}
static class SameFloatInstance {
private final Float i;
public SameFloatInstance(Float i) {
this.i = checkNotNull(i);
}
@Override
public int hashCode() {
return i.hashCode();
}
@Override
@SuppressWarnings("NumericEquality")
public boolean equals(Object obj) {
if (obj instanceof SameFloatInstance) {
SameFloatInstance that = (SameFloatInstance) obj;
return i == that.i;
}
return false;
}
}
static class SameDoubleInstance {
private final Double i;
public SameDoubleInstance(Double i) {
this.i = checkNotNull(i);
}
@Override
public int hashCode() {
return i.hashCode();
}
@Override
@SuppressWarnings("NumericEquality")
public boolean equals(Object obj) {
if (obj instanceof SameDoubleInstance) {
SameDoubleInstance that = (SameDoubleInstance) obj;
return i == that.i;
}
return false;
}
}
static class SameShortInstance {
private final Short i;
public SameShortInstance(Short i) {
this.i = checkNotNull(i);
}
@Override
public int hashCode() {
return i.hashCode();
}
@Override
@SuppressWarnings("NumericEquality")
public boolean equals(Object obj) {
if (obj instanceof SameShortInstance) {
SameShortInstance that = (SameShortInstance) obj;
return i == that.i;
}
return false;
}
}
static class SameByteInstance {
private final Byte i;
public SameByteInstance(Byte i) {
this.i = checkNotNull(i);
}
@Override
public int hashCode() {
return i.hashCode();
}
@Override
@SuppressWarnings("NumericEquality")
public boolean equals(Object obj) {
if (obj instanceof SameByteInstance) {
SameByteInstance that = (SameByteInstance) obj;
return i == that.i;
}
return false;
}
}
static class SameCharacterInstance {
private final Character i;
public SameCharacterInstance(Character i) {
this.i = checkNotNull(i);
}
@Override
public int hashCode() {
return i.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SameCharacterInstance) {
SameCharacterInstance that = (SameCharacterInstance) obj;
return i == that.i;
}
return false;
}
}
static class SameBooleanInstance {
private final Boolean i;
public SameBooleanInstance(Boolean i) {
this.i = checkNotNull(i);
}
@Override
public int hashCode() {
return i.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SameBooleanInstance) {
SameBooleanInstance that = (SameBooleanInstance) obj;
return i == that.i;
}
return false;
}
}
static class SameStringInstance {
private final String s;
public SameStringInstance(String s) {
this.s = checkNotNull(s);
}
@Override
public int hashCode() {
return s.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SameStringInstance) {
SameStringInstance that = (SameStringInstance) obj;
return s == that.s;
}
return false;
}
}
static class SameObjectInstance {
private final Object s;
public SameObjectInstance(Object s) {
this.s = checkNotNull(s);
}
@Override
public int hashCode() {
return s.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SameObjectInstance) {
SameObjectInstance that = (SameObjectInstance) obj;
return s == that.s;
}
return false;
}
}
static class SameInterfaceInstance {
private final Runnable s;
public SameInterfaceInstance(Runnable s) {
this.s = checkNotNull(s);
}
@Override
public int hashCode() {
return s.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SameInterfaceInstance) {
SameInterfaceInstance that = (SameInterfaceInstance) obj;
return s == that.s;
}
return false;
}
}
static class SameListInstance {
private final List<?> s;
public SameListInstance(List<?> s) {
this.s = checkNotNull(s);
}
@Override
public int hashCode() {
return System.identityHashCode(s);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SameListInstance) {
SameListInstance that = (SameListInstance) obj;
return s == that.s;
}
return false;
}
}
static class UsesReferentialEquality {
private final ReferentialEquality s;
public UsesReferentialEquality(ReferentialEquality s) {
this.s = checkNotNull(s);
}
@Override
public int hashCode() {
return s.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof UsesReferentialEquality) {
UsesReferentialEquality that = (UsesReferentialEquality) obj;
return s == that.s;
}
return false;
}
}
static class UsesEnum {
private final TimeUnit s;
public UsesEnum(TimeUnit s) {
this.s = checkNotNull(s);
}
@Override
public int hashCode() {
return s.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof UsesEnum) {
UsesEnum that = (UsesEnum) obj;
return s == that.s;
}
return false;
}
}
public static class ReferentialEquality {
public ReferentialEquality() {}
}
static class BadEqualsWithParameterizedType {
// ignored by testEquals() since it has less parameters.
public BadEqualsWithParameterizedType() {}
public static BadEqualsWithParameterizedType create(
@SuppressWarnings("unused") ImmutableList<Iterable<? extends String>> s) {
return new BadEqualsWithParameterizedType();
}
@Override
public boolean equals(@NullableDecl Object obj) {
return obj instanceof BadEqualsWithParameterizedType;
}
@Override
public int hashCode() {
return 0;
}
}
static class GoodNulls {
public GoodNulls(String s) {
checkNotNull(s);
}
public void rejectNull(String s) {
checkNotNull(s);
}
}
public static class BadNulls {
public void failsToRejectNull(@SuppressWarnings("unused") String s) {}
}
public static class NoNullCheckNeededDespitNotInstantiable {
public NoNullCheckNeededDespitNotInstantiable(NotInstantiable x) {
checkNotNull(x);
}
@SuppressWarnings("unused") // reflected
void primitiveOnly(int i) {}
@SuppressWarnings("unused") // reflected
void nullableOnly(@NullableDecl String s) {}
public void noParameter() {}
@SuppressWarnings("unused") // reflected
void primitiveAndNullable(@NullableDecl String s, int i) {}
}
static class FactoryMethodReturnsNullButNotAnnotated {
private FactoryMethodReturnsNullButNotAnnotated() {}
static FactoryMethodReturnsNullButNotAnnotated returnsNull() {
return null;
}
}
static class FactoryMethodReturnsNullAndAnnotated {
private FactoryMethodReturnsNullAndAnnotated() {}
@NullableDecl
public static FactoryMethodReturnsNullAndAnnotated returnsNull() {
return null;
}
}
static class FactoryMethodAcceptsNull {
final String name;
private FactoryMethodAcceptsNull(String name) {
this.name = name;
}
static FactoryMethodAcceptsNull create(@NullableDecl String name) {
return new FactoryMethodAcceptsNull(name);
}
}
static class FactoryMethodDoesNotAcceptNull {
final String name;
private FactoryMethodDoesNotAcceptNull(String name) {
this.name = checkNotNull(name);
}
public static FactoryMethodDoesNotAcceptNull create(String name) {
return new FactoryMethodDoesNotAcceptNull(name);
}
}
static class ConstructorAcceptsNull {
final String name;
public ConstructorAcceptsNull(@NullableDecl String name) {
this.name = name;
}
}
static class ConstructorDoesNotAcceptNull {
final String name;
ConstructorDoesNotAcceptNull(String name) {
this.name = checkNotNull(name);
}
}
static class ConstructorParameterNotInstantiable {
public ConstructorParameterNotInstantiable(@SuppressWarnings("unused") NotInstantiable x) {}
}
static class ConstructorParameterMapOfNotInstantiable {
private final Map<NotInstantiable, NotInstantiable> m;
public ConstructorParameterMapOfNotInstantiable(Map<NotInstantiable, NotInstantiable> m) {
this.m = checkNotNull(m);
}
@Override
public boolean equals(@NullableDecl Object obj) {
if (obj instanceof ConstructorParameterMapOfNotInstantiable) {
return m.equals(((ConstructorParameterMapOfNotInstantiable) obj).m);
} else {
return false;
}
}
@Override
public int hashCode() {
return m.hashCode();
}
}
// Test that we should get a distinct parameter error when doing equals test.
static class ConstructorParameterWithOptionalNotInstantiable {
public ConstructorParameterWithOptionalNotInstantiable(Optional<NotInstantiable> x) {
checkNotNull(x);
}
@Override
public boolean equals(@NullableDecl Object obj) {
throw new UnsupportedOperationException();
}
@Override
public int hashCode() {
throw new UnsupportedOperationException();
}
}
static class ConstructorParameterSingleValue {
public ConstructorParameterSingleValue(@SuppressWarnings("unused") Singleton s) {}
@Override
public boolean equals(Object obj) {
return obj instanceof ConstructorParameterSingleValue;
}
@Override
public int hashCode() {
return 1;
}
public static class Singleton {
public static final Singleton INSTANCE = new Singleton();
private Singleton() {}
}
}
static class FactoryMethodParameterNotInstantiable {
private FactoryMethodParameterNotInstantiable() {}
static FactoryMethodParameterNotInstantiable create(
@SuppressWarnings("unused") NotInstantiable x) {
return new FactoryMethodParameterNotInstantiable();
}
}
static class ConstructorThrows {
public ConstructorThrows() {
throw new RuntimeException();
}
}
static class FactoryMethodThrows {
private FactoryMethodThrows() {}
public static FactoryMethodThrows create() {
throw new RuntimeException();
}
}
static class NotInstantiable {
private NotInstantiable() {}
}
private enum NoConstantEnum {}
private enum OneConstantEnum {
A
}
private enum EnumFailsToCheckNull {
A;
@SuppressWarnings("unused")
public void failToCheckNull(String s) {}
}
private interface AnInterface {}
private abstract static class AnAbstractClass {
@SuppressWarnings("unused")
public AnAbstractClass(String s) {}
@SuppressWarnings("unused")
public void failsToCheckNull(String s) {}
}
private static class NoPublicStaticMethods {
@SuppressWarnings("unused") // To test non-public factory isn't used.
static String notPublic() {
return "";
}
}
@interface MyAnnotation {}
}