You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/08 04:19:07 UTC

[2/6] incubator-brooklyn git commit: [BROOKLYN-162] Update package name to a.o.b in usage/test-support

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9e04407d/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy b/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy
deleted file mode 100644
index 78fefeb..0000000
--- a/usage/test-support/src/main/java/brooklyn/test/TestUtils.groovy
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * 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 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 org.codehaus.groovy.runtime.InvokerInvocationException
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-
-import brooklyn.entity.Entity
-import brooklyn.event.AttributeSensor
-import brooklyn.util.text.StringFunctions;
-import brooklyn.util.time.Duration
-
-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 :-(
-    //      <T> void assertEventually(Map flags=[:], Supplier<? extends T> supplier, Predicate<T> 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 <T> void assertEventually(Map flags=[:], Supplier<? extends T> supplier, Predicate<T> 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.
-     * <p>
-     * The following flags are supported:
-     * <ul>
-     * <li>abortOnError (boolean, default true)
-     * <li>abortOnException - (boolean, default false)
-     * <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)
-     * <li>timeout - (a Duration or an integer in millis, defaults to 30*SECONDS)
-     * <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>
-     *
-     * @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...
-        Duration duration = Duration.of(flags.timeout) ?: Duration.THIRTY_SECONDS;
-        Duration fixedPeriod = Duration.of(flags.period) ?: null
-        Duration minPeriod = fixedPeriod ?: Duration.of(flags.minPeriod) ?: Duration.millis(1)
-        Duration maxPeriod = fixedPeriod ?: Duration.of(flags.maxPeriod) ?: Duration.millis(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<maxAttempts && lastAttemptTime<expireTime) {
-                try {
-                    attempt++
-                    lastAttemptTime = System.currentTimeMillis()
-                    result = c.call()
-                    log.trace "Attempt {} after {} ms: {}", attempt, System.currentTimeMillis() - startTime, result
-                    if (useGroovyTruth) {
-                        if (result) return;
-                    } else if (result != false) {
-                        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."
-                        return;
-                    }
-                    lastException = null
-                } catch(Throwable e) {
-                    lastException = e
-                    log.trace "Attempt {} after {} ms: {}", attempt, System.currentTimeMillis() - startTime, e.message
-                    if (abortOnException) throw e
-                    if (abortOnError && e in Error) throw e
-                }
-                long sleepTime = Math.min(sleepTimeBetweenAttempts, expireTime-System.currentTimeMillis())
-                if (sleepTime > 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 <T> 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) {
-        Duration duration = Duration.of(flags.timeout) ?: Duration.ONE_SECOND
-        Duration period = Duration.of(flags.period) ?: Duration.millis(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 <T> void assertContinually(Map flags=[:], Supplier<? extends T> supplier, Predicate<T> predicate) {
-        Asserts.continually(flags, supplier, predicate, (String)null);
-    }
-
-    /**
-     * @deprecated since 0.5; use {@link Asserts#continually(Map, Supplier, Predicate, String)}
-     */
-    @Deprecated
-    public static <T> void assertContinually(Map flags=[:], Supplier<? extends T> supplier, Predicate<T> predicate, String errMsg, long durationMs) {
-        flags.put("duration", Duration.millis(durationMs));
-        Asserts.continually(flags, supplier, predicate, errMsg);
-    }
-    
-    /**
-     * @deprecated since 0.5; use {@link Asserts#continually(Map, Supplier, Predicate, String)}
-     */
-    @Deprecated
-    public static <T> void assertContinually(Map flags=[:], Supplier<? extends T> supplier, Predicate<T> 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.5; use {@link EntityTestUtils#assertAttributeEqualsEventually(Entity, AttributeSensor, Object)}
-     */
-    @Deprecated
-    public static <T> void assertAttributeEventually(Entity entity, AttributeSensor<T> attribute, T expected) {
-        executeUntilSucceeds() {
-            assertEquals(entity.getAttribute(attribute), expected);
-        }
-    }
-    
-    /**
-     * @deprecated since 0.5; use {@link EntityTestUtils#assertAttributeEqualsContinually(Entity, AttributeSensor, Object)}
-     */
-    @Deprecated
-    public static <T> void assertAttributeContinually(Entity entity, AttributeSensor<T> 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<? extends Throwable> validException, final Class<? extends Throwable> ...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<Throwable> 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 <T> void assertNonEmpty(Iterable<T> 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 <T> void assertSize(Iterable<T> c, int expectedSize) {
-        int actualSize = Iterables.size(c);
-        if (actualSize==expectedSize) return;
-        fail("Expected collection of size "+expectedSize+" but got size "+actualSize+": "+c);
-    }
-
-    /**
-     * @deprecated since 0.7.0; use {@link Asserts#assertThat(Object, Predicate)} with {@link StringFunctions})}
-     */
-    @Deprecated
-    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+"'");
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9e04407d/usage/test-support/src/main/java/brooklyn/test/TrustingSslSocketFactory.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/brooklyn/test/TrustingSslSocketFactory.java b/usage/test-support/src/main/java/brooklyn/test/TrustingSslSocketFactory.java
deleted file mode 100644
index 3cbd94a..0000000
--- a/usage/test-support/src/main/java/brooklyn/test/TrustingSslSocketFactory.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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 brooklyn.test;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.URLConnection;
-import java.net.UnknownHostException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Throwables;
-
-// FIXME copied from brooklyn-core because core not visible here
-
-public class TrustingSslSocketFactory extends SSLSocketFactory {
-    
-    private static final Logger logger = LoggerFactory.getLogger(TrustingSslSocketFactory.class);
-
-    private static TrustingSslSocketFactory INSTANCE;
-    public synchronized static TrustingSslSocketFactory getInstance() {
-        if (INSTANCE==null) INSTANCE = new TrustingSslSocketFactory();
-        return INSTANCE;
-    }
-    
-    private static SSLContext sslContext; 
-    static {
-        try {
-            sslContext = SSLContext.getInstance("TLS");
-        } catch (Exception e) {
-            logger.error("Unable to set up SSLContext with TLS. Https activity will likely fail.", e);
-        }
-    }
-
-    /** configures a connection to accept all certificates, if it is for https */
-    public static <T extends URLConnection> T configure(T connection) {
-        if (connection instanceof HttpsURLConnection) {
-            ((HttpsURLConnection)connection).setSSLSocketFactory(getInstance());
-        }
-        return connection;
-    }
-    
-    /** trusts all SSL certificates */
-    public static final TrustManager TRUST_ALL = new X509TrustManager() {
-        public X509Certificate[] getAcceptedIssuers() {
-            return new X509Certificate[0];
-        }
-        @Override
-        public void checkClientTrusted(X509Certificate[] chain, String authType)
-                throws java.security.cert.CertificateException {
-            
-        }
-        @Override
-        public void checkServerTrusted(X509Certificate[] chain, String authType)
-                throws java.security.cert.CertificateException {
-        }
-    };
-
-    // no reason this can't be public, but no reason it should be necessary;
-    // just use getInstance to get the shared INSTANCE
-    protected TrustingSslSocketFactory() {
-        super();
-        try {
-            sslContext.init(null, new TrustManager[] { TRUST_ALL }, null);
-        } catch (Exception e) {
-            throw Throwables.propagate(e);
-        }
-    }
-
-    @Override
-    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
-        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
-    }
-
-    @Override
-    public Socket createSocket() throws IOException {
-        return sslContext.getSocketFactory().createSocket();
-    }
-
-    @Override
-    public String[] getDefaultCipherSuites() {
-        return sslContext.getSocketFactory().getDefaultCipherSuites();
-    }
-
-    @Override
-    public String[] getSupportedCipherSuites() {
-        return sslContext.getSocketFactory().getSupportedCipherSuites();
-    }
-
-    @Override
-    public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException {
-        return sslContext.getSocketFactory().createSocket(arg0, arg1);
-    }
-
-    @Override
-    public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
-        return sslContext.getSocketFactory().createSocket(arg0, arg1);
-    }
-
-    @Override
-    public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException {
-        return sslContext.getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
-    }
-
-    @Override
-    public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
-        return sslContext.getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9e04407d/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java b/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java
deleted file mode 100644
index 2d0a457..0000000
--- a/usage/test-support/src/main/java/brooklyn/test/WebAppMonitor.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * 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 brooklyn.test;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.slf4j.Logger;
-import org.testng.Assert;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.time.Duration;
-
-/**
- * Repeatedly polls a given URL, to check if it is always available.
- * 
- * @author Alex, Aled
- */
-public class WebAppMonitor implements Runnable {
-    final AtomicBoolean shouldBeActive = new AtomicBoolean(true);
-    final AtomicBoolean isActive = new AtomicBoolean(false);
-    final AtomicInteger successes = new AtomicInteger(0);
-    final AtomicInteger failures = new AtomicInteger(0);
-    final AtomicLong lastTime = new AtomicLong(-1);
-    final AtomicReference<Object> lastStatus = new AtomicReference<Object>(null);
-    final AtomicReference<Object> lastFailure = new AtomicReference<Object>(null);
-    Logger log;
-    Object problem = null; 
-    String url;
-    long delayMillis = 500;
-    int expectedResponseCode = 200;
-    
-    public WebAppMonitor(String url) {
-        this.url = url;
-    }
-    public WebAppMonitor() {
-    }
-    public WebAppMonitor logFailures(Logger log) {
-        this.log = log;
-        return this;
-    }
-    public WebAppMonitor delayMillis(long val) {
-        this.delayMillis = val;
-        return this;
-    }
-    public WebAppMonitor expectedResponseCode(int val) {
-        this.expectedResponseCode = val;
-        return this;
-    }
-    public WebAppMonitor url(String val) {
-        this.url = val;
-        return this;
-    }
-    
-    public void run() {
-        synchronized (isActive) {
-            if (isActive.getAndSet(true))
-                throw new IllegalStateException("already running");
-        }
-        while (shouldBeActive.get()) {
-            long startTime = System.currentTimeMillis();
-            try {
-                if (preAttempt()) {
-                    int code = HttpTestUtils.getHttpStatusCode(url);
-                    lastTime.set(System.currentTimeMillis() - startTime);
-                    lastStatus.set(code);
-                    if (isResponseOkay(code)) {
-                        successes.incrementAndGet();
-                    } else {
-                        lastFailure.set(code);
-                        failures.incrementAndGet();
-                        onFailure("return code "+code);
-                    }
-                }
-            } catch (Exception e) {
-                lastTime.set(System.currentTimeMillis()-startTime);
-                lastStatus.set(e);
-                lastFailure.set(e);
-                failures.incrementAndGet();
-                onFailure(e);
-            }
-            try {
-                if (delayMillis > 0) {
-                    Thread.sleep(delayMillis);
-                }
-            } catch (InterruptedException e) {
-                onFailure(e);
-                shouldBeActive.set(false);
-            }
-        }
-        synchronized (isActive) {
-            if (!isActive.getAndSet(false))
-                throw new IllegalStateException("shouldn't be possible!");
-            isActive.notifyAll();
-        }
-    }
-    
-    public boolean isResponseOkay(Object code) {
-        return code!=null && new Integer(expectedResponseCode).equals(code);
-    }
-    
-    public void setDelayMillis(long delayMillis) {
-        this.delayMillis = delayMillis;
-    }
-    public long getDelayMillis() {
-        return delayMillis;
-    }
-    public void terminate() throws InterruptedException {
-        shouldBeActive.set(false);
-        synchronized (isActive) {
-            while (isActive.get()) isActive.wait();
-        }
-    }
-    public int getFailures() {
-        return failures.get();
-    }
-    public int getSuccesses() {
-        return successes.get();
-    }
-    public void setUrl(String url) {
-        this.url = url;
-    }
-    public String getUrl() {
-        return url;
-    }
-    public Object getProblem() {
-        return problem;
-    }
-    public int getAttempts() {
-        return getFailures()+getSuccesses();
-    }
-    public boolean getLastWasFailed() {
-        return isResponseOkay(getLastStatus());
-    }
-    public Object getLastStatus() {
-        return lastStatus.get();
-    }
-    public long getLastTime() {
-        return lastTime.get();
-    }
-    /** result code (int) or exception */
-    public Object getLastFailure() {
-        return lastFailure.get();
-    }
-    
-    public void onFailure(Object problem) {
-        if (log != null) {
-            log.warn("Detected failure in monitor accessing "+getUrl()+": "+problem);
-        }
-        this.problem = problem;
-    }
-    
-    /** return false to skip a run */
-    public boolean preAttempt() {
-        return true;
-    }
-    
-    public WebAppMonitor assertNoFailures(String message) {
-        return assertSuccessFraction(message, 1.0);
-    }
-    public WebAppMonitor assertAttemptsMade(int minAttempts, String message) {
-        if (getAttempts()<minAttempts) {
-            Assert.fail(message+" -- webapp access failures! " +
-                    "(0 attempts made; probably blocked on server)");            
-        }
-        return this;
-    }
-    public WebAppMonitor waitForAtLeastOneAttempt() {
-        return waitForAtLeastOneAttempt(Asserts.DEFAULT_TIMEOUT);
-    }
-    public WebAppMonitor waitForAtLeastOneAttempt(Duration timeout) {
-        Asserts.succeedsEventually(MutableMap.of("timeout", timeout), new Runnable() {
-            @Override public void run() {
-                Assert.assertTrue(getAttempts() >= 1);
-            }});
-        return this;
-    }
-    public WebAppMonitor assertSuccessFraction(String message, double fraction) {
-        int failures = getFailures();
-        int attempts = getAttempts();
-        if ((failures > (1-fraction) * attempts + 0.0001) || attempts <= 0) {
-            Assert.fail(message+" -- webapp access failures! " +
-                    "("+failures+" failed of "+attempts+" monitoring attempts) against "+getUrl()+"; " +
-                    "last was "+getLastStatus()+" taking "+getLastTime()+"ms" +
-                    (getLastFailure() != null ? "; last failure was "+getLastFailure() : ""));
-        }
-        return this;
-    }
-    public WebAppMonitor resetCounts() {
-        failures.set(0);
-        successes.set(0);
-        return this;
-    }
-    
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9e04407d/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java b/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java
new file mode 100644
index 0000000..3bceb78
--- /dev/null
+++ b/usage/test-support/src/main/java/org/apache/brooklyn/test/EntityTestUtils.java
@@ -0,0 +1,181 @@
+/*
+ * 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 static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.Group;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.SensorEvent;
+import brooklyn.event.SensorEventListener;
+import brooklyn.management.SubscriptionHandle;
+import brooklyn.test.Asserts;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class EntityTestUtils {
+
+    // TODO would be nice to have this... perhaps moving this class, or perhaps this whole project, to core/src/test ?
+//    public static LocalManagementContext newManagementContext() { return new LocalManagementContextForTests(); }
+    
+    // TODO Delete methods from TestUtils, to just have them here (or switch so TestUtils delegates here,
+    // and deprecate methods in TestUtils until deleted).
+    
+    public static <T> void assertAttributeEquals(Entity entity, AttributeSensor<T> attribute, T expected) {
+        assertEquals(entity.getAttribute(attribute), expected, "entity="+entity+"; attribute="+attribute);
+    }
+    
+    public static <T> void assertConfigEquals(Entity entity, ConfigKey<T> configKey, T expected) {
+        assertEquals(entity.getConfig(configKey), expected, "entity="+entity+"; configKey="+configKey);
+    }
+    
+    public static <T> void assertAttributeEqualsEventually(final Entity entity, final AttributeSensor<T> attribute, final T expected) {
+        assertAttributeEqualsEventually(Maps.newLinkedHashMap(), entity, attribute, expected);
+    }
+
+    public static <T> void assertAttributeEqualsEventually(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, final T expected) {
+        // Not using assertAttributeEventually(predicate) so get nicer error message
+        Asserts.succeedsEventually((Map)flags, new Runnable() {
+            @Override public void run() {
+                assertAttributeEquals(entity, attribute, expected);
+            }});
+    }
+
+    public static <T> T assertAttributeEventuallyNonNull(final Entity entity, final AttributeSensor<T> attribute) {
+        return assertAttributeEventuallyNonNull(Maps.newLinkedHashMap(), entity, attribute);
+    }
+
+    public static <T> T assertAttributeEventuallyNonNull(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute) {
+        return assertAttributeEventually(flags, entity, attribute, Predicates.notNull());
+    }
+
+    public static <T> T assertAttributeEventually(final Entity entity, final AttributeSensor<T> attribute, Predicate<? super T> predicate) {
+        return assertAttributeEventually(ImmutableMap.of(), entity, attribute, predicate);
+    }
+    
+    public static <T> T assertAttributeEventually(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, final Predicate<? super T> predicate) {
+        final AtomicReference<T> result = new AtomicReference<T>();
+        Asserts.succeedsEventually((Map)flags, new Runnable() {
+            @Override public void run() {
+                T val = entity.getAttribute(attribute);
+                assertTrue(predicate.apply(val), "val="+val);
+                result.set(val);
+            }});
+        return result.get();
+    }
+
+    public static <T> T assertAttribute(final Entity entity, final AttributeSensor<T> attribute, final Predicate<? super T> predicate) {
+        T val = entity.getAttribute(attribute);
+        assertTrue(predicate.apply(val), "val="+val);
+        return val;
+    }
+
+    public static <T extends Entity> void assertPredicateEventuallyTrue(final T entity, final Predicate<? super T> predicate) {
+        assertPredicateEventuallyTrue(Maps.newLinkedHashMap(), entity, predicate);
+    }
+
+    public static <T extends Entity> void assertPredicateEventuallyTrue(Map<?,?> flags, final T entity, final Predicate<? super T> predicate) {
+        Asserts.succeedsEventually((Map)flags, new Runnable() {
+                @Override public void run() {
+                    assertTrue(predicate.apply(entity));
+                }});
+    }
+
+    public static <T> void assertAttributeEqualsContinually(final Entity entity, final AttributeSensor<T> attribute, final T expected) {
+        assertAttributeEqualsContinually(Maps.newLinkedHashMap(), entity, attribute, expected);
+    }
+    
+    public static <T> void assertAttributeEqualsContinually(Map<?,?> flags, final Entity entity, final AttributeSensor<T> attribute, final T expected) {
+        Asserts.succeedsContinually(flags, new Runnable() {
+                @Override public void run() {
+                    assertAttributeEquals(entity, attribute, expected);
+                }});
+    }
+
+    public static void assertGroupSizeEqualsEventually(final Group group, int expected) {
+        assertGroupSizeEqualsEventually(ImmutableMap.of(), group, expected);
+    }
+    
+    public static void assertGroupSizeEqualsEventually(Map<?,?> flags, final Group group, final int expected) {
+        Asserts.succeedsEventually((Map)flags, new Runnable() {
+            @Override public void run() {
+                Collection<Entity> members = group.getMembers();
+                assertEquals(members.size(), expected, "members="+members);
+            }});
+    }
+
+    /** checks that the entity's value for this attribute changes, by registering a subscription and checking the value */
+    public static void assertAttributeChangesEventually(final Entity entity, final AttributeSensor<?> attribute) {
+        final Object origValue = entity.getAttribute(attribute);
+        final AtomicBoolean changed = new AtomicBoolean();
+        SubscriptionHandle handle = ((EntityLocal)entity).subscribe(entity, attribute, new SensorEventListener<Object>() {
+            @Override public void onEvent(SensorEvent<Object> event) {
+                if (!Objects.equal(origValue, event.getValue())) {
+                    changed.set(true);
+                }
+            }});
+        try {
+            Asserts.succeedsEventually(new Runnable() {
+                @Override public void run() {
+                    assertTrue(changed.get(), entity+" -> "+attribute+" not changed");
+                }});
+        } finally {
+            ((EntityLocal)entity).unsubscribe(entity, handle);
+        }
+    }
+    
+    /** alternate version of {@link #assertAttributeChangesEventually(Entity, AttributeSensor)} not using subscriptions and 
+     * with simpler code, for comparison */
+    @Beta
+    public static <T> void assertAttributeChangesEventually2(final Entity entity, final AttributeSensor<T> attribute) {
+        assertAttributeEventually(entity, attribute, 
+            Predicates.not(Predicates.equalTo(entity.getAttribute(attribute))));
+    }
+
+    @Beta
+    public static <T> void assertAttributeNever(final Entity entity, final AttributeSensor<T> attribute, T... disallowed) {
+        final Set<T> reject = Sets.newHashSet(disallowed);
+        Asserts.succeedsContinually(new Runnable() {
+            @Override
+            public void run() {
+                T val = entity.getAttribute(attribute);
+                assertFalse(reject.contains(val),
+                        "Attribute " + attribute + " on " + entity + " has disallowed value " + val);
+            }
+        });
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9e04407d/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java b/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
new file mode 100644
index 0000000..455bc7e
--- /dev/null
+++ b/usage/test-support/src/main/java/org/apache/brooklyn/test/HttpTestUtils.java
@@ -0,0 +1,392 @@
+/*
+ * 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 static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.crypto.SslTrustUtils;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+/**
+ * Utility methods to aid testing HTTP.
+ * 
+ * @author aled
+ */
+public class HttpTestUtils {
+
+    // TODO Delete methods from TestUtils, to just have them here (or switch so TestUtils delegates here,
+    // and deprecate methods in TestUtils until deleted).
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpTestUtils.class);
+
+    static final ExecutorService executor = Executors.newCachedThreadPool();
+    
+    /**
+     * Connects to the given url and returns the connection.
+     * Caller should {@code connection.getInputStream().close()} the result of this
+     * (especially if they are making heavy use of this method).
+     */
+    public static URLConnection connectToUrl(String u) throws Exception {
+        final URL url = new URL(u);
+        final AtomicReference<Exception> exception = new AtomicReference<Exception>();
+        
+        // sometimes openConnection hangs, so run in background
+        Future<URLConnection> f = executor.submit(new Callable<URLConnection>() {
+            public URLConnection call() {
+                try {
+                    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+                        @Override public boolean verify(String s, SSLSession sslSession) {
+                            return true;
+                        }
+                    });
+                    URLConnection connection = url.openConnection();
+                    TrustingSslSocketFactory.configure(connection);
+                    connection.connect();
+    
+                    connection.getContentLength(); // Make sure the connection is made.
+                    return connection;
+                } catch (Exception e) {
+                    exception.set(e);
+                    LOG.debug("Error connecting to url "+url+" (propagating): "+e, e);
+                }
+                return null;
+            }
+        });
+        try {
+            URLConnection result = null;
+            try {
+                result = f.get(60, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                throw e;
+            } catch (Exception e) {
+                LOG.debug("Error connecting to url "+url+", probably timed out (rethrowing): "+e);
+                throw new IllegalStateException("Connect to URL not complete within 60 seconds, for url "+url+": "+e);
+            }
+            if (exception.get() != null) {
+                LOG.debug("Error connecting to url "+url+", thread caller of "+exception, new Throwable("source of rethrown error "+exception));
+                throw exception.get();
+            } else {
+                return result;
+            }
+        } finally {
+            f.cancel(true);
+        }
+    }
+
+    public static void assertHealthyStatusCode(int code) {
+        if (code>=200 && code<=299) return;
+        Assert.fail("Wrong status code: "+code);
+    }
+    
+    public static int getHttpStatusCode(String url) throws Exception {
+        URLConnection connection = connectToUrl(url);
+        long startTime = System.currentTimeMillis();
+        int status = ((HttpURLConnection) connection).getResponseCode();
+        
+        // read fully if possible, then close everything, trying to prevent cached threads at server
+        consumeAndCloseQuietly((HttpURLConnection) connection);
+        
+        if (LOG.isDebugEnabled())
+            LOG.debug("connection to {} ({}ms) gives {}", new Object[] { url, (System.currentTimeMillis()-startTime), status });
+        return status;
+    }
+
+    /**
+     * Asserts that gets back any "valid" response - i.e. not an exception. This could be an unauthorized,
+     * a redirect, a 404, or anything else that implies there is web-server listening on that port.
+     */
+    public static void assertUrlReachable(String url) {
+        try {
+            getHttpStatusCode(url);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException("Interrupted for "+url+" (in assertion that is reachable)", e);
+        } catch (Exception e) {
+            throw new IllegalStateException("Server at "+url+" failed to respond (in assertion that is reachable): "+e, e);
+        }
+    }
+
+    public static void assertUrlUnreachable(String url) {
+        try {
+            int statusCode = getHttpStatusCode(url);
+            fail("Expected url "+url+" unreachable, but got status code "+statusCode);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException("Interrupted for "+url+" (in assertion that unreachable)", e);
+        } catch (Exception e) {
+            IOException cause = Exceptions.getFirstThrowableOfType(e, IOException.class);
+            if (cause != null) {
+                // success; clean shutdown transitioning from 400 to error
+            } else {
+                Throwables.propagate(e);
+            }                        
+        }
+    }
+
+    public static void assertUrlUnreachableEventually(final String url) {
+        assertUrlUnreachableEventually(Maps.newLinkedHashMap(), url);
+    }
+    
+    public static void assertUrlUnreachableEventually(Map flags, final String url) {
+        Asserts.succeedsEventually(flags, new Runnable() {
+            public void run() {
+                assertUrlUnreachable(url);
+            }
+         });
+    }
+
+    public static void assertHttpStatusCodeEquals(String url, int... acceptableReturnCodes) {
+        List<Integer> acceptableCodes = Lists.newArrayList();
+        for (int code : acceptableReturnCodes) {
+            acceptableCodes.add((Integer)code);
+        }
+        try {
+            int actualCode = getHttpStatusCode(url);
+            assertTrue(acceptableCodes.contains(actualCode), "code="+actualCode+"; expected="+acceptableCodes+"; url="+url);
+            
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException("Interrupted for "+url+" (in assertion that result code is "+acceptableCodes+")", e);
+        } catch (Exception e) {
+            throw new IllegalStateException("Server at "+url+" failed to respond (in assertion that result code is "+acceptableCodes+"): "+e, e);
+        }
+    }
+
+    public static void assertHttpStatusCodeEventuallyEquals(final String url, final int expectedCode) {
+        assertHttpStatusCodeEventuallyEquals(Maps.newLinkedHashMap(),  url, expectedCode);
+    }
+
+    public static void assertHttpStatusCodeEventuallyEquals(Map flags, final String url, final int expectedCode) {
+        Asserts.succeedsEventually(flags, new Runnable() {
+            public void run() {
+                assertHttpStatusCodeEquals(url, expectedCode);
+            }
+         });
+    }
+
+    public static void assertContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String contents = getContent(url);
+            Assert.assertTrue(contents != null && contents.length() > 0);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (!contents.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" MISSING TEXT: "+text+"\n"+contents);
+                    Assert.fail("URL "+url+" does not contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    public static void assertContentNotContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String contents = getContent(url);
+            Assert.assertTrue(contents != null);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (contents.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" HAS TEXT: "+text+"\n"+contents);
+                    Assert.fail("URL "+url+" contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    public static void assertErrorContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String contents = getErrorContent(url);
+            Assert.assertTrue(contents != null && contents.length() > 0);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (!contents.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" MISSING TEXT: "+text+"\n"+contents);
+                    Assert.fail("URL "+url+" does not contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+
+    public static void assertErrorContentNotContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        try {
+            String err = getErrorContent(url);
+            Assert.assertTrue(err != null);
+            for (String text: Lists.asList(phrase, additionalPhrases)) {
+                if (err.contains(text)) {
+                    LOG.warn("CONTENTS OF URL "+url+" HAS TEXT: "+text+"\n"+err);
+                    Assert.fail("URL "+url+" contain text: "+text);
+                }
+            }
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+    
+    public static void assertContentEventuallyContainsText(final String url, final String phrase, final String ...additionalPhrases) {
+        assertContentEventuallyContainsText(MutableMap.of(), url, phrase, additionalPhrases);
+    }
+    
+    public static void assertContentEventuallyContainsText(Map flags, final String url, final String phrase, final String ...additionalPhrases) {
+        Asserts.succeedsEventually(flags, new Runnable() {
+            public void run() {
+                assertContentContainsText(url, phrase, additionalPhrases);
+            }
+         });
+    }
+    
+    public static void assertContentMatches(String url, String regex) {
+        String contents = getContent(url);
+        Assert.assertNotNull(contents);
+        Assert.assertTrue(contents.matches(regex), "Contents does not match expected regex ("+regex+"): "+contents);
+    }
+
+    public static void assertContentEventuallyMatches(final String url, final String regex) {
+        Asserts.succeedsEventually(new Runnable() {
+            @Override
+            public void run() {
+                assertContentMatches(url, regex);
+            }
+        });
+    }
+    
+    public static String getErrorContent(String url) {
+        try {
+            HttpURLConnection connection = (HttpURLConnection) connectToUrl(url);
+            long startTime = System.currentTimeMillis();
+            
+            String err;
+            int status;
+            try {
+                InputStream errStream = connection.getErrorStream();
+                err = Streams.readFullyString(errStream);
+                status = connection.getResponseCode();
+            } finally {
+                closeQuietly(connection);
+            }
+            
+            if (LOG.isDebugEnabled())
+                LOG.debug("read of err {} ({}ms) complete; http code {}", new Object[] { url, Time.makeTimeStringRounded(System.currentTimeMillis()-startTime), status});
+            return err;
+
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    public static String getContent(String url) {
+        try {
+            return Streams.readFullyString(SslTrustUtils.trustAll(new URL(url).openConnection()).getInputStream());
+        } catch (Exception e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    /**
+     * Schedules (with the given executor) a poller that repeatedly accesses the given url, to confirm it always gives
+     * back the expected status code.
+     * 
+     * Expected usage is to query the future, such as:
+     * 
+     * <pre>
+     * {@code
+     * Future<?> future = assertAsyncHttpStatusCodeContinuallyEquals(executor, url, 200);
+     * // do other stuff...
+     * if (future.isDone()) future.get(); // get exception if it's failed
+     * }
+     * </pre>
+     * 
+     * For stopping it, you can either do future.cancel(true), or you can just do executor.shutdownNow().
+     * 
+     * TODO Look at difference between this and WebAppMonitor, to decide if this should be kept.
+     */
+    public static ListenableFuture<?> assertAsyncHttpStatusCodeContinuallyEquals(ListeningExecutorService executor, final String url, final int expectedStatusCode) {
+        return executor.submit(new Runnable() {
+            @Override public void run() {
+                // TODO Need to drop logging; remove sleep when that's done.
+                while (!Thread.currentThread().isInterrupted()) {
+                    assertHttpStatusCodeEquals(url, expectedStatusCode);
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException e) {
+                        return; // graceful return
+                    }
+                }
+            }
+        });
+    }
+    
+    /**
+     * Consumes the input stream entirely and then cleanly closes the connection.
+     * Ignores all exceptions completely, not even logging them!
+     * 
+     * Consuming the stream fully is useful for preventing idle TCP connections. 
+     * See {@linkplain http://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html}.
+     */
+    public static void consumeAndCloseQuietly(HttpURLConnection connection) {
+        try { Streams.readFully(connection.getInputStream()); } catch (Exception e) {}
+        closeQuietly(connection);
+    }
+    
+    /**
+     * Closes all streams of the connection, and disconnects it. Ignores all exceptions completely,
+     * not even logging them!
+     */
+    public static void closeQuietly(HttpURLConnection connection) {
+        try { connection.disconnect(); } catch (Exception e) {}
+        try { connection.getInputStream().close(); } catch (Exception e) {}
+        try { connection.getOutputStream().close(); } catch (Exception e) {}
+        try { connection.getErrorStream().close(); } catch (Exception e) {}
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9e04407d/usage/test-support/src/main/java/org/apache/brooklyn/test/NetworkingTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/org/apache/brooklyn/test/NetworkingTestUtils.java b/usage/test-support/src/main/java/org/apache/brooklyn/test/NetworkingTestUtils.java
new file mode 100644
index 0000000..9811776
--- /dev/null
+++ b/usage/test-support/src/main/java/org/apache/brooklyn/test/NetworkingTestUtils.java
@@ -0,0 +1,69 @@
+/*
+ * 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 static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.test.Asserts;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.net.Networking;
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.ImmutableMap;
+
+public class NetworkingTestUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NetworkingTestUtils.class);
+
+    public static void assertPortsAvailableEventually(final Map<String, Integer> ports) {
+        // If we get into a TCP TIMED-WAIT state, it could take 4 minutes for the port to come available.
+        // Could that be causing our integration tests to fail sometimes when run in the suite?!
+        // Let's wait for the required ports in setup, rather than running+failing the test.
+        assertPortsAvailableEventually(ports, Duration.minutes(4));
+    }
+    
+    public static void assertPortsAvailableEventually(final Map<String, Integer> ports, final Duration timeout) {
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", Duration.minutes(4)), new Runnable() {
+            private boolean logged = false;
+            public void run() {
+                try {
+                    assertPortsAvailable(ports);
+                } catch (Throwable t) {
+                    if (!logged) {
+                        LOG.warn("Port(s) not available; waiting for up to "+timeout+" ("+Exceptions.getFirstInteresting(t)+")");
+                        logged = true;
+                    }
+                    throw Exceptions.propagate(t);
+                }
+            }});
+        LOG.debug("Ports are available: "+ports);
+    }
+    
+    public static void assertPortsAvailable(final Map<String, Integer> ports) {
+        for (Map.Entry<String, Integer> entry : ports.entrySet()) {
+            String errmsg = "port "+entry.getValue()+" not available for "+entry.getKey();
+            assertTrue(Networking.isPortAvailable(entry.getValue()), errmsg);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9e04407d/usage/test-support/src/main/java/org/apache/brooklyn/test/PerformanceTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/org/apache/brooklyn/test/PerformanceTestUtils.java b/usage/test-support/src/main/java/org/apache/brooklyn/test/PerformanceTestUtils.java
new file mode 100644
index 0000000..2b765cd
--- /dev/null
+++ b/usage/test-support/src/main/java/org/apache/brooklyn/test/PerformanceTestUtils.java
@@ -0,0 +1,99 @@
+/*
+ * 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.management.ManagementFactory;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+
+public class PerformanceTestUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PerformanceTestUtils.class);
+
+    private static boolean hasLoggedProcessCpuTimeUnavailable;
+    
+    public static long getProcessCpuTime() {
+        try {
+            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+            ObjectName osMBeanName = ObjectName.getInstance(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
+            return (Long) mbeanServer.getAttribute(osMBeanName, "ProcessCpuTime");
+        } catch (Exception e) {
+            if (!hasLoggedProcessCpuTimeUnavailable) {
+                hasLoggedProcessCpuTimeUnavailable = true;
+                LOG.warn("ProcessCPuTime not available in local JVM MXBean "+ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME+" (only available in sun JVM?)");
+            }
+            return -1;
+        }
+    }
+
+    /**
+     * Creates a background thread that will log.info the CPU fraction usage repeatedly, sampling at the given period.
+     * Callers <em>must</em> cancel the returned future, e.g. {@code future.cancel(true)}, otherwise it will keep
+     * logging until the JVM exits.
+     */
+    public static Future<?> sampleProcessCpuTime(final Duration period, final String loggingContext) {
+        final ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
+                @Override public Thread newThread(Runnable r) {
+                    Thread thread = new Thread(r, "brooklyn-sampleProcessCpuTime-"+loggingContext);
+                    thread.setDaemon(true); // let the JVM exit
+                    return thread;
+                }});
+        Future<?> future = executor.submit(new Runnable() {
+                @Override public void run() {
+                    try {
+                        long prevCpuTime = getProcessCpuTime();
+                        if (prevCpuTime == -1) {
+                            LOG.warn("ProcessCPuTime not available; cannot sample; aborting");
+                            return;
+                        }
+                        while (true) {
+                            Stopwatch stopwatch = Stopwatch.createStarted();
+                            Thread.sleep(period.toMilliseconds());
+                            long currentCpuTime = getProcessCpuTime();
+                            
+                            long elapsedTime = stopwatch.elapsed(TimeUnit.MILLISECONDS);
+                            double fractionCpu = (elapsedTime > 0) ? ((double)currentCpuTime-prevCpuTime) / TimeUnit.MILLISECONDS.toNanos(elapsedTime) : -1;
+                            prevCpuTime = currentCpuTime;
+                            
+                            LOG.info("CPU fraction over last {} was {} ({})", new Object[] {
+                                    Time.makeTimeStringRounded(elapsedTime), fractionCpu, loggingContext});
+                        }
+                    } catch (InterruptedException e) {
+                        return; // graceful termination
+                    } finally {
+                        executor.shutdownNow();
+                    }
+                }});
+        return future;
+    }
+}