diff options
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/testutil/MoreAsserts.java')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/testutil/MoreAsserts.java | 230 |
1 files changed, 228 insertions, 2 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/MoreAsserts.java b/src/test/java/com/google/devtools/build/lib/testutil/MoreAsserts.java index 3b7a6b1b9d..c2c01d268d 100644 --- a/src/test/java/com/google/devtools/build/lib/testutil/MoreAsserts.java +++ b/src/test/java/com/google/devtools/build/lib/testutil/MoreAsserts.java @@ -19,17 +19,27 @@ import static com.google.common.truth.Truth.assert_; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import com.google.devtools.build.lib.events.Event; +import com.google.devtools.build.lib.events.EventCollector; +import com.google.devtools.build.lib.events.EventKind; +import com.google.devtools.build.lib.util.Pair; import java.lang.ref.Reference; import java.lang.reflect.Field; import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; @@ -305,10 +315,226 @@ public class MoreAsserts { return set; } - public static <T> void - assertSameContents(Iterable<? extends T> expected, Iterable<? extends T> actual) { + public static <T> void assertSameContents( + Iterable<? extends T> expected, Iterable<? extends T> actual) { if (!Sets.newHashSet(expected).equals(Sets.newHashSet(actual))) { fail("got string set: " + asStringSet(actual) + "\nwant: " + asStringSet(expected)); } } + + /** + * If the specified EventCollector contains any events, an informative + * assertion fails in the context of the specified TestCase. + */ + public static void assertNoEvents(Iterable<Event> eventCollector) { + String eventsString = eventsToString(eventCollector); + assertThat(eventsString).isEmpty(); + } + + /** + * If the specified EventCollector contains an unexpected number of events, an informative + * assertion fails in the context of the specified TestCase. + */ + public static void assertEventCount(int expectedCount, EventCollector eventCollector) { + assertWithMessage(eventsToString(eventCollector)) + .that(eventCollector.count()).isEqualTo(expectedCount); + } + + /** + * If the specified EventCollector does not contain an event which has + * 'expectedEvent' as a substring, an informative assertion fails. Otherwise + * the matching event is returned. + */ + public static Event assertContainsEvent(Iterable<Event> eventCollector, + String expectedEvent) { + return assertContainsEvent(eventCollector, expectedEvent, EventKind.ALL_EVENTS); + } + + /** + * If the specified EventCollector does not contain an event of a kind of 'kinds' which has + * 'expectedEvent' as a substring, an informative assertion fails. Otherwise + * the matching event is returned. + */ + public static Event assertContainsEvent(Iterable<Event> eventCollector, + String expectedEvent, + Set<EventKind> kinds) { + for (Event event : eventCollector) { + if (event.getMessage().contains(expectedEvent) && kinds.contains(event.getKind())) { + return event; + } + } + String eventsString = eventsToString(eventCollector); + assertWithMessage("Event '" + expectedEvent + "' not found" + + (eventsString.length() == 0 ? "" : ("; found these though:" + eventsString))) + .that(false).isTrue(); + return null; // unreachable + } + + /** + * If the specified EventCollector contains an event which has + * 'expectedEvent' as a substring, an informative assertion fails. + */ + public static void assertDoesNotContainEvent(Iterable<Event> eventCollector, + String expectedEvent) { + for (Event event : eventCollector) { + assertWithMessage("Unexpected string '" + expectedEvent + "' matched following event:\n" + + event.getMessage()).that(event.getMessage()).doesNotContain(expectedEvent); + } + } + + /** + * If the specified EventCollector does not contain an event which has + * each of {@code words} surrounded by single quotes as a substring, an + * informative assertion fails. Otherwise the matching event is returned. + */ + public static Event assertContainsEventWithWordsInQuotes( + Iterable<Event> eventCollector, + String... words) { + for (Event event : eventCollector) { + boolean found = true; + for (String word : words) { + if (!event.getMessage().contains("'" + word + "'")) { + found = false; + break; + } + } + if (found) { + return event; + } + } + String eventsString = eventsToString(eventCollector); + assertWithMessage("Event containing words " + Arrays.toString(words) + " in " + + "single quotes not found" + + (eventsString.length() == 0 ? "" : ("; found these though:" + eventsString))) + .that(false).isTrue(); + return null; // unreachable + } + + /** + * Returns a string consisting of each event in the specified collector, + * preceded by a newline. + */ + private static String eventsToString(Iterable<Event> eventCollector) { + StringBuilder buf = new StringBuilder(); + eventLoop: for (Event event : eventCollector) { + for (String ignoredPrefix : TestConstants.IGNORED_MESSAGE_PREFIXES) { + if (event.getMessage().startsWith(ignoredPrefix)) { + continue eventLoop; + } + } + buf.append('\n').append(event); + } + return buf.toString(); + } + + /** + * If "expectedSublist" is not a sublist of "arguments", an informative + * assertion is failed in the context of the specified TestCase. + * + * <p>Argument order mnemonic: assert(X)ContainsSublist(Y). + */ + @SuppressWarnings({"unchecked", "varargs"}) + public static <T> void assertContainsSublist(List<T> arguments, T... expectedSublist) { + List<T> sublist = Arrays.asList(expectedSublist); + try { + assertThat(Collections.indexOfSubList(arguments, sublist)).isNotEqualTo(-1); + } catch (AssertionError e) { + throw new AssertionError("Did not find " + sublist + " as a sublist of " + arguments, e); + } + } + + /** + * If "expectedSublist" is a sublist of "arguments", an informative + * assertion is failed in the context of the specified TestCase. + * + * <p>Argument order mnemonic: assert(X)DoesNotContainSublist(Y). + */ + @SuppressWarnings({"unchecked", "varargs"}) + public static <T> void assertDoesNotContainSublist(List<T> arguments, T... expectedSublist) { + List<T> sublist = Arrays.asList(expectedSublist); + try { + assertThat(Collections.indexOfSubList(arguments, sublist)).isEqualTo(-1); + } catch (AssertionError e) { + throw new AssertionError("Found " + sublist + " as a sublist of " + arguments, e); + } + } + + /** + * If "arguments" does not contain "expectedSubset" as a subset, an + * informative assertion is failed in the context of the specified TestCase. + * + * <p>Argument order mnemonic: assert(X)ContainsSubset(Y). + */ + public static <T> void assertContainsSubset(Iterable<T> arguments, + Iterable<T> expectedSubset) { + Set<T> argumentsSet = arguments instanceof Set<?> + ? (Set<T>) arguments + : Sets.newHashSet(arguments); + + for (T x : expectedSubset) { + assertWithMessage("assertContainsSubset failed: did not find element " + x + + "\nExpected subset = " + expectedSubset + "\nArguments = " + arguments) + .that(argumentsSet).contains(x); + } + } + + /** + * Check to see if each element of expectedMessages is the beginning of a message + * in eventCollector, in order, as in {@link #containsSublistWithGapsAndEqualityChecker}. + * If not, an informative assertion is failed + */ + protected static void assertContainsEventsInOrder(Iterable<Event> eventCollector, + String... expectedMessages) { + String failure = containsSublistWithGapsAndEqualityChecker( + ImmutableList.copyOf(eventCollector), + new Function<Pair<Event, String>, Boolean> () { + @Override + public Boolean apply(Pair<Event, String> pair) { + return pair.first.getMessage().contains(pair.second); + } + }, expectedMessages); + + String eventsString = eventsToString(eventCollector); + assertWithMessage("Event '" + failure + "' not found in proper order" + + (eventsString.length() == 0 ? "" : ("; found these though:" + eventsString))) + .that(failure).isNull(); + } + + /** + * Check to see if each element of expectedSublist is in arguments, according to + * the equalityChecker, in the same order as in expectedSublist (although with + * other interspersed elements in arguments allowed). + * @param equalityChecker function that takes a Pair<S, T> element and returns true + * if the elements of the pair are equal by its lights. + * @return first element not in arguments in order, or null if success. + */ + @SuppressWarnings({"unchecked"}) + protected static <S, T> T containsSublistWithGapsAndEqualityChecker(List<S> arguments, + Function<Pair<S, T>, Boolean> equalityChecker, T... expectedSublist) { + Iterator<S> iter = arguments.iterator(); + outerLoop: + for (T expected : expectedSublist) { + while (iter.hasNext()) { + S actual = iter.next(); + if (equalityChecker.apply(Pair.of(actual, expected))) { + continue outerLoop; + } + } + return expected; + } + return null; + } + + public static List<Event> assertContainsEventWithFrequency(Iterable<Event> events, + String expectedMessage, int expectedFrequency) { + ImmutableList.Builder<Event> builder = ImmutableList.builder(); + for (Event event : events) { + if (event.getMessage().contains(expectedMessage)) { + builder.add(event); + } + } + List<Event> foundEvents = builder.build(); + assertWithMessage(events.toString()).that(foundEvents).hasSize(expectedFrequency); + return foundEvents; + } } |