Skip to content

Commit

Permalink
Don't use LinkedHashSet in SubjectUtil.countDuplicates() in case the …
Browse files Browse the repository at this point in the history
…elements

don't implement hashCode() (e.g., ProtoBuf's MessageSet!)

See []where the user can't use .containsExactlyElementsIn().

This at least partially addresses #176
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=89605122
  • Loading branch information
kluever authored and cgruber committed Apr 25, 2015
1 parent f375d2d commit 31f8f9d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
11 changes: 8 additions & 3 deletions core/src/main/java/com/google/common/truth/SubjectUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
* Utility methods used in Subject<T> implementors.
Expand Down Expand Up @@ -71,7 +69,14 @@ static <T> int countOf(T t, Iterable<T> items) {
}

static <T> List<Object> countDuplicates(Collection<T> items) {
Set<T> itemSet = new LinkedHashSet<T>(items);
// We use a List to de-dupe instead of a Set in case the elements don't have a proper
// .hashCode() method (e.g., MessageSet from old versions of protobuf).
List<T> itemSet = new ArrayList<T>();
for (T item : items) {
if (!itemSet.contains(item)) {
itemSet.add(item);
}
}
Object[] params = new Object[itemSet.size()];
int n = 0;
for (T item : itemSet) {
Expand Down
32 changes: 32 additions & 0 deletions core/src/test/java/com/google/common/truth/IterableTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,38 @@ public class IterableTest {
assertThat(iterable(1, null, 3)).containsExactly(1, 3, (Integer) null);
}

@Test public void iterableContainsExactlyWithElementsThatThrowWhenYouCallHashCode() {
HashCodeThrower one = new HashCodeThrower();
HashCodeThrower two = new HashCodeThrower();

assertThat(iterable(one, two)).containsExactly(two, one);
assertThat(iterable(one, two)).containsExactly(one, two).inOrder();
assertThat(iterable(one, two)).containsExactlyElementsIn(iterable(two, one));
assertThat(iterable(one, two)).containsExactlyElementsIn(iterable(one, two)).inOrder();

try {
assertThat(iterable(one, two)).containsExactly(one);
} catch (AssertionError expected) {
assertThat(expected).hasMessage(
"Not true that <[HCT, HCT]> contains exactly <[HCT]>. "
+ "It has unexpected items <[HCT]>");
return;
}
fail();
}

private static class HashCodeThrower {
@Override public boolean equals(Object other) {
return this == other;
}
@Override public int hashCode() {
throw new UnsupportedOperationException();
}
@Override public String toString() {
return "HCT";
}
}

@Test public void iterableContainsExactlyElementsInErrorMessageIsOrdered() {
try {
assertThat(asList("foo OR bar")).containsExactlyElementsIn(asList("foo", "bar"));
Expand Down

0 comments on commit 31f8f9d

Please sign in to comment.