-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Assertions.assertIterableEquals overflows the stack #2157
Comments
Prior to this commit an iterable of iterables (here instances of java.nio.file.Path) passed to method `assertIterableEquals` in class `Assertions` of the JUnit Jupiter API yielded a `StackOverflowError`. This commit prevent the eternal while-loop by leveraging the `equals()`-implementation of the non-null expected element. Fixes #2157
Prior to this commit an iterable of iterables (here instances of java.nio.file.Path) passed to method `assertIterableEquals` in class `Assertions` of the JUnit Jupiter API yielded a `StackOverflowError`. This commit prevent the eternal while-loop by leveraging the `equals()`-implementation of the non-null expected element. Fixes #2157
Oh wow, that's a really insidious bug! Thank you very much for finding and fixing it @sormuras. 👏 |
I wonder if this bug could have been caught earlier with mutation testing. 🤔 |
Interesting thought. Perhaps also a candidate for property-based testing ... @jlink? |
@sormuras Can you point me to the test? I'll make it a simple property and see if it catches the bug. |
Lines 446 to 452 in 0e39392
And the one below -- which is expected to fail. With and with the fix. Edit: Revert this if-clause back to if (expectedElement == actualElement) {
continue;
} This will show the |
I could detect the bug with the following rather straightforward property:
I had to register a default arbitrary provider for There's an additional drawback: Shrinking does not produce something meaningful in this setup. That means that the falsifying sample is very large and hard to identify. |
The special thing about path is that its iterator returns paths whose iterator will return instances that are equal to themselves. For instance, the following Groovy snippet import java.nio.file.Paths
def path = Paths.get("bar");
println path.iterator().next().equals(path)
println path.iterator().next().is(path) prints
The code did not account for this kind of recursiveness. |
That's some strange kind of behaviour indeed. Nothing in Iterator's contract that would exclude that, though. |
Steps to reproduce
The following code:
Yields:
Deliverables
Iterable<? extends Iterable<?>>
instances.The text was updated successfully, but these errors were encountered: