Repository: incubator-brooklyn Updated Branches: refs/heads/master b92d03925 -> 26c6542ce
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32cf5dea/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java new file mode 100644 index 0000000..a1add01 --- /dev/null +++ b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java @@ -0,0 +1,235 @@ +package brooklyn.launcher; + +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.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) { + 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) + .persistenceDir(dir) + .application(appSpec) + .start(); + launcher.terminate(); + launcher = null; + 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/32cf5dea/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java new file mode 100644 index 0000000..569aa57 --- /dev/null +++ b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java @@ -0,0 +1,92 @@ +package brooklyn.launcher; + +import static org.testng.Assert.assertEquals; + +import java.io.File; + +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.config.BrooklynServerConfig; +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.test.entity.TestApplication; +import brooklyn.util.javalang.JavaClassNames; +import brooklyn.util.os.Os; +import brooklyn.util.text.Identifiers; + +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) { + assertEquals(getPersistenceDir(lastMgmt()).getAbsolutePath(), expected); + } + + static File getPersistenceDir(ManagementContext managementContext) { + BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister(); + FileBasedObjectStore store = (FileBasedObjectStore)persister.getObjectStore(); + return store.getBaseDir(); + } + + protected void checkPersistenceContainerNameIsDefault() { + checkPersistenceContainerNameIs(BrooklynServerConfig.getPersistenceDir(BrooklynProperties.Factory.newDefault())); + } + + @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, "not a directory"); + runRebindFails(PersistMode.REBIND, tempFileName, "not a directory"); + runRebindFails(PersistMode.CLEAN, tempFileName, "not a directory"); + } 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); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32cf5dea/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java new file mode 100644 index 0000000..15ce172 --- /dev/null +++ b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java @@ -0,0 +1,58 @@ +package brooklyn.launcher; + +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.config.BrooklynServerConfig; +import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore; +import brooklyn.entity.rebind.persister.jclouds.JcloudsBlobStoreBasedObjectStore; +import brooklyn.management.ManagementContext; +import brooklyn.test.entity.LocalManagementContextForTests; +import brooklyn.util.javalang.JavaClassNames; +import brooklyn.util.text.Identifiers; + +@Test(groups="Integration") +// Jun 2014: Alex has confirmed setting Integration here means that inherited methods are NOT run as part of normal build +public class BrooklynLauncherRebindToCloudObjectStoreTest extends BrooklynLauncherRebindTestFixture { + + public static final String LOCATION_SPEC = "named:softlayer-objectstore-amsterdam-1"; + + { persistenceLocationSpec = LOCATION_SPEC; } + + @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(BrooklynServerConfig.PERSISTENCE_PATH_SEGMENT); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32cf5dea/utils/common/src/main/java/brooklyn/util/exceptions/FatalConfigurationRuntimeException.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/exceptions/FatalConfigurationRuntimeException.java b/utils/common/src/main/java/brooklyn/util/exceptions/FatalConfigurationRuntimeException.java new file mode 100644 index 0000000..4a57a3e --- /dev/null +++ b/utils/common/src/main/java/brooklyn/util/exceptions/FatalConfigurationRuntimeException.java @@ -0,0 +1,15 @@ +package brooklyn.util.exceptions; + +/** Exception indicating a fatal config error, typically used in CLI routines. */ +public class FatalConfigurationRuntimeException extends RuntimeException { + + private static final long serialVersionUID = -5361951925760434821L; + + public FatalConfigurationRuntimeException(String message) { + super(message); + } + + public FatalConfigurationRuntimeException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32cf5dea/utils/common/src/main/java/brooklyn/util/os/Os.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/os/Os.java b/utils/common/src/main/java/brooklyn/util/os/Os.java index 0123a7b..9257452 100644 --- a/utils/common/src/main/java/brooklyn/util/os/Os.java +++ b/utils/common/src/main/java/brooklyn/util/os/Os.java @@ -177,7 +177,7 @@ public class Os { char separatorChar = File.separatorChar; StringBuilder result = new StringBuilder(); for (String item: items) { - if (item.isEmpty()) continue; + if (Strings.isEmpty(item)) continue; if (result.length() > 0 && result.charAt(result.length()-1) != separatorChar) result.append(separatorChar); result.append(item); }