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

Documented recursive data structure error message #34

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

Documented recursive data structure error message #34

GoogleCodeExporter opened this issue Mar 29, 2015 · 8 comments

Comments

@GoogleCodeExporter
Copy link

Try a test of the Money class at 
http://www.javapractices.com/topic/TopicAction.do?Id=13

It will throw

java.lang.AssertionError: Recursive datastructure.
Add prefab values for one of the following types: java.math.BigDecimal, 
java.math.BigInteger, java.util.Random, java.util.concurrent.atomic.AtomicLong.
For more information, go to: 
http://code.google.com/p/equalsverifier/wiki/ErrorMessages

How can that be resolved?


Original issue reported on code.google.com by [email protected] on 18 Jan 2011 at 11:03

@GoogleCodeExporter
Copy link
Author

This is actually two issues, which I will fix in the next release. The first 
one is a bug: EqualsVerifier erroneously suggests that adding BigInteger, 
Random or AtomicLong to the prefab values will fix the problem. The second one 
is an enhancement: it shouldn't be necessary to add BigDecimal and BigInteger 
to the prefab values manually in the first place.

Until I've fixed this, you can work around it by calling .withPrefabValues, 
like this:

EqualsVerifier.forClass(Money.class)
    .withPrefabValues(BigDecimal.class, new BigDecimal("0.0"), new BigDecimal("1.0"))
    .verify();

Original comment by [email protected] on 20 Jan 2011 at 7:31

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

@GoogleCodeExporter
Copy link
Author

Both problems have now been fixed.
(I'll still need a few days to prepare the actual release though.)

Original comment by [email protected] on 21 Feb 2011 at 8:59

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

@GoogleCodeExporter
Copy link
Author

Awesome! Thx.

Original comment by [email protected] on 21 Feb 2011 at 4:50

  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

When I test that class now with         
EqualsVerifier.forClass(Money.class).suppress(Warning.NULL_FIELDS).verify();
and the 1.0 release I get

 Significant fields: equals relies on fAmount, but hashCode does not.

although that is not true.  What now?

Original comment by [email protected] on 17 Mar 2011 at 5:42

  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

Original comment by [email protected] on 22 Mar 2011 at 7:03

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

@GoogleCodeExporter
Copy link
Author

I've finally had a chance to try it out.

It turns out Money caches its hashCode, in a way similar to what String does: 
it assigns it when hashCode is first called. (The way it's implemented in Money 
is not thread-safe BTW, but that's a story for another time.)

Anyway, EqualsVerifier thinks fHashCode is a regular field like all the others, 
and assigns it a value other than 0. The first thing the hashCode method does 
is compare it to 0. This yields false, so the method always returns EV's 
(incorrect) value. EV doesn't know about this, so when it tries changing 
fAmount, it notices a difference in the result of equals, but not in the result 
of hashCode (since the latter is never properly initialized). And this is why 
EV thinks the problem is caused by fAmount.

If you insert the following line before the if-statement (and add 
Warning.NONFINAL_FIELDS to EV's suppress method), everything will work fine:
    int fHashCode = 0;

Unfortunately, this kind of trick is really hard to detect for EqualsVerifier. 
Furthermore, if you use this trick, you either *really* know what you're doing 
and then you probably don't need EqualsVerifier anyway (this applies to 
String), or you're doing it wrong and shouldn't be using this trick in the 
first place (this applies to Money, IMHO). So I won't fix this issue in 
EqualsVerifier.

Original comment by [email protected] on 22 Mar 2011 at 4:24

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

@GoogleCodeExporter
Copy link
Author

Thanks a lot for this great explanation. You might want to put some of this 
text on the wiki somewhere. 

Original comment by [email protected] on 22 Mar 2011 at 6:44

  • Added labels: ****
  • Removed labels: ****

@GoogleCodeExporter
Copy link
Author

Thanks for the tip; I just added an edited version to the ErrorMessages wiki 
page.

Original comment by [email protected] on 3 Apr 2011 at 7:12

  • 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