You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/08/12 17:55:22 UTC
[04/35] incubator-brooklyn git commit: [BROOKLYN-162] package rename
to org.apache.brooklyn: software/webapp
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterIntegrationTest.java
new file mode 100644
index 0000000..b004a8c
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterIntegrationTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.entity.webapp;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.test.HttpTestUtils;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.apache.brooklyn.test.entity.TestJavaWebAppEntity;
+import org.apache.brooklyn.entity.basic.RecordingSensorEventListener;
+import org.apache.brooklyn.entity.proxy.AbstractController;
+import org.apache.brooklyn.entity.proxy.LoadBalancer;
+import org.apache.brooklyn.entity.proxy.nginx.NginxController;
+import org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppLiveTestSupport;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.CollectionFunctionals;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class ControlledDynamicWebAppClusterIntegrationTest extends BrooklynAppLiveTestSupport {
+ private static final Logger log = LoggerFactory.getLogger(ControlledDynamicWebAppClusterIntegrationTest.class);
+
+ private static final int TIMEOUT_MS = 10*1000;
+
+ private LocalhostMachineProvisioningLocation loc;
+ private List<LocalhostMachineProvisioningLocation> locs;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+
+ loc = app.newLocalhostProvisioningLocation();
+ locs = ImmutableList.of(loc);
+ }
+
+ public String getTestWar() {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+ return "classpath://hello-world.war";
+ }
+
+ @Test(groups="Integration")
+ public void testPropogateHttpPorts() {
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 1));
+ app.start(locs);
+
+ EntityTestUtils.assertAttributeEventuallyNonNull(cluster, LoadBalancer.PROXY_HTTP_PORT);
+ EntityTestUtils.assertAttributeEventuallyNonNull(cluster, LoadBalancer.PROXY_HTTPS_PORT);
+ }
+
+ @Test(groups="Integration")
+ public void testConfiguresController() {
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 1)
+ .configure("memberSpec", EntitySpec.create(TomcatServer.class).configure("war", getTestWar())));
+ app.start(locs);
+
+ String url = cluster.getController().getAttribute(NginxController.ROOT_URL);
+ HttpTestUtils.assertHttpStatusCodeEventuallyEquals(url, 200);
+ HttpTestUtils.assertContentEventuallyContainsText(url, "Hello");
+ }
+
+ @Test(groups="Integration")
+ public void testSetsToplevelHostnameFromController() {
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 1)
+ .configure("memberSpec", EntitySpec.create(TomcatServer.class).configure("war", getTestWar())));
+ app.start(locs);
+
+ String expectedHostname = cluster.getController().getAttribute(LoadBalancer.HOSTNAME);
+ String expectedRootUrl = cluster.getController().getAttribute(LoadBalancer.ROOT_URL);
+ boolean expectedServiceUp = true;
+
+ assertNotNull(expectedHostname);
+ assertNotNull(expectedRootUrl);
+
+ EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), cluster, ControlledDynamicWebAppCluster.HOSTNAME, expectedHostname);
+ EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), cluster, ControlledDynamicWebAppCluster.ROOT_URL, expectedRootUrl);
+ EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), cluster, ControlledDynamicWebAppCluster.SERVICE_UP, expectedServiceUp);
+ }
+
+ @Test(groups="Integration")
+ public void testCustomWebClusterSpecGetsMemberSpec() {
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 1)
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TomcatServer.class)
+ .configure(TomcatServer.ROOT_WAR, getTestWar()))
+ .configure(ControlledDynamicWebAppCluster.WEB_CLUSTER_SPEC, EntitySpec.create(DynamicWebAppCluster.class)
+ .displayName("mydisplayname")));
+ app.start(locs);
+
+ String url = cluster.getController().getAttribute(NginxController.ROOT_URL);
+ HttpTestUtils.assertContentEventuallyContainsText(url, "Hello");
+
+ // and make sure it really was using our custom spec
+ assertEquals(cluster.getCluster().getDisplayName(), "mydisplayname");
+ }
+
+ // Needs to be integration test because still using nginx controller; could pass in mock controller
+ @Test(groups="Integration")
+ public void testSetsServiceLifecycle() {
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild( EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 1)
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) );
+
+ EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+
+ RecordingSensorEventListener<Lifecycle> listener = new RecordingSensorEventListener<Lifecycle>(true);
+ app.subscribe(cluster, Attributes.SERVICE_STATE_ACTUAL, listener);
+ app.start(locs);
+
+ Asserts.eventually(Suppliers.ofInstance(listener.getEventValues()), CollectionFunctionals.sizeEquals(2));
+ assertEquals(listener.getEventValues(), ImmutableList.of(Lifecycle.STARTING, Lifecycle.RUNNING), "vals="+listener.getEventValues());
+ listener.clearEvents();
+
+ app.stop();
+ EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+ Asserts.eventually(Suppliers.ofInstance(listener), CollectionFunctionals.sizeEquals(2));
+ assertEquals(listener.getEventValues(), ImmutableList.of(Lifecycle.STOPPING, Lifecycle.STOPPED), "vals="+listener.getEventValues());
+ }
+
+ @Test(groups="Integration")
+ public void testTomcatAbsoluteRedirect() {
+ final ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TomcatServer.class)
+ .configure(TomcatServer.ROOT_WAR, getTestWar()))
+ .configure("initialSize", 1)
+ .configure(AbstractController.SERVICE_UP_URL_PATH, "hello/redirectAbsolute")
+ );
+ app.start(locs);
+
+ final NginxController nginxController = (NginxController) cluster.getController();
+ Asserts.succeedsEventually(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return nginxController.getServerPoolAddresses().size() == 1;
+ }
+ });
+
+ Entity tomcatServer = Iterables.getOnlyElement(cluster.getCluster().getMembers());
+ EntityTestUtils.assertAttributeEqualsEventually(tomcatServer, Attributes.SERVICE_UP, true);
+
+ EntityTestUtils.assertAttributeEqualsContinually(nginxController, Attributes.SERVICE_UP, true);
+
+ app.stop();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java
new file mode 100644
index 0000000..30b66ba
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.entity.webapp;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+
+import org.apache.brooklyn.entity.proxy.AbstractController;
+import org.apache.brooklyn.entity.proxy.LoadBalancer;
+import org.apache.brooklyn.entity.proxy.TrackingAbstractController;
+import org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.jboss.JBoss7Server;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.apache.brooklyn.test.entity.TestJavaWebAppEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.entity.Group;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.BasicGroup;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.test.Asserts;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+public class ControlledDynamicWebAppClusterTest extends BrooklynAppUnitTestSupport {
+ private static final Logger log = LoggerFactory.getLogger(ControlledDynamicWebAppClusterTest.class);
+
+ private LocalhostMachineProvisioningLocation loc;
+ private List<LocalhostMachineProvisioningLocation> locs;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+
+ loc = app.newLocalhostProvisioningLocation();
+ locs = ImmutableList.of(loc);
+ }
+
+ public String getTestWar() {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+ return "classpath://hello-world.war";
+ }
+
+ @Test
+ public void testUsesCustomController() {
+ AbstractController controller = app.createAndManageChild(EntitySpec.create(TrackingAbstractController.class).displayName("mycustom"));
+
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 0)
+ .configure(ControlledDynamicWebAppCluster.CONTROLLER, controller)
+ .configure("memberSpec", EntitySpec.create(JBoss7Server.class).configure("war", getTestWar())));
+ app.start(locs);
+
+ EntityTestUtils.assertAttributeEqualsEventually(controller, AbstractController.SERVICE_UP, true);
+ assertEquals(cluster.getController(), controller);
+
+ // Stopping cluster should not stop controller (because it didn't create it)
+ cluster.stop();
+ EntityTestUtils.assertAttributeEquals(controller, AbstractController.SERVICE_UP, true);
+ }
+
+ @Test
+ public void testUsesCustomControlledGroup() {
+ TestJavaWebAppEntity webServer = app.createAndManageChild(EntitySpec.create(TestJavaWebAppEntity.class));
+ webServer.setAttribute(Attributes.SUBNET_HOSTNAME, "myhostname");
+ webServer.setAttribute(Attributes.HTTP_PORT, 1234);
+
+ TrackingAbstractController controller = app.createAndManageChild(EntitySpec.create(TrackingAbstractController.class));
+ Group controlledGroup = app.createAndManageChild(EntitySpec.create(BasicGroup.class));
+ controlledGroup.addMember(webServer);
+
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 0)
+ .configure(ControlledDynamicWebAppCluster.CONTROLLER, controller)
+ .configure(ControlledDynamicWebAppCluster.CONTROLLED_GROUP, controlledGroup)
+ .configure("memberSpec", EntitySpec.create(JBoss7Server.class).configure("war", getTestWar())));
+ app.start(locs);
+
+ assertEquals(controller.getUpdates(), ImmutableList.of(ImmutableSet.of("myhostname:1234")));
+ }
+
+ @Test
+ public void testUsesCustomControllerSpec() {
+ EntitySpec<TrackingAbstractController> controllerSpec = EntitySpec.create(TrackingAbstractController.class).displayName("mycustom");
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 0)
+ .configure(ControlledDynamicWebAppCluster.CONTROLLER_SPEC, controllerSpec)
+ .configure("memberSpec", EntitySpec.create(JBoss7Server.class).configure("war", getTestWar())));
+ app.start(locs);
+ LoadBalancer controller = cluster.getController();
+
+ EntityTestUtils.assertAttributeEqualsEventually(controller, AbstractController.SERVICE_UP, true);
+ assertEquals(controller.getDisplayName(), "mycustom");
+
+ // Stopping cluster should stop the controller (because it created it)
+ cluster.stop();
+ EntityTestUtils.assertAttributeEquals(controller, AbstractController.SERVICE_UP, false);
+ }
+
+ @Test
+ public void testTheTestJavaWebApp() {
+ SoftwareProcess n = app.createAndManageChild(EntitySpec.create(TestJavaWebAppEntity.class));
+ app.start(locs);
+
+ EntityTestUtils.assertAttributeEqualsEventually(n, AbstractController.SERVICE_UP, true);
+
+ app.stop();
+ EntityTestUtils.assertAttributeEqualsEventually(n, AbstractController.SERVICE_UP, false);
+ }
+
+ @Test
+ public void testSetsInitialSize() {
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 2)
+ .configure(ControlledDynamicWebAppCluster.CONTROLLER_SPEC, EntitySpec.create(TrackingAbstractController.class))
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) );
+ app.start(locs);
+
+ Iterable<TestJavaWebAppEntity> webservers = Iterables.filter(cluster.getCluster().getMembers(), TestJavaWebAppEntity.class);
+ assertEquals(Iterables.size(webservers), 2, "webservers="+webservers);
+ }
+
+ @Test
+ public void testUsesCustomWebClusterSpec() {
+ ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 0)
+ .configure(ControlledDynamicWebAppCluster.CONTROLLER_SPEC, EntitySpec.create(TrackingAbstractController.class))
+ .configure(ControlledDynamicWebAppCluster.WEB_CLUSTER_SPEC, EntitySpec.create(DynamicWebAppCluster.class)
+ .displayName("mydisplayname")));
+ app.start(locs);
+
+ assertEquals(cluster.getCluster().getDisplayName(), "mydisplayname");
+ }
+
+ @Test
+ public void testMembersReflectChildClusterMembers() {
+ final ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 1)
+ .configure(ControlledDynamicWebAppCluster.CONTROLLER_SPEC, EntitySpec.create(TrackingAbstractController.class))
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) );
+ app.start(locs);
+ final DynamicWebAppCluster childCluster = cluster.getCluster();
+
+ // Expect initial member(s) to be the same
+ assertEquals(childCluster.getMembers().size(), 1);
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ Asserts.assertEqualsIgnoringOrder(childCluster.getMembers(), cluster.getMembers());
+ }});
+
+ // After resize up, same members
+ cluster.resize(2);
+ assertEquals(childCluster.getMembers().size(), 2);
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ Asserts.assertEqualsIgnoringOrder(childCluster.getMembers(), cluster.getMembers());
+ }});
+
+ // After resize down, same members
+ cluster.resize(1);
+ assertEquals(childCluster.getMembers().size(), 1);
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ Asserts.assertEqualsIgnoringOrder(childCluster.getMembers(), cluster.getMembers());
+ }});
+ }
+
+ @Test
+ public void testStopOnChildUnmanaged() {
+ final ControlledDynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("initialSize", 1)
+ .configure(ControlledDynamicWebAppCluster.CONTROLLER_SPEC, EntitySpec.create(TrackingAbstractController.class))
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) );
+ app.start(locs);
+ final DynamicWebAppCluster childCluster = cluster.getCluster();
+ LoadBalancer controller = cluster.getController();
+
+ Entities.unmanage(childCluster);
+ Entities.unmanage(controller);
+
+ cluster.stop();
+ EntityTestUtils.assertAttributeEquals(cluster, ControlledDynamicWebAppCluster.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
new file mode 100644
index 0000000..ec063f4
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.entity.webapp;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.test.entity.TestJavaWebAppEntity;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.trait.Startable;
+import brooklyn.location.basic.SimulatedLocation;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public class DynamicWebAppClusterTest {
+
+ private static final int SHORT_WAIT_MS = 250;
+
+ private TestApplication app;
+ private SimulatedLocation loc;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ loc = app.newSimulatedLocation();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ }
+
+ @Test
+ public void testTestJavaWebAppEntityStarts() throws Exception {
+ Entity test = app.createAndManageChild(EntitySpec.create(TestJavaWebAppEntity.class));
+ test.invoke(Startable.START, ImmutableMap.of("locations", ImmutableList.of(loc))).get();
+
+ EntityTestUtils.assertAttributeEqualsEventually(test, Attributes.SERVICE_UP, true);
+ }
+
+ @Test
+ public void testRequestCountAggregation() throws Exception {
+ final DynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicWebAppCluster.class)
+ .configure("initialSize", 2)
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) );
+
+ app.start(ImmutableList.of(loc));
+
+ for (Entity member : cluster.getMembers()) {
+ ((TestJavaWebAppEntity)member).spoofRequest();
+ }
+ EntityTestUtils.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.REQUEST_COUNT, 2);
+
+ for (Entity member : cluster.getMembers()) {
+ for (int i = 0; i < 2; i++) {
+ ((TestJavaWebAppEntity)member).spoofRequest();
+ }
+ }
+ EntityTestUtils.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.REQUEST_COUNT_PER_NODE, 3d);
+ }
+
+ @Test
+ public void testSetsServiceUpIfMemberIsUp() throws Exception {
+ DynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicWebAppCluster.class)
+ .configure("initialSize", 1)
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) );
+
+ app.start(ImmutableList.of(loc));
+
+ // Should initially be true (now that TestJavaWebAppEntity sets true)
+ EntityTestUtils.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.SERVICE_UP, true);
+
+ // When child is !service_up, should report false
+ ((EntityLocal)Iterables.get(cluster.getMembers(), 0)).setAttribute(Startable.SERVICE_UP, false);
+ EntityTestUtils.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.SERVICE_UP, false);
+ EntityTestUtils.assertAttributeEqualsContinually(MutableMap.of("timeout", SHORT_WAIT_MS), cluster, DynamicWebAppCluster.SERVICE_UP, false);
+
+ cluster.resize(2);
+
+ // When one of the two children is service_up, should report true
+ EntityTestUtils.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.SERVICE_UP, true);
+
+ // And if that serviceUp child goes away, should again report false
+ Entities.unmanage(Iterables.get(cluster.getMembers(), 1));
+ ((EntityLocal)Iterables.get(cluster.getMembers(), 0)).setAttribute(Startable.SERVICE_UP, false);
+
+ EntityTestUtils.assertAttributeEqualsEventually(cluster, DynamicWebAppCluster.SERVICE_UP, false);
+ }
+
+ @Test
+ public void testPropertiesToChildren() throws Exception {
+ DynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicWebAppCluster.class)
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)
+ .configure("a", 1))
+ .configure(DynamicWebAppCluster.CUSTOM_CHILD_FLAGS, ImmutableMap.of("b", 2)));
+
+ app.start(ImmutableList.of(loc));
+
+ TestJavaWebAppEntity we = (TestJavaWebAppEntity) Iterables.getOnlyElement(cluster.getMembers());
+ assertEquals(we.getA(), 1);
+ assertEquals(we.getB(), 2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppFabricTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppFabricTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppFabricTest.java
new file mode 100644
index 0000000..63954e8
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/DynamicWebAppFabricTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.entity.webapp;
+
+import java.util.List;
+
+import org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.DynamicWebAppFabric;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.test.entity.TestJavaWebAppEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.DynamicGroup;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.trait.Changeable;
+import brooklyn.location.basic.SimulatedLocation;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * TODO clarify test purpose
+ */
+public class DynamicWebAppFabricTest {
+ private static final Logger log = LoggerFactory.getLogger(DynamicWebAppFabricTest.class);
+
+ private static final long TIMEOUT_MS = 10*1000;
+
+ private TestApplication app;
+ private SimulatedLocation loc1;
+ private SimulatedLocation loc2;
+ private List<SimulatedLocation> locs;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ loc1 = app.newSimulatedLocation();
+ loc2 = app.newSimulatedLocation();
+ locs = ImmutableList.of(loc1, loc2);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ }
+
+ @Test
+ public void testRequestCountAggregation() {
+ DynamicWebAppFabric fabric = app.createAndManageChild(EntitySpec.create(DynamicWebAppFabric.class)
+ .configure(DynamicWebAppFabric.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) );
+
+ app.start(locs);
+ for (Entity member : fabric.getChildren()) {
+ ((EntityLocal)member).setAttribute(Changeable.GROUP_SIZE, 1);
+ }
+
+ for (Entity member : fabric.getChildren()) {
+ ((EntityInternal)member).setAttribute(DynamicGroup.GROUP_SIZE, 1);
+ ((TestJavaWebAppEntity)member).spoofRequest();
+ }
+ EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), fabric, DynamicWebAppFabric.REQUEST_COUNT, 2);
+
+ // Note this is time-sensitive: need to do the next two sends before the previous one has dropped out
+ // of the time-window.
+ for (Entity member : fabric.getChildren()) {
+ for (int i = 0; i < 2; i++) {
+ ((TestJavaWebAppEntity)member).spoofRequest();
+ }
+ }
+ EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), fabric, DynamicWebAppFabric.REQUEST_COUNT_PER_NODE, 3d);
+ }
+
+ @Test
+ public void testRequestCountAggregationOverClusters() {
+ DynamicWebAppFabric fabric = app.createAndManageChild(EntitySpec.create(DynamicWebAppFabric.class)
+ .configure(DynamicWebAppFabric.MEMBER_SPEC,
+ EntitySpec.create(DynamicWebAppCluster.class)
+ .configure("initialSize", 2)
+ .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) ));
+
+ app.start(locs);
+
+ for (Entity cluster : fabric.getChildren()) {
+ for (Entity node : ((DynamicWebAppCluster)cluster).getMembers()) {
+ ((TestJavaWebAppEntity)node).spoofRequest();
+ }
+ }
+ EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), fabric, DynamicWebAppFabric.REQUEST_COUNT, 4);
+
+ // Note this is time-sensitive: need to do the next two sends before the previous one has dropped out
+ // of the time-window.
+ for (Entity cluster : fabric.getChildren()) {
+ for (Entity node : ((DynamicWebAppCluster)cluster).getMembers()) {
+ for (int i = 0; i < 2; i++) {
+ ((TestJavaWebAppEntity)node).spoofRequest();
+ }
+ }
+ }
+ EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), fabric, DynamicWebAppFabric.REQUEST_COUNT_PER_NODE, 3d);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ElasticCustomLocationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ElasticCustomLocationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ElasticCustomLocationTest.java
new file mode 100644
index 0000000..7a13ac2
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ElasticCustomLocationTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.entity.webapp;
+
+import java.util.Map;
+
+import org.apache.brooklyn.entity.webapp.ElasticJavaWebAppService;
+import org.apache.brooklyn.entity.webapp.ElasticJavaWebAppService.ElasticJavaWebAppServiceAwareLocation;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.BasicConfigurableEntityFactory;
+import brooklyn.entity.basic.ConfigurableEntityFactory;
+import brooklyn.entity.basic.Entities;
+import brooklyn.location.basic.SimulatedLocation;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestEntityImpl;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+
+public class ElasticCustomLocationTest {
+
+ public static class MockWebServiceLocation extends SimulatedLocation implements ElasticJavaWebAppServiceAwareLocation {
+ public MockWebServiceLocation() {
+ }
+
+ @Override
+ public ConfigurableEntityFactory<ElasticJavaWebAppService> newWebClusterFactory() {
+ return new BasicConfigurableEntityFactory(MockWebService.class);
+ }
+ }
+
+ public static class MockWebService extends TestEntityImpl implements ElasticJavaWebAppService {
+ public MockWebService() {
+ }
+ // TODO Used by asicConfigurableEntityFactory.newEntity2, via MockWebServiceLocation.newWebClusterFactory
+ public MockWebService(Map flags, Entity parent) {
+ super(flags, parent);
+ }
+ }
+
+ private TestApplication app;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ app = ApplicationBuilder.newManagedApp(TestApplication.class);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ }
+
+ @Test
+ public void testElasticClusterCreatesTestEntity() {
+ MockWebServiceLocation l = new MockWebServiceLocation();
+ app.setConfig(MockWebService.ROOT_WAR, "WAR0");
+ app.setConfig(MockWebService.NAMED_WARS, ImmutableList.of("ignore://WARn"));
+
+ ElasticJavaWebAppService svc =
+ new ElasticJavaWebAppService.Factory().newFactoryForLocation(l).newEntity(MutableMap.of("war", "WAR1"), app);
+ Entities.manage(svc);
+
+ Assert.assertTrue(svc instanceof MockWebService, "expected MockWebService, got "+svc);
+ //check config has been set correctly, where overridden, and where inherited
+ Assert.assertEquals(svc.getConfig(MockWebService.ROOT_WAR), "WAR1");
+ Assert.assertEquals(svc.getConfig(MockWebService.NAMED_WARS), ImmutableList.of("ignore://WARn"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ElasticJavaWebAppServiceIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ElasticJavaWebAppServiceIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ElasticJavaWebAppServiceIntegrationTest.java
new file mode 100644
index 0000000..93859a2
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/ElasticJavaWebAppServiceIntegrationTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.entity.webapp;
+
+import org.apache.brooklyn.entity.webapp.ElasticJavaWebAppService;
+import org.apache.brooklyn.test.HttpTestUtils;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+
+public class ElasticJavaWebAppServiceIntegrationTest {
+
+ private LocalhostMachineProvisioningLocation loc;
+ private TestApplication app;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ loc = app.newLocalhostProvisioningLocation();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ }
+
+ public String getTestWar() {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+ return "classpath://hello-world.war";
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test(groups = "Integration")
+ // TODO a new approach to what ElasticJavaWebAppService.Factory does, giving a different entity depending on location!
+ public void testLegacyFactory() {
+ ElasticJavaWebAppService svc =
+ new ElasticJavaWebAppService.Factory().newEntity(MutableMap.of("war", getTestWar()), app);
+ Entities.manage(svc);
+ app.start(ImmutableList.of(loc));
+
+ String url = svc.getAttribute(ElasticJavaWebAppService.ROOT_URL);
+ Assert.assertNotNull(url);
+ HttpTestUtils.assertContentEventuallyContainsText(url, "Hello");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/FilenameToWebContextMapperTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/FilenameToWebContextMapperTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/FilenameToWebContextMapperTest.java
new file mode 100644
index 0000000..e49cf12
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/FilenameToWebContextMapperTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.entity.webapp;
+
+import org.apache.brooklyn.entity.webapp.FilenameToWebContextMapper;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test
+public class FilenameToWebContextMapperTest {
+
+// * either ROOT.WAR or / denotes root context
+// * <p>
+// * anything of form FOO.?AR (ending .?AR) is copied with that name (unless copying not necessary)
+// * and is expected to be served from /FOO
+// * <p>
+// * anything of form /FOO (with leading slash) is expected to be served from /FOO
+// * (and is copied as FOO.WAR)
+// * <p>
+// * anything of form FOO (without a dot) is expected to be served from /FOO
+// * (and is copied as FOO.WAR)
+// * <p>
+// * otherwise <i>please note</i> behaviour may vary on different appservers;
+// * e.g. FOO.FOO would probably be ignored on appservers which expect a file copied across (usually),
+// * but served as /FOO.FOO on systems that take a deployment context.
+
+ FilenameToWebContextMapper m = new FilenameToWebContextMapper();
+
+ private void assertMapping(String input, String context, String filename) {
+ Assert.assertEquals(m.convertDeploymentTargetNameToContext(input), context);
+ Assert.assertEquals(m.convertDeploymentTargetNameToFilename(input), filename);
+ }
+
+ public void testRootNames() {
+ assertMapping("/", "/", "ROOT.war");
+ assertMapping("ROOT.war", "/", "ROOT.war");
+
+ //bad ones -- some of these aren't invertible
+ assertMapping("/ROOT.war", "/ROOT.war", "ROOT.war.war");
+ assertMapping("/ROOT", "/ROOT", "ROOT.war");
+
+ //and leave empty string alone (will cause subsequent error)
+ assertMapping("", "", "");
+ }
+
+ public void testOtherNames() {
+ assertMapping("/foo", "/foo", "foo.war");
+ assertMapping("/foo.foo", "/foo.foo", "foo.foo.war");
+ assertMapping("foo.war", "/foo", "foo.war");
+ assertMapping("foo.Ear", "/foo", "foo.Ear");
+ assertMapping("foo", "/foo", "foo.war");
+
+ //bad ones -- some of these aren't invertible
+ assertMapping("foo.foo", "/foo.foo", "foo.foo");
+ }
+
+ public void testInferFromUrl() {
+ Assert.assertEquals(m.findArchiveNameFromUrl("http//localhost/simple.war", false), "simple.war");
+ Assert.assertEquals(m.findArchiveNameFromUrl("http//localhost/simple.Ear?type=raw", false), "simple.Ear");
+ Assert.assertEquals(m.findArchiveNameFromUrl("http//localhost/simple.war?type=raw*other=sample.war", false), "simple.war");
+ Assert.assertEquals(m.findArchiveNameFromUrl("http//localhost/get?file=simple.war", false), "simple.war");
+ Assert.assertEquals(m.findArchiveNameFromUrl("http//localhost/get?file=simple.war&other=ignore", false), "simple.war");
+ //takes the first (but logs warning in verbose mode)
+ Assert.assertEquals(m.findArchiveNameFromUrl("http//localhost/get?file=simple.war&other=sample.war", false), "simple.war");
+ //allows hyphen
+ Assert.assertEquals(m.findArchiveNameFromUrl("http//localhost/get?file=simple-simon.war&other=sample", false), "simple-simon.war");
+ Assert.assertEquals(m.findArchiveNameFromUrl("http//localhost/get?file=simple\\simon.war&other=sample", false), "simon.war");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java
new file mode 100644
index 0000000..d21c0d9
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/HttpsSslConfigTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.entity.webapp;
+
+import org.apache.brooklyn.entity.webapp.HttpsSslConfig;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.flags.TypeCoercions;
+
+public class HttpsSslConfigTest {
+
+ @Test
+ public void testCoerce() {
+ HttpsSslConfig config = TypeCoercions.coerce(MutableMap.of("keystoreUrl", "http://foo", "keystorePassword", "b4r", "keyAlias", "baz"),
+ HttpsSslConfig.class);
+ Assert.assertEquals(config.getKeystoreUrl(), "http://foo");
+ Assert.assertEquals(config.getKeystorePassword(), "b4r");
+ Assert.assertEquals(config.getKeyAlias(), "baz");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/TomcatAutoScalerPolicyTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/TomcatAutoScalerPolicyTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/TomcatAutoScalerPolicyTest.java
new file mode 100644
index 0000000..2158d2d
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/TomcatAutoScalerPolicyTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.entity.webapp;
+
+import static org.apache.brooklyn.test.HttpTestUtils.connectToUrl;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
+import org.apache.brooklyn.entity.webapp.tomcat.TomcatServerImpl;
+import org.apache.brooklyn.management.ManagementContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.LocationSpec;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.policy.autoscaling.AutoScalerPolicy;
+import brooklyn.test.Asserts;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class TomcatAutoScalerPolicyTest {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = LoggerFactory.getLogger(TomcatAutoScalerPolicyTest.class);
+
+ // TODO Test is time-sensitive: we send two web-requests in rapid succession, and expect the average workrate to
+ // be 2 msgs/sec; we then expect resizing to kick-in.
+ // P speculate that... if for some reason things are running slow (e.g. GC during that one second), then brooklyn
+ // may not report the 2 msgs/sec.
+
+ private LocalhostMachineProvisioningLocation loc;
+ private TestApplication app;
+ private ManagementContext managementContext;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ managementContext = app.getManagementContext();
+ loc = managementContext.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class)
+ .configure("name", "london"));
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ }
+
+ @Test(groups="Integration")
+ public void testWithTomcatServers() throws Exception {
+ /*
+ * One DynamicWebAppClster with auto-scaler policy
+ * AutoScaler listening to DynamicWebAppCluster.TOTAL_REQS
+ * AutoScaler minSize 1
+ * AutoScaler upper metric 1
+ * AutoScaler lower metric 0
+ * .. send one request
+ * wait til auto-scaling complete
+ * assert cluster size 2
+ */
+
+ final DynamicWebAppCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicWebAppCluster.class)
+ .configure(DynamicWebAppCluster.INITIAL_SIZE, 1)
+ .configure(DynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TomcatServer.class)));
+
+ final AutoScalerPolicy policy = AutoScalerPolicy.builder()
+ .metric(DynamicWebAppCluster.REQUEST_COUNT_PER_NODE)
+ .metricRange(0, 1)
+ .minPoolSize(1)
+ .build();
+ cluster.addPolicy(policy);
+
+ app.start(ImmutableList.of(loc));
+
+ assertEquals(cluster.getCurrentSize(), (Integer)1);
+
+ // Scaling based on *total requests* processed, rather than the requests per second.
+ // So just hit it with 2 requests.
+ // Alternatively could hit each tomcat server's URL twice per second; but that's less deterministic.
+ TomcatServer tc = (TomcatServer) Iterables.getOnlyElement(cluster.getMembers());
+ for (int i = 0; i < 2; i++) {
+ connectToUrl(tc.getAttribute(TomcatServerImpl.ROOT_URL));
+ }
+
+ // We'll scale to two members as soon as the policy detects it.
+ // But the second member won't count in the requests-per-node until it has started up.
+ // Expect to see (if we polled at convenient times):
+ // - zero requests per node (because haven't yet retrieved over JMX the metric)
+ // - two requests per node, with one member
+ // - two requests per node, with two members (one of whom is still starting up, so doesn't count)
+ // - one request per node (i.e. two divided across the two active members)
+ Asserts.succeedsEventually(MutableMap.of("timeout", 5*60*1000), new Runnable() {
+ @Override public void run() {
+ String err = "policy="+policy.isRunning()+"; size="+cluster.getCurrentSize()+"; reqCountPerNode="+cluster.getAttribute(DynamicWebAppCluster.REQUEST_COUNT_PER_NODE);
+ assertTrue(policy.isRunning(), "err="+err);
+ assertEquals(cluster.getCurrentSize(), (Integer)2, "err="+err);
+ assertEquals(cluster.getAttribute(DynamicWebAppCluster.REQUEST_COUNT_PER_NODE), 1.0d, "err="+err);
+ }});
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java
new file mode 100644
index 0000000..5b64cb6
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppConcurrentDeployTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.entity.webapp;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+import java.util.Collection;
+
+import org.apache.http.client.HttpClient;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.BrooklynConfigKeys;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.Location;
+import brooklyn.location.LocationSpec;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.test.Asserts;
+
+import org.apache.brooklyn.entity.webapp.JavaWebAppSoftwareProcess;
+import org.apache.brooklyn.entity.webapp.jboss.JBoss7Server;
+import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
+import org.apache.brooklyn.management.Task;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class WebAppConcurrentDeployTest extends BrooklynAppUnitTestSupport {
+ private Location loc;
+
+ @Override
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+ app.config().set(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, false);
+// tested on loc = mgmt.getLocationRegistry().resolve("byon:(hosts=\"hostname\")");
+ loc = mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachineProvisioningLocation.class));
+ }
+
+ @DataProvider(name = "basicEntities")
+ public Object[][] basicEntities() {
+ return new Object[][]{
+ {EntitySpec.create(TomcatServer.class)},
+ // Hot Deploy not enabled?
+ // {EntitySpec.create(JBoss6Server.class)},
+ {EntitySpec.create(JBoss7Server.class)},
+ };
+ }
+
+ @Test(groups = "Live", dataProvider="basicEntities")
+ public void testConcurrentDeploys(EntitySpec<? extends JavaWebAppSoftwareProcess> webServerSpec) throws Exception {
+ JavaWebAppSoftwareProcess server = app.createAndManageChild(webServerSpec);
+ app.start(ImmutableList.of(loc));
+ EntityTestUtils.assertAttributeEqualsEventually(server, Attributes.SERVICE_UP, Boolean.TRUE);
+ Collection<Task<Void>> deploys = MutableList.of();
+ for (int i = 0; i < 5; i++) {
+ deploys.add(server.invoke(TomcatServer.DEPLOY, MutableMap.of("url", getTestWar(), "targetName", "/")));
+ }
+ for(Task<Void> t : deploys) {
+ t.getUnchecked();
+ }
+
+ final HttpClient client = HttpTool.httpClientBuilder().build();
+ final URI warUrl = URI.create(server.getAttribute(JavaWebAppSoftwareProcess.ROOT_URL));
+ Asserts.succeedsEventually(new Runnable() {
+ @Override
+ public void run() {
+ HttpToolResponse resp = HttpTool.httpGet(client, warUrl, ImmutableMap.<String,String>of());
+ assertEquals(resp.getResponseCode(), 200);
+ }
+ });
+ }
+
+ public String getTestWar() {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+ return "classpath://hello-world.war";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppLiveIntegrationTest.groovy
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppLiveIntegrationTest.groovy b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppLiveIntegrationTest.groovy
new file mode 100644
index 0000000..db16cbd
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/WebAppLiveIntegrationTest.groovy
@@ -0,0 +1,115 @@
+/*
+ * 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.entity.webapp
+
+import static brooklyn.entity.basic.ConfigKeys.*
+import static org.apache.brooklyn.entity.webapp.jboss.JBoss6Server.*
+import static org.apache.brooklyn.test.TestUtils.*
+import static java.util.concurrent.TimeUnit.*
+import static org.testng.Assert.*
+
+import java.util.concurrent.TimeUnit
+
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.testng.annotations.AfterMethod
+import org.testng.annotations.BeforeMethod
+import org.testng.annotations.DataProvider
+import org.testng.annotations.Test
+
+import brooklyn.config.BrooklynProperties
+import brooklyn.entity.Application
+import brooklyn.entity.basic.SoftwareProcess
+import brooklyn.entity.basic.Entities
+import brooklyn.entity.trait.Startable
+import org.apache.brooklyn.entity.webapp.jboss.JBoss6Server
+import org.apache.brooklyn.entity.webapp.jboss.JBoss6ServerImpl
+import org.apache.brooklyn.entity.webapp.jboss.JBoss7Server
+import org.apache.brooklyn.entity.webapp.jboss.JBoss7ServerImpl
+import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer
+import org.apache.brooklyn.entity.webapp.tomcat.TomcatServerImpl
+import brooklyn.location.Location
+import brooklyn.location.basic.BasicLocationRegistry
+import org.apache.brooklyn.test.TestUtils
+import brooklyn.test.entity.TestApplicationImpl
+import brooklyn.util.internal.TimeExtras
+
+/**
+ * This tests that we can run jboss entity on AWS.
+ */
+public class WebAppLiveIntegrationTest {
+ private static final Logger logger = LoggerFactory.getLogger(WebAppLiveIntegrationTest.class)
+
+ static { TimeExtras.init() }
+
+ public static final int DEFAULT_HTTP_PORT = 8080
+ public static final int DEFAULT_JMX_PORT = 32199
+
+ // Port increment for JBoss 6.
+ public static final int PORT_INCREMENT = 400
+
+ // The parent application entity for these tests
+ Application application = new TestApplicationImpl()
+
+ Location loc
+
+ /**
+ * Provides instances of {@link TomcatServer}, {@link JBoss6Server} and {@link JBoss7Server} to the tests below.
+ *
+ * TODO combine the data provider here with the integration tests
+ *
+ * @see WebAppIntegrationTest#basicEntities()
+ */
+ @DataProvider(name = "basicEntities")
+ public Object[][] basicEntities() {
+ TomcatServer tomcat = new TomcatServerImpl(parent:application, httpPort:DEFAULT_HTTP_PORT, jmxPort:DEFAULT_JMX_PORT)
+ JBoss6Server jboss6 = new JBoss6ServerImpl(parent:application, portIncrement:PORT_INCREMENT, jmxPort:DEFAULT_JMX_PORT)
+ JBoss7Server jboss7 = new JBoss7ServerImpl(parent:application, httpPort:DEFAULT_HTTP_PORT, jmxPort:DEFAULT_JMX_PORT)
+ return [ [ tomcat ], [ jboss6 ], [ jboss7 ] ]
+ }
+
+ private File getResource(String path) {
+ return TestUtils.getResource(path, getClass().getClassLoader());
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() {
+ Entities.manage(application)
+
+ BrooklynProperties props = BrooklynProperties.Factory.newDefault()
+ props.put("brooklyn.location.jclouds.aws-ec2.imagel-id", "us-east-1/ami-2342a94a")
+ props.put("brooklyn.location.jclouds.aws-ec2.image-owner", "411009282317")
+
+ loc = new BasicLocationRegistry(props).resolve("aws-ec2:us-east-1")
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void shutdown() {
+ if (application != null) Entities.destroyAll(application.getManagementContext());
+ }
+
+ @Test(groups = "Live", dataProvider="basicEntities")
+ public void testStartsWebAppInAws(final SoftwareProcess entity) {
+ entity.start([ loc ])
+ executeUntilSucceedsWithShutdown(entity, abortOnError:false, timeout:75*SECONDS, useGroovyTruth:true) {
+ assertTrue(entity.getAttribute(Startable.SERVICE_UP))
+ true
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java
new file mode 100644
index 0000000..59232e6
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.entity.webapp.jboss;
+
+import static org.apache.brooklyn.test.EntityTestUtils.assertAttributeEqualsEventually;
+import static org.apache.brooklyn.test.HttpTestUtils.assertHttpStatusCodeEquals;
+import static org.apache.brooklyn.test.HttpTestUtils.assertHttpStatusCodeEventuallyEquals;
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.brooklyn.entity.proxy.nginx.NginxController;
+import org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.jboss.JBoss7Server;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.apache.brooklyn.test.WebAppMonitor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.internal.TimeExtras;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+
+public class ControlledDynamicWebAppClusterRebindIntegrationTest {
+ private static final Logger LOG = LoggerFactory.getLogger(ControlledDynamicWebAppClusterRebindIntegrationTest.class);
+
+ static { TimeExtras.init(); }
+
+ private LocalhostMachineProvisioningLocation localhostProvisioningLocation;
+ private TestApplication origApp;
+ private TestApplication newApp;
+ private List<WebAppMonitor> webAppMonitors = new CopyOnWriteArrayList<WebAppMonitor>();
+ private ExecutorService executor;
+
+ private ClassLoader classLoader = getClass().getClassLoader();
+ private LocalManagementContext origManagementContext;
+ private File mementoDir;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() {
+ executor = Executors.newCachedThreadPool();
+
+ mementoDir = Files.createTempDir();
+ LOG.info("Test persisting to "+mementoDir);
+ origManagementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader);
+
+ localhostProvisioningLocation = new LocalhostMachineProvisioningLocation();
+ origApp = ApplicationBuilder.newManagedApp(TestApplication.class, origManagementContext);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ for (WebAppMonitor monitor : webAppMonitors) {
+ monitor.terminate();
+ }
+ if (executor != null) executor.shutdownNow();
+ if (newApp != null) Entities.destroyAll(newApp.getManagementContext());
+ if (origApp != null) Entities.destroyAll(origApp.getManagementContext());
+ if (mementoDir != null) RebindTestUtils.deleteMementoDir(mementoDir);
+ }
+
+ public String getTestWar() {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+ return "classpath://hello-world.war";
+ }
+
+ private TestApplication rebind() throws Exception {
+ RebindTestUtils.waitForPersisted(origApp);
+
+ // Stop the old management context, so original nginx won't interfere
+ origManagementContext.terminate();
+
+ return (TestApplication) RebindTestUtils.rebind(mementoDir, getClass().getClassLoader());
+ }
+
+ private WebAppMonitor newWebAppMonitor(String url) {
+ WebAppMonitor monitor = new WebAppMonitor(url)
+// .delayMillis(0)
+ .logFailures(LOG);
+ webAppMonitors.add(monitor);
+ executor.execute(monitor);
+ return monitor;
+ }
+
+ @Test(groups = {"Integration"})
+ public void testRebindsToRunningCluster() throws Exception {
+ NginxController origNginx = origApp.createAndManageChild(EntitySpec.create(NginxController.class).configure("domain", "localhost"));
+
+ origApp.createAndManageChild(EntitySpec.create(ControlledDynamicWebAppCluster.class)
+ .configure("memberSpec", EntitySpec.create(JBoss7Server.class).configure("war", getTestWar()))
+ .configure("initialSize", 1)
+ .configure("controller", origNginx));
+
+ origApp.start(ImmutableList.of(localhostProvisioningLocation));
+ String rootUrl = origNginx.getAttribute(JBoss7Server.ROOT_URL);
+
+ assertHttpStatusCodeEventuallyEquals(rootUrl, 200);
+ WebAppMonitor monitor = newWebAppMonitor(rootUrl);
+
+ // Rebind
+ newApp = rebind();
+ NginxController newNginx = (NginxController) Iterables.find(newApp.getChildren(), Predicates.instanceOf(NginxController.class));
+ ControlledDynamicWebAppCluster newCluster = (ControlledDynamicWebAppCluster) Iterables.find(newApp.getChildren(), Predicates.instanceOf(ControlledDynamicWebAppCluster.class));
+
+ assertAttributeEqualsEventually(newNginx, SoftwareProcess.SERVICE_UP, true);
+ assertHttpStatusCodeEquals(rootUrl, 200);
+
+ // Confirm the cluster is usable: we can scale-up
+ assertEquals(newCluster.getCurrentSize(), (Integer)1);
+ newCluster.resize(2);
+
+ Iterable<Entity> newJbosses = Iterables.filter(newCluster.getCluster().getChildren(), Predicates.instanceOf(JBoss7Server.class));
+ assertEquals(Iterables.size(newJbosses), 2);
+
+ Thread.sleep(1000);
+ for (int i = 0; i < 10; i++) {
+ assertHttpStatusCodeEquals(rootUrl, 200);
+ }
+
+ // Ensure while doing all of this the original jboss server remained reachable
+ assertEquals(monitor.getFailures(), 0);
+
+ // Ensure cluster is usable: we can scale back to stop the original jboss server
+ newCluster.resize(0);
+
+ assertHttpStatusCodeEventuallyEquals(rootUrl, 404);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java
new file mode 100644
index 0000000..30c0068
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.entity.webapp.jboss;
+
+import static org.apache.brooklyn.test.HttpTestUtils.assertHttpStatusCodeEquals;
+import static org.apache.brooklyn.test.HttpTestUtils.assertHttpStatusCodeEventuallyEquals;
+import static org.apache.brooklyn.test.HttpTestUtils.assertUrlUnreachableEventually;
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+import java.net.URL;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
+import org.apache.brooklyn.entity.webapp.jboss.JBoss7Server;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.apache.brooklyn.test.WebAppMonitor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.collections.MutableMap;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+
+public class DynamicWebAppClusterRebindIntegrationTest {
+ private static final Logger LOG = LoggerFactory.getLogger(DynamicWebAppClusterRebindIntegrationTest.class);
+
+ private LocalhostMachineProvisioningLocation localhostProvisioningLocation;
+ private TestApplication origApp;
+ private TestApplication newApp;
+ private List<WebAppMonitor> webAppMonitors = new CopyOnWriteArrayList<WebAppMonitor>();
+ private ExecutorService executor;
+
+ private ClassLoader classLoader = getClass().getClassLoader();
+ private LocalManagementContext origManagementContext;
+ private File mementoDir;
+
+ @BeforeMethod(groups = "Integration")
+ public void setUp() {
+ executor = Executors.newCachedThreadPool();
+
+ mementoDir = Files.createTempDir();
+ origManagementContext = RebindTestUtils.newPersistingManagementContext(mementoDir, classLoader);
+
+ localhostProvisioningLocation = new LocalhostMachineProvisioningLocation();
+ origApp = ApplicationBuilder.newManagedApp(TestApplication.class, origManagementContext);
+ }
+
+ @AfterMethod(groups = "Integration", alwaysRun=true)
+ public void tearDown() throws Exception {
+ for (WebAppMonitor monitor : webAppMonitors) {
+ monitor.terminate();
+ }
+ if (executor != null) executor.shutdownNow();
+ if (newApp != null) Entities.destroyAll(newApp.getManagementContext());
+ if (origApp != null) Entities.destroyAll(origApp.getManagementContext());
+ if (mementoDir != null) RebindTestUtils.deleteMementoDir(mementoDir);
+ }
+
+ public String getTestWar() {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+ return "classpath://hello-world.war";
+ }
+
+ private TestApplication rebind() throws Exception {
+ RebindTestUtils.waitForPersisted(origApp);
+
+ // Stop the old management context, so original nginx won't interfere
+ origManagementContext.terminate();
+
+ return (TestApplication) RebindTestUtils.rebind(mementoDir, getClass().getClassLoader());
+ }
+
+ private WebAppMonitor newWebAppMonitor(String url) {
+ WebAppMonitor monitor = new WebAppMonitor(url)
+// .delayMillis(0)
+ .logFailures(LOG);
+ webAppMonitors.add(monitor);
+ executor.execute(monitor);
+ return monitor;
+ }
+
+ @Test(groups = "Integration")
+ public void testRebindsToRunningCluster() throws Exception {
+ DynamicWebAppCluster origCluster = origApp.createAndManageChild(EntitySpec.create(DynamicWebAppCluster.class)
+ .configure("memberSpec", EntitySpec.create(JBoss7Server.class).configure("war", getTestWar()))
+ .configure("initialSize", 1));
+
+ origApp.start(ImmutableList.of(localhostProvisioningLocation));
+ JBoss7Server origJboss = (JBoss7Server) Iterables.find(origCluster.getChildren(), Predicates.instanceOf(JBoss7Server.class));
+ String jbossUrl = origJboss.getAttribute(JBoss7Server.ROOT_URL);
+
+ assertHttpStatusCodeEventuallyEquals(jbossUrl, 200);
+ WebAppMonitor monitor = newWebAppMonitor(jbossUrl);
+
+ // Rebind
+ newApp = rebind();
+ DynamicWebAppCluster newCluster = (DynamicWebAppCluster) Iterables.find(newApp.getChildren(), Predicates.instanceOf(DynamicWebAppCluster.class));
+
+ assertHttpStatusCodeEquals(jbossUrl, 200);
+
+ // Confirm the cluster is usable: we can scale-up
+ assertEquals(newCluster.getCurrentSize(), (Integer)1);
+ newCluster.resize(2);
+
+ Iterable<Entity> newJbosses = Iterables.filter(newCluster.getChildren(), Predicates.instanceOf(JBoss7Server.class));
+ assertEquals(Iterables.size(newJbosses), 2);
+ for (Entity j : newJbosses) {
+ assertHttpStatusCodeEventuallyEquals(j.getAttribute(JBoss7Server.ROOT_URL), 200);
+ }
+
+ // Ensure while doing all of this the original jboss server remained reachable
+ assertEquals(monitor.getFailures(), 0);
+
+ // Ensure cluster is usable: we can scale back to stop the original jboss server
+ newCluster.resize(0);
+
+ assertUrlUnreachableEventually(jbossUrl);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/77dff880/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6ServerAwsEc2LiveTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6ServerAwsEc2LiveTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6ServerAwsEc2LiveTest.java
new file mode 100644
index 0000000..1262765
--- /dev/null
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/JBoss6ServerAwsEc2LiveTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.entity.webapp.jboss;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.testng.Assert.assertNotNull;
+
+import java.net.URL;
+
+import org.apache.brooklyn.entity.webapp.jboss.JBoss6Server;
+import org.apache.brooklyn.test.HttpTestUtils;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.AbstractEc2LiveTest;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.location.Location;
+import brooklyn.test.Asserts;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * A simple test of installing+running on AWS-EC2, using various OS distros and versions.
+ */
+public class JBoss6ServerAwsEc2LiveTest extends AbstractEc2LiveTest {
+
+ public String getTestWar() {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world-no-mapping.war");
+ return "classpath://hello-world-no-mapping.war";
+ }
+
+ @Override
+ protected void doTest(Location loc) throws Exception {
+ final JBoss6Server server = app.createAndManageChild(EntitySpec.create(JBoss6Server.class)
+ .configure("war", getTestWar()));
+
+ app.start(ImmutableList.of(loc));
+
+ String url = server.getAttribute(JBoss6Server.ROOT_URL);
+
+ HttpTestUtils.assertHttpStatusCodeEventuallyEquals(url, 200);
+ HttpTestUtils.assertContentContainsText(url, "Hello");
+
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ assertNotNull(server.getAttribute(JBoss6Server.REQUEST_COUNT));
+ assertNotNull(server.getAttribute(JBoss6Server.ERROR_COUNT));
+ assertNotNull(server.getAttribute(JBoss6Server.TOTAL_PROCESSING_TIME));
+ assertNotNull(server.getAttribute(JBoss6Server.MAX_PROCESSING_TIME));
+ assertNotNull(server.getAttribute(JBoss6Server.BYTES_RECEIVED));
+ assertNotNull(server.getAttribute(JBoss6Server.BYTES_SENT));
+ }});
+ }
+
+ @Test(enabled=false)
+ public void testDummy() {} // Convince testng IDE integration that this really does have test methods
+}