152 lines
5.4 KiB
Java
152 lines
5.4 KiB
Java
/*
|
|
* Copyright 2011 Google Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.google.testing.util;
|
|
|
|
import static java.util.Arrays.asList;
|
|
|
|
import com.google.common.base.Objects;
|
|
import com.google.common.collect.HashMultiset;
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.Lists;
|
|
import java.util.Comparator;
|
|
|
|
import junit.framework.Assert;
|
|
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
|
|
public final class MoreAsserts {
|
|
|
|
private MoreAsserts() { }
|
|
|
|
/**
|
|
* Asserts that {@code actual} contains precisely the elements
|
|
* {@code expected}, in any order. Both collections may contain
|
|
* duplicates, and this method will only pass if the quantities are
|
|
* exactly the same.
|
|
*/
|
|
public static void assertContentsAnyOrder(
|
|
String message, Iterable<?> actual, Object... expected) {
|
|
assertEqualsImpl(message,
|
|
HashMultiset.create(asList(expected)), HashMultiset.create(actual));
|
|
}
|
|
|
|
/**
|
|
* Variant of {@link #assertContentsAnyOrder(String,Iterable,Object...)}
|
|
* using a generic message.
|
|
*/
|
|
public static void assertContentsAnyOrder(
|
|
Iterable<?> actual, Object... expected) {
|
|
assertContentsAnyOrder((String) null, actual, expected);
|
|
}
|
|
|
|
/**
|
|
* Asserts that {@code actual} contains precisely the elements
|
|
* {@code expected}, in any order. Both collections may contain
|
|
* duplicates, and this method will only pass if the quantities are
|
|
* exactly the same. This method uses the user-provided Comparator
|
|
* object for doing the object comparison, instead of relying on the
|
|
* contents' implementation of {@link Object#equals(Object)}. It also takes
|
|
* in the expected set of objects as an Iterable.
|
|
* <p>
|
|
* Note the different order of expected and actual from the other
|
|
* {@link #assertContentsAnyOrder(String,Iterable,Object...)}
|
|
*/
|
|
public static <T> void assertContentsAnyOrder(String message,
|
|
Iterable<? extends T> expected, Iterable<? extends T> actual,
|
|
Comparator<? super T> comparator) {
|
|
// We should not iterate over an Iterable more than once. There's
|
|
// no guarentees that Iterable.iterator() returns an iterator over the
|
|
// entire collection every time.
|
|
//
|
|
// Why don't we use TreeMultiset? Unfortunately, TreeMultiset.toString()
|
|
// produces really odd output for duplicates. In addition, our contract
|
|
// states that we use the comparator to compare equality, not to order
|
|
// items.
|
|
ImmutableList<T> actualList = ImmutableList.copyOf(actual);
|
|
ImmutableList<T> expectedList = ImmutableList.copyOf(expected);
|
|
|
|
// First compare sizes to save ourselves on N X M operation.
|
|
// This also handles the case where "expected" is a subset of "actual".
|
|
if (actualList.size() != expectedList.size()) {
|
|
failNotEqual(message, expectedList, actualList);
|
|
}
|
|
|
|
// Now for each expected value, iterate through actuals and delete entry
|
|
// if found. We need to make another copy of the "actual" items because
|
|
// we will be removing items from this list, and we need to keep the original
|
|
// for the failure message.
|
|
List<T> unfoundItems = Lists.newLinkedList(actualList);
|
|
for (T ex : expectedList) {
|
|
boolean found = false;
|
|
Iterator<T> iter = unfoundItems.iterator();
|
|
while (iter.hasNext()) {
|
|
T ac = iter.next();
|
|
if (comparator.compare(ex, ac) == 0) {
|
|
iter.remove();
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
failNotEqual(message, expectedList, actualList);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Variant of {@link #assertContentsAnyOrder(String,Iterable,Object...)}
|
|
* using a generic message.
|
|
*/
|
|
public static <T> void assertContentsAnyOrder(
|
|
Iterable<? extends T> expected, Iterable<? extends T> actual,
|
|
Comparator<? super T> comparator) {
|
|
assertContentsAnyOrder((String) null, expected, actual, comparator);
|
|
}
|
|
|
|
private static void failNotEqual(String message, Object expected,
|
|
Object actual) {
|
|
if ((expected != null) && (actual != null)
|
|
&& expected.toString().equals(actual.toString())) {
|
|
failWithMessage(message, "expected:<("
|
|
+ expected.getClass().getName() + ") " + expected + "> but was:<("
|
|
+ actual.getClass().getName() + ") " + actual + ">");
|
|
} else {
|
|
failWithMessage(message, "expected:<" + expected + "> but was:<" + actual
|
|
+ ">");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Replacement of {@link Assert#assertEquals} which provides the same error
|
|
* message in GWT and java.
|
|
*/
|
|
private static void assertEqualsImpl(
|
|
String message, Object expected, Object actual) {
|
|
if (!Objects.equal(expected, actual)) {
|
|
failWithMessage(
|
|
message, "expected:<" + expected + "> but was:<" + actual + ">");
|
|
}
|
|
}
|
|
|
|
private static void failWithMessage(String userMessage, String ourMessage) {
|
|
Assert.fail((userMessage == null)
|
|
? ourMessage
|
|
: userMessage + ' ' + ourMessage);
|
|
}
|
|
}
|