You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2015/11/04 16:47:51 UTC

[6/9] incubator-brooklyn git commit: Add unit tests for HttpAsserts.

Add unit tests for HttpAsserts.


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/885b6ac4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/885b6ac4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/885b6ac4

Branch: refs/heads/master
Commit: 885b6ac47c4a72a400ef16c9a11555f1e980eb64
Parents: 70a7189
Author: Geoff Macartney <ge...@cloudsoftcorp.com>
Authored: Tue Nov 3 17:13:44 2015 +0000
Committer: Geoff Macartney <ge...@cloudsoftcorp.com>
Committed: Tue Nov 3 17:38:11 2015 +0000

----------------------------------------------------------------------
 .../core/sensor/http/HttpRequestSensorTest.java |   5 +-
 .../core/test/TestHttpRequestHandler.java       |  72 -----
 .../brooklyn/core/test/TestHttpServer.java      | 143 ---------
 .../util/core/ResourceUtilsHttpTest.java        |   5 +-
 .../rest/resources/CatalogResetTest.java        |   4 +-
 utils/common/pom.xml                            |   8 +-
 .../test/http/TestHttpRequestHandler.java       |  72 +++++
 .../brooklyn/test/http/TestHttpServer.java      | 146 +++++++++
 .../apache/brooklyn/util/http/HttpAsserts.java  | 108 +++++--
 .../apache/brooklyn/util/HttpAssertsTest.java   | 293 +++++++++++++++++++
 10 files changed, 600 insertions(+), 256 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/core/src/test/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensorTest.java b/core/src/test/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensorTest.java
index 0e7495f..20169a9 100644
--- a/core/src/test/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensorTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/sensor/http/HttpRequestSensorTest.java
@@ -25,9 +25,8 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.core.entity.Attributes;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.core.sensor.http.HttpRequestSensor;
-import org.apache.brooklyn.core.test.TestHttpRequestHandler;
-import org.apache.brooklyn.core.test.TestHttpServer;
+import org.apache.brooklyn.test.http.TestHttpRequestHandler;
+import org.apache.brooklyn.test.http.TestHttpServer;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.apache.brooklyn.test.EntityTestUtils;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/core/src/test/java/org/apache/brooklyn/core/test/TestHttpRequestHandler.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/TestHttpRequestHandler.java b/core/src/test/java/org/apache/brooklyn/core/test/TestHttpRequestHandler.java
deleted file mode 100644
index d4ab712..0000000
--- a/core/src/test/java/org/apache/brooklyn/core/test/TestHttpRequestHandler.java
+++ /dev/null
@@ -1,72 +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 org.apache.brooklyn.core.test;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Collection;
-
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpException;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.message.BasicHeader;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.HttpRequestHandler;
-
-public class TestHttpRequestHandler implements HttpRequestHandler {
-    private HttpEntity entity;
-    private int responseCode = HttpStatus.SC_OK;
-    private Collection<Header> headers = new ArrayList<Header>();
-
-    public TestHttpRequestHandler response(String response) {
-        try {
-            this.entity = new StringEntity(response);
-        } catch (UnsupportedEncodingException e) {
-            throw Exceptions.propagate(e);
-        }
-        return this;
-    }
-
-    public TestHttpRequestHandler code(int responseCode) {
-        this.responseCode = responseCode;
-        return this;
-    }
-
-    public TestHttpRequestHandler header(String name, String value) {
-        headers.add(new BasicHeader(name, value));
-        return this;
-    }
-
-    @Override
-    public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
-        for (Header h : headers) {
-            response.setHeader(h);
-        }
-
-        response.setStatusCode(responseCode);
-        response.setEntity(entity);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/core/src/test/java/org/apache/brooklyn/core/test/TestHttpServer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/TestHttpServer.java b/core/src/test/java/org/apache/brooklyn/core/test/TestHttpServer.java
deleted file mode 100644
index a9eb7df..0000000
--- a/core/src/test/java/org/apache/brooklyn/core/test/TestHttpServer.java
+++ /dev/null
@@ -1,143 +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 org.apache.brooklyn.core.test;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.brooklyn.util.collections.MutableList;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.net.Networking;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpResponseInterceptor;
-import org.apache.http.impl.bootstrap.HttpServer;
-import org.apache.http.impl.bootstrap.ServerBootstrap;
-import org.apache.http.protocol.HttpProcessor;
-import org.apache.http.protocol.HttpRequestHandler;
-import org.apache.http.protocol.ImmutableHttpProcessor;
-import org.apache.http.protocol.ResponseConnControl;
-import org.apache.http.protocol.ResponseContent;
-
-public class TestHttpServer {
-    private static class HandlerTuple {
-        String path;
-        HttpRequestHandler handler;
-        public HandlerTuple(String path, HttpRequestHandler handler) {
-            this.path = path;
-            this.handler = handler;
-        }
-    }
-    private HttpServer server;
-    private List<HttpRequestInterceptor> requestInterceptors = MutableList.of();
-    private List<HttpResponseInterceptor> responseInterceptors = MutableList.of(new ResponseContent(), new ResponseConnControl());
-    private int basePort = 50505;
-    private Collection<HandlerTuple> handlers = MutableList.of();
-
-    public TestHttpServer interceptor(HttpResponseInterceptor interceptor) {
-        checkNotStarted();
-        responseInterceptors.add(interceptor);
-        return this;
-    }
-
-    public TestHttpServer requestInterceptors(List<HttpResponseInterceptor> interceptors) {
-        checkNotStarted();
-        this.responseInterceptors = interceptors;
-        return this;
-    }
-
-    public TestHttpServer interceptor(HttpRequestInterceptor interceptor) {
-        checkNotStarted();
-        requestInterceptors.add(interceptor);
-        return this;
-    }
-
-    public TestHttpServer responseInterceptors(List<HttpRequestInterceptor> interceptors) {
-        checkNotStarted();
-        this.requestInterceptors = interceptors;
-        return this;
-    }
-
-    public TestHttpServer basePort(int basePort) {
-        checkNotStarted();
-        this.basePort = basePort;
-        return this;
-    }
-
-    public TestHttpServer handler(String path, HttpRequestHandler handler) {
-        checkNotStarted();
-        handlers.add(new HandlerTuple(path, handler));
-        return this;
-    }
-
-    public TestHttpServer start() {
-        checkNotStarted();
-
-        HttpProcessor httpProcessor = new ImmutableHttpProcessor(requestInterceptors, responseInterceptors);
-        int port = Networking.nextAvailablePort(basePort);
-        ServerBootstrap bootstrap = ServerBootstrap.bootstrap()
-            .setListenerPort(port)
-            .setLocalAddress(getLocalAddress())
-            .setHttpProcessor(httpProcessor);
-
-        for (HandlerTuple tuple : handlers) {
-            bootstrap.registerHandler(tuple.path, tuple.handler);
-        }
-        server = bootstrap.create();
-
-        try {
-            server.start();
-        } catch (IOException e) {
-            throw Exceptions.propagate(e);
-        }
-
-        return this;
-    }
-
-    public void stop() {
-        server.stop();
-    }
-
-    private void checkNotStarted() {
-        if (server != null) {
-            throw new IllegalStateException("Server already started");
-        }
-    }
-
-    private InetAddress getLocalAddress() {
-        try {
-            return InetAddress.getLocalHost();
-        } catch (UnknownHostException e) {
-            throw Exceptions.propagate(e);
-        }
-    }
-
-    public String getUrl() {
-        try {
-            return new URL("http", server.getInetAddress().getHostAddress(), server.getLocalPort(), "").toExternalForm();
-        } catch (MalformedURLException e) {
-            throw Exceptions.propagate(e);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsHttpTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsHttpTest.java b/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsHttpTest.java
index c1cebb8..0952707 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsHttpTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/ResourceUtilsHttpTest.java
@@ -24,9 +24,8 @@ import static org.testng.Assert.assertFalse;
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.apache.brooklyn.core.test.TestHttpRequestHandler;
-import org.apache.brooklyn.core.test.TestHttpServer;
-import org.apache.brooklyn.util.core.ResourceUtils;
+import org.apache.brooklyn.test.http.TestHttpRequestHandler;
+import org.apache.brooklyn.test.http.TestHttpServer;
 import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.http.HttpException;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java
index 6adfdb5..c0e0089 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResetTest.java
@@ -27,8 +27,8 @@ import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 import org.apache.brooklyn.api.catalog.BrooklynCatalog;
-import org.apache.brooklyn.core.test.TestHttpRequestHandler;
-import org.apache.brooklyn.core.test.TestHttpServer;
+import org.apache.brooklyn.test.http.TestHttpRequestHandler;
+import org.apache.brooklyn.test.http.TestHttpServer;
 import org.apache.brooklyn.rest.testing.BrooklynRestResourceTest;
 import org.apache.brooklyn.util.core.ResourceUtils;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/utils/common/pom.xml
----------------------------------------------------------------------
diff --git a/utils/common/pom.xml b/utils/common/pom.xml
index 8bc0ae9..037dcd9 100644
--- a/utils/common/pom.xml
+++ b/utils/common/pom.xml
@@ -66,7 +66,13 @@
             <artifactId>snakeyaml</artifactId>
             <version>${snakeyaml.version}</version>
         </dependency>
-        
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.testng</groupId>
             <artifactId>testng</artifactId>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/utils/common/src/main/java/org/apache/brooklyn/test/http/TestHttpRequestHandler.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/test/http/TestHttpRequestHandler.java b/utils/common/src/main/java/org/apache/brooklyn/test/http/TestHttpRequestHandler.java
new file mode 100644
index 0000000..18f5c44
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/test/http/TestHttpRequestHandler.java
@@ -0,0 +1,72 @@
+/*
+ * 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.http;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+
+public class TestHttpRequestHandler implements HttpRequestHandler {
+    private HttpEntity entity;
+    private int responseCode = HttpStatus.SC_OK;
+    private Collection<Header> headers = new ArrayList<Header>();
+
+    public TestHttpRequestHandler response(String response) {
+        try {
+            this.entity = new StringEntity(response);
+        } catch (UnsupportedEncodingException e) {
+            throw Exceptions.propagate(e);
+        }
+        return this;
+    }
+
+    public TestHttpRequestHandler code(int responseCode) {
+        this.responseCode = responseCode;
+        return this;
+    }
+
+    public TestHttpRequestHandler header(String name, String value) {
+        headers.add(new BasicHeader(name, value));
+        return this;
+    }
+
+    @Override
+    public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
+        for (Header h : headers) {
+            response.setHeader(h);
+        }
+
+        response.setStatusCode(responseCode);
+        response.setEntity(entity);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/utils/common/src/main/java/org/apache/brooklyn/test/http/TestHttpServer.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/test/http/TestHttpServer.java b/utils/common/src/main/java/org/apache/brooklyn/test/http/TestHttpServer.java
new file mode 100644
index 0000000..75f5e60
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/test/http/TestHttpServer.java
@@ -0,0 +1,146 @@
+/*
+ * 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.http;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.net.Networking;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.HttpResponseInterceptor;
+import org.apache.http.impl.bootstrap.HttpServer;
+import org.apache.http.impl.bootstrap.ServerBootstrap;
+import org.apache.http.protocol.HttpProcessor;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.protocol.ImmutableHttpProcessor;
+import org.apache.http.protocol.ResponseConnControl;
+import org.apache.http.protocol.ResponseContent;
+
+public class TestHttpServer {
+    private static class HandlerTuple {
+        String path;
+        HttpRequestHandler handler;
+        public HandlerTuple(String path, HttpRequestHandler handler) {
+            this.path = path;
+            this.handler = handler;
+        }
+    }
+    private HttpServer server;
+    private List<HttpRequestInterceptor> requestInterceptors = MutableList.of();
+    private List<HttpResponseInterceptor> responseInterceptors = MutableList.of(new ResponseContent(), new ResponseConnControl());
+    private int basePort = 50505;
+    private Collection<HandlerTuple> handlers = MutableList.of();
+
+    public TestHttpServer interceptor(HttpResponseInterceptor interceptor) {
+        checkNotStarted();
+        responseInterceptors.add(interceptor);
+        return this;
+    }
+
+    public TestHttpServer requestInterceptors(List<HttpResponseInterceptor> interceptors) {
+        checkNotStarted();
+        this.responseInterceptors = interceptors;
+        return this;
+    }
+
+    public TestHttpServer interceptor(HttpRequestInterceptor interceptor) {
+        checkNotStarted();
+        requestInterceptors.add(interceptor);
+        return this;
+    }
+
+    public TestHttpServer responseInterceptors(List<HttpRequestInterceptor> interceptors) {
+        checkNotStarted();
+        this.requestInterceptors = interceptors;
+        return this;
+    }
+
+    public TestHttpServer basePort(int basePort) {
+        checkNotStarted();
+        this.basePort = basePort;
+        return this;
+    }
+
+    public TestHttpServer handler(String path, HttpRequestHandler handler) {
+        checkNotStarted();
+        handlers.add(new HandlerTuple(path, handler));
+        return this;
+    }
+
+    public TestHttpServer start() {
+        checkNotStarted();
+
+        HttpProcessor httpProcessor = new ImmutableHttpProcessor(requestInterceptors, responseInterceptors);
+        int port = Networking.nextAvailablePort(basePort);
+        ServerBootstrap bootstrap = ServerBootstrap.bootstrap()
+            .setListenerPort(port)
+            .setLocalAddress(getLocalAddress())
+            .setHttpProcessor(httpProcessor);
+
+        for (HandlerTuple tuple : handlers) {
+            bootstrap.registerHandler(tuple.path, tuple.handler);
+        }
+        server = bootstrap.create();
+
+        try {
+            server.start();
+        } catch (IOException e) {
+            throw Exceptions.propagate(e);
+        }
+
+        return this;
+    }
+
+    public void stop() {
+        if (null != server) {
+            server.stop();
+            server = null;
+        }
+    }
+
+    private void checkNotStarted() {
+        if (server != null) {
+            throw new IllegalStateException("Server already started");
+        }
+    }
+
+    private InetAddress getLocalAddress() {
+        try {
+            return InetAddress.getLocalHost();
+        } catch (UnknownHostException e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    public String getUrl() {
+        try {
+            return new URL("http", server.getInetAddress().getHostAddress(), server.getLocalPort(), "").toExternalForm();
+        } catch (MalformedURLException e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java
index 35d8252..0479b79 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/HttpAsserts.java
@@ -52,7 +52,7 @@ import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
 /**
- * Utility methods to aid testing HTTP.
+ * Utility assertions on HTTP.
  * 
  * @author aled
  */
@@ -63,31 +63,26 @@ public class HttpAsserts {
 
     private static final Logger LOG = LoggerFactory.getLogger(HttpAsserts.class);
 
+    /**
+     * Assert that a 'successful' (2xx) status code has been provided.
+     *
+     * @param code The status code.
+     */
     public static void assertHealthyStatusCode(int code) {
         if (code>=200 && code<=299) return;
         Asserts.fail("Wrong status code: " + code);
     }
     
-    public static int getHttpStatusCode(String url) throws Exception {
-        URLConnection connection = HttpTool.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
-        HttpTool.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.
+     *
+     * @param url The URL to connect to.
      */
     public static void assertUrlReachable(String url) {
         try {
-            getHttpStatusCode(url);
+            HttpTool.getHttpStatusCode(url);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             throw new RuntimeException("Interrupted for "+url+" (in assertion that is reachable)", e);
@@ -96,9 +91,15 @@ public class HttpAsserts {
         }
     }
 
+    /**
+     * Asserts that the URL could not be reached, detected as an IOException.
+     *
+     * @param url The URL to connect to.
+     */
+
     public static void assertUrlUnreachable(String url) {
         try {
-            int statusCode = getHttpStatusCode(url);
+            int statusCode = HttpTool.getHttpStatusCode(url);
             Asserts.fail("Expected url " + url + " unreachable, but got status code " + statusCode);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
@@ -108,30 +109,49 @@ public class HttpAsserts {
             if (cause != null) {
                 // success; clean shutdown transitioning from 400 to error
             } else {
-                Throwables.propagate(e);
+                propagateAsAssertionError(e);
             }                        
         }
     }
 
+    /**
+     * Asserts that the URL becomes unreachable within a default time period.
+     *
+     * @param url The URL
+     */
     public static void assertUrlUnreachableEventually(final String url) {
         assertUrlUnreachableEventually(Maps.newLinkedHashMap(), url);
     }
-    
+
+
+    /**
+     * Asserts that the URL becomes unreachable within a configurable time period.
+     *
+     * @param flags The flags controlling the timeout.
+     *              For details see {@link org.apache.brooklyn.test.Asserts#succeedsEventually(java.util.Map, java.util.concurrent.Callable)}
+     * @param url The URL
+     */
     public static void assertUrlUnreachableEventually(Map flags, final String url) {
-        Asserts.succeedsEventually(flags, new Runnable() {
+        assertEventually(flags, new Runnable() {
             public void run() {
                 assertUrlUnreachable(url);
             }
-         });
+        });
     }
 
+    /**
+     * Assert that the status code returned from the URL is in the given codes.
+     *
+     * @param url The URL to get.
+     * @param acceptableReturnCodes The return codes that are expected.
+     */
     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);
+            int actualCode = HttpTool.getHttpStatusCode(url);
             Asserts.assertTrue(acceptableCodes.contains(actualCode), "code=" + actualCode + "; expected=" + acceptableCodes + "; url=" + url);
             
         } catch (InterruptedException e) {
@@ -147,11 +167,11 @@ public class HttpAsserts {
     }
 
     public static void assertHttpStatusCodeEventuallyEquals(Map flags, final String url, final int expectedCode) {
-        Asserts.succeedsEventually(flags, new Runnable() {
+        assertEventually(flags, new Runnable() {
             public void run() {
                 assertHttpStatusCodeEquals(url, expectedCode);
             }
-         });
+        });
     }
 
     public static void assertContentContainsText(final String url, final String phrase, final String ...additionalPhrases) {
@@ -165,7 +185,7 @@ public class HttpAsserts {
                 }
             }
         } catch (Exception e) {
-            throw Throwables.propagate(e);
+            throw propagateAsAssertionError(e);
         }
     }
 
@@ -180,7 +200,7 @@ public class HttpAsserts {
                 }
             }
         } catch (Exception e) {
-            throw Throwables.propagate(e);
+            throw propagateAsAssertionError(e);
         }
     }
 
@@ -195,7 +215,7 @@ public class HttpAsserts {
                 }
             }
         } catch (Exception e) {
-            throw Throwables.propagate(e);
+            throw propagateAsAssertionError(e);
         }
     }
 
@@ -211,22 +231,43 @@ public class HttpAsserts {
                 }
             }
         } catch (Exception e) {
-            throw Throwables.propagate(e);
+            throw propagateAsAssertionError(e);
         }
     }
-    
+
+    private static AssertionError propagateAsAssertionError(Exception e) {
+        final AssertionError assertionError = new AssertionError("Assertion failed", e);
+        return assertionError;
+    }
+
     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() {
+        assertEventually(flags, new Runnable() {
             public void run() {
                 assertContentContainsText(url, phrase, additionalPhrases);
             }
-         });
+        });
     }
-    
+
+    private static void assertEventually(Map flags, Runnable r) {
+        try {
+            Asserts.succeedsEventually(flags, r);
+        } catch (Exception e) {
+            throw propagateAsAssertionError(e);
+        }
+    }
+
+    private static void assertEventually(Runnable r) {
+        try {
+            Asserts.succeedsEventually(r);
+        } catch (Exception e) {
+            throw propagateAsAssertionError(e);
+        }
+    }
+
     public static void assertContentMatches(String url, String regex) {
         String contents = HttpTool.getContent(url);
         Asserts.assertNotNull(contents);
@@ -234,7 +275,7 @@ public class HttpAsserts {
     }
 
     public static void assertContentEventuallyMatches(final String url, final String regex) {
-        Asserts.succeedsEventually(new Runnable() {
+        assertEventually(new Runnable() {
             @Override
             public void run() {
                 assertContentMatches(url, regex);
@@ -243,7 +284,7 @@ public class HttpAsserts {
     }
 
     public static void assertContentEventuallyMatches(Map<String,?> flags, final String url, final String regex) {
-        Asserts.succeedsEventually(flags, new Runnable() {
+        assertEventually(flags, new Runnable() {
             @Override
             public void run() {
                 assertContentMatches(url, regex);
@@ -266,6 +307,9 @@ public class HttpAsserts {
      * if (future.isDone()) future.get(); // get exception if it's Asserts.failed
      * }
      * </pre>
+     *
+     * NOTE that the exception thrown by future.get() is a java.util.concurrent.ExecutionException,
+     * not an AssertionError.
      * 
      * For stopping it, you can either do future.cancel(true), or you can just do executor.shutdownNow().
      * 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/885b6ac4/utils/common/src/test/java/org/apache/brooklyn/util/HttpAssertsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/HttpAssertsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/HttpAssertsTest.java
new file mode 100644
index 0000000..3b0c7c1
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/HttpAssertsTest.java
@@ -0,0 +1,293 @@
+/*
+ * 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.util;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.apache.brooklyn.test.http.TestHttpRequestHandler;
+import org.apache.brooklyn.test.http.TestHttpServer;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.http.HttpAsserts;
+import org.apache.brooklyn.util.http.HttpTool;
+import org.apache.brooklyn.util.http.HttpToolResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.HttpClient;
+import org.apache.http.localserver.RequestBasicAuth;
+import org.apache.http.localserver.ResponseBasicUnauthorized;
+import org.apache.http.protocol.ResponseServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.*;
+
+import java.net.URI;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by geoff on 03/11/2015.
+ */
+public class HttpAssertsTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HttpAssertsTest.class);
+    HttpClient httpClient;
+    URI baseUri;
+    private TestHttpServer server;
+    private String baseUrl;
+    private ScheduledExecutorService executor;
+
+
+    @BeforeMethod(alwaysRun = true)
+    public void setUp() throws Exception {
+        server = initializeServer();
+        baseUrl = server.getUrl();
+        httpClient = HttpTool.httpClientBuilder()
+            .uri(baseUrl)
+            .build();
+        baseUri = URI.create(baseUrl);
+        executor = Executors.newScheduledThreadPool(3);
+        TimeUnit.SECONDS.sleep(2);
+    }
+
+    private TestHttpServer initializeServer() {
+        return new TestHttpServer()
+            .interceptor(new ResponseServer())
+            .interceptor(new ResponseBasicUnauthorized())
+            .interceptor(new RequestBasicAuth())
+            .handler("/simple", new TestHttpRequestHandler().response("OK"))
+            .handler("/empty", new TestHttpRequestHandler().code(HttpStatus.SC_NO_CONTENT))
+            .handler("/missing", new TestHttpRequestHandler().code(HttpStatus.SC_NOT_FOUND).response("Missing"))
+            .handler("/redirect", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "/simple"))
+            .handler("/cycle", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "/cycle"))
+            .handler("/secure", new TestHttpRequestHandler().code(HttpStatus.SC_MOVED_TEMPORARILY).response("Redirect").header("Location", "https://0.0.0.0/"))
+            .start();
+    }
+
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() throws Exception {
+        if (executor != null) executor.shutdownNow();
+        server.stop();
+        TimeUnit.SECONDS.sleep(2);
+    }
+
+    // schedule a stop of server after n seconds
+    private void stopAfter(int delay) {
+        executor.schedule(new Runnable() {
+            @Override
+            public void run() {
+                server.stop();
+            }
+        }, delay, TimeUnit.SECONDS);
+    }
+
+    // stop server and pause to wait for it to finish
+    private void stopServer() {
+        server.stop();
+        try {
+            TimeUnit.SECONDS.sleep(2);
+        } catch (InterruptedException e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    // schedule a start of server after n seconds
+    private void startAfter(int delay) {
+        executor.schedule(new Runnable() {
+            @Override
+            public void run() {
+                server = initializeServer();
+            }
+        }, delay, TimeUnit.SECONDS);
+    }
+
+    private HttpToolResponse doGet(String str) {
+        final URI address = baseUri.resolve(str);
+        return HttpTool.httpGet(httpClient, address,
+            ImmutableMap.<String, String>of());
+    }
+
+    @Test
+    public void shouldAssertHealthyStatusCode() {
+        final HttpToolResponse response = doGet("/simple");
+        HttpAsserts.assertHealthyStatusCode(response.getResponseCode());
+    }
+
+    @Test
+    public void shouldAssertUrlReachable() {
+        HttpAsserts.assertUrlReachable(baseUrl);
+    }
+
+    @Test
+    public void shouldAssertUrlUnreachable() {
+        stopServer();
+        HttpAsserts.assertUrlUnreachable(testUri("/simple"));
+    }
+
+    @Test
+    public void shouldAssertUrlUnreachableEventually() {
+        HttpAsserts.assertUrlReachable(baseUrl);
+        stopAfter(1);
+        HttpAsserts.assertUrlUnreachableEventually(baseUrl);
+    }
+
+    @Test
+    public void shouldAssertUrlUnreachableEventuallyWithFlags() throws Exception {
+        stopAfter(5);
+        TimeUnit.SECONDS.sleep(3);
+        HttpAsserts.assertUrlReachable(baseUrl);
+        HttpAsserts.assertUrlUnreachableEventually(ImmutableMap.of("timeout", "10s"), baseUrl);
+    }
+
+    @Test(expectedExceptions = AssertionError.class)
+    public void shouldAssertUrlUnreachableEventuallyWithTimeout() throws Exception {
+        HttpAsserts.assertUrlReachable(baseUrl);
+        HttpAsserts.assertUrlUnreachableEventually(ImmutableMap.of("timeout", "3s"), baseUrl);
+    }
+
+
+    @Test
+    public void shouldAssertHttpStatusCodeEquals() {
+        HttpAsserts.assertHttpStatusCodeEquals(baseUrl, 500, 501);
+        HttpAsserts.assertHttpStatusCodeEquals(testUri("/simple"), 201, 200);
+        HttpAsserts.assertHttpStatusCodeEquals(testUri("/missing"), 400, 404);
+    }
+
+    @Test
+    public void shouldAssertHttpStatusCodeEventuallyEquals() throws Exception {
+        stopServer();
+        final String simple = testUri("/simple");
+        HttpAsserts.assertUrlUnreachable(simple);
+        startAfter(2);
+        HttpAsserts.assertHttpStatusCodeEventuallyEquals(simple, 200);
+    }
+
+    private String testUri(String str) {
+        return baseUri.resolve(str).toString();
+    }
+
+    @Test
+    public void shouldAssertContentContainsText() {
+        HttpAsserts.assertContentContainsText(testUri("/simple"), "OK");
+    }
+
+    @Test
+    public void shouldAssertContentNotContainsText() {
+        HttpAsserts.assertContentNotContainsText(testUri("/simple"), "Bad");
+    }
+
+    @Test
+    public void shouldAssertErrorContentsContainsText() {
+        HttpAsserts.assertErrorContentContainsText(testUri("/missing"), "Missing");
+    }
+
+    @Test
+    public void shouldAssertErrorContentNotContainsText() {
+        HttpAsserts.assertErrorContentNotContainsText(testUri("/missing"), "Bogus");
+    }
+
+    @Test
+    public void shouldAssertContentEventuallyContainsText() {
+        stopServer();
+        final String simple = testUri("/simple");
+        HttpAsserts.assertUrlUnreachable(simple);
+        startAfter(2);
+        HttpAsserts.assertContentEventuallyContainsText(simple, "OK");
+    }
+
+    @Test
+    public void shouldAssertContentEventuallyContainsTextWithFlags() {
+        stopServer();
+        final String simple = testUri("/simple");
+        HttpAsserts.assertUrlUnreachable(simple);
+        startAfter(2);
+        HttpAsserts.assertContentEventuallyContainsText(ImmutableMap.of("timeout", "3s"), simple, "OK");
+    }
+
+    @Test(expectedExceptions = AssertionError.class)
+    public void shouldAssertContentEventuallyContainsTextWithTimeout() {
+        stopServer();
+        final String simple = testUri("/simple");
+        HttpAsserts.assertUrlUnreachable(simple);
+        startAfter(4);
+        HttpAsserts.assertContentEventuallyContainsText(ImmutableMap.of("timeout", "3s"), simple, "OK");
+    }
+
+
+    @Test
+    public void shouldAssertContentMatches() {
+        HttpAsserts.assertContentMatches(testUri("/simple"), "[Oo][Kk]");
+    }
+
+    @Test
+    public void shouldAssertContentEventuallyMatches() throws Exception {
+        stopServer();
+        TimeUnit.SECONDS.sleep(2);
+        final String simple = testUri("/simple");
+        HttpAsserts.assertUrlUnreachable(simple);
+        TimeUnit.SECONDS.sleep(2);
+        startAfter(2);
+        HttpAsserts.assertContentEventuallyMatches(testUri("/simple"), "[Oo][Kk]");
+    }
+
+    @Test
+    public void shouldAssertContentEventuallyMatchesWithFlags() {
+        stopServer();
+        final String simple = testUri("/simple");
+        HttpAsserts.assertUrlUnreachable(simple);
+        startAfter(2);
+        HttpAsserts.assertContentEventuallyMatches(ImmutableMap.of("timeout", "3s"), testUri("/simple"), "[Oo][Kk]");
+    }
+
+    @Test(expectedExceptions = AssertionError.class)
+    public void shouldAssertContentEventuallyMatchesWithTimeout() {
+        stopServer();
+        final String simple = testUri("/simple");
+        HttpAsserts.assertUrlUnreachable(simple);
+        startAfter(4);
+        HttpAsserts.assertContentEventuallyMatches(ImmutableMap.of("timeout", "3s"), testUri("/simple"), "[Oo][Kk]");
+    }
+
+    @Test
+    public void shouldAssertAsyncHttpStatusCodeContinuallyEquals() throws Exception {
+        ListeningExecutorService listeningExecutor = MoreExecutors.listeningDecorator(executor);
+        final ListenableFuture<?> future =
+            HttpAsserts.assertAsyncHttpStatusCodeContinuallyEquals(listeningExecutor, testUri("/simple"), 200);
+        TimeUnit.SECONDS.sleep(3);
+        if (future.isDone()) {
+            future.get(); // should not throw exception
+        }
+        future.cancel(true);
+    }
+
+    @Test(expectedExceptions = ExecutionException.class)
+    public void shouldAssertAsyncHttpStatusCodeContinuallyEqualsFails() throws Exception {
+        ListeningExecutorService listeningExecutor = MoreExecutors.listeningDecorator(executor);
+        final ListenableFuture<?> future =
+            HttpAsserts.assertAsyncHttpStatusCodeContinuallyEquals(listeningExecutor, testUri("/missing"), 200);
+        TimeUnit.SECONDS.sleep(3);
+        if (future.isDone()) {
+            future.get(); // should throw exception
+        }
+        future.cancel(true);
+    }
+}