/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.brooklyn.test;

import java.lang.reflect.Array;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collection;
import java.util.Deque;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;

import com.google.common.annotations.Beta;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import groovy.lang.Closure;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.javalang.JavaClassNames;
import org.apache.brooklyn.util.repeat.Repeater;
import org.apache.brooklyn.util.text.ByteSizeStrings;
import org.apache.brooklyn.util.text.StringPredicates;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.CountdownTimer;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.time.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TODO should move this to new package brooklyn.util.assertions
 * and TODO should add a repeating() method which returns an AssertingRepeater extending Repeater
 * and:
 * <ul>
 * <li> adds support for requireAllIterationsTrue
 * <li> convenience run methods equivalent to succeedsEventually and succeedsContinually
 * </ul>
 * <p>
 * NOTE Selected routines in this class are originally copied from <a href="http://testng.org">TestNG</a>, to allow us to make assertions without having to
 * introduce a runtime dependency on TestNG.
 * </p>
 */
@Beta
public class Asserts {

    // Used in annotations so needs to be a constant - can't be initialized similarly to DEFAULT_LONG_TIMEOUT
    // TODO Can we force this by default on all unit tests, beforeMethod, afterMethod methods?
    public static final long THIRTY_SECONDS_TIMEOUT_MS = 30000;

    /** 
     * Timeout for use when something should happen. This is the *default timeout* that should
     * be used by tests (unless that test is asserting performance).
     * 
     * We willingly accept the hit of slow failing tests, in exchange for removing the 
     * false-negative failures that have historically littered our jenkins builds 
     * (which are presumably sometimes run on over-contended or low-spec machines).
     * 
     * If the long timeout is irritates during dev (e.g. when doing TDD, where failing tests are 
     * an important step), then one can change this value locally or set using something like
     * {@code -Dbrooklyn.test.defaultTimeout=1s}.
     */
    public static final Duration DEFAULT_LONG_TIMEOUT;

    static {
        String defaultTimeout = System.getProperty("brooklyn.test.defaultTimeout");
        if (defaultTimeout == null){
            DEFAULT_LONG_TIMEOUT = Duration.millis(THIRTY_SECONDS_TIMEOUT_MS);
        } else {
            DEFAULT_LONG_TIMEOUT = Duration.of(defaultTimeout);
        }
    }

    /** 
     * Timeout for use when waiting for other threads to (normally) finish.
     * <p>
     * Long enough for parallel execution to (normally!) catch up, even on overloaded mediocre 
     * test boxes most of the time, but short enough not to irritate too much when waiting
     * this long.
     * 
     * Never use this for asserting that a condition is satisfied within a given length of time.
     * Instead use {@link #DEFAULT_LONG_TIMEOUT} to avoid the false-negatives that have 
     * historically littered our jenkins builds.
     * 
     * Use this constant for asserting that something does *not* happen. If it was going to happen,
     * then it's reasonable to expect it would normally have happened within this time. For 
     * example, if we are asserting that no more events are received after unsubscribing, then
     * this would be an appropriate timeout to use (perhaps by using 
     * {@link #succeedsContinually(Runnable)}, which defaults to this timeout).
     */
    public static final Duration DEFAULT_SHORT_TIMEOUT = Duration.ONE_SECOND;
    
    private static final Duration DEFAULT_SHORT_PERIOD = Repeater.DEFAULT_REAL_QUICK_PERIOD;

    private static final Logger log = LoggerFactory.getLogger(Asserts.class);

    private Asserts() {}

    private static final Character OPENING_CHARACTER = '[';
    private static final Character CLOSING_CHARACTER = ']';

    private static final String ASSERT_LEFT = "expected " + OPENING_CHARACTER;
    private static final String ASSERT_MIDDLE = CLOSING_CHARACTER + " but found " + OPENING_CHARACTER;
    private static final String ASSERT_RIGHT = Character.toString(CLOSING_CHARACTER);

    static String format(Object actual, Object expected, String message) {
        String formatted = "";
        if (null != message) {
            formatted = message + " ";
        }

        return formatted + ASSERT_LEFT + expected + ASSERT_MIDDLE + actual + ASSERT_RIGHT;
    }

    static private void failNotEquals(Object actual , Object expected, String message ) {
        fail(format(actual, expected, message));
    }

    /**
     * Assert that an object reference is null.
     *
     * @param object The object reference.
     *
     * @throws AssertionError if the assertion fails.
     */
    static public void assertNull(final Object object) {
        assertNull(object, null);
    }

    /**
     * Assert that an object reference is not null.
     *
     * @param object The object reference.
     *
     * @throws AssertionError if the assertion fails.
     */
    static public void assertNotNull(final Object object) {
        assertNotNull(object, null);
    }

    /**
     * Assert that an object reference is null.
     *
     * @param object The object reference.
     * @param message The assertion error message.
     *
     * @throws AssertionError if the assertion fails.
     */
    static public void assertNull(final Object object, final String message) {
        if (null != object) {
            throw new AssertionError(message == null ? "object reference is not null" : message);
        }
    }

    /**
     * Assert that an object reference is not null.
     *
     * @param object The object reference.
     * @param message The assertion error message.
     *
     * @throws AssertionError if the assertion fails.
     */
    static public <T> T assertNotNull(final T object, final String message) {
        if (null == object) {
            throw new AssertionError(message == null ? "object reference is null" : message);
        }
        return object;
    }

    /**
     * Asserts that two collections contain the same elements in the same order. If they do not,
     * an AssertionError is thrown.
     *
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(Collection<?> actual, Collection<?> expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that two collections contain the same elements in the same order. If they do not,
     * an AssertionError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(Collection<?> actual, Collection<?> expected, String message) {
        if(actual == expected) {
            return;
        }

        if (actual == null || expected == null) {
            if (message != null) {
                fail(message);
            } else {
                fail("Collections not equal: expected: " + expected + " and actual: " + actual);
            }
        }

        assertEquals(actual.size(), expected.size(), message + ": lists don't have the same size");

        Iterator<?> actIt = actual.iterator();
        Iterator<?> expIt = expected.iterator();
        int i = -1;
        while(actIt.hasNext() && expIt.hasNext()) {
            i++;
            Object e = expIt.next();
            Object a = actIt.next();
            String explanation = "Lists differ at element [" + i + "]: " + e + " != " + a;
            String errorMessage = message == null ? explanation : message + ": " + explanation;

            assertEquals(a, e, errorMessage);
        }
    }

    /** Asserts that two iterators return the same elements in the same order. If they do not,
     * an AssertionError is thrown.
     * Please note that this assert iterates over the elements and modifies the state of the iterators.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(Iterator<?> actual, Iterator<?> expected) {
        assertEquals(actual, expected, null);
    }

    /** Asserts that two iterators return the same elements in the same order. If they do not,
     * an AssertionError, with the given message, is thrown.
     * Please note that this assert iterates over the elements and modifies the state of the iterators.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(Iterator<?> actual, Iterator<?> expected, String message) {
        if(actual == expected) {
            return;
        }

        if(actual == null || expected == null) {
            if(message != null) {
                fail(message);
            } else {
                fail("Iterators not equal: expected: " + expected + " and actual: " + actual);
            }
        }

        int i = -1;
        while(actual.hasNext() && expected.hasNext()) {

            i++;
            Object e = expected.next();
            Object a = actual.next();
            String explanation = "Iterators differ at element [" + i + "]: " + e + " != " + a;
            String errorMessage = message == null ? explanation : message + ": " + explanation;

            assertEquals(a, e, errorMessage);

        }

        if(actual.hasNext()) {

            String explanation = "Actual iterator returned more elements than the expected iterator.";
            String errorMessage = message == null ? explanation : message + ": " + explanation;
            fail(errorMessage);

        } else if(expected.hasNext()) {

            String explanation = "Expected iterator returned more elements than the actual iterator.";
            String errorMessage = message == null ? explanation : message + ": " + explanation;
            fail(errorMessage);

        }

    }

    /** Asserts that two iterables return iterators with the same elements in the same order. If they do not,
     * an AssertionError is thrown.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(Iterable<?> actual, Iterable<?> expected) {
        assertEquals(actual, expected, null);
    }

    /** Asserts that two iterables return iterators with the same elements in the same order. If they do not,
     * an AssertionError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(Iterable<?> actual, Iterable<?> expected, String message) {
        if(actual == expected) {
            return;
        }

        if(actual == null || expected == null) {
            if(message != null) {
                fail(message);
            } else {
                fail("Iterables not equal: expected: " + expected + " and actual: " + actual);
            }
        }

        Iterator<?> actIt = actual.iterator();
        Iterator<?> expIt = expected.iterator();

        assertEquals(actIt, expIt, message);
    }



    /**
     * Asserts that two sets are equal.
     */
    static public void assertEquals(Set<?> actual, Set<?> expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Assert set equals
     */
    static public void assertEquals(Set<?> actual, Set<?> expected, String message) {
        if (actual == expected) {
            return;
        }

        if (actual == null || expected == null) {
            // Keep the back compatible
            if (message == null) {
                fail("Sets not equal: expected: " + expected + " and actual: " + actual);
            } else {
                failNotEquals(actual, expected, message);
            }
        }

        if (!actual.equals(expected)) {
            if (message == null) {
                fail("Sets differ: expected " + expected + " but got " + actual);
            } else {
                failNotEquals(actual, expected, message);
            }
        }
    }

    /**
     * Asserts that two maps are equal.
     */
    static public void assertEquals(Map<?, ?> actual, Map<?, ?> expected) {
        if (actual == expected) {
            return;
        }

        if (actual == null || expected == null) {
            fail("Maps not equal: expected: " + expected + " and actual: " + actual);
        }

        if (actual.size() != expected.size()) {
            fail("Maps do not have the same size:" + actual.size() + " != " + expected.size());
        }

        Set<?> entrySet = actual.entrySet();
        for (Iterator<?> iterator = entrySet.iterator(); iterator.hasNext();) {
            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) iterator.next();
            Object key = entry.getKey();
            Object value = entry.getValue();
            Object expectedValue = expected.get(key);
            assertEquals(value, expectedValue, "Maps do not match for key:" + key + " actual:" + value
                    + " expected:" + expectedValue);
        }

    }


    /**
     * Asserts that two arrays contain the same elements in the same order. If they do not,
     * an AssertionError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(Object[] actual, Object[] expected, String message) {
        if(actual == expected) {
            return;
        }

        if ((actual == null && expected != null) || (actual != null && expected == null)) {
            if (message != null) {
                fail(message);
            } else {
                fail("Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual));
            }
        }
        assertEquals(Arrays.asList(actual), Arrays.asList(expected), message);
    }

    /**
     * Asserts that two arrays contain the same elements in the same order. If they do not,
     * an AssertionError is thrown.
     *
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(Object[] actual, Object[] expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that two objects are equal. 
     * @param actual the actual value
     * @param expected the expected value
     *                 
     * @throws AssertionError if the values are not equal.
     */
    static public void assertEquals(Object actual, Object expected) {
        assertEquals(actual, expected, null);
    }
    
    /**
     * Asserts that two objects are equal. 
     * 
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     *
     * @throws AssertionError if the values are not equal.
     */
    static public void assertEquals(Object actual, Object expected, String message) {
        if((expected == null) && (actual == null)) {
            return;
        }
        if(expected != null) {
            if (expected.getClass().isArray()) {
                assertArrayEquals(actual, expected, message);
                return;
            } else if (expected.equals(actual)) {
                return;
            }
        }
        failNotEquals(actual, expected, message);
    }


    /**
     * Asserts that two objects are equal. It they are not, an AssertionError,
     * with given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value (should be an non-null array value)
     * @param message the assertion error message
     */
    private static void assertArrayEquals(Object actual, Object expected, String message) {
        //is called only when expected is an array
        if (actual.getClass().isArray()) {
            int expectedLength = Array.getLength(expected);
            if (expectedLength == Array.getLength(actual)) {
                for (int i = 0 ; i < expectedLength ; i++) {
                    Object _actual = Array.get(actual, i);
                    Object _expected = Array.get(expected, i);
                    try {
                        assertEquals(_actual, _expected);
                    } catch (AssertionError ae) {
                        failNotEquals(actual, expected, message == null ? "" : message
                                + " (values at index " + i + " are not the same)");
                    }
                }
                //array values matched
                return;
            } else {
                failNotEquals(Array.getLength(actual), expectedLength, message == null ? "" : message
                        + " (Array lengths are not the same)");
            }
        }
        failNotEquals(actual, expected, message);
    }


    /**
     * Asserts that two Strings are equal. If they are not,
     * an AssertionError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(String actual, String expected, String message) {
        assertEquals((Object) actual, (Object) expected, message);
    }

    /**
     * Asserts that two Strings are equal. If they are not,
     * an AssertionError is thrown.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(String actual, String expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that two doubles are equal within a delta.  If they are not,
     * an AssertionError, with the given message, is thrown.  If the expected
     * value is infinity then the delta value is ignored.
     * @param actual the actual value
     * @param expected the expected value
     * @param delta the absolute tolerable difference between the actual and expected values
     * @param message the assertion error message
     */
    static public void assertEquals(double actual, double expected, double delta, String message) {
        // handle infinity specially since subtracting to infinite values gives NaN and the
        // the following test fails
        if(Double.isInfinite(expected)) {
            if(!(expected == actual)) {
                failNotEquals(new Double(actual), new Double(expected), message);
            }
        }
        else if(!(Math.abs(expected - actual) <= delta)) { // Because comparison with NaN always returns false
            failNotEquals(new Double(actual), new Double(expected), message);
        }
    }

    /**
     * Asserts that two doubles are equal within a delta. If they are not,
     * an AssertionError is thrown. If the expected value is infinity then the
     * delta value is ignored.
     * @param actual the actual value
     * @param expected the expected value
     * @param delta the absolute tolerable difference between the actual and expected values
     */
    static public void assertEquals(double actual, double expected, double delta) {
        assertEquals(actual, expected, delta, null);
    }

    /**
     * Asserts that two floats are equal within a delta. If they are not,
     * an AssertionError, with the given message, is thrown.  If the expected
     * value is infinity then the delta value is ignored.
     * @param actual the actual value
     * @param expected the expected value
     * @param delta the absolute tolerable difference between the actual and expected values
     * @param message the assertion error message
     */
    static public void assertEquals(float actual, float expected, float delta, String message) {
        // handle infinity specially since subtracting to infinite values gives NaN and the
        // the following test fails
        if(Float.isInfinite(expected)) {
            if(!(expected == actual)) {
                failNotEquals(new Float(actual), new Float(expected), message);
            }
        }
        else if(!(Math.abs(expected - actual) <= delta)) {
            failNotEquals(new Float(actual), new Float(expected), message);
        }
    }

    /**
     * Asserts that two floats are equal within a delta. If they are not,
     * an AssertionError is thrown. If the expected
     * value is infinity then the delta value is ignored.
     * @param actual the actual value
     * @param expected the expected value
     * @param delta the absolute tolerable difference between the actual and expected values
     */
    static public void assertEquals(float actual, float expected, float delta) {
        assertEquals(actual, expected, delta, null);
    }

    /**
     * Asserts that two longs are equal. If they are not,
     * an AssertionError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(long actual, long expected, String message) {
        assertEquals(Long.valueOf(actual), Long.valueOf(expected), message);
    }

    /**
     * Asserts that two longs are equal. If they are not,
     * an AssertionError is thrown.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(long actual, long expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that two booleans are equal. If they are not,
     * an AssertionError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(boolean actual, boolean expected, String message) {
        assertEquals( Boolean.valueOf(actual), Boolean.valueOf(expected), message);
    }

    /**
     * Asserts that two booleans are equal. If they are not,
     * an AssertionError is thrown.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(boolean actual, boolean expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that two bytes are equal. If they are not,
     * an AssertionError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(byte actual, byte expected, String message) {
        assertEquals(Byte.valueOf(actual), Byte.valueOf(expected), message);
    }

    /**
     * Asserts that two bytes are equal. If they are not,
     * an AssertionError is thrown.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(byte actual, byte expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that two chars are equal. If they are not,
     * an AssertionFailedError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(char actual, char expected, String message) {
        assertEquals(Character.valueOf(actual), Character.valueOf(expected), message);
    }

    /**
     * Asserts that two chars are equal. If they are not,
     * an AssertionError is thrown.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(char actual, char expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that two shorts are equal. If they are not,
     * an AssertionFailedError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(short actual, short expected, String message) {
        assertEquals(Short.valueOf(actual), Short.valueOf(expected), message);
    }

    /**
     * Asserts that two shorts are equal. If they are not,
     * an AssertionError is thrown.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(short actual, short expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that two ints are equal. If they are not,
     * an AssertionFailedError, with the given message, is thrown.
     * @param actual the actual value
     * @param expected the expected value
     * @param message the assertion error message
     */
    static public void assertEquals(int actual,  int expected, String message) {
        assertEquals(Integer.valueOf(actual), Integer.valueOf(expected), message);
    }

    /**
     * Asserts that two ints are equal. If they are not,
     * an AssertionError is thrown.
     * @param actual the actual value
     * @param expected the expected value
     */
    static public void assertEquals(int actual, int expected) {
        assertEquals(actual, expected, null);
    }

    /**
     * Asserts that a condition is true. If it isn't, an AssertionError is thrown.
     * @param condition the condition to evaluate
     */
    public static void assertTrue(boolean condition) {
        if (!condition) fail();
    }

    /**
     * Asserts that a condition is true. If it isn't,
     * an AssertionError, with the given message, is thrown.
     * @param condition the condition to evaluate
     * @param message the assertion error message
     */
    public static void assertTrue(boolean condition, String message) {
        if (!condition) fail(message);
    }

    /**
     * Asserts that a condition is false. If it isn't,
     * an AssertionError, with the given message, is thrown.
     * @param condition the condition to evaluate
     * @param message the assertion error message
     */
    public static void assertFalse(boolean condition, String message) {
        if (condition) fail(message);
    }
    public static void assertFalse(boolean condition) {
        if (condition) fail();
    }

    /**
     * Fails a test with the given message.
     * @param message the assertion error message
     */
    public static AssertionError fail(String message) {
        throw new AssertionError(message);
    }
    public static AssertionError fail(Throwable error) {
        throw new AssertionError(error);
    }
    public static AssertionError fail() { throw new AssertionError(); }

    public static void assertEqualsIgnoringOrder(Iterable<?> actual, Iterable<?> expected) {
        assertEqualsIgnoringOrder(actual, expected, false, null);
    }

    public static void assertEqualsIgnoringOrder(Iterable<?> actual, Iterable<?> expected, boolean logDuplicates, String errmsg) {
        Set<?> actualSet = Sets.newLinkedHashSet(actual);
        Set<?> expectedSet = Sets.newLinkedHashSet(expected);
        Set<?> extras = Sets.difference(actualSet, expectedSet);
        Set<?> missing = Sets.difference(expectedSet, actualSet);
        List<Object> duplicates = Lists.newArrayList(actual);
        for (Object a : actualSet) {
            duplicates.remove(a);
        }
        String fullErrmsg = "extras="+extras+"; missing="+missing
                + (logDuplicates ? "; duplicates="+MutableSet.copyOf(duplicates) : "")
                +"; actualSize="+Iterables.size(actual)+"; expectedSize="+Iterables.size(expected)
                +"; actual="+actual+"; expected="+expected+"; "+errmsg;
        assertTrue(extras.isEmpty(), fullErrmsg);
        assertTrue(missing.isEmpty(), fullErrmsg);
        assertTrue(Iterables.size(actual) == Iterables.size(expected), fullErrmsg);
        assertTrue(actualSet.equals(expectedSet), fullErrmsg); // should be covered by extras/missing/size test
    }

    // --- new routines
    
    /**  As {@link #eventually(Supplier, java.util.function.Predicate, Duration, Duration, String)} with defaults. */
    public static <T> void eventually(Supplier<? extends T> supplier, java.util.function.Predicate<T> predicate) {
        eventually(supplier, predicate, null, null, null);
    }
    public static <T> void eventually(Supplier<? extends T> supplier, com.google.common.base.Predicate<T> predicate) {
        eventually(supplier, predicate, null, null, null);
    }
    
    /**  As {@link #eventually(Supplier, java.util.function.Predicate, Duration, Duration, String)} with default. */
    public static <T> void eventually(Supplier<? extends T> supplier, java.util.function.Predicate<T> predicate, Duration timeout) {
        eventually(supplier, predicate, timeout, null, null);
    }
    public static <T> void eventually(Supplier<? extends T> supplier, com.google.common.base.Predicate<T> predicate, Duration timeout) {
        eventually(supplier, predicate, timeout, null, null);
    }

    /** As {@link #eventually(Supplier, java.util.function.Predicate, Duration, Duration, String)} when no object is going to be notified. */
    public static <T> void eventually(Supplier<? extends T> supplier, java.util.function.Predicate<T> predicate, Duration timeout, Duration period, String errMsg) {
        eventually(supplier, predicate, timeout, period, errMsg, null);
    }
    public static <T> void eventually(Supplier<? extends T> supplier, com.google.common.base.Predicate<T> predicate, Duration timeout, Duration period, String errMsg) {
        eventually(supplier, predicate, timeout, period, errMsg, null);
    }
    /** Asserts that eventually the supplier gives a value accepted by the predicate. 
     * Tests periodically and succeeds as soon as the supplier gives an allowed value.
     * Other arguments can be null.
     * 
     * @param supplier supplies the value to test, such as {@link Suppliers#ofInstance(Object)} for a constant 
     * @param predicate the {@link java.util.function.Predicate} to apply to each value given by the supplier
     * @param timeout how long to wait, default {@link #DEFAULT_LONG_TIMEOUT}
     * @param period how often to check, default quite often so you won't notice but letting the CPU do work
     * @param errMsg optional error message to display if not satisfied, in addition to the last-tested supplied value and the predicate
     * @param notifyObject optional object that will be notified of change and should pre-empt the period to redo the check
     */
    public static <T> void eventually(Supplier<? extends T> supplier, java.util.function.Predicate<T> predicate, Duration timeout, Duration period, String errMsg, Object notifyObject) {
        // TODO use Repeater (there are too many args here)
        
        if (timeout==null) timeout = DEFAULT_LONG_TIMEOUT;
        if (period==null) period = DEFAULT_SHORT_PERIOD;
        CountdownTimer timeleft = timeout.countdownTimer();
        
        T supplied;
        int count = 0;
        do {
            if (count++ > 0) {
                if (notifyObject!=null) {
                    synchronized (notifyObject) {
                        try {
                            notifyObject.wait(period.toMilliseconds());
                        } catch (InterruptedException e) {
                            throw Exceptions.propagate(e);
                        }
                    }
                } else {
                    Duration.sleep(period);
                }
            }
            supplied = supplier.get();
            if (predicate.test(supplied)) return;
        } while (timeleft.isNotExpired());

        fail("Expected: eventually "+predicate+"; got most recently: "+supplied
            +" (waited "+timeleft.getDurationElapsed()+", checked "+count+")"
            +(errMsg!=null?"; "+errMsg:""));
    }
    public static <T> void eventually(Supplier<? extends T> supplier, com.google.common.base.Predicate<T> predicate, Duration timeout, Duration period, String errMsg, Object notifyObject) {
        eventually(supplier, (java.util.function.Predicate<T>) predicate, timeout, period, errMsg, null);
    }

    /**  As {@link #continually(Supplier, java.util.function.Predicate, Duration, Duration, String)} with defaults. */
    public static <T> void continually(Supplier<? extends T> supplier, java.util.function.Predicate<T> predicate) {
        continually(supplier, predicate, (Duration)null, (Duration)null, (String)null);
    }
    public static <T> void continually(Supplier<? extends T> supplier, com.google.common.base.Predicate<T> predicate) {
        continually(supplier, predicate, (Duration)null, (Duration)null, (String)null);
    }

    /** 
     * Asserts that continually the supplier gives a value accepted by the predicate. 
     * Tests periodically and fails if the supplier gives a disallowed value.
     * Other arguments can be null.
     * 
     * @param supplier supplies the value to test, such as {@link Suppliers#ofInstance(Object)} for a constant 
     * @param predicate the {@link java.util.function.Predicate} to apply to each value given by the supplier
     * @param duration how long to test for, default {@link #DEFAULT_SHORT_TIMEOUT}
     * @param period how often to check, default quite often to minimise chance of missing a flashing violation but letting the CPU do work
     * @param errMsg an error message to display if not satisfied, in addition to the last-tested supplied value and the predicate
     */
    public static <T> void continually(Supplier<? extends T> supplier, com.google.common.base.Predicate<T> predicate, Duration duration, Duration period, String errMsg) {
        continually(supplier, (java.util.function.Predicate<T>) predicate, duration, period, errMsg);
    }
    public static <T> void continually(Supplier<? extends T> supplier, java.util.function.Predicate<T> predicate, Duration duration, Duration period, String errMsg) {
        if (duration==null) duration = DEFAULT_SHORT_TIMEOUT;
        if (period==null) period = DEFAULT_SHORT_PERIOD;

        CountdownTimer timeleft = duration.countdownTimer();
        
        T supplied;
        int count = 0;
        do {
            if (count > 0) Duration.sleep(period);
            supplied = supplier.get();
            if (!predicate.test(supplied)) {
                fail("Expected: continually "+predicate+"; got violation: "+supplied
                    // tell timing if it worked the first time and then failed
                    +(count > 0 ? " (after "+timeleft.getDurationElapsed()+", successfully checked "+count+")" : "")
                    +(errMsg!=null?"; "+errMsg:""));
            }
            count++;
        } while (timeleft.isNotExpired());
    }
    
    /**
     * @see #succeedsEventually(Map, Callable)
     */
    public static void succeedsEventually(Runnable r) {
        succeedsEventually(ImmutableMap.<String,Object>of(), r);
    }

    /**
     * @see #succeedsEventually(Map, Callable)
     */
    public static void succeedsEventually(Map<String,?> flags, Runnable r) {
        succeedsEventually(flags, toCallable(r));
    }
    
    /**
     * @see #succeedsEventually(Map, Callable)
     */
    public static <T> T succeedsEventually(Callable<T> c) {
        return succeedsEventually(ImmutableMap.<String,Object>of(), c);
    }
    
    // FIXME duplication with TestUtils.BooleanWithMessage
    public static class BooleanWithMessage {
        boolean value; String message;
        public BooleanWithMessage(boolean value, String message) {
            this.value = value; this.message = message;
        }
        public boolean asBoolean() {
            return value;
        }
        @Override
        public String toString() {
            return message;
        }
    }

    // TODO flags are ugly; remove this in favour of something strongly typed,
    // e.g. extending Repeater and taking the extra semantics.
    // TODO remove the #succeedsEventually in favour of #eventually (and same for continually)
    //      Aled says why? I've found succeedsEventually to be a concise & clear way to write tests.
    /**
     * Convenience method for cases where we need to test until something is true.
     *
     * The Callable will be invoked periodically until it succesfully concludes.
     * <p>
     * The following flags are supported:
     * <ul>
     * <li>abortOnError (boolean, default true)
     * <li>abortOnException - (boolean, default false)
     * <li>timeout - (a Duration or an integer in millis, defaults to {@link Asserts#DEFAULT_LONG_TIMEOUT})
     * <li>period - (a Duration or an integer in millis, for fixed retry time; if not set, defaults to exponentially increasing from 1 to 500ms)
     * <li>minPeriod - (a Duration or an integer in millis; only used if period not explicitly set; the minimum period when exponentially increasing; defaults to 1ms)
     * <li>maxPeriod - (a Duration or an integer in millis; only used if period not explicitly set; the maximum period when exponentially increasing; defaults to 500ms)
     * <li>maxAttempts - (integer, Integer.MAX_VALUE)
     * </ul>
     * 
     * The following flags are deprecated:
     * <ul>
     * <li>useGroovyTruth - (defaults to false; any result code apart from 'false' will be treated as success including null; ignored for Runnables which aren't Callables)
     * </ul>
     * 
     * @param flags, accepts the flags listed above
     * @param c The callable to invoke
     */
    public static <T> T succeedsEventually(Map<String,?> flags, Callable<T> c) {
        boolean abortOnException = get(flags, "abortOnException", false);
        boolean abortOnError = get(flags, "abortOnError", false);
        boolean useGroovyTruth = get(flags, "useGroovyTruth", false);
        boolean logException = get(flags, "logException", true);

        // To speed up tests, default is for the period to start small and increase...
        Duration duration = toDuration(flags.get("timeout"), DEFAULT_LONG_TIMEOUT);
        Duration fixedPeriod = toDuration(flags.get("period"), null);
        Duration minPeriod = (fixedPeriod != null) ? fixedPeriod : toDuration(flags.get("minPeriod"), Duration.millis(1));
        Duration maxPeriod = (fixedPeriod != null) ? fixedPeriod : toDuration(flags.get("maxPeriod"), Duration.millis(500));
        int maxAttempts = get(flags, "maxAttempts", Integer.MAX_VALUE);
        int attempt = 0;
        long startTime = System.currentTimeMillis();
        try {
            Throwable lastException = null;
            T result = null;
            long lastAttemptTime = 0;
            long expireTime = startTime+duration.toMilliseconds();
            long sleepTimeBetweenAttempts = minPeriod.toMilliseconds();
            
            while (attempt < maxAttempts && lastAttemptTime < expireTime) {
                try {
                    attempt++;
                    lastAttemptTime = System.currentTimeMillis();
                    result = c.call();
                    if (log.isTraceEnabled()) log.trace("Attempt {} after {} ms: {}", new Object[] {attempt, System.currentTimeMillis() - startTime, result});
                    if (useGroovyTruth) {
                        if (groovyTruth(result)) return result;
                    } else if (Boolean.FALSE.equals(result)) {
                        if (result instanceof BooleanWithMessage) 
                            log.warn("Test returned an instance of BooleanWithMessage but useGroovyTruth is not set! " +
                                     "The result of this probably isn't what you intended.");
                        // FIXME surprising behaviour, "false" result here is acceptable
                        return result;
                    } else {
                        return result;
                    }
                    lastException = null;
                } catch(Throwable e) {
                    Exceptions.propagateIfInterrupt(e);
                    lastException = e;
                    if (log.isTraceEnabled()) log.trace("Attempt {} after {} ms: {}", new Object[] {attempt, System.currentTimeMillis() - startTime, e.getMessage()});
                    if (abortOnException) throw e;
                    if (abortOnError && e instanceof Error) throw e;
                }
                long sleepTime = Math.min(sleepTimeBetweenAttempts, expireTime-System.currentTimeMillis());
                if (sleepTime > 0) Thread.sleep(sleepTime);
                sleepTimeBetweenAttempts = Math.min(
                    // grow by 1.5x; doubling causes longer extra waits than we like in tests
                    sleepTimeBetweenAttempts + Math.max(1, sleepTimeBetweenAttempts/2), 
                    maxPeriod.toMilliseconds());
            }
            
            log.info("succeedsEventually exceeded max attempts or timeout - {} attempts lasting {} ms, for {}", new Object[] {attempt, System.currentTimeMillis()-startTime, c});
            if (lastException != null)
                throw lastException;
            throw fail("invalid results; last was: "+result);
        } catch (Throwable t) {
            Exceptions.propagateIfInterrupt(t);
            if (logException) log.info("failed succeeds-eventually, "+attempt+" attempts, "+
                    (System.currentTimeMillis()-startTime)+"ms elapsed "+
                    "(rethrowing): "+t);
            throw new AssertionError("failed succeeds-eventually, "+attempt+" attempts, "+
                (System.currentTimeMillis()-startTime)+"ms elapsed: "+Exceptions.collapseText(t), t);
        }
    }

    public static <T> void succeedsContinually(Runnable r) {
        succeedsContinually(ImmutableMap.<String,Object>of(), r);
    }
    
    public static <T> void succeedsContinually(Map<?,?> flags, Runnable r) {
        succeedsContinually(flags, toCallable(r));
    }

    public static <T> T succeedsContinually(Callable<T> c) {
        return succeedsContinually(ImmutableMap.<String,Object>of(), c);
    }

    // TODO unify with "continually"; see also eventually, some of those options might be useful
    public static <T> T succeedsContinually(Map<?,?> flags, Callable<T> job) {
        Duration duration = toDuration(flags.get("timeout"), DEFAULT_SHORT_TIMEOUT);
        Duration period = toDuration(flags.get("period"), Duration.millis(10));
        long periodMs = period.toMilliseconds();
        long startTime = System.currentTimeMillis();
        long expireTime = startTime+duration.toMilliseconds();
        int attempt = 0;
        
        boolean first = true;
        T result = null;
        while (first || System.currentTimeMillis() <= expireTime) {
            attempt++;
            try {
                result = job.call();
            } catch (Exception e) {
                log.info("succeedsContinually failed - {} attempts lasting {} ms, for {} (rethrowing)", new Object[] {attempt, System.currentTimeMillis()-startTime, job});
                throw propagate(e);
            }
            if (periodMs > 0) sleep(periodMs);
            first = false;
        }
        return result;
    }
    
    private static Duration toDuration(Object duration, Duration defaultVal) {
        if (duration == null)
            return defaultVal;
        else 
            return Duration.of(duration);
    }
    
    public static void assertFails(Runnable r) {
        assertFailsWith(toCallable(r), Predicates.alwaysTrue());
    }
    
    public static void assertFails(Callable<?> c) {
        assertFailsWith(c, Predicates.alwaysTrue());
    }
    
    /**
     * @deprecated since 0.11.0; explicit groovy utilities/support will be deleted.
     */
    @Deprecated
    public static void assertFailsWith(Callable<?> c, final Closure<Boolean> exceptionChecker) {
        assertFailsWith(c, (input) -> exceptionChecker.call(input));
    }
    
    @SafeVarargs
    public static void assertFailsWith(Runnable c, final Class<? extends Throwable> validException0, final Class<? extends Throwable> ...otherValidExceptions) {
        final List<Class<?>> validExceptions = ImmutableList.<Class<?>>builder()
                .add(validException0)
                .addAll(ImmutableList.copyOf(otherValidExceptions))
                .build();
        
        assertFailsWith(c, (e) -> {
                for (Class<?> validExceptionI: validExceptions) {
                    if (validExceptionI.isInstance(e)) return true;
                }
                fail("Test threw exception of unexpected type "+e.getClass()+"; expecting "+validExceptions);
                return false;
            });
    }

    public static void assertFailsWith(Runnable r, java.util.function.Predicate<? super Throwable> exceptionChecker) {
        assertFailsWith(toCallable(r), exceptionChecker, false);
    }
    public static void assertFailsWith(Runnable r, com.google.common.base.Predicate<? super Throwable> exceptionChecker) {
        assertFailsWith(toCallable(r), exceptionChecker, false);
    }
    
    public static void assertFailsWith(Callable<?> c, java.util.function.Predicate<? super Throwable> exceptionChecker) {
        assertFailsWith(c, exceptionChecker, true);
    }
    public static void assertFailsWith(Callable<?> c, com.google.common.base.Predicate<? super Throwable> exceptionChecker) {
        assertFailsWith(c, exceptionChecker, true);
    }

    private static void assertFailsWith(Callable<?> c, java.util.function.Predicate<? super Throwable> exceptionChecker, boolean showResult) {
        boolean failed = false;
        Object result = null;
        try {
            result = c.call();
        } catch (Throwable e) {
            failed = true;
            try {
                if (!exceptionChecker.test(e)) {
                    log.warn("Test threw invalid exception (failing)", e);
                    fail("Test threw invalid exception: " + e);
                }
                log.debug("Test for exception successful (" + e + ")");
            } catch (Exception e2) {
                log.warn("Test threw invalid exception (failing)", e);
                throw Exceptions.propagate(e2);
            }
        }
        if (!failed) fail("Test code should have thrown exception but did not" +
                (showResult ? "; returned: "+result : ""));
    }

    public static void assertReturnsEventually(final Runnable r, Duration timeout) throws InterruptedException, ExecutionException, TimeoutException {
        final AtomicReference<Throwable> throwable = new AtomicReference<Throwable>();
        Runnable wrappedR = new Runnable() {
            @Override public void run() {
                try {
                    r.run();
                } catch (Throwable t) {
                    throwable.set(t);
                    throw Exceptions.propagate(t);
                }
            }
        };
        Thread thread = new Thread(wrappedR, "assertReturnsEventually("+r+")");
        try {
            thread.start();
            thread.join(timeout.toMilliseconds());
            if (thread.isAlive()) {
                throw new TimeoutException("Still running: r="+r+"; thread="+Arrays.toString(thread.getStackTrace()));
            }
        } catch (InterruptedException e) {
            throw Exceptions.propagate(e);
        } finally {
            thread.interrupt();
        }
        
        if (throwable.get() !=  null) {
            throw new ExecutionException(throwable.get());
        }
    }

    public static <T> void assertThat(T object, com.google.common.base.Predicate<T> condition) {
        assertThat(object, condition, null);
    }
    public static <T> void assertThat(T object, java.util.function.Predicate<T> condition) {
        assertThat(object, condition, null);
    }
    public static <T> void assertThat(T object, com.google.common.base.Predicate<T> condition, String message) {
        assertThat(object, (java.util.function.Predicate<T>) condition, message);
    }
    public static <T> void assertThat(T object, java.util.function.Predicate<T> condition, String message) {
        if (condition.test(object)) return;
        fail(Strings.isBlank(message) ? "Failed "+condition+": "+object : message);
    }

    public static void assertStringContains(String input, String phrase1ToContain, String ...optionalOtherPhrasesToContain) {
        if (input==null) fail("Input is null.");
        if (phrase1ToContain!=null) {
            assertThat(input, StringPredicates.containsLiteral(phrase1ToContain));
        }
        for (String otherPhrase: optionalOtherPhrasesToContain) {
            if (otherPhrase!=null) {
                assertThat(input, StringPredicates.containsLiteral(otherPhrase));
            }
        }
    }
    
    public static void assertStringDoesNotContain(String input, String phrase1ToNotContain, String ...optionalOtherPhrasesToNotContain) {
        if (input==null) fail("Input is null.");
        if (phrase1ToNotContain!=null) {
            assertThat(input, Predicates.not(StringPredicates.containsLiteral(phrase1ToNotContain)));
        }
        for (String otherPhrase: optionalOtherPhrasesToNotContain) {
            if (otherPhrase!=null) {
                assertThat(input, Predicates.not(StringPredicates.containsLiteral(otherPhrase)));
            }
        }
    }
    
    public static void assertStringContainsAtLeastOne(String input, String possiblePhrase1ToContain, String ...optionalOtherPossiblePhrasesToContain) {
        if (input==null) fail("Input is null.");
        List<String> missing = MutableList.of();
        if (possiblePhrase1ToContain!=null) {
            if (input.contains(possiblePhrase1ToContain)) return;
            missing.add(possiblePhrase1ToContain);
        }
        for (String otherPhrase: optionalOtherPossiblePhrasesToContain) {
            if (otherPhrase!=null) {
                if (input.contains(otherPhrase)) return;
                missing.add(otherPhrase);
            }
        }
        fail("Input did not contain any of the expected phrases "+missing+": "+input);
    }
    
    public static void assertStringContainsIgnoreCase(String input, String phrase1ToContain, String ...optionalOtherPhrasesToContain) {
        if (input==null) fail("Input is null.");
        if (phrase1ToContain!=null) {
            assertThat(input, StringPredicates.containsLiteralIgnoreCase(phrase1ToContain));
        }
        for (String otherPhrase: optionalOtherPhrasesToContain) {
            if (otherPhrase!=null) {
                assertThat(input, StringPredicates.containsLiteralIgnoreCase(otherPhrase));
            }
        }
    }

    public static void assertStringDoesNotContainIgnoreCase(String input, String phrase1ToNotContain, String ...optionalOtherPhrasesToNotContain) {
        if (input==null) fail("Input is null.");
        if (phrase1ToNotContain!=null) {
            assertThat(input, Predicates.not(StringPredicates.containsLiteralIgnoreCase(phrase1ToNotContain)));
        }
        for (String otherPhrase: optionalOtherPhrasesToNotContain) {
            if (otherPhrase!=null) {
                assertThat(input, Predicates.not(StringPredicates.containsLiteralIgnoreCase(otherPhrase)));
            }
        }
    }
    
    public static void assertStringMatchesRegex(String input, String regex1ToMatch, String ...optionalOtherRegexesToMatch) {
        if (input==null) fail("Input is null.");
        if (regex1ToMatch!=null) {
            assertThat(input, StringPredicates.matchesRegex(regex1ToMatch));
        }
        for (String otherRegex: optionalOtherRegexesToMatch) {
            if (otherRegex!=null) {
                assertThat(input, StringPredicates.matchesRegex(otherRegex));
            }
        }
    }

    /** Subclass of {@link AssertionError} which indicates that code which should have thrown did not, 
     * so that callers can disambiguate expected errors from this one.
     * See {@link #shouldHaveFailedPreviously()} */
    public static class ShouldHaveFailedPreviouslyAssertionError extends AssertionError {
        private static final long serialVersionUID = 4359541529633617518L;
        public ShouldHaveFailedPreviouslyAssertionError() { this("Should have failed previously."); }
        public ShouldHaveFailedPreviouslyAssertionError(String message) { super(message); }
    }
    
    /** Throws a {@link ShouldHaveFailedPreviouslyAssertionError} exception, 
     * to more easily distinguish this failure from other fails.
     * In particular, use one of the <code>expectedFailure</code> methods
     * in the surrounding <code>catch</code> block and this error will pass through it.
     * <p>
     * This method throws, never returning normally, but declares a return type 
     * so you can pretend to throw the result,
     * for instance if your calling code otherwise warns about needing to return something. */
    public static RuntimeException shouldHaveFailedPreviously() {
        throw new ShouldHaveFailedPreviouslyAssertionError();
    }
    /** As {@link #shouldHaveFailedPreviously()} but allowing detail,
     * for example a value which was received when it shouldn't have been. */
    public static void shouldHaveFailedPreviously(String message) {
        throw new ShouldHaveFailedPreviouslyAssertionError(message);
    }

    /** Tests that an exception is not {@link ShouldHaveFailedPreviouslyAssertionError}.
     * See {@link #shouldHaveFailedPreviously()} */
    public static void expectedFailure(Throwable e) {
        if (e instanceof ShouldHaveFailedPreviouslyAssertionError) throw (Error)e;
    }
    
    /**
     * Tests that an exception is not {@link ShouldHaveFailedPreviouslyAssertionError}
     * and is either one of the given types, or has a caused-by of one of the given types.
     * 
     * If you want *just* the instanceof (without checking the caused-by), then just catch
     * those exception types, treat that as success, and let any other exception be propagated.
     * 
     * @return If the test is satisfied, this method returns normally. 
     * The caller can decide whether anything more should be done with the exception.
     * If the test fails, then either it is propagated, 
     * if the {@link Throwable} is a fatal ({@link Exceptions#propagateIfFatal(Throwable)}) other than an {@link AssertionError}, 
     * or more usually the test failure of this method is thrown, 
     * with detail of the original {@link Throwable} logged and included in the caused-by.
     */
    public static void expectedFailureOfType(Throwable e, Class<?> permittedSupertype, Class<?> ...permittedSupertypes) {
        expectedFailureOfType(null, e, permittedSupertype, permittedSupertypes);
    }
    @SuppressWarnings("unchecked")
    public static void expectedFailureOfType(String message, Throwable e, Class<?> permittedSupertype, Class<?> ...permittedSupertypeExtras) {
        @SuppressWarnings("rawtypes")
        List<Class<?>> permittedSupertypes = MutableList.of(permittedSupertype).appendAll((List)Arrays.asList(permittedSupertypeExtras));
        if (e instanceof ShouldHaveFailedPreviouslyAssertionError) throw (Error) e;
        for (Class<?> clazz: permittedSupertypes) {
            if (Exceptions.getFirstThrowableOfType(e, (Class<? extends Throwable>)clazz) != null) {
                return;
            }
        }
        rethrowPreferredException(e, 
            new AssertionError((message!=null ? message+": " : "") + "Error "+JavaClassNames.simpleClassName(e)+" is not any of the expected types: " + permittedSupertypes, e));
    }
    
    /** Tests {@link #expectedFailure(Throwable)} and that the <code>toString</code>
     * satisfies {@link #assertStringContains(String, String, String...)}.
     * @return as per {@link #expectedFailureOfType(Throwable, Class, Class...)} */
    public static boolean expectedFailureContains(Throwable e, String phrase1ToContain, String ...optionalOtherPhrasesToContain) {
        if (e instanceof ShouldHaveFailedPreviouslyAssertionError) throw (Error)e;
        try {
            assertStringContains(Exceptions.collapseText(e), phrase1ToContain, optionalOtherPhrasesToContain);
        } catch (AssertionError ee) {
            rethrowPreferredException(e, ee);
        }
        return true;
    }

    /** As {@link #expectedFailureContains(Throwable, String, String...)} but case insensitive */
    public static boolean expectedFailureContainsIgnoreCase(Throwable e, String phrase1ToContain, String ...optionalOtherPhrasesToContain) {
        if (e instanceof ShouldHaveFailedPreviouslyAssertionError) throw (Error)e;
        try {
            assertStringContainsIgnoreCase(Exceptions.collapseText(e), phrase1ToContain, optionalOtherPhrasesToContain);
        } catch (AssertionError ee) {
            rethrowPreferredException(e, ee);
        }
        return true;
    }
    public static Predicate<Throwable> expectedFailureContains(String phrase1ToContain, String ...optionalOtherPhrasesToContain) {
        return e -> expectedFailureContains(e, phrase1ToContain, optionalOtherPhrasesToContain);
    }
    public static Predicate<Throwable> expectedFailureContainsIgnoreCase(String phrase1ToContain, String ...optionalOtherPhrasesToContain) {
        return e -> expectedFailureContainsIgnoreCase(e, phrase1ToContain, optionalOtherPhrasesToContain);
    }

    /** As {@link #expectedFailureContains(Throwable, String, String...)} but case insensitive */
    public static boolean expectedCompoundExceptionContainsIgnoreCase(CompoundRuntimeException e, String phrase1ToContain, String ...optionalOtherPhrasesToContain) {
        for (Throwable t : e.getAllCauses()) {
            if (t instanceof ShouldHaveFailedPreviouslyAssertionError) throw (Error)t;
            try {
                expectedFailureContainsIgnoreCase(t, phrase1ToContain, optionalOtherPhrasesToContain);
                return true;
            } catch (AssertionError ee) {}
        }
        throw new CompoundRuntimeException("Expected literals not found: " + phrase1ToContain + ", " + optionalOtherPhrasesToContain, e);
    }

    /** Tests {@link #expectedFailure(Throwable)} and that the <code>toString</code>
     * satisfies {@link #assertStringContains(String, String, String...)}.
     * @return as per {@link #expectedFailureOfType(Throwable, Class, Class...)} */
    public static boolean expectedFailureDoesNotContain(Throwable e, String phrase1ToNotContain, String ...optionalOtherPhrasesToNotContain) {
        if (e instanceof ShouldHaveFailedPreviouslyAssertionError) throw (Error)e;
        try {
            assertStringDoesNotContain(Exceptions.collapseText(e), phrase1ToNotContain, optionalOtherPhrasesToNotContain);
        } catch (AssertionError ee) {
            rethrowPreferredException(e, ee);
        }
        return true;
    }
    public static boolean expectedFailureDoesNotContainIgnoreCase(Throwable e, String phrase1ToNotContain, String ...optionalOtherPhrasesToNotContain) {
        if (e instanceof ShouldHaveFailedPreviouslyAssertionError) throw (Error)e;
        try {
            assertStringDoesNotContainIgnoreCase(Exceptions.collapseText(e), phrase1ToNotContain, optionalOtherPhrasesToNotContain);
        } catch (AssertionError ee) {
            rethrowPreferredException(e, ee);
        }
        return true;
    }
    public static Predicate<Throwable> expectedFailureDoesNotContain( String phrase1ToNotContain, String ...optionalOtherPhrasesToNotContain) {
        return e -> expectedFailureDoesNotContain(e, phrase1ToNotContain, optionalOtherPhrasesToNotContain);
    }
    public static Predicate<Throwable> expectedFailureDoesNotContainIgnoreCase(String phrase1ToNotContain, String ...optionalOtherPhrasesToNotContain) {
        return e -> expectedFailureDoesNotContainIgnoreCase(e, phrase1ToNotContain, optionalOtherPhrasesToNotContain);
    }

    /** Implements the return behavior for {@link #expectedFailureOfType(Throwable, Class, Class...)} and others,
     * to log interesting earlier errors but to suppress those which are internal or redundant. */
    private static void rethrowPreferredException(Throwable earlierPreferredIfFatalElseLogged, Throwable laterPreferredOtherwise) throws AssertionError {
        if (!(earlierPreferredIfFatalElseLogged instanceof AssertionError)) {
            Exceptions.propagateIfFatal(earlierPreferredIfFatalElseLogged);
        }
        log.warn("Detail of unexpected error: "+earlierPreferredIfFatalElseLogged, earlierPreferredIfFatalElseLogged);
        throw Exceptions.propagate(laterPreferredOtherwise);
    }

    @SuppressWarnings("rawtypes")
    private static boolean groovyTruth(Object o) {
        // TODO Doesn't handle matchers (see http://docs.codehaus.org/display/GROOVY/Groovy+Truth)
        if (o == null) {
            return false;
        } else if (o instanceof Boolean) {
            return (Boolean)o;
        } else if (o instanceof String) {
            return !((String)o).isEmpty();
        } else if (o instanceof Collection) {
            return !((Collection)o).isEmpty();
        } else if (o instanceof Map) {
            return !((Map)o).isEmpty();
        } else if (o instanceof Iterator) {
            return ((Iterator)o).hasNext();
        } else if (o instanceof Enumeration) {
            return ((Enumeration)o).hasMoreElements();
        } else {
            return true;
        }
    }
    
    @SuppressWarnings("unchecked")
    private static <T> T get(Map<String,?> map, String key, T defaultVal) {
        Object val = map.get(key);
        return (T) ((val == null) ? defaultVal : val);
    }
    
    private static Callable<?> toCallable(Runnable r) {
        return (r instanceof Callable) ? (Callable<?>)r : new RunnableAdapter<Void>(r, null);
    }
    
    /** Same as {@link java.util.concurrent.Executors#callable(Runnable)}, except includes toString() */
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        @Override
        public T call() {
            task.run();
            return result;
        }
        @Override
        public String toString() {
            return "RunnableAdapter("+task+")";
        }
    }
    
    private static void sleep(long periodMs) {
        if (periodMs > 0) {
            try {
                Thread.sleep(periodMs);
            } catch (InterruptedException e) {
                throw propagate(e);
            }
        }
    }
    
    private static RuntimeException propagate(Throwable t) {
        throw Exceptions.propagate(t);
    }

    /** As {@link #eventuallyOnNotify(Object, Supplier, java.util.function.Predicate, Duration)} with default timeout. */
    public static <T> void eventuallyOnNotify(Object notifyTarget, Supplier<T> supplier, com.google.common.base.Predicate<T> predicate) {
        eventuallyOnNotify(notifyTarget, supplier, predicate, null);
    }
    public static <T> void eventuallyOnNotify(Object notifyTarget, Supplier<T> supplier, java.util.function.Predicate<T> predicate) {
        eventuallyOnNotify(notifyTarget, supplier, predicate, null);
    }
    
    /** as {@link #eventually(Supplier, java.util.function.Predicate)} for cases where an object is notified;
     * more efficient as it waits on the notify target object. 
     * See also the simpler {@link #eventuallyOnNotify(Object, java.util.function.Predicate)} when looking at a collection which is getting notified.
     * Timeout defaults to {@link #DEFAULT_SHORT_TIMEOUT}. 
     * <p>
     * This synchronizes on the notify target for the duration of the wait, 
     * including while getting and checking the value, so as not to miss any notification. */
    public static <T> void eventuallyOnNotify(Object notifyTarget, Supplier<T> supplier, com.google.common.base.Predicate<T> predicate, Duration timeout) {
        eventuallyOnNotify(notifyTarget, supplier, (java.util.function.Predicate<T>)predicate, timeout);
    }
    public static <T> void eventuallyOnNotify(Object notifyTarget, Supplier<T> supplier, java.util.function.Predicate<T> predicate, Duration timeout) {
        T supplied = null;
        if (timeout==null) timeout = DEFAULT_SHORT_TIMEOUT;
        CountdownTimer remaining = timeout.countdownTimer();
        int checks = 0;
        synchronized (notifyTarget) {
            do {
                if (checks>0) {
                    remaining.waitOnForExpiryUnchecked(notifyTarget);
                }
                supplied = supplier.get();
                if (predicate.test(supplied)) return;
                checks++;
            } while (remaining.isNotExpired());
        }
        
        // should get 2 checks, 1 before and 1 after, if no notifications; if more, tell the user
        fail("Expected: eventually "+predicate+"; got most recently: "+supplied+
            " (waited "+remaining.getDurationElapsed()+
                (checks>2 ? "; notification count "+(checks-2) : "")+
            ")");
    }

    /** Convenience for {@link #eventuallyOnNotify(Object, Supplier, java.util.function.Predicate, Duration)}
     * when the notify target and the value under test are the same. */
    public static <T> void eventuallyOnNotify(T object, java.util.function.Predicate<T> predicate, Duration timeout) {
        eventuallyOnNotify(object, Suppliers.ofInstance(object), predicate, timeout);
    }
    public static <T> void eventuallyOnNotify(T object, com.google.common.base.Predicate<T> predicate, Duration timeout) {
        eventuallyOnNotify(object, Suppliers.ofInstance(object), predicate, timeout);
    }

    /** As {@link #eventuallyOnNotify(Object, java.util.function.Predicate, Duration)} with the default duration of {@link #eventuallyOnNotify(Object, Supplier, java.util.function.Predicate)}. */
    public static <T> void eventuallyOnNotify(T object, java.util.function.Predicate<T> predicate) {
        eventuallyOnNotify(object, Suppliers.ofInstance(object), predicate, null);
    }
    public static <T> void eventuallyOnNotify(T object, com.google.common.base.Predicate<T> predicate) {
        eventuallyOnNotify(object, Suppliers.ofInstance(object), predicate, null);
    }

    public static void assertSize(Iterable<?> list, int expectedSize) {
        if (list==null) fail("Collection is null");
        if (Iterables.size(list)!=expectedSize) fail("Collection has wrong size "+Iterables.size(list)+" (expected "+expectedSize+"): "+list);
    }

    public static void assertSize(Map<?,?> map, int expectedSize) {
        if (map==null) fail("Map is null");
        if (Iterables.size(map.keySet())!=expectedSize) fail("Map has wrong size "+map.size()+" (expected "+expectedSize+"): "+map);
    }

    /** Ignores duplicates and order */
    public static void assertSameUnorderedContents(Iterable<?> i1, Iterable<?> i2) {
        if (i1==null || i2==null) {
            if (i1==null && i2==null) {
                return ;
            }
            fail("Collections differ in that one is null: "+i1+" and "+i2);
        }
        assertEquals(MutableSet.copyOf(i1), MutableSet.copyOf(i2));
    }

    public static void assertInstanceOf(Object obj, Class<?> type) {
        assertThat(obj, Predicates.instanceOf(type), "Expected "+type+" but found "+(obj==null ? "null" : obj+" ("+obj.getClass()+")"));
    }

    public static <T> T assertPresent(Maybe<T> candidate) {
        if (candidate.isPresent()) return candidate.get();
        throw fail( Maybe.getException(candidate) );
    }

    public static <T> void assertNotPresent(Maybe<T> candidate) {
        if (candidate.isAbsent()) return;
        throw fail("Expected absent value; instead got: "+candidate.get());
    }

    public static <T> void assertEntriesSatisfy(Collection<T> list, Collection<java.util.function.Predicate<T>> tests) {
        Asserts.assertEquals(list.size(), tests.size(), "List of test is different length to list of data to test");
        Iterator<T> li = list.iterator();
        Iterator<java.util.function.Predicate<T>> ti = tests.iterator();
        for (int i=0; i<list.size(); i++) {
            T l = li.next();
            Asserts.assertTrue(ti.next().test(l), "Failed at index "+i+": "+l);
        }
    }

    public static MemoryAssertions startMemoryAssertions(String message) {
        MemoryAssertions result = new MemoryAssertions();
        result.pushUsedMemory(message);
        return result;
    }

    public static class MemoryAssertions {
        public MemoryAssertions() {
        }

        Runnable extraTaskOnNoteMemory;
        Deque<Long> usedMemoryQueue = new ArrayDeque<>();

        public void setExtraTaskOnNoteMemory(Runnable extraTaskOnNoteMemory) {
            this.extraTaskOnNoteMemory = extraTaskOnNoteMemory;
        }

        public long pushUsedMemory(String message) {
            Time.sleep(Duration.millis(200));
            if (extraTaskOnNoteMemory!=null) {
                extraTaskOnNoteMemory.run();
            }
            System.gc(); System.gc();
            Time.sleep(Duration.millis(50));
            System.gc(); System.gc();
            long mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
            usedMemoryQueue.addLast(mem);
            log.info("Memory used - "+message+": "+ByteSizeStrings.java().apply(mem));
            return mem;
        }

        public long popUsedMemory() {
            return usedMemoryQueue.removeLast();
        }

        public long peekLastUsedMemory() {
            return usedMemoryQueue.peekLast();
        }

        public void assertUsedMemoryLessThan(String event, long max, boolean push) {
            assertUsedMemoryLessThan(event, max, push, null);
        }

        public void assertUsedMemoryLessThan(String event, long max, boolean push, String extraFailMessage) {
            long nowUsed = pushUsedMemory(event);
            if (nowUsed > max) {
                // aggressively try to force GC
                Time.sleep(Duration.ONE_SECOND);
                popUsedMemory();
                nowUsed = pushUsedMemory(event+" (extra GC)");
                if (nowUsed > max) {
                    fail("Too much memory used - "+ ByteSizeStrings.java().apply(nowUsed)+" > max "+ByteSizeStrings.java().apply(max)+
                            (extraFailMessage==null ? "" : " "+extraFailMessage));
                }
            }
            if (!push) popUsedMemory();
        }
        public void assertUsedMemoryMaxDelta(String event, long deltaMegabytes, boolean push) {
            final long last = peekLastUsedMemory();
            assertUsedMemoryLessThan(event, last + deltaMegabytes*1024*1024, push, "(prev was "+ByteSizeStrings.java().apply(last)+", delta limit was "+ByteSizeStrings.java().apply(deltaMegabytes*1024*1024)+")");
        }
    }
}
