brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [22/26] git commit: write comprehensive tests for ServiceStateLogic, and tidy some of the semantics and usages elsewhere
Date Fri, 29 Aug 2014 23:01:22 GMT
write comprehensive tests for ServiceStateLogic, and tidy some of the semantics and usages
elsewhere


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

Branch: refs/heads/master
Commit: 31c5a0c2fd15ec23904bf438ba7b39579064dc8c
Parents: ab1381b
Author: Alex Heneveld <alex.heneveld@cloudsoftcorp.com>
Authored: Tue Aug 26 22:10:47 2014 -0500
Committer: Alex Heneveld <alex.heneveld@cloudsoftcorp.com>
Committed: Wed Aug 27 02:21:22 2014 -0400

----------------------------------------------------------------------
 .../brooklyn/enricher/basic/Transformer.java    |   5 +-
 .../entity/basic/AbstractApplication.java       |  10 +-
 .../brooklyn/entity/basic/AbstractEntity.java   |  10 +
 .../brooklyn/entity/basic/EntityAdjuncts.java   |  69 ++++++
 .../java/brooklyn/entity/basic/QuorumCheck.java |   2 +-
 .../entity/basic/ServiceStateLogic.java         |  75 ++++--
 .../entity/group/DynamicClusterImpl.java        |   5 +-
 .../java/brooklyn/enricher/EnrichersTest.java   |  31 +--
 .../entity/basic/ServiceStateLogicTest.java     | 246 +++++++++++++++++++
 .../brooklyn/test/entity/TestEntityImpl.java    |   1 +
 .../camp/brooklyn/EnrichersYamlTest.java        |  18 +-
 11 files changed, 416 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/core/src/main/java/brooklyn/enricher/basic/Transformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/enricher/basic/Transformer.java b/core/src/main/java/brooklyn/enricher/basic/Transformer.java
index c517e88..81ee346 100644
--- a/core/src/main/java/brooklyn/enricher/basic/Transformer.java
+++ b/core/src/main/java/brooklyn/enricher/basic/Transformer.java
@@ -106,6 +106,9 @@ public class Transformer<T,U> extends AbstractEnricher implements
SensorEventLis
     }
 
     protected Object compute(SensorEvent<T> event) {
-        return transformation.apply(event);
+        U result = transformation.apply(event);
+        if (LOG.isTraceEnabled())
+            LOG.trace("Enricher "+this+" computed "+result+" from "+event);
+        return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/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 961906f..4cab77c 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
@@ -35,6 +35,7 @@ import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.exceptions.RuntimeInterruptedException;
 import brooklyn.util.flags.SetFromFlag;
+import brooklyn.util.time.Time;
 
 /**
  * Users can extend this to define the entities in their application, and the relationships
between
@@ -125,6 +126,7 @@ public abstract class AbstractApplication extends AbstractEntity implements
Star
         
         // default app logic; easily overridable by adding a different enricher with the
same tag
         ServiceStateLogic.newEnricherFromChildren().checkChildrenAndMembers().addTo(this);
+        ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL,
"Application created but not yet started, at "+Time.makeDateString());
     }
     
     /**
@@ -137,13 +139,17 @@ public abstract class AbstractApplication extends AbstractEntity implements
Star
         Collection<? extends Location> locationsToUse = getLocations();
         ServiceProblemsLogic.clearProblemsIndicator(this, START);
         ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
+        ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL,
"Application starting");
         recordApplicationEvent(Lifecycle.STARTING);
         try {
             preStart(locationsToUse);
+            // if there are other items which should block service_up, they should be done
in preStart
+            ServiceStateLogic.ServiceNotUpLogic.clearNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL);
+            
             doStart(locationsToUse);
             postStart(locationsToUse);
         } catch (Exception e) {
-            // TODO should probably remember these problems then clear?  if so, do it here
or on all effectors?
+            // TODO should probably remember these problems then clear?  if so, do it here
... or on all effectors?
 //            ServiceProblemsLogic.updateProblemsIndicator(this, START, e);
             
             recordApplicationEvent(Lifecycle.ON_FIRE);
@@ -188,6 +194,7 @@ public abstract class AbstractApplication extends AbstractEntity implements
Star
     public void stop() {
         logApplicationLifecycle("Stopping");
 
+        ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL,
"Application stopping");
         setAttribute(SERVICE_UP, false);
         ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING);
         recordApplicationEvent(Lifecycle.STOPPING);
@@ -199,6 +206,7 @@ public abstract class AbstractApplication extends AbstractEntity implements
Star
             log.warn("Error stopping application " + this + " (rethrowing): "+e);
             throw Exceptions.propagate(e);
         }
+        ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL,
"Application stopping");
         ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED);
         recordApplicationEvent(Lifecycle.STOPPED);
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index eb5f099..a612b0c 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -761,12 +761,16 @@ public abstract class AbstractEntity extends AbstractBrooklynObject
implements E
         return attributesInternal.getValue(attribute);
     }
 
+    @SuppressWarnings("unchecked")
     public <T> T getAttributeByNameParts(List<String> nameParts) {
         return (T) attributesInternal.getValue(nameParts);
     }
     
     @Override
     public <T> T setAttribute(AttributeSensor<T> attribute, T val) {
+        if (LOG.isTraceEnabled())
+            LOG.trace(""+this+" setAttribute "+attribute+" "+val);
+        
         T result = attributesInternal.update(attribute, val);
         if (result == null) {
             // could be this is a new sensor
@@ -779,6 +783,9 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements
E
 
     @Override
     public <T> T setAttributeWithoutPublishing(AttributeSensor<T> attribute,
T val) {
+        if (LOG.isTraceEnabled())
+            LOG.trace(""+this+" setAttributeWithoutPublishing "+attribute+" "+val);
+        
         T result = attributesInternal.updateWithoutPublishing(attribute, val);
         if (result == null) {
             // could be this is a new sensor
@@ -791,6 +798,9 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements
E
 
     @Override
     public void removeAttribute(AttributeSensor<?> attribute) {
+        if (LOG.isTraceEnabled())
+            LOG.trace(""+this+" removeAttribute "+attribute);
+        
         attributesInternal.remove(attribute);
         entityType.removeSensor(attribute);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/core/src/main/java/brooklyn/entity/basic/EntityAdjuncts.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityAdjuncts.java b/core/src/main/java/brooklyn/entity/basic/EntityAdjuncts.java
new file mode 100644
index 0000000..ab1d003
--- /dev/null
+++ b/core/src/main/java/brooklyn/entity/basic/EntityAdjuncts.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.basic;
+
+import java.util.Iterator;
+import java.util.List;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
+import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceState;
+import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic;
+import brooklyn.policy.Enricher;
+import brooklyn.policy.EntityAdjunct;
+import brooklyn.util.collections.MutableList;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Convenience methods for working with entity adjunts.
+ */
+public class EntityAdjuncts {
+
+    public static <T extends EntityAdjunct> T findWithUniqueTag(Iterable<T> adjuncts,
Object tag) {
+        Preconditions.checkNotNull(tag, "tag");
+        for (T adjunct: adjuncts)
+            if (tag.equals(adjunct.getUniqueTag())) 
+                return adjunct;
+        return null;
+    }
+    
+    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 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 boolean isSystemEnricher(Enricher enr) {
+        if (enr.getUniqueTag()==null) return false;
+        if (SYSTEM_ENRICHER_UNIQUE_TAGS.contains(enr.getUniqueTag())) return true;
+        return false;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/core/src/main/java/brooklyn/entity/basic/QuorumCheck.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/QuorumCheck.java b/core/src/main/java/brooklyn/entity/basic/QuorumCheck.java
index 17195e8..5235413 100644
--- a/core/src/main/java/brooklyn/entity/basic/QuorumCheck.java
+++ b/core/src/main/java/brooklyn/entity/basic/QuorumCheck.java
@@ -70,7 +70,7 @@ public interface QuorumCheck {
         
         @Override
         public String toString() {
-            return "QuorumCheck[require="+minRequiredSize+","+((int)100*minRequiredRatio)+"%]";
+            return "QuorumCheck[require="+minRequiredSize+","+((int)100*minRequiredRatio)+"%"+(allowEmpty
? "|0" : "")+"]";
         }
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/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 749c83d..388f80d 100644
--- a/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
+++ b/core/src/main/java/brooklyn/entity/basic/ServiceStateLogic.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.annotation.Nullable;
 
@@ -47,6 +48,7 @@ import brooklyn.policy.EnricherSpec.ExtensibleEnricherSpec;
 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;
 import brooklyn.util.text.Strings;
 
@@ -54,6 +56,8 @@ import com.google.common.base.Function;
 import com.google.common.base.Functions;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.TypeToken;
 
 /** Logic, sensors and enrichers, and conveniences, for computing service status */ 
 public class ServiceStateLogic {
@@ -139,11 +143,19 @@ public class ServiceStateLogic {
         }
         
         /** puts the given value into the {@link Attributes#SERVICE_NOT_UP_INDICATORS} map
as if the 
-         * {@link UpdatingMap} enricher for the given sensor reported */
+         * {@link UpdatingMap} enricher for the given key */
+        public static void updateNotUpIndicator(EntityLocal entity, String key, Object value)
{
+            updateMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, key, value);
+        }
+        /** clears any entry for the given key in the {@link Attributes#SERVICE_NOT_UP_INDICATORS}
map */
+        public static void clearNotUpIndicator(EntityLocal entity, String key) {
+            clearMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, key);
+        }
+        /** as {@link #updateNotUpIndicator(EntityLocal, String, Object)} using the given
sensor as the key */
         public static void updateNotUpIndicator(EntityLocal entity, Sensor<?> sensor,
Object value) {
             updateMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, sensor.getName(),
value);
         }
-        /** clears any entry for the given sensor in the {@link Attributes#SERVICE_NOT_UP_INDICATORS}
map */
+        /** as {@link #clearNotUpIndicator(EntityLocal, String)} using the given sensor as
the key */
         public static void clearNotUpIndicator(EntityLocal entity, Sensor<?> sensor)
{
             clearMapSensorEntry(entity, Attributes.SERVICE_NOT_UP_INDICATORS, sensor.getName());
         }
@@ -222,12 +234,19 @@ public class ServiceStateLogic {
         
         protected Lifecycle computeActualStateWhenNotExpectedRunning(Map<String, Object>
problems, Boolean up, Lifecycle.Transition stateTransition) {
             if (stateTransition!=null) {
+                // if expected state is present but not running, just echo the expected state
(ignore problems and up-ness)
                 return stateTransition.getState();
+                
             } else if (problems!=null && !problems.isEmpty()) {
-                return Lifecycle.ON_FIRE;
+                // if there is no expected state, then if service is not up, say stopped,
else say on fire (whether service up is true or not present)
+                if (Boolean.FALSE.equals(up))
+                    return Lifecycle.STOPPED;
+                else
+                    return Lifecycle.ON_FIRE;
             } else {
-                // no expected transition
-                // if the problems map is non-null, then infer, else leave unchanged
+                // no expected transition and no problems
+                // if the problems map is non-null, then infer from service up;
+                // if there is no problems map, then leave unchanged (user may have set it
explicitly)
                 if (problems!=null)
                     return (up==null ? null /* remove if up is not set */ : 
                         up ? Lifecycle.RUNNING : Lifecycle.STOPPED);
@@ -240,6 +259,7 @@ public class ServiceStateLogic {
             if (log.isTraceEnabled()) log.trace("{} setting actual state {}", this, state);
             emit(SERVICE_STATE_ACTUAL, (state==null ? Entities.REMOVE : state));
         }
+
     }
     
     public static final EnricherSpec<?> newEnricherForServiceStateFromProblemsAndUp()
{
@@ -293,8 +313,12 @@ public class ServiceStateLogic {
             "Logic for checking whether this service is healthy, based on children and/or
members running, defaulting to requiring none to be ON-FIRE", QuorumCheck.QuorumChecks.all());
         public static final ConfigKey<Boolean> DERIVE_SERVICE_NOT_UP = ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.service_up.publish",
"Whether to derive a service-not-up indicator from children", true);
         public static final ConfigKey<Boolean> DERIVE_SERVICE_PROBLEMS = ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.service_problems.publish",
"Whether to derive a service-problem indicator from children", true);
-        public static final ConfigKey<Boolean> IGNORE_NULL_VALUES = ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.ignore_nulls",
"Whether to ignore children reporting null values for the sensor", true);
-        public static final ConfigKey<Boolean> IGNORE_TRANSITIONING = ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.ignore_transitioning",
"Whether to ignore children reporting transitional states (starting, stopping, etc) for service
state", true);
+        public static final ConfigKey<Boolean> IGNORE_ENTITIES_WITH_SERVICE_UP_NULL
= ConfigKeys.newBooleanConfigKey("enricher.service_state.children_and_members.ignore_entities.service_up_null",
"Whether to ignore children reporting null values for service up", true);
+        @SuppressWarnings("serial")
+        public static final ConfigKey<Set<Lifecycle>> IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES
= ConfigKeys.newConfigKey(new TypeToken<Set<Lifecycle>>() {},
+            "enricher.service_state.children_and_members.ignore_entities.service_state_values",

+            "Service states (including null) which indicate an entity should be ignored when
looking at children service states; anything apart from RUNNING not in this list will be treated
as not healthy (by default just ON_FIRE will mean not healthy)", 
+            MutableSet.<Lifecycle>builder().addAll(Lifecycle.values()).add(null).remove(Lifecycle.RUNNING).remove(Lifecycle.ON_FIRE).build().asUnmodifiable());
 
         protected String getKeyForMapSensor() {
             return Preconditions.checkNotNull(super.getUniqueTag());
@@ -326,6 +350,27 @@ public class ServiceStateLogic {
             }
         }
 
+        final static Set<ConfigKey<?>> RECONFIGURABLE_KEYS = ImmutableSet.<ConfigKey<?>>of(
+            UP_QUORUM_CHECK, RUNNING_QUORUM_CHECK,
+            DERIVE_SERVICE_NOT_UP, DERIVE_SERVICE_NOT_UP, 
+            IGNORE_ENTITIES_WITH_SERVICE_UP_NULL, IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES);
+        
+        @Override
+        protected <T> void doReconfigureConfig(ConfigKey<T> key, T val) {
+            if (RECONFIGURABLE_KEYS.contains(key)) {
+                return;
+            } else {
+                super.doReconfigureConfig(key, val);
+            }
+        }
+        
+        @Override
+        protected void onChanged() {
+            super.onChanged();
+            if (entity != null && isRunning())
+                onUpdated();
+        }
+        
         private final List<Sensor<?>> SOURCE_SENSORS = ImmutableList.<Sensor<?>>of(SERVICE_UP,
SERVICE_STATE_ACTUAL);
         @Override
         protected Collection<Sensor<?>> getSourceSensors() {
@@ -334,8 +379,13 @@ public class ServiceStateLogic {
 
         @Override
         protected void onUpdated() {
-            // override superclass to publish potentially several items
+            if (entity==null || !Entities.isManaged(entity)) {
+                // either invoked during setup or entity has become unmanaged; just ignore
+                log.debug("Ignoring {} onUpdated when entity is not in valid state ({})",
this, entity);
+                return;
+            }
 
+            // override superclass to publish multiple sensors
             if (getConfig(DERIVE_SERVICE_PROBLEMS))
                 updateMapSensor(SERVICE_PROBLEMS, computeServiceProblems());
 
@@ -346,7 +396,7 @@ public class ServiceStateLogic {
         protected Object computeServiceNotUp() {
             Map<Entity, Boolean> values = getValues(SERVICE_UP);
             List<Entity> violators = MutableList.of();
-            boolean ignoreNull = getConfig(IGNORE_NULL_VALUES);
+            boolean ignoreNull = getConfig(IGNORE_ENTITIES_WITH_SERVICE_UP_NULL);
             int entries=0;
             for (Map.Entry<Entity, Boolean> state: values.entrySet()) {
                 if (ignoreNull && state.getValue()==null)
@@ -379,13 +429,10 @@ public class ServiceStateLogic {
         protected Object computeServiceProblems() {
             Map<Entity, Lifecycle> values = getValues(SERVICE_STATE_ACTUAL);
             int numRunning=0, numNotHealthy=0;
-            boolean ignoreNull = getConfig(IGNORE_NULL_VALUES);
-            boolean ignoreTransition = getConfig(IGNORE_TRANSITIONING);
+            Set<Lifecycle> ignoreStates = getConfig(IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES);
             for (Lifecycle state: values.values()) {
                 if (state==Lifecycle.RUNNING) numRunning++;
-                else if (state==Lifecycle.ON_FIRE) numNotHealthy++;
-                else if (state==null) { if (!ignoreNull) numNotHealthy++; }
-                else { if (!ignoreTransition) numNotHealthy++; }
+                else if (!ignoreStates.contains(state)) numNotHealthy++;
             }
 
             QuorumCheck qc = getConfig(RUNNING_QUORUM_CHECK);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
index 1023db6..553d453 100644
--- a/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
+++ b/core/src/main/java/brooklyn/entity/group/DynamicClusterImpl.java
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.AbstractGroupImpl;
+import brooklyn.entity.basic.Attributes;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityFactory;
 import brooklyn.entity.basic.EntityFactoryForLocation;
@@ -141,7 +142,6 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
     @Override
     public void init() {
         super.init();
-        setAttribute(SERVICE_UP, false);
     }
 
     @Override
@@ -149,6 +149,9 @@ public class DynamicClusterImpl extends AbstractGroupImpl implements DynamicClus
         if (getConfigRaw(UP_QUORUM_CHECK, true).isAbsent() && getConfig(INITIAL_SIZE)==0)
{
             // if initial size is 0 then override up check to allow zero if empty
             setConfig(UP_QUORUM_CHECK, QuorumChecks.atLeastOneUnlessEmpty());
+            setAttribute(SERVICE_UP, true);
+        } else {
+            setAttribute(SERVICE_UP, false);
         }
         super.initEnrichers();
         // override previous enricher so that only members are checked

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/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 aeffe6a..12f1cad 100644
--- a/core/src/test/java/brooklyn/enricher/EnrichersTest.java
+++ b/core/src/test/java/brooklyn/enricher/EnrichersTest.java
@@ -19,8 +19,6 @@
 package brooklyn.enricher;
 
 import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -29,13 +27,10 @@ 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.EntityAdjuncts;
 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;
@@ -45,7 +40,6 @@ 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;
@@ -63,27 +57,6 @@ 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");
@@ -117,7 +90,7 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
                 .computingSum()
                 .build());
         
-        Assert.assertEquals(EnrichersTest.getNonSystemEnrichers(entity), ImmutableList.of(enr));
+        Assert.assertEquals(EntityAdjuncts.getNonSystemEnrichers(entity), ImmutableList.of(enr));
         
         entity.setAttribute(NUM1, 2);
         entity.setAttribute(NUM2, 3);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java b/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java
new file mode 100644
index 0000000..ca5d8c1
--- /dev/null
+++ b/core/src/test/java/brooklyn/entity/basic/ServiceStateLogicTest.java
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.basic;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.QuorumCheck.QuorumChecks;
+import brooklyn.entity.basic.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
+import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic;
+import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.event.AttributeSensor;
+import brooklyn.location.Location;
+import brooklyn.policy.Enricher;
+import brooklyn.test.EntityTestUtils;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+@Test
+public class ServiceStateLogicTest extends BrooklynAppUnitTestSupport {
+    
+    private static final Logger log = LoggerFactory.getLogger(ServiceStateLogicTest.class);
+    
+    final static String INDICATOR_KEY_1 = "test-indicator-1";
+    final static String INDICATOR_KEY_2 = "test-indicator-2";
+
+    protected TestEntity entity;
+
+    protected void setUpApp() {
+        super.setUpApp();
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+    }
+
+
+    public void testManuallySettingIndicatorsOnEntities() {
+        // if we set a not up indicator, entity service up should become false
+        ServiceNotUpLogic.updateNotUpIndicator(entity, INDICATOR_KEY_1, "We're pretending
to block service up");
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);
+        
+        // but state will not change unless we also set either a problem or expected state
+        assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, null);
+        ServiceProblemsLogic.updateProblemsIndicator(entity, INDICATOR_KEY_1, "We're pretending
to block service state also");
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        
+        // and if we clear the not up indicator, service up becomes true, but there is a
problem, so it shows on-fire
+        ServiceNotUpLogic.clearNotUpIndicator(entity, INDICATOR_KEY_1);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+        
+        // if we then clear the problem also, state goes to RUNNING
+        ServiceProblemsLogic.clearProblemsIndicator(entity, INDICATOR_KEY_1);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+
+        // now add not-up indicator again, and it reverts to up=false, state=stopped
+        ServiceNotUpLogic.updateNotUpIndicator(entity, INDICATOR_KEY_1, "We're again pretending
to block service up");
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        
+        // but if we expect it to be running it will show on fire (because service is not
up)
+        ServiceStateLogic.setExpectedState(entity, Lifecycle.RUNNING);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+        
+        // and if we again clear the not up indicator it will deduce up=true and state=running
+        ServiceNotUpLogic.clearNotUpIndicator(entity, INDICATOR_KEY_1);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+    }
+
+    public void testAppStoppedAndEntityNullBeforeStarting() {
+        // AbstractApplication has default logic to ensure service is not up if it hasn't
been started,
+        // (this can be removed by updating the problem indicator associated with the SERVICE_STATE_ACTUAL
sensor)
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, false);
+        // and from that it imputes stopped state
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        
+        // TestEntity has no such indicators however
+        assertAttributeEquals(entity, Attributes.SERVICE_UP, null);
+        assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, null);
+    }
+    
+    public void testAllUpAndRunningAfterStart() {
+        app.start(ImmutableList.<Location>of());
+        
+        assertAttributeEquals(app, Attributes.SERVICE_UP, true);
+        assertAttributeEquals(entity, Attributes.SERVICE_UP, true);
+        // above should be immediate, entity should then derive RUNNING from expected state,
and then so should app from children
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+    }
+    
+    public void testStopsNicelyToo() {
+        app.start(ImmutableList.<Location>of());
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        
+        app.stop();
+        
+        assertAttributeEquals(app, Attributes.SERVICE_UP, false);
+        assertAttributeEquals(entity, Attributes.SERVICE_UP, false);
+        // above should be immediate, app and entity should then derive STOPPED from the
expected state
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+    }
+
+    public void testTwoIndicatorsAreBetterThanOne() {        
+        // if we set a not up indicator, entity service up should become false
+        ServiceNotUpLogic.updateNotUpIndicator(entity, INDICATOR_KEY_1, "We're pretending
to block service up");
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);
+        ServiceNotUpLogic.updateNotUpIndicator(entity, INDICATOR_KEY_2, "We're also pretending
to block service up");
+        ServiceNotUpLogic.clearNotUpIndicator(entity, INDICATOR_KEY_1);
+        // clearing one indicator is not sufficient
+        assertAttributeEquals(entity, Attributes.SERVICE_UP, false);
+        
+        // but it does not become true when both are cleared
+        ServiceNotUpLogic.clearNotUpIndicator(entity, INDICATOR_KEY_2);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true);
+    }
+
+    public void testManuallySettingIndicatorsOnApplicationsIsMoreComplicated() {
+        // indicators on application are more complicated because it is configured with additional
indicators from its children
+        // test a lot of situations, including reconfiguring some of the quorum config
+        
+        // to begin with, an entity has not reported anything, so the ComputeServiceIndicatorsFromChildren
ignores it
+        // but the AbstractApplication has emitted a not-up indicator because it has not
been started
+        // both as asserted by this other test:
+        testAppStoppedAndEntityNullBeforeStarting();
+        
+        // if we clear the not up indicator, the app will show as up, and as running, because
it has no reporting children 
+        ServiceNotUpLogic.clearNotUpIndicator(app, Attributes.SERVICE_STATE_ACTUAL);
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true);
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        
+        // if we then put a not-up indicator on the TestEntity, it publishes false, so app
also is false, and thus stopped
+        ServiceNotUpLogic.updateNotUpIndicator(entity, INDICATOR_KEY_1, "We're also pretending
to block service up");
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, false);
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        // but the entity still has no opinion about its state
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, null);
+        
+        // if the entity expects to be stopped, it will report stopped
+        ServiceStateLogic.setExpectedState(entity, Lifecycle.STOPPED);
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        // and now so does the app 
+        assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        
+        // if we clear the not-up indicator, both the entity and the app report service up
(with the entity first)
+        ServiceNotUpLogic.clearNotUpIndicator(entity, INDICATOR_KEY_1);
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true);
+        assertAttributeEquals(entity, Attributes.SERVICE_UP, true);
+        // but entity is still stopped because that is what is expected there, and that's
okay even if service is apparently up
+        assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        
+        // the app however is running, because the default state quorum check is "all are
healthy"
+        assertAttributeEquals(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        // if we change the state quorum check for the app to be "all are healthy and at
least one running" *then* it shows stopped
+        // (normally this would be done in `initEnrichers` of course)
+        Enricher appChildrenBasedEnricher = EntityAdjuncts.findWithUniqueTag(app.getEnrichers(),
ComputeServiceIndicatorsFromChildrenAndMembers.DEFAULT_UNIQUE_TAG);
+        Assert.assertNotNull(appChildrenBasedEnricher, "Expected enricher not found");
+        appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK,
QuorumChecks.allAndAtLeastOne());
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+        
+        // if entity is expected running, then it shows running, because service is up, and
it's reflected at app and at entity
+        ServiceStateLogic.setExpectedState(entity, Lifecycle.RUNNING);
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        
+        // now, when the entity is unmanaged, the app is still running because children are
empty
+        Entities.unmanage(entity);
+        assertAttributeEquals(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        // but if we change its up quorum to atLeastOne then service up becomes false
+        appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK,
QuorumChecks.atLeastOne());
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, false);
+        // and state becomes stopped (because there is no expected state)
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
+        
+        // if we now start it will successfully start (because unlike entities it does not
wait for service up) 
+        // but will remain down and will go on fire
+        app.start(ImmutableList.<Location>of());
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, false);
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+        // restoring this to atLeastOneUnlessEmpty causes it to become RUNNING
+        appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK,
QuorumChecks.atLeastOneUnlessEmpty());
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true);
+        appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK,
QuorumChecks.all());
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        
+        // now add a child, it's still up and running because null values are ignored by
default
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        assertAttributeEquals(app, Attributes.SERVICE_UP, true);
+        assertAttributeEquals(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        // tell it not to ignore null values for children states, and it will go onfire (but
still be service up)
+        appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_THESE_SERVICE_STATES,

+            ImmutableSet.<Lifecycle>of());
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+        assertAttributeEquals(app, Attributes.SERVICE_UP, true);
+        // tell it not to ignore null values for service up and it will go service down
+        appChildrenBasedEnricher.setConfig(ComputeServiceIndicatorsFromChildrenAndMembers.IGNORE_ENTITIES_WITH_SERVICE_UP_NULL,
false);
+        assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, false);
+    }
+        
+    private static <T> void assertAttributeEqualsEventually(Entity x, AttributeSensor<T>
sensor, T value) {
+        try {
+            EntityTestUtils.assertAttributeEqualsEventually(ImmutableMap.of("timeout", Duration.seconds(10)),
x, sensor, value);
+        } catch (Throwable e) {
+            log.warn("Expected "+x+" eventually to have "+sensor+" = "+value+"; instead:");
+            Entities.dumpInfo(x);
+            throw Exceptions.propagate(e);
+        }
+    }
+    private static <T> void assertAttributeEquals(Entity x, AttributeSensor<T>
sensor, T value) {
+        try {
+            EntityTestUtils.assertAttributeEquals(x, sensor, value);
+        } catch (Throwable e) {
+            log.warn("Expected "+x+" to have "+sensor+" = "+value+"; instead:");
+            Entities.dumpInfo(x);
+            throw Exceptions.propagate(e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/core/src/test/java/brooklyn/test/entity/TestEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/entity/TestEntityImpl.java b/core/src/test/java/brooklyn/test/entity/TestEntityImpl.java
index 3ccf614..d58aa86 100644
--- a/core/src/test/java/brooklyn/test/entity/TestEntityImpl.java
+++ b/core/src/test/java/brooklyn/test/entity/TestEntityImpl.java
@@ -137,6 +137,7 @@ public class TestEntityImpl extends AbstractEntity implements TestEntity
{
         ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPING);
         counter.decrementAndGet();
         ServiceStateLogic.setExpectedState(this, Lifecycle.STOPPED);
+        setAttribute(SERVICE_UP, false);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/31c5a0c2/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 7d3feaf..4391ba9 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
@@ -28,10 +28,10 @@ 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;
+import brooklyn.entity.basic.EntityAdjuncts;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.policy.Enricher;
 import brooklyn.test.Asserts;
@@ -57,8 +57,8 @@ public class EnrichersYamlTest extends AbstractYamlTest {
         log.info("App started:");
         Entities.dumpInfo(app);
         
-        Assert.assertEquals(EnrichersTest.getNonSystemEnrichers(app).size(), 1);
-        final Enricher enricher = EnrichersTest.getNonSystemEnrichers(app).iterator().next();
+        Assert.assertEquals(EntityAdjuncts.getNonSystemEnrichers(app).size(), 1);
+        final Enricher enricher = EntityAdjuncts.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");
@@ -90,16 +90,16 @@ public class EnrichersYamlTest extends AbstractYamlTest {
         log.info("App started:");
         Entities.dumpInfo(app);
 
-        Assert.assertEquals(EnrichersTest.getNonSystemEnrichers(app).size(), 0);
+        Assert.assertEquals(EntityAdjuncts.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 EnrichersTest.getNonSystemEnrichers(child).size();
+                return EntityAdjuncts.getNonSystemEnrichers(child).size();
             }
         }, Predicates.<Integer> equalTo(1));        
-        final Enricher enricher = EnrichersTest.getNonSystemEnrichers(child).iterator().next();
+        final Enricher enricher = EntityAdjuncts.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");
@@ -151,10 +151,10 @@ public class EnrichersYamlTest extends AbstractYamlTest {
         Asserts.eventually(new Supplier<Integer>() {
             @Override
             public Integer get() {
-                return EnrichersTest.getNonSystemEnrichers(parentEntity).size();
+                return EntityAdjuncts.getNonSystemEnrichers(parentEntity).size();
             }
         }, Predicates.<Integer>equalTo(1));
-        Enricher enricher = EnrichersTest.getNonSystemEnrichers(parentEntity).iterator().next();
+        Enricher enricher = EntityAdjuncts.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>() {
@@ -242,7 +242,7 @@ public class EnrichersYamlTest extends AbstractYamlTest {
     }
     
     private Enricher getEnricher(Entity entity) {
-        List<Enricher> enrichers = EnrichersTest.getNonSystemEnrichers(entity);
+        List<Enricher> enrichers = EntityAdjuncts.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);


Mime
View raw message