All Downloads are FREE. Search and download functionalities are using the official Maven repository.

brooklyn.test.TestUtils.groovy Maven / Gradle / Ivy

There is a newer version: 0.7.0-M1
Show newest version
package brooklyn.test

import static org.testng.Assert.*
import groovy.time.TimeDuration

import java.util.concurrent.Callable
import java.util.concurrent.ExecutionException
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

import org.codehaus.groovy.runtime.InvokerInvocationException
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import brooklyn.entity.Entity
import brooklyn.event.AttributeSensor

import com.google.common.base.Predicate
import com.google.common.base.Supplier
import com.google.common.collect.Iterables

/**
 * Helper functions for tests of Tomcat, JBoss and others.
 * 
 * Note that methods will migrate from here to {@link Asserts} in future releases.
 */
public class TestUtils {
    private static final Logger log = LoggerFactory.getLogger(TestUtils.class)

    private TestUtils() { }

    /**
     * True if two attempts to connect to the port succeed.
     * 
     * @deprecated since 0.5; use {@link brooklyn.util.NetworkUtils#isPortAvailable(int)}
     */
    @Deprecated
    public static boolean isPortInUse(int port, long retryAfterMillis=0) {
        try {
            def s = new Socket("localhost", port)
            s.close()
            if (retryAfterMillis>0) {
                log.debug "port {} still open, waiting 1s for it to really close", port
                //give it 1s to close
                Thread.sleep retryAfterMillis
                s = new Socket("localhost", port)
                s.close()
            }
            log.debug "port {} still open (conclusive)", port
            return true
        } catch (ConnectException e) {
            return false
        }
    }

    /**
     * Connects to the given HTTP URL and asserts that the response had status code 200.
     * @deprecated Use HttpTestUtils.getHttpStatusCode(url) == 200
     */
    @Deprecated
    public static boolean urlRespondsWithStatusCode200(String url) {
        int status = HttpTestUtils.getHttpStatusCode(url);
        log.debug "connection to {} gives {}", url, status
        if (status == 404)
            throw new Exception("Connection to $url gave 404");
        return status == 200
    }
    
    /** 
     * Connects to the given HTTP URL and asserts that the response had status code 200.
     * @deprecated Use HttpTestUtils.getHttpStatusCode(url)
     */
    @Deprecated
    public static int urlRespondsStatusCode(String url) {
        return HttpTestUtils.getHttpStatusCode(url);
    }
    
    /** 
     * Connects to the given url and returns the connection.
     * @deprecated Use HttpTestUtils.connectToUrl(url)
     */
    @Deprecated
    public static URLConnection connectToURL(String url) {
        return HttpTestUtils.connectToUrl(url);
    }
    
    // calling groovy from java doesn't cope with generics here; stripping them from here :-(
    //       void assertEventually(Map flags=[:], Supplier supplier, Predicate predicate)
    /**
     * @deprecated since 0.5; use {@link Asserts#eventually(Map, Supplier, Predicate)}
     */
    @Deprecated
    public static void assertEventually(Map flags=[:], Supplier supplier, Predicate predicate) {
        Asserts.eventually(flags, supplier, predicate);
    }
    
    /**
     * @deprecated since 0.5; use {@link Asserts#eventually(Map, Supplier, Predicate, String)}
     */
    @Deprecated
    public static  void assertEventually(Map flags=[:], Supplier supplier, Predicate predicate, String errMsg) {
        Asserts.eventually(flags, supplier, predicate, errMsg);
    }

    /**    
     * @deprecated since 0.5; use {@link Asserts#succeedsEventually(java.util.Map, Callable)}
     */
    @Deprecated
    public static void assertEventually(Map flags=[:], Callable c) {
        executeUntilSucceeds(flags, c);
    }
    
    /**
     * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Runnable)}
     */
    @Deprecated
    public static void assertEventually(Map flags=[:], Runnable c) {
        executeUntilSucceeds(flags, c);
    }

    /**
     * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Callable)}
     */
    @Deprecated
    public static void executeUntilSucceeds(Map flags=[:], Closure c) {
        Asserts.succeedsEventually(flags, c);
    }

    /**
     * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Callable)}
     */
    @Deprecated
    public static void executeUntilSucceeds(Map flags=[:], Callable c) {
        Asserts.succeedsEventually(flags, c);
    }
    
    /**
     * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Runnable)}
     */
    @Deprecated
    public static void executeUntilSucceeds(Map flags=[:], Runnable r) {
        if (r in Callable) 
            executeUntilSucceedsWithFinallyBlock(flags, {return ((Callable)r).call();}, { })
        else if (r in Closure)  // Closure check probably not necessary, just was trying to fix a server build which had a screwy problem
            executeUntilSucceedsWithFinallyBlock(flags, {return ((Closure)r).call();}, { })
        else
            executeUntilSucceedsWithFinallyBlock(flags, {r.run(); return true}, { })
    }

    /**
     * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Callable)}, and tear-down with {@link AfterMethod}.
     */
    @Deprecated
    public static void executeUntilSucceedsElseShutdown(Map flags=[:], Entity entity, Closure c) {
        try { 
            executeUntilSucceedsWithFinallyBlock(flags, c) { }
        } catch (Throwable t) {
            entity.stop()
            throw t
        }
    }

    /**
     * convenience for entities to ensure they shutdown afterwards.
     * 
     * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Callable)}, and tear-down with {@link AfterMethod}.
     */
    @Deprecated
    public static void executeUntilSucceedsWithShutdown(Map flags=[:], Entity entity, Closure c) {
        executeUntilSucceedsWithFinallyBlock(flags, c) { entity.stop() }
    }

    /**
     * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Callable)}, and tear-down with {@link AfterMethod}.
     */
    @Deprecated
    public static void executeUntilSucceedsWithFinallyBlock(Map flags=[:], Closure c, Closure finallyBlock={}) {
        executeUntilSucceedsWithFinallyBlockInternal(flags, c, finallyBlock)
    }
    
    /**
     * Convenience method for cases where we need to test until something is true.
     *
     * The runnable will be invoked periodically until it succesfully concludes.
     * Additionally, a finally block can be supplied.
     * 

* The following flags are supported: *

    *
  • abortOnError (boolean, default true) *
  • abortOnException - (boolean, default false) *
  • useGroovyTruth - (defaults to false; any result code apart from 'false' will be treated as success including null; ignored for Runnables which aren't Callables) *
  • timeout - (a TimeDuration or an integer in millis, defaults to 30*SECONDS) *
  • period - (a TimeDuration or an integer in millis, for fixed retry time; if not set, defaults to exponentially increasing from 1 to 500ms) *
  • minPeriod - (a TimeDuration or an integer in millis; only used if period not explicitly set; the minimum period when exponentially increasing; defaults to 1ms) *
  • maxPeriod - (a TimeDuration or an integer in millis; only used if period not explicitly set; the maximum period when exponentially increasing; defaults to 500ms) *
  • maxAttempts - (integer, Integer.MAX_VALUE) *
* * @param flags, accepts the flags listed above * @param r * @param finallyBlock * * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Callable)}, and tear-down with {@link AfterMethod}. */ @Deprecated public static void executeUntilSucceedsWithFinallyBlock(Map flags=[:], Callable c, Closure finallyBlock={}) { executeUntilSucceedsWithFinallyBlockInternal(flags, c, finallyBlock); } /** * the "real" implementation, renamed to allow multiple entry points (depending whether closure cast to callable) * * @deprecated since 0.5; use {@link Asserts#succeedsEventually(Map, Callable)}, and tear-down with {@link AfterMethod}. */ @Deprecated private static void executeUntilSucceedsWithFinallyBlockInternal(Map flags=[:], Callable c, Closure finallyBlock={}) { // log.trace "abortOnError = {}", flags.abortOnError boolean abortOnException = flags.abortOnException ?: false boolean abortOnError = flags.abortOnError ?: false boolean useGroovyTruth = flags.useGroovyTruth ?: false boolean logException = flags.logException ?: true // To speed up tests, default is for the period to start small and increase... TimeDuration duration = toTimeDuration(flags.timeout) ?: new TimeDuration(0,0,30,0) TimeDuration fixedPeriod = toTimeDuration(flags.period) ?: null TimeDuration minPeriod = fixedPeriod ?: toTimeDuration(flags.minPeriod) ?: new TimeDuration(0,0,0,1) TimeDuration maxPeriod = fixedPeriod ?: toTimeDuration(flags.maxPeriod) ?: new TimeDuration(0,0,0,500) int maxAttempts = flags.maxAttempts ?: Integer.MAX_VALUE; int attempt = 0; long startTime = System.currentTimeMillis(); try { Throwable lastException = null; Object result; long lastAttemptTime = 0; long expireTime = startTime+duration.toMilliseconds(); long sleepTimeBetweenAttempts = minPeriod.toMilliseconds(); while (attempt 0) Thread.sleep(sleepTime) sleepTimeBetweenAttempts = Math.min(sleepTimeBetweenAttempts*2, maxPeriod.toMilliseconds()) } log.debug "TestUtils.executeUntilSucceedsWithFinallyBlockInternal exceeded max attempts or timeout - {} attempts lasting {} ms", attempt, System.currentTimeMillis()-startTime if (lastException != null) throw lastException fail "invalid result: $result" } catch (Throwable t) { if (logException) log.info("failed execute-until-succeeds, "+attempt+" attempts, "+ (System.currentTimeMillis()-startTime)+"ms elapsed "+ "(rethrowing): "+t); throw t } finally { finallyBlock.call() } } /** * @deprecated since 0.5; use {@link Asserts#succeedsContinually(Map, Runnable)} */ @Deprecated public static void assertSucceedsContinually(Map flags=[:], Runnable job) { assertSucceedsContinually(flags, Executors.callable(job)); } /** * @deprecated since 0.5; use {@link Asserts#succeedsContinually(Map, Callable)} */ @Deprecated public static void assertSucceedsContinually(Map flags=[:], Callable job) { TimeDuration duration = toTimeDuration(flags.timeout) ?: new TimeDuration(0,0,1,0) TimeDuration period = toTimeDuration(flags.period) ?: new TimeDuration(0,0,0,10) long periodMs = period.toMilliseconds() long startTime = System.currentTimeMillis() long expireTime = startTime+duration.toMilliseconds() boolean first = true; while (first || System.currentTimeMillis() <= expireTime) { job.call(); if (periodMs > 0) sleep(periodMs); first = false; } } /** * @deprecated since 0.5; use {@link Asserts#continually(Map, Supplier, Predicate)} */ @Deprecated // FIXME When calling from java, the generics declared in groovy messing things up! public static void assertContinuallyFromJava(Map flags=[:], Supplier supplier, Predicate predicate) { Asserts.continually(flags, supplier, predicate); } /** * @deprecated since 0.5; use {@link Asserts#continually(Map, Supplier, Predicate)} */ @Deprecated public static void assertContinually(Map flags=[:], Supplier supplier, Predicate predicate) { Asserts.continually(flags, supplier, predicate, (String)null); } /** * @deprecated since 0.5; use {@link Asserts#continually(Map, Supplier, Predicate, String)} */ @Deprecated public static void assertContinually(Map flags=[:], Supplier supplier, Predicate predicate, String errMsg, long durationMs) { flags.put("duration", toTimeDuration(durationMs)); Asserts.continually(flags, supplier, predicate, errMsg); } /** * @deprecated since 0.5; use {@link Asserts#continually(Map, Supplier, Predicate, String)} */ @Deprecated public static void assertContinually(Map flags=[:], Supplier supplier, Predicate predicate, String errMsg) { Asserts.continually(flags, supplier, predicate, errMsg); } 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 } public String toString() { return message } } /** * @deprecated since 0.5; use {@link brooklyn.util.ResourceUtils} */ @Deprecated public static File getResource(String path, ClassLoader loader) { URL resource = loader.getResource(path) if (resource==null) throw new IllegalArgumentException("cannot find required entity '"+path+"'"); return new File(resource.path) } /** * @deprecated since 0.5; use long and {@link TimeUnit} */ @Deprecated public static TimeDuration toTimeDuration(Object duration) { return toTimeDuration(duration, null); } /** * @deprecated since 0.5; use long and {@link TimeUnit} */ @Deprecated public static TimeDuration toTimeDuration(Object duration, TimeDuration defaultVal) { if (duration == null) { return defaultVal; } else if (duration instanceof TimeDuration) { return (TimeDuration) duration } else if (duration instanceof Number) { return new TimeDuration(0,0,0,(int)duration) // TODO would be nice to have this, but we need to sort out utils / test-utils dependency // } else if (duration instanceof String) { // return Time.parseTimeString((String)duration); } else { throw new IllegalArgumentException("Cannot convert $duration of type ${duration.class.name} to a TimeDuration") } } public static Throwable unwrapThrowable(Throwable t) { if (t.getCause() == null) { return t; } else if (t instanceof ExecutionException) { return unwrapThrowable(t.getCause()) } else if (t instanceof InvokerInvocationException) { return unwrapThrowable(t.getCause()) } else { return t } } /** @deprecated since 0.4.0 use HttpTestUtils.assertUrlEventuallyHasText or HttpTestUtils.assertUrlHasText * (NB: this method has "eventually" logic, with default timeout of 30s, despite the absence of that in the name) */ @Deprecated public static void assertUrlHasText(Map flags=[:], String url, String ...phrases) { String contents; TimeDuration timeout = flags.timeout in Number ? flags.timeout*TimeUnit.MILLISECONDS : flags.timeout ?: 30*TimeUnit.SECONDS executeUntilSucceeds(timeout:timeout, maxAttempts:50) { //URLConnection connection = connectToURL(url); //connection.getContent(); //int status = ((HttpURLConnection) connection).getResponseCode() def connection = connectToURL(url); contents = new URL(url).openStream().getText(); assertTrue(contents!=null && contents.length()>0) } for (String text: phrases) { if (!contents.contains(text)) { log.warn("CONTENTS OF URL MISSING TEXT: $text\n"+contents) fail("URL $url does not contain text: $text") } } } /** * @deprecated since 0.5; use {@link EntityTestUtils#assertAttributeEqualsEventually(Entity, AttributeSensor, Object)} */ @Deprecated public static void assertAttributeEventually(Entity entity, AttributeSensor attribute, T expected) { executeUntilSucceeds() { assertEquals(entity.getAttribute(attribute), expected); } } /** * @deprecated since 0.5; use {@link EntityTestUtils#assertAttributeEqualsContinually(Entity, AttributeSensor, Object)} */ @Deprecated public static void assertAttributeContinually(Entity entity, AttributeSensor attribute, T expected) { assertSucceedsContinually() { assertEquals(entity.getAttribute(attribute), expected); } } /** * @deprecated since 0.5; use {@link HttpTestUtils#assertHttpStatusCodeEquals(String, int)} */ @Deprecated public static void assertUrlStatusCodeEventually(final String url, final int expected) { executeUntilSucceeds() { assertEquals(urlRespondsStatusCode(url), expected); } } /** * @deprecated since 0.5; use {@link Asserts#assertFails(Runnable)} */ @Deprecated public static void assertFails(Runnable c) { assertFailsWith(c, (Predicate)null); } /** * @deprecated since 0.5; use {@link Asserts#assertFailsWith(Closure)} */ @Deprecated public static void assertFailsWith(Runnable c, Closure exceptionChecker) { assertFailsWith(c, exceptionChecker as Predicate); } /** * @deprecated since 0.5; use {@link Asserts#assertFailsWith(Runnable, Class, Class...)} */ @Deprecated public static void assertFailsWith(Runnable c, final Class validException, final Class ...otherValidExceptions) { assertFailsWith(c, { e -> if (validException.isInstance(e)) return true; if (otherValidExceptions.find {it.isInstance(e)}) return true; List expectedTypes = [validException]; expectedTypes.addAll(Arrays.asList(otherValidExceptions)); fail("Test threw exception of unexpected type "+e.getClass()+"; expecting "+expectedTypes); }); } /** * @deprecated since 0.5; use {@link Asserts#assertFailsWith(Runnable, Predicate)} */ @Deprecated public static void assertFailsWith(Runnable c, Predicate exceptionChecker) { boolean failed = false; try { c.run(); } catch (Throwable e) { failed = true; if (exceptionChecker!=null) { if (!exceptionChecker.apply(e)) { fail("Test threw invalid exception: "+e); } } log.debug("Test for exception successful ("+e+")"); } if (!failed) fail("Test code should have thrown exception but did not"); } public static void assertSetsEqual(Collection c1, Collection c2) { Set s = new LinkedHashSet(); s.addAll(c1); s.removeAll(c2); if (!s.isEmpty()) fail("First argument contains additional contents: "+s); s.clear(); s.addAll(c2); s.removeAll(c1); if (!s.isEmpty()) fail("Second argument contains additional contents: "+s); } /** * @deprecated since 0.5; use {@code assertFalse(Iterables.isEmpty(c))} */ @Deprecated public static void assertNonEmpty(Iterable c) { if (c.iterator().hasNext()) return; fail("Expected non-empty set"); } /** * @deprecated since 0.5; use {@code assertEquals(Iterables.size(c), expectedSize)} */ @Deprecated public static void assertSize(Iterable c, int expectedSize) { int actualSize = Iterables.size(c); if (actualSize==expectedSize) return; fail("Expected collection of size "+expectedSize+" but got size "+actualSize+": "+c); } public static void assertStringContainsLiteral(String string, String substring) { if (string==null) fail("String is null"); if (substring==null) fail("Substring is null"); if (string.indexOf(substring)>=0) return; fail("String '"+string+"' does not contain expected pattern '"+substring+"'"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy