You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/08/30 01:01:20 UTC

[20/26] git commit: fix all tests and related entities to get service lifecycle, including REST app creation attaching all interfaces (previously it did not get "startable" so entities did not start)

fix all tests and related entities to get service lifecycle, including REST app creation attaching all interfaces (previously it did not get "startable" so entities did not start)


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/5db500e4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/5db500e4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/5db500e4

Branch: refs/heads/master
Commit: 5db500e43fbc1973d5b941ff41f681e51c134217
Parents: bfb8737
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Aug 26 08:46:02 2014 -0500
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Wed Aug 27 02:21:22 2014 -0400

----------------------------------------------------------------------
 .../main/java/brooklyn/enricher/Enrichers.java  |  4 +--
 .../entity/basic/AbstractApplication.java       |  3 +-
 .../entity/basic/ServiceStateLogic.java         | 23 +++++++------
 .../java/brooklyn/enricher/EnrichersTest.java   | 34 +++++++++++++++++++-
 .../enricher/basic/BasicEnricherTest.java       | 13 +++++++-
 .../entity/BrooklynAppUnitTestSupport.java      |  4 +++
 .../entity/brooklyn/BrooklynMetricsTest.java    | 13 +++++---
 .../autoscaling/AutoScalerPolicyTest.java       |  2 +-
 .../policy/ha/ServiceFailureDetectorTest.java   | 10 ++++--
 .../brooklyn/entity/basic/SameServerEntity.java |  4 +++
 .../entity/basic/SameServerEntityImpl.java      |  6 ++++
 .../ControlledDynamicWebAppClusterTest.java     | 17 ++++++----
 .../entity/webapp/DynamicWebAppClusterTest.java | 12 ++++---
 .../test/entity/TestJavaWebAppEntity.java       |  6 ++++
 .../camp/brooklyn/EnrichersYamlTest.java        | 23 +++++++------
 .../camp/brooklyn/EntitiesYamlTest.java         |  2 +-
 .../rest/util/BrooklynRestResourceUtils.java    |  2 +-
 .../rest/resources/ApplicationResourceTest.java |  9 ++++--
 .../rest/testing/BrooklynRestResourceTest.java  | 26 ++++++++++++---
 .../rest/testing/mocks/RestMockAppBuilder.java  |  5 ++-
 .../testing/mocks/RestMockSimpleEntity.java     | 11 ++++---
 .../java/brooklyn/test/EntityTestUtils.java     |  1 +
 22 files changed, 171 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/core/src/main/java/brooklyn/enricher/Enrichers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/Enrichers.java b/core/src/main/java/brooklyn/enricher/Enrichers.java
index 73b7a3b..48b7a56 100644
--- a/core/src/main/java/brooklyn/enricher/Enrichers.java
+++ b/core/src/main/java/brooklyn/enricher/Enrichers.java
@@ -95,11 +95,11 @@ public class Enrichers {
 
         protected abstract String getDefaultUniqueTag();
         
-        protected EnricherSpec<?> build() {
+        protected EnricherSpec<? extends Enricher> build() {
             EnricherSpec<? extends Enricher> spec = EnricherSpec.create(enricherType);
             
             String uniqueTag2 = uniqueTag;
-            if (uniqueTag!=null)
+            if (uniqueTag2==null)
                 uniqueTag2 = getDefaultUniqueTag();
             if (uniqueTag2!=null)
                 spec.uniqueTag(uniqueTag2);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java b/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
index 35e0083..961906f 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
@@ -27,7 +27,6 @@ import org.slf4j.LoggerFactory;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.entity.Application;
 import brooklyn.entity.Entity;
-import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic;
 import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic;
 import brooklyn.entity.trait.StartableMethods;
 import brooklyn.location.Location;
@@ -58,8 +57,8 @@ public abstract class AbstractApplication extends AbstractEntity implements Star
     }
 
     public void init() { 
-        initApp();
         super.init();
+        initApp();
     }
     
     protected void initApp() {}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
index e3d5090..749c83d 100644
--- a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
+++ b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
@@ -121,6 +121,8 @@ public class ServiceStateLogic {
     }
     
     public static class ServiceNotUpLogic {
+        public static final String DEFAULT_ENRICHER_UNIQUE_TAG = "service.isUp if no service.notUp.indicators";
+        
         /** static only; not for instantiation */
         private ServiceNotUpLogic() {}
         
@@ -132,7 +134,7 @@ public class ServiceStateLogic {
                     Functionals.<Map<String,?>>
                         ifNotEquals(null).<Object>apply(Functions.forPredicate(CollectionFunctionals.<String>mapSizeEquals(0)))
                         .defaultValue(Entities.REMOVE) )
-                .uniqueTag("service.isUp if no service.notUp.indicators")
+                .uniqueTag(DEFAULT_ENRICHER_UNIQUE_TAG)
                 .build();
         }
         
@@ -170,13 +172,16 @@ public class ServiceStateLogic {
      * {@link ServiceStateLogic#newEnricherForServiceState(Class)} and added to an entity.
      */
     public static class ComputeServiceState extends AbstractEnricher implements SensorEventListener<Object> {
+        
+        public static final String DEFAULT_ENRICHER_UNIQUE_TAG = "service.state.actual";
+
         public ComputeServiceState() {}
         public ComputeServiceState(Map<?,?> flags) { super(flags); }
             
         @Override
         public void init() {
             super.init();
-            if (uniqueTag==null) uniqueTag = "service.state.actual";
+            if (uniqueTag==null) uniqueTag = DEFAULT_ENRICHER_UNIQUE_TAG;
         }
         
         public void setEntity(EntityLocal entity) {
@@ -277,10 +282,10 @@ public class ServiceStateLogic {
     
     public static class ComputeServiceIndicatorsFromChildrenAndMembers extends AbstractMultipleSensorAggregator<Void> implements SensorEventListener<Object> {
         /** standard unique tag identifying instances of this enricher at runtime, also used for the map sensor if no unique tag specified */
-        public final static String IDENTIFIER_DEFAULT = "service-lifecycle-indicators-from-children-and-members";
+        public final static String DEFAULT_UNIQUE_TAG = "service-lifecycle-indicators-from-children-and-members";
         
-        /** as {@link #IDENTIFIER_LIFECYCLE}, but when a second distinct instance is responsible for computing service up */
-        public final static String IDENTIFIER_UP = "service-not-up-indicators-from-children-and-members";
+        /** as {@link #DEFAULT_UNIQUE_TAG}, but when a second distinct instance is responsible for computing service up */
+        public final static String DEFAULT_UNIQUE_TAG_UP = "service-not-up-indicators-from-children-and-members";
 
         public static final ConfigKey<QuorumCheck> UP_QUORUM_CHECK = ConfigKeys.newConfigKey(QuorumCheck.class, "enricher.service_state.children_and_members.quorum.up", 
             "Logic for checking whether this service is up, based on children and/or members, defaulting to allowing none but if there are any requiring at least one to be up", QuorumCheck.QuorumChecks.atLeastOneUnlessEmpty());
@@ -457,22 +462,22 @@ public class ServiceStateLogic {
     }
 
     /** provides the default {@link ComputeServiceIndicatorsFromChildrenAndMembers} enricher, 
-     * using the default unique tag ({@link ComputeServiceIndicatorsFromChildrenAndMembers#IDENTIFIER_DEFAULT}),
+     * using the default unique tag ({@link ComputeServiceIndicatorsFromChildrenAndMembers#DEFAULT_UNIQUE_TAG}),
      * configured here to require none on fire, and either no children or at least one up child,
      * the spec can be further configured as appropriate */
     public static ComputeServiceIndicatorsFromChildrenAndMembersSpec newEnricherFromChildren() {
         return new ComputeServiceIndicatorsFromChildrenAndMembersSpec()
-            .uniqueTag(ComputeServiceIndicatorsFromChildrenAndMembers.IDENTIFIER_DEFAULT);
+            .uniqueTag(ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG);
     }
 
     /** as {@link #newEnricherFromChildren()} but only publishing service not-up indicators, 
-     * using a different unique tag ({@link ComputeServiceIndicatorsFromChildrenAndMembers#IDENTIFIER_UP}),
+     * using a different unique tag ({@link ComputeServiceIndicatorsFromChildrenAndMembers#DEFAULT_UNIQUE_TAG_UP}),
      * listening to children only, ignoring lifecycle/service-state,
      * and using the same logic 
      * (viz looking only at children (not members) and requiring either no children or at least one child up) by default */
     public static ComputeServiceIndicatorsFromChildrenAndMembersSpec newEnricherFromChildrenUp() {
         return newEnricherFromChildren()
-            .uniqueTag(ComputeServiceIndicatorsFromChildrenAndMembers.IDENTIFIER_UP)
+            .uniqueTag(ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG_UP)
             .checkChildrenOnly()
             .configure(ComputeServiceIndicatorsFromChildrenAndMembers.DERIVE_SERVICE_PROBLEMS, false);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/core/src/test/java/brooklyn/enricher/EnrichersTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/enricher/EnrichersTest.java b/core/src/test/java/brooklyn/enricher/EnrichersTest.java
index 66d1bdd..aeffe6a 100644
--- a/core/src/test/java/brooklyn/enricher/EnrichersTest.java
+++ b/core/src/test/java/brooklyn/enricher/EnrichersTest.java
@@ -19,24 +19,33 @@
 package brooklyn.enricher;
 
 import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.entity.Entity;
 import brooklyn.entity.basic.BasicGroup;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntitySubscriptionTest.RecordingSensorEventListener;
+import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
+import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceState;
+import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.basic.Sensors;
+import brooklyn.policy.Enricher;
 import brooklyn.test.Asserts;
 import brooklyn.test.EntityTestUtils;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.util.collections.CollectionFunctionals;
+import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.guava.Functionals;
@@ -54,6 +63,27 @@ import com.google.common.reflect.TypeToken;
 @SuppressWarnings("serial")
 public class EnrichersTest extends BrooklynAppUnitTestSupport {
 
+    public static List<Enricher> getNonSystemEnrichers(Entity entity) {
+        List<Enricher> result = MutableList.copyOf(entity.getEnrichers());
+        Iterator<Enricher> ri = result.iterator();
+        while (ri.hasNext()) {
+            if (isSystemEnricher(ri.next())) ri.remove();
+        }
+        return result;
+    }
+
+    public static final List<String> SYSTEM_ENRICHER_UNIQUE_TAGS = ImmutableList.of(
+        ServiceNotUpLogic.DEFAULT_ENRICHER_UNIQUE_TAG,
+        ComputeServiceState.DEFAULT_ENRICHER_UNIQUE_TAG,
+        ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG,
+        ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG_UP);
+    
+    public static boolean isSystemEnricher(Enricher enr) {
+        if (enr.getUniqueTag()==null) return false;
+        if (SYSTEM_ENRICHER_UNIQUE_TAGS.contains(enr.getUniqueTag())) return true;
+        return false;
+    }
+    
     public static final AttributeSensor<Integer> NUM1 = Sensors.newIntegerSensor("test.num1");
     public static final AttributeSensor<Integer> NUM2 = Sensors.newIntegerSensor("test.num2");
     public static final AttributeSensor<Integer> NUM3 = Sensors.newIntegerSensor("test.num3");
@@ -81,12 +111,14 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
     @SuppressWarnings("unchecked")
     @Test
     public void testAdding() {
-        entity.addEnricher(Enrichers.builder()
+        Enricher enr = entity.addEnricher(Enrichers.builder()
                 .combining(NUM1, NUM2)
                 .publishing(NUM3)
                 .computingSum()
                 .build());
         
+        Assert.assertEquals(EnrichersTest.getNonSystemEnrichers(entity), ImmutableList.of(enr));
+        
         entity.setAttribute(NUM1, 2);
         entity.setAttribute(NUM2, 3);
         EntityTestUtils.assertAttributeEqualsEventually(entity, NUM3, 5);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java b/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java
index 59bc7e8..8d6ed80 100644
--- a/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java
+++ b/core/src/test/java/brooklyn/enricher/basic/BasicEnricherTest.java
@@ -29,9 +29,14 @@ import com.google.common.collect.Iterables;
 
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.BrooklynConfigKeys;
+import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.basic.BasicConfigKey;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.EnricherSpec;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestApplicationNoEnrichersImpl;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.flags.SetFromFlag;
 
@@ -42,7 +47,13 @@ public class BasicEnricherTest extends BrooklynAppUnitTestSupport {
     
     // TODO These tests are a copy of BasicPolicyTest, which is a code smell.
     // However, the src/main/java code does not contain as much duplication.
-    
+
+    protected void setUpApp() {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class, TestApplicationNoEnrichersImpl.class)
+                .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution());
+        app = ApplicationBuilder.newManagedApp(appSpec, mgmt);
+    }
+
     public static class MyEnricher extends AbstractEnricher {
         @SetFromFlag("intKey")
         public static final BasicConfigKey<Integer> INT_KEY = new BasicConfigKey<Integer>(Integer.class, "bkey", "b key");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java b/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java
index 523a6e2..bad3b1a 100644
--- a/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java
+++ b/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java
@@ -52,6 +52,10 @@ public class BrooklynAppUnitTestSupport {
         if (mgmt == null) {
             mgmt = new LocalManagementContextForTests();
         }
+        setUpApp();
+    }
+
+    protected void setUpApp() {
         EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class)
                 .configure(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, shouldSkipOnBoxBaseDirResolution());
         app = ApplicationBuilder.newManagedApp(appSpec, mgmt);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/policy/src/test/java/brooklyn/entity/brooklyn/BrooklynMetricsTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/entity/brooklyn/BrooklynMetricsTest.java b/policy/src/test/java/brooklyn/entity/brooklyn/BrooklynMetricsTest.java
index 319b345..1c12319 100644
--- a/policy/src/test/java/brooklyn/entity/brooklyn/BrooklynMetricsTest.java
+++ b/policy/src/test/java/brooklyn/entity/brooklyn/BrooklynMetricsTest.java
@@ -26,13 +26,17 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.BrooklynConfigKeys;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.SensorEventListener;
 import brooklyn.location.basic.SimulatedLocation;
 import brooklyn.test.Asserts;
+import brooklyn.test.entity.LocalManagementContextForTests;
 import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestApplicationNoEnrichersImpl;
 import brooklyn.test.entity.TestEntity;
 import brooklyn.test.entity.TestEntityNoEnrichersImpl;
 import brooklyn.util.collections.MutableMap;
@@ -43,7 +47,7 @@ import com.google.common.collect.ImmutableList;
 public class BrooklynMetricsTest {
 
     private static final long TIMEOUT_MS = 2*1000;
-    private final static int DEFAULT_SUBSCRIPTIONS_PER_ENTITY = 2;
+    private final static int NUM_SUBSCRIPTIONS_PER_ENTITY = 4;
     
     TestApplication app;
     SimulatedLocation loc;
@@ -52,7 +56,8 @@ public class BrooklynMetricsTest {
     @BeforeMethod(alwaysRun=true)
     public void setUp() {
         loc = new SimulatedLocation();
-        app = TestApplication.Factory.newManagedInstanceForTests();
+        app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class, TestApplicationNoEnrichersImpl.class),
+            LocalManagementContextForTests.newInstance());
         brooklynMetrics = app.createAndManageChild(EntitySpec.create(BrooklynMetrics.class).configure("updatePeriod", 10L));
     }
     
@@ -73,7 +78,7 @@ public class BrooklynMetricsTest {
                 assertEquals(brooklynMetrics.getAttribute(BrooklynMetrics.NUM_ACTIVE_TASKS), (Long)0L);
                 assertTrue(brooklynMetrics.getAttribute(BrooklynMetrics.TOTAL_EVENTS_PUBLISHED) > 0);
                 assertEquals(brooklynMetrics.getAttribute(BrooklynMetrics.TOTAL_EVENTS_DELIVERED), (Long)0L);
-                assertEquals(brooklynMetrics.getAttribute(BrooklynMetrics.NUM_SUBSCRIPTIONS), (Long)(2L*DEFAULT_SUBSCRIPTIONS_PER_ENTITY));
+                assertEquals(brooklynMetrics.getAttribute(BrooklynMetrics.NUM_SUBSCRIPTIONS), (Long)(0L+NUM_SUBSCRIPTIONS_PER_ENTITY));
             }});
     }
     
@@ -112,7 +117,7 @@ public class BrooklynMetricsTest {
                 assertTrue(brooklynMetrics.getAttribute(BrooklynMetrics.TOTAL_EVENTS_PUBLISHED) > eventsPublished);
                 assertTrue(brooklynMetrics.getAttribute(BrooklynMetrics.TOTAL_EVENTS_DELIVERED) > eventsDelivered);
                 assertEquals(brooklynMetrics.getAttribute(BrooklynMetrics.NUM_SUBSCRIPTIONS), (Long)
-                    (1L + 2*DEFAULT_SUBSCRIPTIONS_PER_ENTITY));
+                    (1L + NUM_SUBSCRIPTIONS_PER_ENTITY));
             }});
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyTest.java b/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyTest.java
index 1bc8a3b..eeab7cd 100644
--- a/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyTest.java
+++ b/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyTest.java
@@ -69,7 +69,7 @@ public class AutoScalerPolicyTest {
     
     @BeforeMethod(alwaysRun=true)
     public void setUp() throws Exception {
-        app = ApplicationBuilder.newManagedApp(TestApplication.class);
+        app = TestApplication.Factory.newManagedInstanceForTests();
         cluster = app.createAndManageChild(EntitySpec.create(TestCluster.class).configure(TestCluster.INITIAL_SIZE, 1));
         resizable = new LocallyResizableEntity(cluster, cluster);
         Entities.manage(resizable);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/policy/src/test/java/brooklyn/policy/ha/ServiceFailureDetectorTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/ha/ServiceFailureDetectorTest.java b/policy/src/test/java/brooklyn/policy/ha/ServiceFailureDetectorTest.java
index 5c9dd66..2741ef6 100644
--- a/policy/src/test/java/brooklyn/policy/ha/ServiceFailureDetectorTest.java
+++ b/policy/src/test/java/brooklyn/policy/ha/ServiceFailureDetectorTest.java
@@ -30,6 +30,7 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.Lifecycle;
 import brooklyn.entity.basic.ServiceStateLogic;
@@ -55,7 +56,7 @@ import com.google.common.base.Predicates;
 
 public class ServiceFailureDetectorTest {
 
-    private static final int TIMEOUT_MS = 1*1000;
+    private static final int TIMEOUT_MS = 10*1000;
 
     private ManagementContext managementContext;
     private TestApplication app;
@@ -206,13 +207,14 @@ public class ServiceFailureDetectorTest {
     }
     
     @Test
-    public void testDisablingSetsOnFireOnFailure() throws Exception {
+    public void testDisablingOnFire() throws Exception {
         e1.addEnricher(EnricherSpec.create(ServiceFailureDetector.class)
             .configure(ServiceFailureDetector.SERVICE_ON_FIRE_STABILIZATION_DELAY, Duration.PRACTICALLY_FOREVER));
         
         // Make the entity fail
         e1.setAttribute(TestEntity.SERVICE_UP, true);
         ServiceStateLogic.setExpectedState(e1, Lifecycle.RUNNING);
+        EntityTestUtils.assertAttributeEqualsEventually(e1, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
         e1.setAttribute(TestEntity.SERVICE_UP, false);
 
         assertEquals(e1.getAttribute(TestEntity.SERVICE_STATE_ACTUAL), Lifecycle.RUNNING);
@@ -226,6 +228,8 @@ public class ServiceFailureDetectorTest {
         // Make the entity fail
         e1.setAttribute(TestEntity.SERVICE_UP, true);
         ServiceStateLogic.setExpectedState(e1, Lifecycle.RUNNING);
+        EntityTestUtils.assertAttributeEqualsEventually(e1, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        
         e1.setAttribute(TestEntity.SERVICE_UP, false);
 
         assertEquals(e1.getAttribute(TestEntity.SERVICE_STATE_ACTUAL), Lifecycle.RUNNING);
@@ -244,7 +248,7 @@ public class ServiceFailureDetectorTest {
         e1.setAttribute(TestEntity.SERVICE_UP, true);
         ServiceStateLogic.setExpectedState(e1, Lifecycle.RUNNING);
 
-        assertEquals(e1.getAttribute(TestEntity.SERVICE_STATE_ACTUAL), Lifecycle.RUNNING);
+        EntityTestUtils.assertAttributeEqualsEventually(e1, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
         ServiceStateLogic.ServiceProblemsLogic.updateProblemsIndicator(e1, "test", "foo");
         
         assertEquals(e1.getAttribute(TestEntity.SERVICE_STATE_ACTUAL), Lifecycle.RUNNING);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
index f7ddddd..09a2cc4 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
@@ -22,6 +22,7 @@ import java.util.Map;
 
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
 import brooklyn.entity.proxying.ImplementedBy;
 import brooklyn.entity.trait.Startable;
 import brooklyn.event.AttributeSensor;
@@ -51,6 +52,9 @@ public interface SameServerEntity extends Entity, Startable {
             "provisioning.properties", "Custom properties to be passed in when provisioning a new machine",
             MutableMap.<String, Object>of());
     
+    ConfigKey<QuorumCheck> UP_QUORUM_CHECK = ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK;
+    ConfigKey<QuorumCheck> RUNNING_QUORUM_CHECK = ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK;
+
     AttributeSensor<Lifecycle> SERVICE_STATE_ACTUAL = Attributes.SERVICE_STATE_ACTUAL;
 
     @SuppressWarnings("rawtypes")

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
index f509249..40a7db2 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
@@ -32,6 +32,12 @@ public class SameServerEntityImpl extends AbstractEntity implements SameServerEn
 
     private static final MachineLifecycleEffectorTasks LIFECYCLE_TASKS = new SameServerDriverLifecycleEffectorTasks();
 
+    @Override
+    protected void initEnrichers() {
+        super.initEnrichers();
+        addEnricher(ServiceStateLogic.newEnricherFromChildren());
+    }
+    
     /**
      * Restarts the entity and its children.
      * <p/>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/software/webapp/src/test/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java b/software/webapp/src/test/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java
index df486aa..f80d10c 100644
--- a/software/webapp/src/test/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java
+++ b/software/webapp/src/test/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterTest.java
@@ -52,15 +52,15 @@ import brooklyn.test.EntityTestUtils;
 import brooklyn.test.HttpTestUtils;
 import brooklyn.test.entity.TestApplication;
 import brooklyn.test.entity.TestJavaWebAppEntity;
+import brooklyn.util.collections.CollectionFunctionals;
 import brooklyn.util.collections.MutableMap;
+import brooklyn.util.guava.Functionals;
 
+import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
-/**
- * TODO clarify test purpose
- */
 public class ControlledDynamicWebAppClusterTest {
     private static final Logger log = LoggerFactory.getLogger(ControlledDynamicWebAppClusterTest.class);
 
@@ -76,7 +76,7 @@ public class ControlledDynamicWebAppClusterTest {
         String warPath = "hello-world.war";
         warUrl = getClass().getClassLoader().getResource(warPath);
         
-        app = ApplicationBuilder.newManagedApp(TestApplication.class);
+        app = TestApplication.Factory.newManagedInstanceForTests();
         loc = new LocalhostMachineProvisioningLocation();
         locs = ImmutableList.of(loc);
     }
@@ -201,14 +201,19 @@ public class ControlledDynamicWebAppClusterTest {
                 .configure("initialSize", 1)
                 .configure("factory", new BasicConfigurableEntityFactory<TestJavaWebAppEntity>(TestJavaWebAppEntity.class)));
         
+        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        
         RecordingSensorEventListener<Lifecycle> listener = new RecordingSensorEventListener<Lifecycle>(true);
-        app.subscribe(cluster, Attributes.SERVICE_STATE, listener);
+        app.subscribe(cluster, Attributes.SERVICE_STATE_ACTUAL, listener);
         app.start(locs);
-
+        
+        Asserts.eventually(Suppliers.ofInstance(listener.getValues()), CollectionFunctionals.sizeEquals(2));
         assertEquals(listener.getValues(), ImmutableList.of(Lifecycle.STARTING, Lifecycle.RUNNING), "vals="+listener.getValues());
         listener.getValues().clear();
         
         app.stop();
+        EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        Asserts.eventually(Suppliers.ofInstance(listener.getValues()), CollectionFunctionals.sizeEquals(2));
         assertEquals(listener.getValues(), ImmutableList.of(Lifecycle.STOPPING, Lifecycle.STOPPED), "vals="+listener.getValues());
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/software/webapp/src/test/java/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/brooklyn/entity/webapp/DynamicWebAppClusterTest.java b/software/webapp/src/test/java/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
index 1cec3c9..8def438 100644
--- a/software/webapp/src/test/java/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
+++ b/software/webapp/src/test/java/brooklyn/entity/webapp/DynamicWebAppClusterTest.java
@@ -109,21 +109,23 @@ public class DynamicWebAppClusterTest {
     
         app.start(ImmutableList.of(new SimulatedLocation()));
         
-        // Should initially be false (when child has no service_up value) 
-        EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), cluster, DynamicWebAppCluster.SERVICE_UP, false);
+        // Should initially be true (now that TestJavaWebAppEntity sets true) 
+        EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), cluster, DynamicWebAppCluster.SERVICE_UP, true);
         
-        // When child is !service_up, should continue to report false
+        // When child is !service_up, should report false
         ((EntityLocal)Iterables.get(cluster.getMembers(), 0)).setAttribute(Startable.SERVICE_UP, false);
+        EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), cluster, DynamicWebAppCluster.SERVICE_UP, false);
         EntityTestUtils.assertAttributeEqualsContinually(MutableMap.of("timeout", SHORT_WAIT_MS), cluster, DynamicWebAppCluster.SERVICE_UP, false);
         
         cluster.resize(2);
         
         // When one of the two children is service_up, should report true
-        ((EntityLocal)Iterables.get(cluster.getMembers(), 0)).setAttribute(Startable.SERVICE_UP, true);
         EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), cluster, DynamicWebAppCluster.SERVICE_UP, true);
 
         // And if that serviceUp child goes away, should again report false
-        Entities.unmanage(Iterables.get(cluster.getMembers(), 0));
+        Entities.unmanage(Iterables.get(cluster.getMembers(), 1));
+        ((EntityLocal)Iterables.get(cluster.getMembers(), 0)).setAttribute(Startable.SERVICE_UP, false);
+        
         EntityTestUtils.assertAttributeEqualsEventually(MutableMap.of("timeout", TIMEOUT_MS), cluster, DynamicWebAppCluster.SERVICE_UP, false);
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java b/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java
index 96edbcd..9a3e08a 100644
--- a/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java
+++ b/software/webapp/src/test/java/brooklyn/test/entity/TestJavaWebAppEntity.java
@@ -26,7 +26,10 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.Effector;
 import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.Lifecycle;
 import brooklyn.entity.basic.MethodEffector;
+import brooklyn.entity.basic.ServiceStateLogic;
 import brooklyn.entity.basic.SoftwareProcessImpl;
 import brooklyn.entity.effector.EffectorAndBody;
 import brooklyn.entity.java.VanillaJavaAppImpl;
@@ -52,7 +55,10 @@ public class TestJavaWebAppEntity extends VanillaJavaAppImpl {
 
     
 	public void customStart(Collection<? extends Location> loc) {
+	    ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
         LOG.trace("Starting {}", this);
+        ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING);
+        setAttribute(Attributes.SERVICE_UP, true);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EnrichersYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EnrichersYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EnrichersYamlTest.java
index e3b0352..7d3feaf 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EnrichersYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EnrichersYamlTest.java
@@ -18,6 +18,7 @@
  */
 package io.brooklyn.camp.brooklyn;
 
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
 
@@ -27,6 +28,7 @@ import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import brooklyn.config.ConfigKey;
+import brooklyn.enricher.EnrichersTest;
 import brooklyn.enricher.basic.Propagator;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.Entities;
@@ -55,8 +57,8 @@ public class EnrichersYamlTest extends AbstractYamlTest {
         log.info("App started:");
         Entities.dumpInfo(app);
         
-        Assert.assertEquals(app.getEnrichers().size(), 1);
-        final Enricher enricher = app.getEnrichers().iterator().next();
+        Assert.assertEquals(EnrichersTest.getNonSystemEnrichers(app).size(), 1);
+        final Enricher enricher = EnrichersTest.getNonSystemEnrichers(app).iterator().next();
         Assert.assertTrue(enricher instanceof TestEnricher, "enricher="+enricher);
         Assert.assertEquals(enricher.getConfig(TestEnricher.CONF_NAME), "Name from YAML");
         Assert.assertEquals(enricher.getConfig(TestEnricher.CONF_FROM_FUNCTION), "$brooklyn: is a fun place");
@@ -88,16 +90,16 @@ public class EnrichersYamlTest extends AbstractYamlTest {
         log.info("App started:");
         Entities.dumpInfo(app);
 
-        Assert.assertEquals(app.getEnrichers().size(), 0);
+        Assert.assertEquals(EnrichersTest.getNonSystemEnrichers(app).size(), 0);
         Assert.assertEquals(app.getChildren().size(), 1);
         final Entity child = app.getChildren().iterator().next();
         Asserts.eventually(new Supplier<Integer>() {
             @Override
             public Integer get() {
-                return child.getEnrichers().size();
+                return EnrichersTest.getNonSystemEnrichers(child).size();
             }
         }, Predicates.<Integer> equalTo(1));        
-        final Enricher enricher = child.getEnrichers().iterator().next();
+        final Enricher enricher = EnrichersTest.getNonSystemEnrichers(child).iterator().next();
         Assert.assertNotNull(enricher);
         Assert.assertTrue(enricher instanceof TestEnricher, "enricher=" + enricher + "; type=" + enricher.getClass());
         Assert.assertEquals(enricher.getConfig(TestEnricher.CONF_NAME), "Name from YAML");
@@ -149,10 +151,10 @@ public class EnrichersYamlTest extends AbstractYamlTest {
         Asserts.eventually(new Supplier<Integer>() {
             @Override
             public Integer get() {
-                return parentEntity.getEnrichers().size();
+                return EnrichersTest.getNonSystemEnrichers(parentEntity).size();
             }
         }, Predicates.<Integer>equalTo(1));
-        Enricher enricher = parentEntity.getEnrichers().iterator().next();
+        Enricher enricher = EnrichersTest.getNonSystemEnrichers(parentEntity).iterator().next();
         Asserts.assertTrue(enricher instanceof Propagator, "Expected enricher to be Propagator, found:" + enricher);
         final Propagator propagator = (Propagator)enricher;
         Entity producer = ((EntityInternal)parentEntity).getExecutionContext().submit(MutableMap.of(), new Callable<Entity>() {
@@ -240,9 +242,10 @@ public class EnrichersYamlTest extends AbstractYamlTest {
     }
     
     private Enricher getEnricher(Entity entity) {
-        Assert.assertEquals(entity.getEnrichers().size(), 1);
-        Enricher enricher = entity.getEnrichers().iterator().next();
-        Assert.assertTrue(enricher instanceof TestReferencingEnricher);
+        List<Enricher> enrichers = EnrichersTest.getNonSystemEnrichers(entity);
+        Assert.assertEquals(enrichers.size(), 1, "Wrong number of enrichers: "+enrichers);
+        Enricher enricher = enrichers.iterator().next();
+        Assert.assertTrue(enricher instanceof TestReferencingEnricher, "Wrong enricher: "+enricher);
         return enricher;
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java
index 14c7c10..53bb4aa 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/EntitiesYamlTest.java
@@ -602,7 +602,7 @@ public class EntitiesYamlTest extends AbstractYamlTest {
         Entity app = createAndStartApplication(loadYaml("same-server-entity-test.yaml"));
         waitForApplicationTasks(app);
         assertNotNull(app);
-        assertEquals(app.getAttribute(Attributes.SERVICE_STATE), Lifecycle.RUNNING, "service state");
+        assertEquals(app.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.RUNNING, "service state");
         assertTrue(app.getAttribute(Attributes.SERVICE_UP), "service up");
 
         assertEquals(app.getChildren().size(), 1);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
index 7075fa5..7c86d6a 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -341,7 +341,7 @@ public class BrooklynRestResourceUtils {
         if (clazz.isInterface()) {
             result = brooklyn.entity.proxying.EntitySpec.create(clazz);
         } else {
-            result = brooklyn.entity.proxying.EntitySpec.create(Entity.class).impl(clazz);
+            result = brooklyn.entity.proxying.EntitySpec.create(Entity.class).impl(clazz).additionalInterfaces(Reflections.getAllInterfaces(clazz));
         }
         if (!Strings.isEmpty(name)) result.displayName(name);
         result.configure( convertFlagsToKeys(result.getType(), config) );

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java
index 47e4b2c..2b36c5d 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/resources/ApplicationResourceTest.java
@@ -71,6 +71,8 @@ import brooklyn.test.Asserts;
 import brooklyn.test.HttpTestUtils;
 import brooklyn.util.collections.CollectionFunctionals;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
 
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
@@ -82,6 +84,7 @@ import com.sun.jersey.api.client.ClientHandlerException;
 import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.GenericType;
 import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
 import com.sun.jersey.core.util.MultivaluedMapImpl;
 
 @Test(singleThreaded = true)
@@ -196,7 +199,7 @@ public class ApplicationResourceTest extends BrooklynRestResourceTest {
     
     // Expect app to be running
     URI appUri = response.getLocation();
-    waitForApplicationToBeRunning(response.getLocation());
+    waitForApplicationToBeRunning(response.getLocation(), Duration.TEN_SECONDS);
     assertEquals(client().resource(appUri).get(ApplicationSummary.class).getSpec().getName(), "simple-app-builder");
     
     // Expect app to have the child-entity
@@ -452,8 +455,8 @@ public class ApplicationResourceTest extends BrooklynRestResourceTest {
 
   @Test(dependsOnMethods = "testTriggerSampleEffector")
   public void testBatchSensorValues() {
-    Map<String,String> sensors = client().resource("/v1/applications/simple-app/entities/simple-ent/sensors/current-state")
-        .get(new GenericType<Map<String,String>>() {});
+    WebResource resource = client().resource("/v1/applications/simple-app/entities/simple-ent/sensors/current-state");
+    Map<String,Object> sensors = resource.get(new GenericType<Map<String,Object>>() {});
     assertTrue(sensors.size() > 0);
     assertEquals(sensors.get(RestMockSimpleEntity.SAMPLE_SENSOR.getName()), "foo4");
   }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestResourceTest.java b/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestResourceTest.java
index 8ec14b2..672537e 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestResourceTest.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/testing/BrooklynRestResourceTest.java
@@ -19,9 +19,9 @@
 package brooklyn.rest.testing;
 
 import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
 
 import java.net.URI;
+import java.util.Collection;
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
@@ -29,14 +29,20 @@ import java.util.logging.Level;
 import javax.ws.rs.core.MediaType;
 
 import org.codehaus.jackson.map.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 
+import brooklyn.entity.Application;
+import brooklyn.entity.basic.Entities;
 import brooklyn.rest.domain.ApplicationSpec;
 import brooklyn.rest.domain.ApplicationSummary;
 import brooklyn.rest.domain.Status;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.repeat.Repeater;
+import brooklyn.util.time.Duration;
 
 import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.UniformInterfaceException;
@@ -44,6 +50,8 @@ import com.sun.jersey.spi.inject.Errors;
 
 public abstract class BrooklynRestResourceTest extends BrooklynRestApiTest {
 
+    private static final Logger log = LoggerFactory.getLogger(BrooklynRestResourceTest.class);
+    
     @BeforeClass(alwaysRun = true)
     public void setUp() throws Exception {
         // need this to debug jersey inject errors
@@ -71,6 +79,9 @@ public abstract class BrooklynRestResourceTest extends BrooklynRestApiTest {
     }
     
     protected void waitForApplicationToBeRunning(final URI applicationRef) {
+        waitForApplicationToBeRunning(applicationRef, Duration.minutes(3));
+    }
+    protected void waitForApplicationToBeRunning(final URI applicationRef, Duration timeout) {
         if (applicationRef==null)
             throw new NullPointerException("No application URI available (consider using BrooklynRestResourceTest.clientDeploy)");
         
@@ -80,14 +91,21 @@ public abstract class BrooklynRestResourceTest extends BrooklynRestApiTest {
                     public Boolean call() throws Exception {
                         Status status = getApplicationStatus(applicationRef);
                         if (status == Status.ERROR) {
-                            fail("Application failed with ERROR");
+                            Assert.fail("Application failed with ERROR");
                         }
                         return status == Status.RUNNING;
                     }
                 })
-                .every(100, TimeUnit.MILLISECONDS)
-                .limitTimeTo(3, TimeUnit.MINUTES)
+                .every(Duration.millis(100))
+                .limitTimeTo(timeout)
                 .run();
+        
+        if (!started) {
+            log.warn("Did not start application "+applicationRef+":");
+            Collection<Application> apps = getManagementContext().getApplications();
+            for (Application app: apps)
+                Entities.dumpInfo(app);
+        }
         assertTrue(started);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockAppBuilder.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockAppBuilder.java b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockAppBuilder.java
index 82d1ab7..cb68cf3 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockAppBuilder.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockAppBuilder.java
@@ -22,6 +22,7 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.util.javalang.Reflections;
 
 public class RestMockAppBuilder extends ApplicationBuilder {
 
@@ -31,6 +32,8 @@ public class RestMockAppBuilder extends ApplicationBuilder {
     
     @Override
     protected void doBuild() {
-        addChild(EntitySpec.create(Entity.class).impl(RestMockSimpleEntity.class).displayName("child1"));
+        addChild(EntitySpec.create(Entity.class).impl(RestMockSimpleEntity.class)
+            .additionalInterfaces(Reflections.getAllInterfaces(RestMockSimpleEntity.class))
+            .displayName("child1"));
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java
index 10ee1cc..d1c6cb2 100644
--- a/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java
+++ b/usage/rest-server/src/test/java/brooklyn/rest/testing/mocks/RestMockSimpleEntity.java
@@ -56,6 +56,12 @@ public class RestMockSimpleEntity extends SoftwareProcessImpl {
     public RestMockSimpleEntity(@SuppressWarnings("rawtypes") Map flags) {
         super(flags);
     }
+    
+    @Override
+    protected void connectSensors() {
+        super.connectSensors();
+        connectServiceUpIsRunning();
+    }
 
     @SetFromFlag("sampleConfig")
     public static final ConfigKey<String> SAMPLE_CONFIG = new BasicConfigKey<String>(
@@ -75,11 +81,6 @@ public class RestMockSimpleEntity extends SoftwareProcessImpl {
         return result;
     }
 
-    @Override
-    public void waitForServiceUp() {
-        return;
-    }
-    
     @SuppressWarnings("rawtypes")
     @Override
     public Class getDriverInterface() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/5db500e4/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java
----------------------------------------------------------------------
diff --git a/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java b/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java
index 3b8dab2..693c807 100644
--- a/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java
+++ b/usage/test-support/src/main/java/brooklyn/test/EntityTestUtils.java
@@ -160,4 +160,5 @@ public class EntityTestUtils {
         assertAttributeEventually(entity, attribute, 
             Predicates.not(Predicates.equalTo(entity.getAttribute(attribute))));
     }
+    
 }