Test case improvements: config error-handling Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/386ae39a Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/386ae39a Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/386ae39a
Branch: refs/heads/master Commit: 386ae39a55df50d4cad0b2b37b5baeae2ebba7e2 Parents: 90d2781 Author: Aled Sage <aled.s...@gmail.com> Authored: Tue Jul 26 14:41:00 2016 +0100 Committer: Aled Sage <aled.s...@gmail.com> Committed: Wed Aug 3 20:56:01 2016 +0100 ---------------------------------------------------------------------- .../LoopOverGroupMembersTestCaseImpl.java | 18 ++--- .../framework/RelativeEntityTestCaseImpl.java | 11 +-- .../framework/TargetableTestComponentImpl.java | 9 ++- .../test/framework/TestEffectorImpl.java | 16 +++-- .../test/framework/TestHttpCallImpl.java | 37 +++++----- .../brooklyn/test/framework/TestSensorImpl.java | 28 +++++--- .../test/framework/TestEffectorTest.java | 51 +++++++++++--- .../brooklyn/test/framework/TestSensorTest.java | 72 ++++++++++++++------ 8 files changed, 166 insertions(+), 76 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/386ae39a/test-framework/src/main/java/org/apache/brooklyn/test/framework/LoopOverGroupMembersTestCaseImpl.java ---------------------------------------------------------------------- diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/LoopOverGroupMembersTestCaseImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/LoopOverGroupMembersTestCaseImpl.java index cbde76e..46edf2e 100644 --- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/LoopOverGroupMembersTestCaseImpl.java +++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/LoopOverGroupMembersTestCaseImpl.java @@ -20,11 +20,6 @@ package org.apache.brooklyn.test.framework; import java.util.Collection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Lists; - import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.entity.Group; @@ -34,6 +29,11 @@ import org.apache.brooklyn.core.entity.Attributes; import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; import org.apache.brooklyn.core.entity.trait.Startable; import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.guava.Maybe; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; public class LoopOverGroupMembersTestCaseImpl extends TargetableTestComponentImpl implements LoopOverGroupMembersTestCase { @@ -44,14 +44,14 @@ public class LoopOverGroupMembersTestCaseImpl extends TargetableTestComponentImp // Let everyone know we're starting up (so that the GUI shows the correct icon). sensors().set(Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STARTING); - Entity target = resolveTarget(); - if (target == null) { + Maybe<Entity> target = tryResolveTarget(); + if (!target.isPresent()) { logger.debug("Tasks NOT successfully run. LoopOverGroupMembersTestCaseImpl group not set"); setServiceState(false, Lifecycle.ON_FIRE); return; } - if (!(target instanceof Group)) { + if (!(target.get() instanceof Group)) { logger.debug("Tasks NOT successfully run. LoopOverGroupMembersTestCaseImpl target is not a group"); setServiceState(false, Lifecycle.ON_FIRE); return; @@ -65,7 +65,7 @@ public class LoopOverGroupMembersTestCaseImpl extends TargetableTestComponentImp } // Create the child-assertions (one per group-member) - Group group = (Group) target; + Group group = (Group) target.get(); Collection<Entity> members = group.getMembers(); boolean allSuccesful = true; for (Entity member : members) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/386ae39a/test-framework/src/main/java/org/apache/brooklyn/test/framework/RelativeEntityTestCaseImpl.java ---------------------------------------------------------------------- diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/RelativeEntityTestCaseImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/RelativeEntityTestCaseImpl.java index ea78e7b..5df2c81 100644 --- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/RelativeEntityTestCaseImpl.java +++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/RelativeEntityTestCaseImpl.java @@ -44,12 +44,15 @@ public class RelativeEntityTestCaseImpl extends TargetableTestComponentImpl impl public Entity resolveTarget() { Entity anchor = config().get(ANCHOR); if (anchor == null) { - anchor = super.resolveTarget(); - } - if (anchor == null) { - throw new IllegalArgumentException("No anchor entity found for " + this); + Maybe<Entity> resolvedTarget = tryResolveTarget(); + if (resolvedTarget.isPresent()) { + anchor = resolvedTarget.get(); + } else { + throw new IllegalArgumentException("No anchor entity found for " + this); + } } sensors().set(ANCHOR, anchor); + Maybe<Object> component = config().getRaw(COMPONENT); if (component.isAbsentOrNull()) { throw new IllegalArgumentException("No component found for " + this); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/386ae39a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TargetableTestComponentImpl.java ---------------------------------------------------------------------- diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TargetableTestComponentImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TargetableTestComponentImpl.java index fcfecab..cedbaa0 100644 --- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TargetableTestComponentImpl.java +++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TargetableTestComponentImpl.java @@ -33,6 +33,7 @@ import org.apache.brooklyn.core.entity.AbstractEntity; import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; import org.apache.brooklyn.util.core.task.Tasks; import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.repeat.Repeater; import org.apache.brooklyn.util.time.Duration; import org.slf4j.Logger; @@ -56,14 +57,20 @@ public abstract class TargetableTestComponentImpl extends AbstractEntity impleme */ @Override public Entity resolveTarget() { + return tryResolveTarget().get(); + } + + protected Maybe<Entity> tryResolveTarget() { Entity target = resolveTarget(getExecutionContext(), this); sensors().set(TARGET_ENTITY, target); if (target != null) { sensors().set(TARGET_ENTITY_ID, target.getId()); sensors().set(TARGET_ENTITY_NAME, target.getDisplayName()); sensors().set(TARGET_ENTITY_TYPE, target.getEntityType().getName()); + return Maybe.of(target); + } else { + return Maybe.absent("Cannot resolve target entity"); } - return target; } /** http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/386ae39a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java ---------------------------------------------------------------------- diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java index 2ff0337..3aaf712 100644 --- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java +++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestEffectorImpl.java @@ -43,6 +43,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; public class TestEffectorImpl extends TargetableTestComponentImpl implements TestEffector { + @SuppressWarnings("unused") private static final Logger LOG = LoggerFactory.getLogger(TestEffectorImpl.class); @@ -50,15 +51,16 @@ public class TestEffectorImpl extends TargetableTestComponentImpl implements Tes * {@inheritDoc} */ public void start(Collection<? extends Location> locations) { - if (!getChildren().isEmpty()) { - throw new RuntimeException(String.format("The entity [%s] cannot have child entities", getClass().getName())); - } ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); - final Entity targetEntity = resolveTarget(); - final String effectorName = getConfig(EFFECTOR_NAME); - final Map<String, ?> effectorParams = getConfig(EFFECTOR_PARAMS); - final Duration timeout = getConfig(TIMEOUT); try { + final Entity targetEntity = resolveTarget(); + final String effectorName = getRequiredConfig(EFFECTOR_NAME); + final Map<String, ?> effectorParams = getConfig(EFFECTOR_PARAMS); + final Duration timeout = getConfig(TIMEOUT); + if (!getChildren().isEmpty()) { + throw new RuntimeException(String.format("The entity [%s] cannot have child entities", getClass().getName())); + } + Maybe<Effector<?>> effector = EffectorUtils.findEffectorDeclared(targetEntity, effectorName); if (effector.isAbsentOrNull()) { throw new AssertionError(String.format("No effector with name [%s]", effectorName)); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/386ae39a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java ---------------------------------------------------------------------- diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java index cb1c313..928830f 100644 --- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java +++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java @@ -24,20 +24,18 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; - import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.core.entity.Attributes; import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.http.HttpTool; import org.apache.brooklyn.util.time.Duration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; /** * {@inheritDoc} @@ -50,21 +48,28 @@ public class TestHttpCallImpl extends TargetableTestComponentImpl implements Tes * {@inheritDoc} */ public void start(Collection<? extends Location> locations) { - if (!getChildren().isEmpty()) { - throw new RuntimeException(String.format("The entity [%s] cannot have child entities", getClass().getName())); - } + String url = null; + ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); - final String url = getConfig(TARGET_URL); - final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS); - final Duration timeout = getConfig(TIMEOUT); - final HttpAssertionTarget target = getConfig(ASSERTION_TARGET); try { + url = getRequiredConfig(TARGET_URL); + final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS); + final Duration timeout = getConfig(TIMEOUT); + final HttpAssertionTarget target = getRequiredConfig(ASSERTION_TARGET); + if (!getChildren().isEmpty()) { + throw new RuntimeException(String.format("The entity [%s] cannot have child entities", getClass().getName())); + } + doRequestAndCheckAssertions(ImmutableMap.of("timeout", timeout), assertions, target, url); setUpAndRunState(true, Lifecycle.RUNNING); } catch (Throwable t) { - LOG.info("{} Url [{}] test failed", this, url); + if (url != null) { + LOG.info("{} Url [{}] test failed (rethrowing)", this, url); + } else { + LOG.info("{} Url test failed (no url; rethrowing)", this); + } setUpAndRunState(false, Lifecycle.ON_FIRE); throw Exceptions.propagate(t); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/386ae39a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java ---------------------------------------------------------------------- diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java index 8952f62..aa8eb60 100644 --- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java +++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java @@ -23,6 +23,7 @@ import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.getAsse import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,27 +54,34 @@ public class TestSensorImpl extends TargetableTestComponentImpl implements TestS * {@inheritDoc} */ public void start(Collection<? extends Location> locations) { - if (!getChildren().isEmpty()) { - throw new RuntimeException(String.format("The entity [%s] cannot have child entities", getClass().getName())); - } + final AtomicReference<String> sensor = new AtomicReference<>(); + ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); - final Entity target = resolveTarget(); - final String sensor = getConfig(SENSOR_NAME); - final Duration timeout = getConfig(TIMEOUT); - final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS); try { - TestFrameworkAssertions.checkAssertions(ImmutableMap.of("timeout", timeout), assertions, sensor, + sensor.set(getRequiredConfig(SENSOR_NAME)); + final Entity target = resolveTarget(); + final Duration timeout = getConfig(TIMEOUT); + final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS); + if (!getChildren().isEmpty()) { + throw new RuntimeException(String.format("The entity [%s] cannot have child entities", getClass().getName())); + } + + TestFrameworkAssertions.checkAssertions(ImmutableMap.of("timeout", timeout), assertions, sensor.get(), new Supplier<Object>() { @Override public Object get() { - final Object sensorValue = target.sensors().get(Sensors.newSensor(Object.class, sensor)); + final Object sensorValue = target.sensors().get(Sensors.newSensor(Object.class, sensor.get())); return sensorValue; } }); setUpAndRunState(true, Lifecycle.RUNNING); } catch (Throwable t) { - LOG.debug("Sensor [{}] test failed", sensor); + if (sensor.get() != null) { + LOG.debug("Sensor [{}] test failed for {} (rethrowing)", sensor, TestSensorImpl.this); + } else { + LOG.debug("Sensor test failed for {} (no sensor; rethrowing)", TestSensorImpl.this); + } setUpAndRunState(false, Lifecycle.ON_FIRE); throw Exceptions.propagate(t); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/386ae39a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java ---------------------------------------------------------------------- diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java index fab67e9..91c4e0e 100644 --- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java +++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestEffectorTest.java @@ -39,6 +39,7 @@ import org.apache.brooklyn.test.framework.entity.TestEntity; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException; import org.apache.brooklyn.util.text.Identifiers; +import org.apache.brooklyn.util.time.Duration; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -179,17 +180,47 @@ public class TestEffectorTest extends BrooklynAppUnitTestSupport { } - protected void assertStartFails(TestApplication app, Class<? extends Throwable> clazz) { - try { - app.start(locs); - Asserts.shouldHaveFailedPreviously(); - } catch (PropagatedRuntimeException pre) { - final Throwable throwable = Exceptions.getFirstThrowableOfType(pre, clazz); - assertThat(throwable).isNotNull().as("A "+clazz.getSimpleName()+" should have been thrown"); - } catch (Throwable throwable) { - Asserts.expectedFailureOfType(throwable, AssertionError.class); + @Test + public void testFailFastIfNoTargetEntity() throws Exception { + testCase.addChild(EntitySpec.create(TestEffector.class) + .configure(TestEffector.EFFECTOR_NAME, "simpleEffector")); + + assertStartFails(app, IllegalStateException.class, Asserts.DEFAULT_LONG_TIMEOUT); + } + + @Test + public void testFailFastIfNoEffector() throws Exception { + testCase.addChild(EntitySpec.create(TestEffector.class) + .configure(TestEffector.TARGET_ENTITY, testEntity)); + + assertStartFails(app, NullPointerException.class, Asserts.DEFAULT_LONG_TIMEOUT); + } + + protected void assertStartFails(TestApplication app, Class<? extends Throwable> clazz) throws Exception { + assertStartFails(app, clazz, null); + } + + protected void assertStartFails(final TestApplication app, final Class<? extends Throwable> clazz, Duration execTimeout) throws Exception { + Runnable task = new Runnable() { + public void run() { + try { + app.start(locs); + Asserts.shouldHaveFailedPreviously(); + } catch (final PropagatedRuntimeException pre) { + final Throwable throwable = Exceptions.getFirstThrowableOfType(pre, clazz); + if (throwable == null) { + throw pre; + } + } + } + }; + + if (execTimeout == null) { + task.run(); + } else { + Asserts.assertReturnsEventually(task, execTimeout); } - + Entity entity = Iterables.find(Entities.descendantsWithoutSelf(app), Predicates.instanceOf(TestEffector.class)); EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/386ae39a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java ---------------------------------------------------------------------- diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java index 34bbd73..17435fe 100644 --- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java +++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java @@ -19,8 +19,6 @@ package org.apache.brooklyn.test.framework; -import static org.assertj.core.api.Assertions.assertThat; - import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -68,7 +66,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { } @Test - public void testAssertEqual() { + public void testAssertEqual() throws Exception { int testInteger = 100; //Add Sensor Test for BOOLEAN sensor @@ -101,7 +99,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { } @Test - public void testAssertEqualFailure() { + public void testAssertEqualFailure() throws Exception { //Add Sensor Test for BOOLEAN sensor app.createAndManageChild(EntitySpec.create(TestSensor.class) .configure(TestSensor.TIMEOUT, Duration.millis(10)) @@ -115,7 +113,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { } @Test - public void testAssertEqualOnNullSensor() { + public void testAssertEqualOnNullSensor() throws Exception { //Add Sensor Test for BOOLEAN sensor app.createAndManageChild(EntitySpec.create(TestSensor.class) .configure(TestSensor.TIMEOUT, Duration.millis(10)) @@ -127,7 +125,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { } @Test - public void testAssertNull() { + public void testAssertNull() throws Exception { //Add Sensor Test for BOOLEAN sensor app.createAndManageChild(EntitySpec.create(TestSensor.class) .configure(TestSensor.TARGET_ENTITY, app) @@ -148,7 +146,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { @Test - public void testAssertNullFail() { + public void testAssertNullFail() throws Exception { //Add Sensor Test for STRING sensor app.createAndManageChild(EntitySpec.create(TestSensor.class) .configure(TestSensor.TIMEOUT, Duration.millis(10)) @@ -162,7 +160,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { } @Test - public void testAssertMatches() { + public void testAssertMatches() throws Exception { final long time = System.currentTimeMillis(); final String sensorValue = String.format("%s%s%s", Identifiers.makeRandomId(8), time, Identifiers.makeRandomId(8)); @@ -185,7 +183,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { } @Test - public void testAssertMatchesFail() { + public void testAssertMatchesFail() throws Exception { final String sensorValue = String.format("%s%s%s", Identifiers.makeRandomId(8), System.currentTimeMillis(), Identifiers.makeRandomId(8)); //Add Sensor Test for STRING sensor @@ -201,7 +199,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { } @Test - public void testAssertMatchesOnNullSensor() { + public void testAssertMatchesOnNullSensor() throws Exception { //Add Sensor Test for STRING sensor app.createAndManageChild(EntitySpec.create(TestSensor.class) .configure(TestSensor.TIMEOUT, Duration.millis(10)) @@ -214,7 +212,7 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { @Test - public void testAssertMatchesOnNonStringSensor() { + public void testAssertMatchesOnNonStringSensor() throws Exception { //Add Sensor Test for OBJECT sensor app.createAndManageChild(EntitySpec.create(TestSensor.class) .configure(TestSensor.TARGET_ENTITY, app) @@ -227,15 +225,51 @@ public class TestSensorTest extends BrooklynAppUnitTestSupport { } - protected void assertStartFails(TestApplication app, Class<? extends Throwable> clazz) { - try { - app.start(locs); - Asserts.shouldHaveFailedPreviously(); - } catch (final PropagatedRuntimeException pre) { - final Throwable throwable = Exceptions.getFirstThrowableOfType(pre, clazz); - assertThat(throwable).isNotNull().as("A "+clazz.getSimpleName()+" should have been thrown"); + @Test + public void testFailFastIfNoTargetEntity() throws Exception { + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TIMEOUT, Duration.ONE_MINUTE) + .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName()) + .configure(TestSensor.ASSERTIONS, newMapAssertion("isNull", true))); + + assertStartFails(app, IllegalStateException.class, Asserts.DEFAULT_LONG_TIMEOUT); + } + + @Test + public void testFailFastIfNoSensor() throws Exception { + app.createAndManageChild(EntitySpec.create(TestSensor.class) + .configure(TestSensor.TIMEOUT, Duration.ONE_MINUTE) + .configure(TestSensor.TARGET_ENTITY, app) + .configure(TestSensor.ASSERTIONS, newMapAssertion("isNull", true))); + + assertStartFails(app, NullPointerException.class, Asserts.DEFAULT_LONG_TIMEOUT); + } + + protected void assertStartFails(TestApplication app, Class<? extends Throwable> clazz) throws Exception { + assertStartFails(app, clazz, null); + } + + protected void assertStartFails(final TestApplication app, final Class<? extends Throwable> clazz, Duration execTimeout) throws Exception { + Runnable task = new Runnable() { + public void run() { + try { + app.start(locs); + Asserts.shouldHaveFailedPreviously(); + } catch (final PropagatedRuntimeException pre) { + final Throwable throwable = Exceptions.getFirstThrowableOfType(pre, clazz); + if (throwable == null) { + throw pre; + } + } + } + }; + + if (execTimeout == null) { + task.run(); + } else { + Asserts.assertReturnsEventually(task, execTimeout); } - + Entity entity = Iterables.find(Entities.descendantsWithoutSelf(app), Predicates.instanceOf(TestSensor.class)); EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE); EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);