You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/07 03:09:46 UTC
[2/8] incubator-brooklyn git commit: brooklyn-launcher: add
org.apache package prefix
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
new file mode 100644
index 0000000..66a9f67
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.File;
+
+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.config.BrooklynProperties;
+import brooklyn.entity.Application;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.management.ha.ManagementPlaneSyncRecordPersister;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.test.Asserts;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.os.Os;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+
+public class BrooklynLauncherHighAvailabilityTest {
+
+ private static final Logger log = LoggerFactory.getLogger(BrooklynLauncherHighAvailabilityTest.class);
+
+ private static final Duration TIMEOUT = Duration.THIRTY_SECONDS;
+
+ private BrooklynLauncher primary;
+ private BrooklynLauncher secondary;
+ private BrooklynLauncher tertiary;
+ private File persistenceDir;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ persistenceDir = Files.createTempDir();
+ Os.deleteOnExitRecursively(persistenceDir);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (primary != null) primary.terminate();
+ primary = null;
+ if (secondary != null) secondary.terminate();
+ secondary = null;
+ if (tertiary != null) tertiary.terminate();
+ tertiary = null;
+ if (persistenceDir != null) RebindTestUtils.deleteMementoDir(persistenceDir);
+ persistenceDir = null;
+ }
+
+ @Test
+ public void testStandbyTakesOverWhenPrimaryTerminatedGracefully() throws Exception {
+ doTestStandbyTakesOver(true);
+ }
+
+ @Test(invocationCount=10, groups="Integration")
+ /** test issues with termination and promotion;
+ * previously we got FileNotFound errors, though these should be fixed with
+ * the various PersistenceObjectStore prepare methods */
+ public void testStandbyTakesOverWhenPrimaryTerminatedGracefullyManyTimes() throws Exception {
+ testStandbyTakesOverWhenPrimaryTerminatedGracefully();
+ }
+
+ @Test(groups="Integration") // because slow waiting for timeouts to promote standbys
+ public void testStandbyTakesOverWhenPrimaryFails() throws Exception {
+ doTestStandbyTakesOver(false);
+ }
+
+ protected void doTestStandbyTakesOver(boolean stopGracefully) throws Exception {
+ log.info("STARTING standby takeover test");
+ primary = BrooklynLauncher.newInstance();
+ primary.webconsole(false)
+ .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+ .highAvailabilityMode(HighAvailabilityMode.AUTO)
+ .persistMode(PersistMode.AUTO)
+ .persistenceDir(persistenceDir)
+ .persistPeriod(Duration.millis(10))
+ .haHeartbeatPeriod(Duration.millis(10))
+ .haHeartbeatTimeout(Duration.millis(1000))
+ .application(EntitySpec.create(TestApplication.class))
+ .start();
+ ManagementContext primaryManagementContext = primary.getServerDetails().getManagementContext();
+ log.info("started mgmt primary "+primaryManagementContext);
+
+ assertOnlyApp(primary.getServerDetails().getManagementContext(), TestApplication.class);
+ primaryManagementContext.getRebindManager().getPersister().waitForWritesCompleted(TIMEOUT);
+
+ // Secondary will come up as standby
+ secondary = BrooklynLauncher.newInstance();
+ secondary.webconsole(false)
+ .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+ .highAvailabilityMode(HighAvailabilityMode.AUTO)
+ .persistMode(PersistMode.AUTO)
+ .persistenceDir(persistenceDir)
+ .persistPeriod(Duration.millis(10))
+ .haHeartbeatPeriod(Duration.millis(10))
+ .haHeartbeatTimeout(Duration.millis(1000))
+ .start();
+ ManagementContext secondaryManagementContext = secondary.getServerDetails().getManagementContext();
+ log.info("started mgmt secondary "+secondaryManagementContext);
+
+ // TODO can assert it sees the apps read only
+// assertNoApps(secondary.getServerDetails().getManagementContext());
+
+ // Terminate primary; expect secondary to take over
+ if (stopGracefully) {
+ ((ManagementContextInternal)primaryManagementContext).terminate();
+ } else {
+ ManagementPlaneSyncRecordPersister planePersister = ((ManagementContextInternal)primaryManagementContext).getHighAvailabilityManager().getPersister();
+ planePersister.stop(); // can no longer write heartbeats
+ ((ManagementContextInternal)primaryManagementContext).terminate();
+ }
+
+ assertOnlyAppEventually(secondaryManagementContext, TestApplication.class);
+
+ // Start tertiary (force up as standby)
+ tertiary = BrooklynLauncher.newInstance();
+ tertiary.webconsole(false)
+ .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+ .highAvailabilityMode(HighAvailabilityMode.STANDBY)
+ .persistMode(PersistMode.AUTO)
+ .persistenceDir(persistenceDir)
+ .persistPeriod(Duration.millis(10))
+ .haHeartbeatPeriod(Duration.millis(10))
+ .haHeartbeatTimeout(Duration.millis(1000))
+ .start();
+ ManagementContext tertiaryManagementContext = tertiary.getServerDetails().getManagementContext();
+ log.info("started mgmt tertiary "+primaryManagementContext);
+
+ assertNoApps(tertiary.getServerDetails().getManagementContext());
+
+ // Terminate secondary; expect tertiary to take over
+ if (stopGracefully) {
+ ((ManagementContextInternal)secondaryManagementContext).terminate();
+ } else {
+ ManagementPlaneSyncRecordPersister planePersister = ((ManagementContextInternal)secondaryManagementContext).getHighAvailabilityManager().getPersister();
+ planePersister.stop(); // can no longer write heartbeats
+ ((ManagementContextInternal)secondaryManagementContext).terminate();
+ }
+
+ assertOnlyAppEventually(tertiaryManagementContext, TestApplication.class);
+ }
+
+ public void testHighAvailabilityMasterModeFailsIfAlreadyHasMaster() throws Exception {
+ primary = BrooklynLauncher.newInstance();
+ primary.webconsole(false)
+ .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+ .highAvailabilityMode(HighAvailabilityMode.AUTO)
+ .persistMode(PersistMode.AUTO)
+ .persistenceDir(persistenceDir)
+ .persistPeriod(Duration.millis(10))
+ .application(EntitySpec.create(TestApplication.class))
+ .start();
+
+ try {
+ // Secondary will come up as standby
+ secondary = BrooklynLauncher.newInstance();
+ secondary.webconsole(false)
+ .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+ .highAvailabilityMode(HighAvailabilityMode.MASTER)
+ .persistMode(PersistMode.AUTO)
+ .persistenceDir(persistenceDir)
+ .persistPeriod(Duration.millis(10))
+ .start();
+ fail();
+ } catch (IllegalStateException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testHighAvailabilityStandbyModeFailsIfNoExistingMaster() throws Exception {
+ try {
+ primary = BrooklynLauncher.newInstance();
+ primary.webconsole(false)
+ .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+ .highAvailabilityMode(HighAvailabilityMode.STANDBY)
+ .persistMode(PersistMode.AUTO)
+ .persistenceDir(persistenceDir)
+ .persistPeriod(Duration.millis(10))
+ .ignorePersistenceErrors(false)
+ .application(EntitySpec.create(TestApplication.class))
+ .start();
+ fail();
+ } catch (IllegalStateException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testHighAvailabilityHotStandbyModeFailsIfNoExistingMaster() throws Exception {
+ try {
+ primary = BrooklynLauncher.newInstance();
+ primary.webconsole(false)
+ .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+ .highAvailabilityMode(HighAvailabilityMode.HOT_STANDBY)
+ .persistMode(PersistMode.AUTO)
+ .persistenceDir(persistenceDir)
+ .persistPeriod(Duration.millis(10))
+ .ignorePersistenceErrors(false)
+ .application(EntitySpec.create(TestApplication.class))
+ .start();
+ fail();
+ } catch (IllegalStateException e) {
+ // success
+ }
+ }
+
+ private void assertOnlyApp(ManagementContext managementContext, Class<? extends Application> expectedType) {
+ assertEquals(managementContext.getApplications().size(), 1, "apps="+managementContext.getApplications());
+ assertNotNull(Iterables.find(managementContext.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+managementContext.getApplications());
+ }
+
+ private void assertNoApps(ManagementContext managementContext) {
+ if (!managementContext.getApplications().isEmpty())
+ log.warn("FAILED assertion (rethrowing), apps="+managementContext.getApplications());
+ assertTrue(managementContext.getApplications().isEmpty(), "apps="+managementContext.getApplications());
+ }
+
+ private void assertOnlyAppEventually(final ManagementContext managementContext, final Class<? extends Application> expectedType) {
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ assertOnlyApp(managementContext, expectedType);
+ }});
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
new file mode 100644
index 0000000..48fb538
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.launcher;
+
+import java.io.File;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+import org.apache.brooklyn.catalog.BrooklynCatalog;
+import org.apache.brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogInitialization;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.os.Os;
+
+public class BrooklynLauncherRebindCatalogTest {
+
+ private static final String TEST_VERSION = "test-version";
+ private static final String CATALOG_INITIAL = "classpath://rebind-test-catalog.bom";
+ private static final String CATALOG_ADDITIONS = "rebind-test-catalog-additions.bom";
+ private static final Iterable<String> EXPECTED_DEFAULT_IDS = ImmutableSet.of("one:" + TEST_VERSION, "two:" + TEST_VERSION);
+ private static final Iterable<String> EXPECTED_ADDED_IDS = ImmutableSet.of("three:" + TEST_VERSION, "four:" + TEST_VERSION);
+
+ private List<BrooklynLauncher> launchers = Lists.newCopyOnWriteArrayList();
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ for (BrooklynLauncher launcher : launchers) {
+ launcher.terminate();
+ }
+ launchers.clear();
+ }
+
+ private BrooklynLauncher newLauncherForTests(String persistenceDir) {
+ CatalogInitialization catalogInitialization = new CatalogInitialization(CATALOG_INITIAL, false, null, false);
+ BrooklynLauncher launcher = BrooklynLauncher.newInstance()
+ .brooklynProperties(LocalManagementContextForTests.builder(true).buildProperties())
+ .catalogInitialization(catalogInitialization)
+ .persistMode(PersistMode.AUTO)
+ .persistenceDir(persistenceDir)
+ .webconsole(false);
+ launchers.add(launcher);
+ return launcher;
+ }
+
+ @Test
+ public void testRebindDoesNotEffectCatalog() {
+ String persistenceDir = newTempPersistenceContainerName();
+
+ BrooklynLauncher launcher = newLauncherForTests(persistenceDir);
+ launcher.start();
+ BrooklynCatalog catalog = launcher.getServerDetails().getManagementContext().getCatalog();
+
+ assertCatalogConsistsOfIds(catalog.getCatalogItems(), EXPECTED_DEFAULT_IDS);
+
+ catalog.deleteCatalogItem("one", TEST_VERSION);
+ catalog.deleteCatalogItem("two", TEST_VERSION);
+
+ Assert.assertEquals(Iterables.size(catalog.getCatalogItems()), 0);
+
+ catalog.addItems(new ResourceUtils(this).getResourceAsString(CATALOG_ADDITIONS));
+
+ assertCatalogConsistsOfIds(catalog.getCatalogItems(), EXPECTED_ADDED_IDS);
+
+ launcher.terminate();
+
+ BrooklynLauncher newLauncher = newLauncherForTests(persistenceDir);
+ newLauncher.start();
+ assertCatalogConsistsOfIds(newLauncher.getServerDetails().getManagementContext().getCatalog().getCatalogItems(), EXPECTED_ADDED_IDS);
+ }
+
+ private void assertCatalogConsistsOfIds(Iterable<CatalogItem<Object, Object>> catalogItems, Iterable<String> ids) {
+ Iterable<String> idsFromItems = Iterables.transform(catalogItems, new Function<CatalogItem<?,?>, String>() {
+ @Nullable
+ @Override
+ public String apply(CatalogItem<?, ?> catalogItem) {
+ return catalogItem.getCatalogItemId();
+ }
+ });
+ Assert.assertTrue(Iterables.elementsEqual(ids, idsFromItems), String.format("Expected %s, found %s", ids, idsFromItems));
+ }
+
+ protected String newTempPersistenceContainerName() {
+ File persistenceDirF = Files.createTempDir();
+ Os.deleteOnExitRecursively(persistenceDirF);
+ return persistenceDirF.getAbsolutePath();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
new file mode 100644
index 0000000..bd804b6
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
@@ -0,0 +1,257 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+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.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.entity.Application;
+import brooklyn.entity.basic.EntityPredicates;
+import brooklyn.entity.basic.StartableApplication;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.location.Location;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.test.Asserts;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public abstract class BrooklynLauncherRebindTestFixture {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(BrooklynLauncherRebindTestFixture.class);
+
+ protected String persistenceDir;
+ protected String persistenceLocationSpec;
+ protected List<BrooklynLauncher> launchers = MutableList.of();
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ persistenceDir = newTempPersistenceContainerName();
+ }
+
+ protected abstract String newTempPersistenceContainerName();
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ for (BrooklynLauncher l: launchers) {
+ if (l.isStarted()) {
+ l.terminate();
+ PersistenceObjectStore store = getPersistenceStore(l.getServerDetails().getManagementContext());
+ if (store!=null) store.deleteCompletely();
+ }
+ }
+ }
+
+ protected BrooklynLauncher newLauncherBase() {
+ BrooklynLauncher l = BrooklynLauncher.newInstance()
+ .webconsole(false);
+ launchers.add(l);
+ return l;
+ }
+ protected BrooklynLauncher newLauncherDefault(PersistMode mode) {
+ return newLauncherBase()
+ .managementContext(newManagementContextForTests(null))
+ .persistMode(mode)
+ .persistenceDir(persistenceDir)
+ .persistPeriod(Duration.millis(10));
+ }
+ protected LocalManagementContextForTests newManagementContextForTests(BrooklynProperties props) {
+ if (props==null)
+ return new LocalManagementContextForTests();
+ else
+ return new LocalManagementContextForTests(props);
+ }
+
+ protected ManagementContext lastMgmt() {
+ return Iterables.getLast(launchers).getServerDetails().getManagementContext();
+ }
+
+ @Test
+ public void testRebindsToExistingApp() throws Exception {
+ populatePersistenceDir(persistenceDir, EntitySpec.create(TestApplication.class).displayName("myorig"));
+
+ // Rebind to the app we just started last time
+
+ newLauncherDefault(PersistMode.REBIND).start();
+
+ assertOnlyApp(lastMgmt(), TestApplication.class);
+ assertNotNull(Iterables.find(lastMgmt().getApplications(), EntityPredicates.displayNameEqualTo("myorig"), null), "apps="+lastMgmt().getApplications());
+ }
+
+ @Test
+ public void testRebindCanAddNewApps() throws Exception {
+ populatePersistenceDir(persistenceDir, EntitySpec.create(TestApplication.class).displayName("myorig"));
+
+ // Rebind to the app we started last time
+ newLauncherDefault(PersistMode.REBIND)
+ .application(EntitySpec.create(TestApplication.class).displayName("mynew"))
+ .start();
+
+ // New app was added, and orig app was rebound
+ assertEquals(lastMgmt().getApplications().size(), 2, "apps="+lastMgmt().getApplications());
+ assertNotNull(Iterables.find(lastMgmt().getApplications(), EntityPredicates.displayNameEqualTo("mynew"), null), "apps="+lastMgmt().getApplications());
+
+ // And subsequently can create new apps
+ StartableApplication app3 = lastMgmt().getEntityManager().createEntity(
+ EntitySpec.create(TestApplication.class).displayName("mynew2"));
+ app3.start(ImmutableList.<Location>of());
+ }
+
+ @Test
+ public void testAutoRebindsToExistingApp() throws Exception {
+ EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+ populatePersistenceDir(persistenceDir, appSpec);
+
+ // Auto will rebind if the dir exists
+ newLauncherDefault(PersistMode.AUTO).start();
+
+ assertOnlyApp(lastMgmt(), TestApplication.class);
+ }
+
+ @Test
+ public void testCleanDoesNotRebindToExistingApp() throws Exception {
+ EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+ populatePersistenceDir(persistenceDir, appSpec);
+
+ // Auto will rebind if the dir exists
+ newLauncherDefault(PersistMode.CLEAN).start();
+
+ assertTrue(lastMgmt().getApplications().isEmpty(), "apps="+lastMgmt().getApplications());
+ }
+
+ @Test
+ public void testAutoRebindCreatesNewIfEmptyDir() throws Exception {
+ // Auto will rebind if the dir exists
+ newLauncherDefault(PersistMode.AUTO)
+ .application(EntitySpec.create(TestApplication.class))
+ .start();
+
+ assertOnlyApp(lastMgmt(), TestApplication.class);
+ assertMementoContainerNonEmptyForTypeEventually("entities");
+ }
+
+ @Test
+ public void testRebindRespectsPersistenceDirSetInProperties() throws Exception {
+ String persistenceDir2 = newTempPersistenceContainerName();
+
+ BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newDefault();
+ brooklynProperties.put(BrooklynServerConfig.PERSISTENCE_DIR, persistenceDir2);
+ LocalManagementContextForTests mgmt = newManagementContextForTests(brooklynProperties);
+
+ // Rebind to the app we started last time
+ newLauncherBase()
+ .persistMode(PersistMode.AUTO)
+ .persistPeriod(Duration.millis(10))
+ .managementContext(mgmt)
+ .start();
+
+ checkPersistenceContainerNameIs(persistenceDir2);
+ }
+
+ // assumes default persistence dir is rebindable
+ @Test(groups="Integration")
+ public void testRebindRespectsDefaultPersistenceDir() throws Exception {
+ newLauncherDefault(PersistMode.AUTO)
+ .persistenceDir((String)null)
+ .start();
+
+ checkPersistenceContainerNameIsDefault();
+ }
+
+ protected abstract void checkPersistenceContainerNameIsDefault();
+ protected abstract void checkPersistenceContainerNameIs(String expected);
+
+ @Test
+ public void testPersistenceFailsIfNoDir() throws Exception {
+ runRebindFails(PersistMode.REBIND, badContainerName(), "does not exist");
+ }
+
+ protected abstract String badContainerName();
+
+ @Test
+ public void testExplicitRebindFailsIfEmpty() throws Exception {
+ runRebindFails(PersistMode.REBIND, persistenceDir, "directory is empty");
+ }
+
+ protected void runRebindFails(PersistMode persistMode, String dir, String errmsg) throws Exception {
+ try {
+ newLauncherDefault(persistMode)
+ .persistenceDir(dir)
+ .start();
+ } catch (FatalConfigurationRuntimeException e) {
+ if (!e.toString().contains(errmsg)) {
+ throw e;
+ }
+ }
+ }
+
+ protected void populatePersistenceDir(String dir, EntitySpec<? extends StartableApplication> appSpec) throws Exception {
+ BrooklynLauncher launcher = newLauncherDefault(PersistMode.CLEAN)
+ .highAvailabilityMode(HighAvailabilityMode.MASTER)
+ .persistenceDir(dir)
+ .application(appSpec)
+ .start();
+ launcher.terminate();
+ assertMementoContainerNonEmptyForTypeEventually("entities");
+ }
+
+ protected void assertOnlyApp(ManagementContext managementContext, Class<? extends Application> expectedType) {
+ assertEquals(managementContext.getApplications().size(), 1, "apps="+managementContext.getApplications());
+ assertNotNull(Iterables.find(managementContext.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+managementContext.getApplications());
+ }
+
+ protected void assertMementoContainerNonEmptyForTypeEventually(final String type) {
+ Asserts.succeedsEventually(ImmutableMap.of("timeout", Duration.TEN_SECONDS), new Runnable() {
+ @Override public void run() {
+ getPersistenceStore(lastMgmt()).listContentsWithSubPath(type);
+ }});
+ }
+
+ static PersistenceObjectStore getPersistenceStore(ManagementContext managementContext) {
+ if (managementContext==null) return null;
+ BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
+ if (persister==null) return null;
+ return persister.getObjectStore();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
new file mode 100644
index 0000000..ee07f67
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
@@ -0,0 +1,154 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerPaths;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.FileBasedObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Identifiers;
+
+import com.google.common.base.Joiner;
+import com.google.common.io.Files;
+
+public class BrooklynLauncherRebindTestToFiles extends BrooklynLauncherRebindTestFixture {
+
+ protected String newTempPersistenceContainerName() {
+ File persistenceDirF = Files.createTempDir();
+ Os.deleteOnExitRecursively(persistenceDirF);
+ return persistenceDirF.getAbsolutePath();
+ }
+
+ protected String badContainerName() {
+ return "/path/does/not/exist/"+Identifiers.makeRandomId(4);
+ }
+
+ protected void checkPersistenceContainerNameIs(String expected) {
+ String expectedFqp = new File(Os.tidyPath(expected)).getAbsolutePath();
+ assertEquals(getPersistenceDir(lastMgmt()).getAbsolutePath(), expectedFqp);
+ }
+
+ static File getPersistenceDir(ManagementContext managementContext) {
+ BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
+ FileBasedObjectStore store = (FileBasedObjectStore)persister.getObjectStore();
+ return store.getBaseDir();
+ }
+
+ protected void checkPersistenceContainerNameIsDefault() {
+ String expected = BrooklynServerPaths.newMainPersistencePathResolver(BrooklynProperties.Factory.newEmpty()).location(null).dir(null).resolve();
+ checkPersistenceContainerNameIs(expected);
+ }
+
+ @Test
+ public void testPersistenceFailsIfIsFile() throws Exception {
+ File tempF = File.createTempFile("test-"+JavaClassNames.niceClassAndMethod(), ".not_dir");
+ tempF.deleteOnExit();
+ String tempFileName = tempF.getAbsolutePath();
+
+ try {
+ runRebindFails(PersistMode.AUTO, tempFileName, "must not be a file");
+ runRebindFails(PersistMode.REBIND, tempFileName, "must not be a file");
+ runRebindFails(PersistMode.CLEAN, tempFileName, "must not be a file");
+ } finally {
+ new File(tempFileName).delete();
+ }
+ }
+
+ @Test
+ public void testPersistenceFailsIfNotWritable() throws Exception {
+ EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+ populatePersistenceDir(persistenceDir, appSpec);
+ new File(persistenceDir).setWritable(false);
+ try {
+ runRebindFails(PersistMode.AUTO, persistenceDir, "not writable");
+ runRebindFails(PersistMode.REBIND, persistenceDir, "not writable");
+ runRebindFails(PersistMode.CLEAN, persistenceDir, "not writable");
+ } finally {
+ new File(persistenceDir).setWritable(true);
+ }
+ }
+
+ @Test
+ public void testPersistenceFailsIfNotReadable() throws Exception {
+ EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+ populatePersistenceDir(persistenceDir, appSpec);
+ new File(persistenceDir).setReadable(false);
+ try {
+ runRebindFails(PersistMode.AUTO, persistenceDir, "not readable");
+ runRebindFails(PersistMode.REBIND, persistenceDir, "not readable");
+ runRebindFails(PersistMode.CLEAN, persistenceDir, "not readable");
+ } finally {
+ new File(persistenceDir).setReadable(true);
+ }
+ }
+
+ @Test(groups="Integration")
+ public void testCopyPersistedState() throws Exception {
+ EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+ populatePersistenceDir(persistenceDir, appSpec);
+
+ File destinationDir = Files.createTempDir();
+ String destination = destinationDir.getAbsolutePath();
+ String destinationLocation = null; // i.e. file system, rather than object store
+ try {
+ // Auto will rebind if the dir exists
+ BrooklynLauncher launcher = newLauncherDefault(PersistMode.AUTO)
+ .highAvailabilityMode(HighAvailabilityMode.MASTER)
+ .webconsole(false);
+ launcher.copyPersistedState(destination, destinationLocation);
+ launcher.terminate();
+
+ File entities = new File(Os.mergePaths(destination), "entities");
+ assertTrue(entities.isDirectory(), "entities directory should exist");
+ assertEquals(entities.listFiles().length, 1, "entities directory should contain one file (contained: "+
+ Joiner.on(", ").join(entities.listFiles()) +")");
+
+ File nodes = new File(Os.mergePaths(destination, "nodes"));
+ assertTrue(nodes.isDirectory(), "nodes directory should exist");
+ assertNotEquals(nodes.listFiles().length, 0, "nodes directory should not be empty");
+
+ // Should now have a usable copy in the destinationDir
+ // Auto will rebind if the dir exists
+ newLauncherDefault(PersistMode.AUTO)
+ .webconsole(false)
+ .persistenceDir(destinationDir)
+ .start();
+ assertOnlyApp(lastMgmt(), TestApplication.class);
+
+ } finally {
+ Os.deleteRecursively(destinationDir);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
new file mode 100644
index 0000000..b2aeaf9
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerPaths;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.jclouds.BlobStoreTest;
+import brooklyn.entity.rebind.persister.jclouds.JcloudsBlobStoreBasedObjectStore;
+import brooklyn.management.ManagementContext;
+import brooklyn.mementos.BrooklynMementoRawData;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Identifiers;
+
+@Test(groups="Live")
+public class BrooklynLauncherRebindToCloudObjectStoreTest extends BrooklynLauncherRebindTestFixture {
+
+ // FIXME BrooklynLauncherRebindToCloudObjectStoreTest.testCleanDoesNotRebindToExistingApp failed:
+ // apps=[Application[mDNfOA7w]] expected [true] but found [false]
+ // Should it really delete everything in the bucket?! Only if we can back up first!
+
+ // FIXME brooklyn.util.exceptions.FatalRuntimeException: Error rebinding to persisted state: Writes not allowed in brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore@7d2f7563
+ // at brooklyn.launcher.BrooklynLauncher.persistState(BrooklynLauncher.java:502)
+ // at brooklyn.launcher.BrooklynLauncherRebindToCloudObjectStoreTest.testCopyPersistedState(BrooklynLauncherRebindToCloudObjectStoreTest.java:144)
+ // Presumably a previous run wasn't tearing down properly, so it joined as a standby rather than being master?!
+
+ { persistenceLocationSpec = BlobStoreTest.PERSIST_TO_OBJECT_STORE_FOR_TEST_SPEC; }
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ persistenceDir = newTempPersistenceContainerName();
+ }
+
+ @Override
+ protected BrooklynLauncher newLauncherBase() {
+ return super.newLauncherBase().persistenceLocation(persistenceLocationSpec);
+ }
+
+ protected LocalManagementContextForTests newManagementContextForTests(BrooklynProperties props) {
+ BrooklynProperties p2 = BrooklynProperties.Factory.newDefault();
+ if (props!=null) p2.putAll(props);
+ return new LocalManagementContextForTests(p2);
+ }
+
+ @Override
+ protected String newTempPersistenceContainerName() {
+ return "test-"+JavaClassNames.callerStackElement(0).getClassName()+"-"+Identifiers.makeRandomId(4);
+ }
+
+ protected String badContainerName() {
+ return "container-does-not-exist-"+Identifiers.makeRandomId(4);
+ }
+
+ protected void checkPersistenceContainerNameIs(String expected) {
+ assertEquals(getPersistenceContainerName(lastMgmt()), expected);
+ }
+
+ static String getPersistenceContainerName(ManagementContext managementContext) {
+ BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
+ JcloudsBlobStoreBasedObjectStore store = (JcloudsBlobStoreBasedObjectStore)persister.getObjectStore();
+ return store.getContainerName();
+ }
+
+ protected void checkPersistenceContainerNameIsDefault() {
+ checkPersistenceContainerNameIs(BrooklynServerPaths.DEFAULT_PERSISTENCE_CONTAINER_NAME);
+ }
+
+ @Override @Test(groups="Live")
+ public void testRebindsToExistingApp() throws Exception {
+ super.testRebindsToExistingApp();
+ }
+
+ @Override @Test(groups="Live")
+ public void testRebindCanAddNewApps() throws Exception {
+ super.testRebindCanAddNewApps();
+ }
+
+ @Override @Test(groups="Live")
+ public void testAutoRebindsToExistingApp() throws Exception {
+ super.testAutoRebindsToExistingApp();
+ }
+
+ // TODO Marked as work-in-progress because "clean" does not backup and then clean out the existing
+ // object store's bucket. Unclear what best behaviour there should be: should we really delete
+ // the data?! We better be confident about our backup!
+ @Override @Test(groups={"Live", "WIP"})
+ public void testCleanDoesNotRebindToExistingApp() throws Exception {
+ super.testCleanDoesNotRebindToExistingApp();
+ }
+
+ @Override @Test(groups="Live")
+ public void testAutoRebindCreatesNewIfEmptyDir() throws Exception {
+ super.testAutoRebindCreatesNewIfEmptyDir();
+ }
+
+ @Override @Test(groups="Live")
+ public void testRebindRespectsPersistenceDirSetInProperties() throws Exception {
+ super.testRebindRespectsPersistenceDirSetInProperties();
+ }
+
+ @Override @Test(groups="Live")
+ public void testRebindRespectsDefaultPersistenceDir() throws Exception {
+ super.testRebindRespectsDefaultPersistenceDir();
+ }
+
+ @Override @Test(groups="Live")
+ public void testPersistenceFailsIfNoDir() throws Exception {
+ super.testPersistenceFailsIfNoDir();
+ }
+
+ @Override @Test(groups="Live")
+ public void testExplicitRebindFailsIfEmpty() throws Exception {
+ super.testExplicitRebindFailsIfEmpty();
+ }
+
+ // TODO Remove duplication from BrooklynLauncherRebindTestToFiles.testCopyPersistedState()
+ @Test(groups="Live")
+ public void testCopyPersistedState() throws Exception {
+ EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+ populatePersistenceDir(persistenceDir, appSpec);
+
+ String destinationDir = newTempPersistenceContainerName();
+ String destinationLocation = persistenceLocationSpec;
+ try {
+ // Auto will rebind if the dir exists
+ BrooklynLauncher launcher = newLauncherDefault(PersistMode.AUTO)
+ .webconsole(false)
+ .persistenceLocation(persistenceLocationSpec);
+ BrooklynMementoRawData memento = launcher.retrieveState();
+ launcher.persistState(memento, destinationDir, destinationLocation);
+ launcher.terminate();
+
+ assertEquals(memento.getEntities().size(), 1, "entityMementos="+memento.getEntities().keySet());
+
+ // Should now have a usable copy in the destionationDir
+ // Auto will rebind if the dir exists
+ newLauncherDefault(PersistMode.AUTO)
+ .webconsole(false)
+ .persistenceDir(destinationDir)
+ .persistenceLocation(destinationLocation)
+ .start();
+ assertOnlyApp(lastMgmt(), TestApplication.class);
+
+ } finally {
+ Os.deleteRecursively(destinationDir);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
new file mode 100644
index 0000000..df295d8
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
@@ -0,0 +1,368 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.Properties;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.internal.CatalogInitialization;
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.entity.Application;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.location.Location;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.test.HttpTestUtils;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestApplicationImpl;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.exceptions.FatalRuntimeException;
+import brooklyn.util.io.FileUtil;
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.StringFunctions;
+import brooklyn.util.text.Strings;
+
+import com.google.api.client.util.Preconditions;
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.io.Files;
+
+public class BrooklynLauncherTest {
+
+ private BrooklynLauncher launcher;
+ private File persistenceDir;
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (launcher != null) launcher.terminate();
+ if (persistenceDir != null) RebindTestUtils.deleteMementoDir(persistenceDir);
+ launcher = null;
+ }
+
+ // Integration because takes a few seconds to start web-console
+ @Test(groups="Integration")
+ public void testStartsWebServerOnExpectectedPort() throws Exception {
+ launcher = newLauncherForTests(true)
+ .webconsolePort("10000+")
+ .start();
+
+ String webServerUrlStr = launcher.getServerDetails().getWebServerUrl();
+ URI webServerUri = new URI(webServerUrlStr);
+
+ assertEquals(launcher.getApplications(), ImmutableList.of());
+ assertTrue(webServerUri.getPort() >= 10000 && webServerUri.getPort() < 10100, "port="+webServerUri.getPort()+"; uri="+webServerUri);
+ HttpTestUtils.assertUrlReachable(webServerUrlStr);
+ }
+
+ // Integration because takes a few seconds to start web-console
+ @Test(groups="Integration")
+ public void testWebServerTempDirRespectsDataDirConfig() throws Exception {
+ String dataDirName = ".brooklyn-foo"+Strings.makeRandomId(4);
+ String dataDir = "~/"+dataDirName;
+
+ launcher = newLauncherForTests(true)
+ .brooklynProperties(BrooklynServerConfig.MGMT_BASE_DIR, dataDir)
+ .start();
+
+ ManagementContext managementContext = launcher.getServerDetails().getManagementContext();
+ String expectedTempDir = Os.mergePaths(Os.home(), dataDirName, "planes", managementContext.getManagementPlaneId(), managementContext.getManagementNodeId(), "jetty");
+
+ File webappTempDir = launcher.getServerDetails().getWebServer().getWebappTempDir();
+ assertEquals(webappTempDir.getAbsolutePath(), expectedTempDir);
+ }
+
+ @Test
+ public void testCanDisableWebServerStartup() throws Exception {
+ launcher = newLauncherForTests(true)
+ .webconsole(false)
+ .start();
+
+ assertNull(launcher.getServerDetails().getWebServer());
+ assertNull(launcher.getServerDetails().getWebServerUrl());
+ Assert.assertTrue( ((ManagementContextInternal)launcher.getServerDetails().getManagementContext()).errors().isEmpty() );
+ }
+
+ @Test
+ public void testStartsAppInstance() throws Exception {
+ launcher = newLauncherForTests(true)
+ .webconsole(false)
+ .application(new TestApplicationImpl())
+ .start();
+
+ assertOnlyApp(launcher, TestApplication.class);
+ }
+
+ @Test
+ public void testStartsAppFromSpec() throws Exception {
+ launcher = newLauncherForTests(true)
+ .webconsole(false)
+ .application(EntitySpec.create(TestApplication.class))
+ .start();
+
+ assertOnlyApp(launcher, TestApplication.class);
+ }
+
+ @Test
+ public void testStartsAppFromBuilder() throws Exception {
+ launcher = newLauncherForTests(true)
+ .webconsole(false)
+ .application(new ApplicationBuilder(EntitySpec.create(TestApplication.class)) {
+ @Override protected void doBuild() {
+ }})
+ .start();
+
+ assertOnlyApp(launcher, TestApplication.class);
+ }
+
+ @Test
+ public void testStartsAppFromYAML() throws Exception {
+ String yaml = "name: example-app\n" +
+ "services:\n" +
+ "- serviceType: brooklyn.test.entity.TestEntity\n" +
+ " name: test-app";
+ launcher = newLauncherForTests(true)
+ .webconsole(false)
+ .application(yaml)
+ .start();
+
+ assertEquals(launcher.getApplications().size(), 1, "apps="+launcher.getApplications());
+ Application app = Iterables.getOnlyElement(launcher.getApplications());
+ assertEquals(app.getChildren().size(), 1, "children=" + app.getChildren());
+ assertTrue(Iterables.getOnlyElement(app.getChildren()) instanceof TestEntity);
+ }
+
+ @Test // may take 2s initializing location if running this test case alone, but noise if running suite
+ public void testStartsAppInSuppliedLocations() throws Exception {
+ launcher = newLauncherForTests(true)
+ .webconsole(false)
+ .location("localhost")
+ .application(new ApplicationBuilder(EntitySpec.create(TestApplication.class)) {
+ @Override protected void doBuild() {
+ }})
+ .start();
+
+ Application app = Iterables.find(launcher.getApplications(), Predicates.instanceOf(TestApplication.class));
+ assertOnlyLocation(app, LocalhostMachineProvisioningLocation.class);
+ }
+
+ @Test
+ public void testUsesSuppliedManagementContext() throws Exception {
+ LocalManagementContext myManagementContext = LocalManagementContextForTests.newInstance();
+ launcher = newLauncherForTests(false)
+ .webconsole(false)
+ .managementContext(myManagementContext)
+ .start();
+
+ assertSame(launcher.getServerDetails().getManagementContext(), myManagementContext);
+ }
+
+ @Test
+ public void testUsesSuppliedBrooklynProperties() throws Exception {
+ BrooklynProperties props = LocalManagementContextForTests.builder(true).buildProperties();
+ props.put("mykey", "myval");
+ launcher = newLauncherForTests(false)
+ .webconsole(false)
+ .brooklynProperties(props)
+ .start();
+
+ assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("mykey"), "myval");
+ }
+
+ @Test
+ public void testUsesSupplementaryBrooklynProperties() throws Exception {
+ launcher = newLauncherForTests(true)
+ .webconsole(false)
+ .brooklynProperties("mykey", "myval")
+ .start();
+
+ assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("mykey"), "myval");
+ }
+
+ @Test
+ public void testReloadBrooklynPropertiesRestoresProgrammaticProperties() throws Exception {
+ launcher = newLauncherForTests(true)
+ .webconsole(false)
+ .brooklynProperties("mykey", "myval")
+ .start();
+ LocalManagementContext managementContext = (LocalManagementContext)launcher.getServerDetails().getManagementContext();
+ assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
+ managementContext.getBrooklynProperties().put("mykey", "newval");
+ assertEquals(managementContext.getConfig().getFirst("mykey"), "newval");
+ managementContext.reloadBrooklynProperties();
+ assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
+ }
+
+ @Test
+ public void testReloadBrooklynPropertiesFromFile() throws Exception {
+ File globalPropertiesFile = File.createTempFile("local-brooklyn-properties-test", ".properties");
+ FileUtil.setFilePermissionsTo600(globalPropertiesFile);
+ try {
+ String property = "mykey=myval";
+ Files.append(getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8);
+ launcher = newLauncherForTests(false)
+ .webconsole(false)
+ .globalBrooklynPropertiesFile(globalPropertiesFile.getAbsolutePath())
+ .start();
+ LocalManagementContext managementContext = (LocalManagementContext)launcher.getServerDetails().getManagementContext();
+ assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
+ property = "mykey=newval";
+ Files.write(getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8);
+ managementContext.reloadBrooklynProperties();
+ assertEquals(managementContext.getConfig().getFirst("mykey"), "newval");
+ } finally {
+ globalPropertiesFile.delete();
+ }
+ }
+
+ @Test(groups="Integration")
+ public void testChecksGlobalBrooklynPropertiesPermissionsX00() throws Exception {
+ File propsFile = File.createTempFile("testChecksGlobalBrooklynPropertiesPermissionsX00", ".properties");
+ propsFile.setReadable(true, false);
+ try {
+ launcher = newLauncherForTests(false)
+ .webconsole(false)
+ .globalBrooklynPropertiesFile(propsFile.getAbsolutePath())
+ .start();
+
+ Assert.fail("Should have thrown");
+ } catch (FatalRuntimeException e) {
+ if (!e.toString().contains("Invalid permissions for file")) throw e;
+ } finally {
+ propsFile.delete();
+ }
+ }
+
+ @Test(groups="Integration")
+ public void testChecksLocalBrooklynPropertiesPermissionsX00() throws Exception {
+ File propsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00", ".properties");
+ propsFile.setReadable(true, false);
+ try {
+ launcher = newLauncherForTests(false)
+ .webconsole(false)
+ .localBrooklynPropertiesFile(propsFile.getAbsolutePath())
+ .start();
+
+ Assert.fail("Should have thrown");
+ } catch (FatalRuntimeException e) {
+ if (!e.toString().contains("Invalid permissions for file")) throw e;
+ } finally {
+ propsFile.delete();
+ }
+ }
+
+ @Test(groups="Integration")
+ public void testStartsWithBrooklynPropertiesPermissionsX00() throws Exception {
+ File globalPropsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00_global", ".properties");
+ Files.write(getMinimalLauncherPropertiesString()+"key_in_global=1", globalPropsFile, Charset.defaultCharset());
+ File localPropsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00_local", ".properties");
+ Files.write("key_in_local=2", localPropsFile, Charset.defaultCharset());
+ FileUtil.setFilePermissionsTo600(globalPropsFile);
+ FileUtil.setFilePermissionsTo600(localPropsFile);
+ try {
+ launcher = newLauncherForTests(false)
+ .webconsole(false)
+ .localBrooklynPropertiesFile(localPropsFile.getAbsolutePath())
+ .globalBrooklynPropertiesFile(globalPropsFile.getAbsolutePath())
+ .start();
+ assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("key_in_global"), "1");
+ assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("key_in_local"), "2");
+ } finally {
+ globalPropsFile.delete();
+ localPropsFile.delete();
+ }
+ }
+
+ @Test // takes a bit of time because starts webapp, but also tests rest api so useful
+ public void testErrorsCaughtByApiAndRestApiWorks() throws Exception {
+ launcher = newLauncherForTests(true)
+ .catalogInitialization(new CatalogInitialization(null, false, null, false).addPopulationCallback(new Function<CatalogInitialization, Void>() {
+ @Override
+ public Void apply(CatalogInitialization input) {
+ throw new RuntimeException("deliberate-exception-for-testing");
+ }
+ }))
+ .start();
+ // such an error should be thrown, then caught in this calling thread
+ ManagementContext mgmt = launcher.getServerDetails().getManagementContext();
+ Assert.assertFalse( ((ManagementContextInternal)mgmt).errors().isEmpty() );
+ Assert.assertTrue( ((ManagementContextInternal)mgmt).errors().get(0).toString().contains("deliberate"), ""+((ManagementContextInternal)mgmt).errors() );
+ HttpTestUtils.assertContentMatches(
+ Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/up"),
+ "true");
+ HttpTestUtils.assertContentMatches(
+ Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/healthy"),
+ "false");
+ // TODO test errors api?
+ }
+
+ private BrooklynLauncher newLauncherForTests(boolean minimal) {
+ Preconditions.checkArgument(launcher==null, "can only be used if no launcher yet");
+ BrooklynLauncher launcher = BrooklynLauncher.newInstance();
+ if (minimal)
+ launcher.brooklynProperties(LocalManagementContextForTests.builder(true).buildProperties());
+ return launcher;
+ }
+
+ private String getMinimalLauncherPropertiesString() throws IOException {
+ BrooklynProperties p1 = LocalManagementContextForTests.builder(true).buildProperties();
+ Properties p = new Properties();
+ p.putAll(Maps.transformValues(p1.asMapWithStringKeys(), StringFunctions.toStringFunction()));
+ Writer w = new StringWriter();
+ p.store(w, "test");
+ w.close();
+ return w.toString()+"\n";
+ }
+
+ private void assertOnlyApp(BrooklynLauncher launcher, Class<? extends Application> expectedType) {
+ assertEquals(launcher.getApplications().size(), 1, "apps="+launcher.getApplications());
+ assertNotNull(Iterables.find(launcher.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+launcher.getApplications());
+ }
+
+ private void assertOnlyLocation(Application app, Class<? extends Location> expectedType) {
+ assertEquals(app.getLocations().size(), 1, "locs="+app.getLocations());
+ assertNotNull(Iterables.find(app.getLocations(), Predicates.instanceOf(LocalhostMachineProvisioningLocation.class), null), "locs="+app.getLocations());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
new file mode 100644
index 0000000..9510754
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynWebServer;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.DefaultHttpClient;
+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.basic.Entities;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.rest.BrooklynWebConfig;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+public class BrooklynWebServerTest {
+
+ public static final Logger log = LoggerFactory.getLogger(BrooklynWebServer.class);
+
+ private BrooklynProperties brooklynProperties;
+ private BrooklynWebServer webServer;
+ private List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList();
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp(){
+ brooklynProperties = BrooklynProperties.Factory.newEmpty();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ for (LocalManagementContext managementContext : managementContexts) {
+ Entities.destroyAll(managementContext);
+ }
+ managementContexts.clear();
+ if (webServer != null) webServer.stop();
+ }
+
+ private LocalManagementContext newManagementContext(BrooklynProperties brooklynProperties) {
+ LocalManagementContext result = new LocalManagementContextForTests(brooklynProperties);
+ managementContexts.add(result);
+ return result;
+ }
+
+ @Test
+ public void verifyHttp() throws Exception {
+ webServer = new BrooklynWebServer(newManagementContext(brooklynProperties));
+ try {
+ webServer.start();
+
+ HttpToolResponse response = HttpTool.execAndConsume(new DefaultHttpClient(), new HttpGet(webServer.getRootUrl()));
+ assertEquals(response.getResponseCode(), 200);
+ } finally {
+ webServer.stop();
+ }
+ }
+
+ @DataProvider(name="keystorePaths")
+ public Object[][] getKeystorePaths() {
+ return new Object[][] {
+ {getFile("server.ks")},
+ {new File(getFile("server.ks")).toURI().toString()},
+ {"classpath://server.ks"}};
+ }
+
+ @Test(dataProvider="keystorePaths")
+ public void verifyHttps(String keystoreUrl) throws Exception {
+ Map<String,?> flags = ImmutableMap.<String,Object>builder()
+ .put("httpsEnabled", true)
+ .put("keystoreUrl", keystoreUrl)
+ .put("keystorePassword", "password")
+ .build();
+ webServer = new BrooklynWebServer(flags, newManagementContext(brooklynProperties));
+ webServer.start();
+
+ try {
+ KeyStore keyStore = load("client.ks", "password");
+ KeyStore trustStore = load("client.ts", "password");
+ SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "password", trustStore, (SecureRandom)null, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+
+ HttpToolResponse response = HttpTool.execAndConsume(
+ HttpTool.httpClientBuilder()
+ .port(webServer.getActualPort())
+ .https(true)
+ .socketFactory(socketFactory)
+ .build(),
+ new HttpGet(webServer.getRootUrl()));
+ assertEquals(response.getResponseCode(), 200);
+ } finally {
+ webServer.stop();
+ }
+ }
+
+ @Test
+ public void verifyHttpsFromConfig() throws Exception {
+ brooklynProperties.put(BrooklynWebConfig.HTTPS_REQUIRED, true);
+ brooklynProperties.put(BrooklynWebConfig.KEYSTORE_URL, getFile("server.ks"));
+ brooklynProperties.put(BrooklynWebConfig.KEYSTORE_PASSWORD, "password");
+ verifyHttpsFromConfig(brooklynProperties);
+ }
+
+ @Test
+ public void verifyHttpsCiphers() throws Exception {
+ brooklynProperties.put(BrooklynWebConfig.HTTPS_REQUIRED, true);
+ brooklynProperties.put(BrooklynWebConfig.TRANSPORT_PROTOCOLS, "XXX");
+ brooklynProperties.put(BrooklynWebConfig.TRANSPORT_CIPHERS, "XXX");
+ try {
+ verifyHttpsFromConfig(brooklynProperties);
+ fail("Expected to fail due to unsupported ciphers during connection negotiation");
+ } catch (Exception e) {
+ assertTrue(Exceptions.getFirstThrowableOfType(e, SSLPeerUnverifiedException.class) != null ||
+ Exceptions.getFirstThrowableOfType(e, SSLHandshakeException.class) != null,
+ "Expected to fail due to inability to negotiate");
+ }
+ }
+
+ private void verifyHttpsFromConfig(BrooklynProperties brooklynProperties) throws Exception {
+ webServer = new BrooklynWebServer(MutableMap.of(), newManagementContext(brooklynProperties));
+ webServer.start();
+
+ try {
+ KeyStore keyStore = load("client.ks", "password");
+ KeyStore trustStore = load("client.ts", "password");
+ SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "password", trustStore, (SecureRandom)null, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+
+ HttpToolResponse response = HttpTool.execAndConsume(
+ HttpTool.httpClientBuilder()
+ .port(webServer.getActualPort())
+ .https(true)
+ .socketFactory(socketFactory)
+ .build(),
+ new HttpGet(webServer.getRootUrl()));
+ assertEquals(response.getResponseCode(), 200);
+ } finally {
+ webServer.stop();
+ }
+ }
+
+ private KeyStore load(String name, String password) throws Exception {
+ KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ FileInputStream instream = new FileInputStream(new File(getFile(name)));
+ keystore.load(instream, password.toCharArray());
+ return keystore;
+ }
+
+ @Test
+ public void testGetFileFromUrl() throws Exception {
+ // On Windows will treat as relative paths
+ String url = "file:///tmp/special%40file%20with%20spaces";
+ String file = "/tmp/special@file with spaces";
+ assertEquals(getFile(new URL(url)), new File(file).getAbsolutePath());
+ }
+
+ private String getFile(String classpathResource) {
+ // this works because both IDE and Maven run tests with classes/resources on the file system
+ return getFile(getClass().getResource("/" + classpathResource));
+ }
+
+ private String getFile(URL url) {
+ try {
+ return new File(url.toURI()).getAbsolutePath();
+ } catch (URISyntaxException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java
new file mode 100644
index 0000000..b2dfc5b
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java
@@ -0,0 +1,31 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher;
+import brooklyn.management.ManagementContext;
+import brooklyn.test.entity.LocalManagementContextForTests;
+
+public class SimpleYamlLauncherForTests extends SimpleYamlLauncher {
+
+ protected ManagementContext newManagementContext() {
+ return new LocalManagementContextForTests();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
new file mode 100644
index 0000000..3aa6334
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynWebServer;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynServerDetails;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.Entities;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.test.HttpTestUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.net.Networking;
+
+import com.google.common.collect.Lists;
+
+
+/**
+ * These tests require the brooklyn.war to work. (Should be placed by maven build.)
+ */
+public class WebAppRunnerTest {
+
+ public static final Logger log = LoggerFactory.getLogger(WebAppRunnerTest.class);
+
+ List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList();
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ for (LocalManagementContext managementContext : managementContexts) {
+ Entities.destroyAll(managementContext);
+ }
+ managementContexts.clear();
+ }
+
+ LocalManagementContext newManagementContext(BrooklynProperties brooklynProperties) {
+ LocalManagementContext result = new LocalManagementContext(brooklynProperties);
+ managementContexts.add(result);
+ return result;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ BrooklynWebServer createWebServer(Map properties) {
+ Map bigProps = MutableMap.copyOf(properties);
+ Map attributes = MutableMap.copyOf( (Map) bigProps.get("attributes") );
+ bigProps.put("attributes", attributes);
+
+ BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
+ brooklynProperties.putAll(bigProps);
+ brooklynProperties.put("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider");
+ brooklynProperties.put("brooklyn.webconsole.security.https.required","false");
+ return new BrooklynWebServer(bigProps, newManagementContext(brooklynProperties));
+ }
+
+ @Test
+ public void testStartWar1() throws Exception {
+ if (!Networking.isPortAvailable(8090))
+ fail("Another process is using port 8090 which is required for this test.");
+ BrooklynWebServer server = createWebServer(MutableMap.of("port", 8090));
+ assertNotNull(server);
+
+ try {
+ server.start();
+ assertBrooklynEventuallyAt("http://localhost:8090/");
+ } finally {
+ server.stop();
+ }
+ }
+
+ public static void assertBrooklynEventuallyAt(String url) {
+ HttpTestUtils.assertContentEventuallyContainsText(url, "Brooklyn Web Console");
+ }
+
+ @Test
+ public void testStartSecondaryWar() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+
+ if (!Networking.isPortAvailable(8090))
+ fail("Another process is using port 8090 which is required for this test.");
+ BrooklynWebServer server = createWebServer(
+ MutableMap.of("port", 8090, "war", "brooklyn.war", "wars", MutableMap.of("hello", "hello-world.war")) );
+ assertNotNull(server);
+
+ try {
+ server.start();
+
+ assertBrooklynEventuallyAt("http://localhost:8090/");
+ HttpTestUtils.assertContentEventuallyContainsText("http://localhost:8090/hello",
+ "This is the home page for a sample application");
+
+ } finally {
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testStartSecondaryWarAfter() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+
+ if (!Networking.isPortAvailable(8090))
+ fail("Another process is using port 8090 which is required for this test.");
+ BrooklynWebServer server = createWebServer(MutableMap.of("port", 8090, "war", "brooklyn.war"));
+ assertNotNull(server);
+
+ try {
+ server.start();
+ server.deploy("/hello", "hello-world.war");
+
+ assertBrooklynEventuallyAt("http://localhost:8090/");
+ HttpTestUtils.assertContentEventuallyContainsText("http://localhost:8090/hello",
+ "This is the home page for a sample application");
+
+ } finally {
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testStartWithLauncher() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+
+ BrooklynLauncher launcher = BrooklynLauncher.newInstance()
+ .brooklynProperties(BrooklynProperties.Factory.newEmpty())
+ .brooklynProperties("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider")
+ .webapp("/hello", "hello-world.war")
+ .start();
+ BrooklynServerDetails details = launcher.getServerDetails();
+
+ try {
+ details.getWebServer().deploy("/hello2", "hello-world.war");
+
+ assertBrooklynEventuallyAt(details.getWebServerUrl());
+ HttpTestUtils.assertContentEventuallyContainsText(details.getWebServerUrl()+"hello", "This is the home page for a sample application");
+ HttpTestUtils.assertContentEventuallyContainsText(details.getWebServerUrl()+"hello2", "This is the home page for a sample application");
+ HttpTestUtils.assertHttpStatusCodeEventuallyEquals(details.getWebServerUrl()+"hello0", 404);
+
+ } finally {
+ details.getWebServer().stop();
+ ((ManagementContextInternal)details.getManagementContext()).terminate();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java
new file mode 100644
index 0000000..f383895
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java
@@ -0,0 +1,35 @@
+/*
+ * 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.launcher;
+
+import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher;
+
+public class YamlLauncher {
+
+ public static void main(String[] args) {
+ SimpleYamlLauncher l = new SimpleYamlLauncher();
+ l.setShutdownAppsOnExit(true);
+
+ l.launchAppYaml("java-web-app-and-db-with-function.yaml");
+// l.launchAppYaml("java-web-app-and-memsql.yaml");
+// l.launchAppYaml("memsql.yaml");
+// l.launchAppYaml("classpath://mongo-blueprint.yaml");
+ }
+
+}