Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

static field of ImmutableList type gives false negative #83

Closed
GoogleCodeExporter opened this issue Mar 29, 2015 · 2 comments
Closed

static field of ImmutableList type gives false negative #83

GoogleCodeExporter opened this issue Mar 29, 2015 · 2 comments

Comments

@GoogleCodeExporter
Copy link

What steps will reproduce the problem?
What is the code (equals method, hashCode method, relevant fields) that
triggers the problem?

run the following test (ImmutableList class is part of 
https://code.google.com/p/guava-libraries/ library. I could not reproduce the 
problem with something simpler than ImmutableList. The bug is probably caused 
by something very specific to this class):

import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.Test;
import com.google.common.collect.ImmutableList;

public class ReproduceBugTest {
  @Test
  public void testName() throws Exception {
    EqualsVerifier.forClass(MyIntValue.class).verify();
  }
}

class MyIntValue {
  private final int value;

  public MyIntValue(int value) {
    this.value = value;
  }

  @Override
  public final boolean equals(Object object) {
    if (object instanceof MyIntValue) {
      MyIntValue that = (MyIntValue) object;
      return this.value == that.value;
    }
    return false;
  }

  @Override
  public final int hashCode() {
    return value;
  }

  private static final ImmutableList<String> UNUSED_FIELD = ImmutableList.of("abc");
}




What error message does EqualsVerifier give?

java.lang.AssertionError: Abstract delegation: ImmutableList's hashCode method 
delegates to an abstract method:
 com.google.common.collect.ImmutableList.size()I
Add prefab values for com.google.common.collect.ImmutableList.
For more information, go to: http://www.jqno.nl/equalsverifier/errormessages
    at nl.jqno.equalsverifier.EqualsVerifier.handleError(EqualsVerifier.java:347)
    at nl.jqno.equalsverifier.EqualsVerifier.verify(EqualsVerifier.java:330)
    at org.smoothbuild.lang.function.ReproduceBugTest.testName(ReproduceBugTest.java:13)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.AbstractMethodError: 
com.google.common.collect.ImmutableList.size()I
    at com.google.common.collect.ImmutableList.listIterator(ImmutableList.java:338)
    at com.google.common.collect.ImmutableList.listIterator(ImmutableList.java:334)
    at com.google.common.collect.ImmutableList.iterator(ImmutableList.java:330)
    at com.google.common.collect.ImmutableList.iterator(ImmutableList.java:62)
    at com.google.common.collect.Lists.hashCodeImpl(Lists.java:1008)
    at com.google.common.collect.ImmutableList.hashCode(ImmutableList.java:592)
    at nl.jqno.equalsverifier.AbstractDelegationChecker.checkAbstractMethods(AbstractDelegationChecker.java:126)
    at nl.jqno.equalsverifier.AbstractDelegationChecker.checkAbstractDelegationInFields(AbstractDelegationChecker.java:57)
    at nl.jqno.equalsverifier.AbstractDelegationChecker.check(AbstractDelegationChecker.java:41)
    at nl.jqno.equalsverifier.EqualsVerifier.verifyWithoutExamples(EqualsVerifier.java:365)
    at nl.jqno.equalsverifier.EqualsVerifier.performVerification(EqualsVerifier.java:354)
    at nl.jqno.equalsverifier.EqualsVerifier.verify(EqualsVerifier.java:327)
    ... 24 more




What did you expect?
test should pass
I don't understand why static fields are even touched by the framework.

What version of EqualsVerifier are you using?
equalsverifier-1.3.1.jar
cglib-nodep-2.2.3.jar
objenesis-1.3.jar
objenesis-1.3-sources.jar


Please provide any additional information below.

Original issue reported on code.google.com by [email protected] on 21 Aug 2013 at 11:11

@GoogleCodeExporter
Copy link
Author

Nice find, thanks for reporting this.

EqualsVerifier doesn't know beforehand what fields are used inside equals and 
hashCode, so it instantiates all of them -- even the static final ones. (For 
all it knows, the hashCode's prime factor might be a static final field.)

Unfortunately, Guava's ImmutableList can't be instantiated properly by 
EqualsVerfier, because of the way it is implemented. This is what's causing 
your problem.

Sadly, there's no easy way to fix this (without potentially breaking users' 
existing code). Maybe I could add a warning that you can suppress. I'll have to 
think about how to do this.

Until then, your workarounds would be to add ImmutableList to your 
PrefabValues, even though it isn't used, or to move ImmutableList out of the 
class you're testing.

Original comment by [email protected] on 23 Aug 2013 at 2:01

  • Changed state: Accepted
  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

Fixed in version 1.5, which was just released. When EqualsVerifier finds Google 
Guava on the classpath, it will automatically generate prefab values.

Original comment by [email protected] on 20 Aug 2014 at 11:00

  • Changed state: Fixed
  • Added labels: ****
  • Removed labels: ****

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant