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

#2293 Fixes ShouldContainExactly for collection containing byte arrays #2360

Merged
merged 1 commit into from
Jul 13, 2021

Conversation

ashishkujoy
Copy link
Contributor

For ShouldContainExactly to work ByteArray , ShortArray etc we have to use the eq instead of using default equals .
One downside of using eq is that it has NumberEq which try to do type change for comparing number of different type, for example if we are comparing a Int with a Long it will convert the Long to Int and then check equality using default equals. This number conversion is not desired for ShouldContainExactly.

"print errors unambiguously" {
shouldThrow<AssertionError> {
listOf<Any>(1L, 2L).shouldContainExactly(listOf<Any>(1, 2))
}.shouldHaveMessage(
"""Expecting: [
1,
2
] but was: [
1L,
2L
]
Some elements were missing: [
1,
2
] and some elements were unexpected: [
1L,
2L
]"""
)
}

So i order to make it work without changing the current behaviour of shouldBe (internally uses eq) and ShouldContainExactly I added a flag strictNumberEq to control conversion of number type in NumberEq . The default value for this is kept false.

One downside of this is that all implementation of need Eq need to keep forwarding strictNumberEq whenever they internally call eq.

@ashishkujoy
Copy link
Contributor Author

This changes still not sufficient to make it work for shouldContainExactlyInAnyOrder as shouldContainExactlyInAnyOrder internally creates a map of all elements as key and number of their occurrence as value. Now it uses keys from one map and equate value for that key from both the map. For one of the map it always get the null value as hash code of ByteArray are not equal.

/** Assert that a collection contains exactly the given values and nothing else, in any order. */
fun <T, C : Collection<T>> containExactlyInAnyOrder(expected: C): Matcher<C?> = neverNullMatcher { value ->
val valueGroupedCounts: Map<T, Int> = value.groupBy { it }.mapValues { it.value.size }
val expectedGroupedCounts: Map<T, Int> = expected.groupBy { it }.mapValues { it.value.size }
val passed = expectedGroupedCounts.size == valueGroupedCounts.size
&& expectedGroupedCounts.all { valueGroupedCounts[it.key] == it.value }
MatcherResult(
passed,
"Collection should contain ${expected.show().value} in any order, but was ${value.show().value}",
"Collection should not contain exactly ${expected.show().value} in any order"
)
}

@sksamuel sksamuel merged commit c4b94f9 into master Jul 13, 2021
@sksamuel sksamuel deleted the shouldContainExactly-bugfix branch July 13, 2021 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants