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);

Reply via email to