You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/08/19 23:20:52 UTC

[18/62] [abbrv] incubator-brooklyn git commit: rename core’s o.a.b.entity to o.a.b.core.entity

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/sensor/feed/FeedConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/feed/FeedConfig.java b/core/src/main/java/org/apache/brooklyn/sensor/feed/FeedConfig.java
index 615745c..d3f7597 100644
--- a/core/src/main/java/org/apache/brooklyn/sensor/feed/FeedConfig.java
+++ b/core/src/main/java/org/apache/brooklyn/sensor/feed/FeedConfig.java
@@ -21,7 +21,7 @@ package org.apache.brooklyn.sensor.feed;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.entity.core.Entities;
+import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.sensor.core.Sensors;
 import org.apache.brooklyn.sensor.feed.http.HttpPollConfig;
 import org.apache.brooklyn.util.collections.MutableList;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/sensor/feed/Poller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/feed/Poller.java b/core/src/main/java/org/apache/brooklyn/sensor/feed/Poller.java
index 2ceafd0..f6e8e24 100644
--- a/core/src/main/java/org/apache/brooklyn/sensor/feed/Poller.java
+++ b/core/src/main/java/org/apache/brooklyn/sensor/feed/Poller.java
@@ -24,10 +24,10 @@ import java.util.concurrent.Callable;
 
 import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.entity.core.Attributes;
-import org.apache.brooklyn.entity.core.Entities;
-import org.apache.brooklyn.entity.core.EntityInternal;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.task.DynamicSequentialTask;
 import org.apache.brooklyn.util.core.task.ScheduledTask;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/sensor/feed/http/HttpFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/feed/http/HttpFeed.java b/core/src/main/java/org/apache/brooklyn/sensor/feed/http/HttpFeed.java
index 43784a0..9ae5431 100644
--- a/core/src/main/java/org/apache/brooklyn/sensor/feed/http/HttpFeed.java
+++ b/core/src/main/java/org/apache/brooklyn/sensor/feed/http/HttpFeed.java
@@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit;
 import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.entity.core.Entities;
+import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.sensor.feed.AbstractFeed;
 import org.apache.brooklyn.sensor.feed.AttributePollHandler;
 import org.apache.brooklyn.sensor.feed.DelegatingPollHandler;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/sensor/feed/shell/ShellFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/feed/shell/ShellFeed.java b/core/src/main/java/org/apache/brooklyn/sensor/feed/shell/ShellFeed.java
index 8db9c70..19e5bf5 100644
--- a/core/src/main/java/org/apache/brooklyn/sensor/feed/shell/ShellFeed.java
+++ b/core/src/main/java/org/apache/brooklyn/sensor/feed/shell/ShellFeed.java
@@ -31,7 +31,7 @@ import org.apache.brooklyn.api.entity.EntityLocal;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.entity.core.EntityInternal;
+import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.sensor.feed.AbstractFeed;
 import org.apache.brooklyn.sensor.feed.AttributePollHandler;
 import org.apache.brooklyn.sensor.feed.DelegatingPollHandler;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeed.java b/core/src/main/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeed.java
index 0e1a3a6..33b284c 100644
--- a/core/src/main/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeed.java
+++ b/core/src/main/java/org/apache/brooklyn/sensor/feed/windows/WindowsPerformanceCounterFeed.java
@@ -40,8 +40,8 @@ import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.effector.core.EffectorTasks;
-import org.apache.brooklyn.entity.core.EntityInternal;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.location.winrm.WinRmMachineLocation;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
index 120caf6..51b0456 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
@@ -45,11 +45,11 @@ import javax.annotation.concurrent.GuardedBy;
 import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.core.entity.factory.ClosureEntityFactory;
+import org.apache.brooklyn.core.entity.factory.ConfigurableEntityFactory;
+import org.apache.brooklyn.core.entity.factory.ConfigurableEntityFactoryFromEntityFactory;
 import org.apache.brooklyn.core.internal.BrooklynInitialization;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.entity.factory.ClosureEntityFactory;
-import org.apache.brooklyn.entity.factory.ConfigurableEntityFactory;
-import org.apache.brooklyn.entity.factory.ConfigurableEntityFactoryFromEntityFactory;
 import org.apache.brooklyn.sensor.core.Sensors;
 import org.apache.brooklyn.util.JavaGroovyEquivalents;
 import org.apache.brooklyn.util.collections.MutableSet;
@@ -600,19 +600,19 @@ public class TypeCoercions {
             }
         });
         @SuppressWarnings({"unused", "deprecation"})
-        Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning1 = registerAdapter(org.apache.brooklyn.entity.factory.EntityFactory.class, ConfigurableEntityFactory.class, new Function<org.apache.brooklyn.entity.factory.EntityFactory,ConfigurableEntityFactory>() {
+        Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning1 = registerAdapter(org.apache.brooklyn.core.entity.factory.EntityFactory.class, ConfigurableEntityFactory.class, new Function<org.apache.brooklyn.core.entity.factory.EntityFactory,ConfigurableEntityFactory>() {
             @SuppressWarnings("unchecked")
             @Override
-            public ConfigurableEntityFactory apply(org.apache.brooklyn.entity.factory.EntityFactory input) {
+            public ConfigurableEntityFactory apply(org.apache.brooklyn.core.entity.factory.EntityFactory input) {
                 if (input instanceof ConfigurableEntityFactory) return (ConfigurableEntityFactory)input;
                 return new ConfigurableEntityFactoryFromEntityFactory(input);
             }
         });
         @SuppressWarnings({"unused", "deprecation"})
-        Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning2 = registerAdapter(Closure.class, org.apache.brooklyn.entity.factory.EntityFactory.class, new Function<Closure,org.apache.brooklyn.entity.factory.EntityFactory>() {
+        Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning2 = registerAdapter(Closure.class, org.apache.brooklyn.core.entity.factory.EntityFactory.class, new Function<Closure,org.apache.brooklyn.core.entity.factory.EntityFactory>() {
             @SuppressWarnings("unchecked")
             @Override
-            public org.apache.brooklyn.entity.factory.EntityFactory apply(Closure input) {
+            public org.apache.brooklyn.core.entity.factory.EntityFactory apply(Closure input) {
                 return new ClosureEntityFactory(input);
             }
         });

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionContext.java b/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionContext.java
index 8eb50b7..74d4ac3 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionContext.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/BasicExecutionContext.java
@@ -36,10 +36,10 @@ import org.apache.brooklyn.api.mgmt.HasTaskChildren;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.mgmt.TaskAdaptable;
 import org.apache.brooklyn.api.mgmt.entitlement.EntitlementContext;
+import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags.WrappedEntity;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
-import org.apache.brooklyn.entity.core.EntityInternal;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/util/core/task/DynamicTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/DynamicTasks.java b/core/src/main/java/org/apache/brooklyn/util/core/task/DynamicTasks.java
index 17546e8..b2791b3 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/DynamicTasks.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/DynamicTasks.java
@@ -28,7 +28,7 @@ import org.apache.brooklyn.api.mgmt.TaskAdaptable;
 import org.apache.brooklyn.api.mgmt.TaskFactory;
 import org.apache.brooklyn.api.mgmt.TaskQueueingContext;
 import org.apache.brooklyn.api.mgmt.TaskWrapper;
-import org.apache.brooklyn.entity.core.EntityInternal;
+import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.time.Duration;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java
index b5366f2..35cae91 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/ValueResolver.java
@@ -29,8 +29,8 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.mgmt.TaskAdaptable;
+import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.entity.core.EntityInternal;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java b/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
index f26097b..afa2f71 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
@@ -31,9 +31,9 @@ import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.sensor.AttributeSensor;
 import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
-import org.apache.brooklyn.entity.core.Entities;
-import org.apache.brooklyn.entity.core.EntityInternal;
 import org.apache.brooklyn.sensor.core.DependentConfiguration;
 import org.apache.brooklyn.sensor.core.Sensors;
 import org.apache.brooklyn.util.collections.MutableMap;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
index 4d28448..0b72c90 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
@@ -38,11 +38,11 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemDo;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.catalog.internal.CatalogXmlSerializer;
 import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.entity.core.Entities;
 import org.apache.brooklyn.util.core.BrooklynMavenArtifacts;
 import org.apache.brooklyn.util.maven.MavenRetriever;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
index 3aed91e..7a4fecb 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
@@ -33,10 +33,10 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.core.catalog.CatalogPredicates;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.catalog.internal.MyCatalogItems.MySillyAppTemplate;
+import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.internal.BrooklynProperties;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.server.BrooklynServerConfig;
-import org.apache.brooklyn.entity.core.Entities;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.net.Urls;
 import org.apache.brooklyn.util.text.Strings;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java
index 9ba1d06..e14e291 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java
@@ -32,9 +32,9 @@ import org.apache.brooklyn.core.catalog.CatalogPredicates;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.entity.core.Entities;
 
 import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java
index e5735dc..9bd108b 100644
--- a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java
@@ -19,8 +19,8 @@
 package org.apache.brooklyn.core.catalog.internal;
 
 import org.apache.brooklyn.api.catalog.Catalog;
-import org.apache.brooklyn.entity.core.AbstractApplication;
-import org.apache.brooklyn.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.entity.AbstractApplication;
+import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
 
 public class MyCatalogItems {
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/config/MapListAndOtherStructuredConfigKeyTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/config/MapListAndOtherStructuredConfigKeyTest.groovy b/core/src/test/java/org/apache/brooklyn/core/config/MapListAndOtherStructuredConfigKeyTest.groovy
index d3dc84b..27b8d95 100644
--- a/core/src/test/java/org/apache/brooklyn/core/config/MapListAndOtherStructuredConfigKeyTest.groovy
+++ b/core/src/test/java/org/apache/brooklyn/core/config/MapListAndOtherStructuredConfigKeyTest.groovy
@@ -31,7 +31,7 @@ import org.apache.brooklyn.core.config.MapConfigKey.MapModifications
 import org.apache.brooklyn.core.config.SetConfigKey.SetModifications
 import org.apache.brooklyn.core.test.entity.TestApplication
 import org.apache.brooklyn.core.test.entity.TestEntity
-import org.apache.brooklyn.entity.core.Entities
+import org.apache.brooklyn.core.entity.Entities
 import org.apache.brooklyn.location.core.SimulatedLocation
 import org.apache.brooklyn.sensor.core.DependentConfiguration
 import org.apache.brooklyn.util.collections.MutableMap

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/entity/AbstractApplicationLegacyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/AbstractApplicationLegacyTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/AbstractApplicationLegacyTest.java
new file mode 100644
index 0000000..66b0659
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/AbstractApplicationLegacyTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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 org.apache.brooklyn.core.entity;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.entity.AbstractApplication;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import org.apache.brooklyn.location.core.SimulatedLocation;
+
+/**
+ * Tests the deprecated use of AbstractAppliation, where its constructor is called directly.
+ * 
+ * @author aled
+ */
+public class AbstractApplicationLegacyTest extends BrooklynAppUnitTestSupport {
+
+    private SimulatedLocation loc;
+    private List<SimulatedLocation> locs;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        loc = mgmt.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+        locs = ImmutableList.of(loc);
+    }
+    
+    // App and its children will be implicitly managed on first effector call on app
+    @Test
+    public void testStartAndStopUnmanagedAppAutomanagesTheAppAndChildren() throws Exception {
+        // deliberately unmanaged
+        TestApplication app2 = mgmt.getEntityManager().createEntity(EntitySpec.create(TestApplication.class));
+        TestEntity child = app2.addChild(EntitySpec.create(TestEntity.class));
+        assertFalse(Entities.isManaged(app2));
+        assertFalse(Entities.isManaged(child));
+        
+        app2.invoke(AbstractApplication.START, ImmutableMap.of("locations", locs)).get();
+        assertTrue(Entities.isManaged(app2));
+        assertTrue(Entities.isManaged(child));
+        assertEquals(child.getCallHistory(), ImmutableList.of("start"));
+        assertEquals(mgmt.getEntityManager().getEntity(app2.getId()), app2);
+        assertEquals(mgmt.getEntityManager().getEntity(child.getId()), child);
+        
+        app2.stop();
+        assertEquals(child.getCallHistory(), ImmutableList.of("start", "stop"));
+        assertFalse(Entities.isManaged(child));
+        assertFalse(Entities.isManaged(app2));
+    }
+    
+    @Test
+    public void testStartAndStopWhenManagedCallsChildren() {
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        assertTrue(Entities.isManaged(app));
+        assertTrue(Entities.isManaged(child));
+
+        app.start(locs);
+        assertEquals(child.getCallHistory(), ImmutableList.of("start"));
+        
+        app.stop();
+        assertEquals(child.getCallHistory(), ImmutableList.of("start", "stop"));
+        assertFalse(Entities.isManaged(child));
+        assertFalse(Entities.isManaged(app));
+    }
+    
+    @Test
+    public void testStartOnManagedAppDoesNotStartPremanagedChildren() {
+        TestEntity child = app.addChild(EntitySpec.create(TestEntity.class));
+        
+        app.start(locs);
+        assertEquals(child.getCallHistory(), ImmutableList.of());
+    }
+    
+    @Test
+    public void testStartOnManagedAppDoesNotStartUnmanagedChildren() {
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        Entities.unmanage(child);
+        
+        app.start(locs);
+        assertEquals(child.getCallHistory(), ImmutableList.of());
+    }
+    
+    @Test
+    public void testStopDoesNotStopUnmanagedChildren() {
+        TestEntity child = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        
+        app.start(locs);
+        assertEquals(child.getCallHistory(), ImmutableList.of("start"));
+        
+        Entities.unmanage(child);
+        
+        app.stop();
+        assertEquals(child.getCallHistory(), ImmutableList.of("start"));
+    }
+    
+    @Test
+    public void testStopOnManagedAppDoesNotStopPremanagedChildren() {
+        app.start(locs);
+        
+        TestEntity child = app.addChild(EntitySpec.create(TestEntity.class));
+        
+        app.stop();
+        assertEquals(child.getCallHistory(), ImmutableList.of());
+    }
+    
+    @Test
+    public void testAppUsesDefaultDisplayName() {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class)
+                .configure(AbstractApplication.DEFAULT_DISPLAY_NAME, "myDefaultName");
+        TestApplication app2 = ApplicationBuilder.newManagedApp(appSpec, mgmt);
+        
+        assertEquals(app2.getDisplayName(), "myDefaultName");
+    }
+    
+    @Test
+    public void testAppUsesDisplayNameOverDefaultName() {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class)
+                .displayName("myName")
+                .configure(AbstractApplication.DEFAULT_DISPLAY_NAME, "myDefaultName");
+        TestApplication app2 = ApplicationBuilder.newManagedApp(appSpec, mgmt);
+        
+        assertEquals(app2.getDisplayName(), "myName");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/entity/AbstractEntityLegacyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/AbstractEntityLegacyTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/AbstractEntityLegacyTest.java
new file mode 100644
index 0000000..c6e89cd
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/AbstractEntityLegacyTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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 org.apache.brooklyn.core.entity;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestApplicationImpl;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.location.core.SimulatedLocation;
+
+/**
+ * Tests the deprecated use of AbstractAppliation, where its constructor is called directly.
+ * 
+ * @author aled
+ */
+public class AbstractEntityLegacyTest {
+
+    private List<SimulatedLocation> locs;
+    private TestApplication app;
+    
+    @ImplementedBy(MyEntityImpl.class)
+    public interface MyEntity extends Entity {
+        int getConfigureCount();
+
+        int getConfigureDuringConstructionCount();
+    }
+    
+    public static class MyEntityImpl extends AbstractEntity implements MyEntity {
+        volatile int configureCount;
+        volatile int configureDuringConstructionCount;
+        
+        public MyEntityImpl() {
+            super();
+            configureDuringConstructionCount = configureCount;
+        }
+        
+        public MyEntityImpl(Entity parent) {
+            super(parent);
+            configureDuringConstructionCount = configureCount;
+        }
+        
+        public MyEntityImpl(Map flags, Entity parent) {
+            super(flags, parent);
+            configureDuringConstructionCount = configureCount;
+        }
+        
+        @Override
+        public AbstractEntity configure(Map flags) {
+            configureCount++;
+            return super.configure(flags);
+        }
+        
+        @Override
+        public int getConfigureCount() {
+            return configureCount;
+        }
+        
+        @Override
+        public int getConfigureDuringConstructionCount() {
+            return configureDuringConstructionCount;
+        }
+    }
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+    }
+    
+    @Test
+    public void testLegacyConstructionCallsConfigureMethod() throws Exception {
+        MyEntity entity = new MyEntityImpl();
+        
+        assertEquals(entity.getConfigureCount(), 1);
+        assertEquals(entity.getConfigureDuringConstructionCount(), 1);
+    }
+
+    @Test
+    public void testLegacyConstructionSetsDefaultDisplayName() throws Exception {
+        app = new TestApplicationImpl();
+        MyEntity entity = new MyEntityImpl(app);
+
+        assertTrue(entity.getDisplayName().startsWith("MyEntityImpl:"+entity.getId().substring(0,4)), "displayName="+entity.getDisplayName());
+        
+        Entities.startManagement(app, LocalManagementContextForTests.newInstance());
+        assertTrue(entity.getDisplayName().startsWith("MyEntity:"+entity.getId().substring(0,4)), "displayName="+entity.getDisplayName());
+    }
+    
+    @Test
+    public void testLegacyConstructionUsesCustomDisplayName() throws Exception {
+        app = new TestApplicationImpl(MutableMap.of("displayName", "appname"));
+        MyEntity entity = new MyEntityImpl(MutableMap.of("displayName", "entityname"), app);
+        MyEntity entity2 = new MyEntityImpl(MutableMap.of("name", "entityname2"), app);
+
+        assertEquals(app.getDisplayName(), "appname");
+        assertEquals(entity.getDisplayName(), "entityname");
+        assertEquals(entity2.getDisplayName(), "entityname2");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/entity/AttributeMapTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/AttributeMapTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/AttributeMapTest.java
new file mode 100644
index 0000000..565b34b
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/AttributeMapTest.java
@@ -0,0 +1,226 @@
+/*
+ * 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 org.apache.brooklyn.core.entity;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.core.test.entity.TestEntityImpl;
+import org.apache.brooklyn.sensor.core.AttributeMap;
+import org.apache.brooklyn.sensor.core.Sensors;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class AttributeMapTest {
+    final int NUM_TASKS = Math.min(500 * Runtime.getRuntime().availableProcessors(), 1000);
+
+    Application app;
+    TestEntityImpl entity;
+    AttributeMap map;
+    ExecutorService executor;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() {
+        app = TestApplication.Factory.newManagedInstanceForTests();
+        entity = new TestEntityImpl(app);
+        map = new AttributeMap(entity, Collections.synchronizedMap(MutableMap.<Collection<String>,Object>of()));
+        Entities.manage(entity);
+        executor = Executors.newCachedThreadPool();
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() {
+        if (executor != null) executor.shutdownNow();
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+    }
+    
+    // See ENGR-2111
+    @Test
+    public void testConcurrentUpdatesDoNotCauseConcurrentModificationException() throws Exception {
+        List<Future<?>> futures = Lists.newArrayList();
+        
+        for (int i = 0; i < NUM_TASKS; i++) {
+            final AttributeSensor<String> nextSensor = Sensors.newStringSensor("attributeMapTest.exampleSensor"+i, "");
+            Future<?> future = executor.submit(newUpdateMapRunnable(map, nextSensor, "a"));
+            futures.add(future);
+        }
+        
+        for (Future<?> future : futures) {
+            future.get();
+        }
+    }
+    
+    @Test
+    public void testConcurrentUpdatesAndGetsDoNotCauseConcurrentModificationException() throws Exception {
+        List<Future<?>> futures = Lists.newArrayList();
+        
+        for (int i = 0; i < NUM_TASKS; i++) {
+            final AttributeSensor<String> nextSensor = Sensors.newStringSensor("attributeMapTest.exampleSensor"+i, "");
+            Future<?> future = executor.submit(newUpdateMapRunnable(map, nextSensor, "a"));
+            Future<?> future2 = executor.submit(newGetAttributeCallable(map, nextSensor));
+            futures.add(future);
+            futures.add(future2);
+        }
+
+        for (Future<?> future : futures) {
+            future.get();
+        }
+    }
+    
+    @Test
+    public void testStoredSensorsCanBeRetrieved() throws Exception {
+        AttributeSensor<String> sensor1 = Sensors.newStringSensor("a", "");
+        AttributeSensor<String> sensor2 = Sensors.newStringSensor("b.c", "");
+        
+        map.update(sensor1, "1val");
+        map.update(sensor2, "2val");
+        
+        assertEquals(map.getValue(sensor1), "1val");
+        assertEquals(map.getValue(sensor2), "2val");
+        
+        assertEquals(map.getValue(ImmutableList.of("a")), "1val");
+        assertEquals(map.getValue(ImmutableList.of("b","c")), "2val");
+    }
+        
+    @Test
+    public void testStoredByPathCanBeRetrieved() throws Exception {
+        AttributeSensor<String> sensor1 = Sensors.newStringSensor("a", "");
+        AttributeSensor<String> sensor2 = Sensors.newStringSensor("b.c", "");
+        
+        map.update(ImmutableList.of("a"), "1val");
+        map.update(ImmutableList.of("b", "c"), "2val");
+        
+        assertEquals(map.getValue(sensor1), "1val");
+        assertEquals(map.getValue(sensor2), "2val");
+        
+        assertEquals(map.getValue(ImmutableList.of("a")), "1val");
+        assertEquals(map.getValue(ImmutableList.of("b","c")), "2val");
+    }
+        
+    @Test
+    public void testCanStoreSensorThenChildSensor() throws Exception {
+        AttributeSensor<String> sensor = Sensors.newStringSensor("a", "");
+        AttributeSensor<String> childSensor = Sensors.newStringSensor("a.b", "");
+        
+        map.update(sensor, "parentValue");
+        map.update(childSensor, "childValue");
+        
+        assertEquals(map.getValue(childSensor), "childValue");
+        assertEquals(map.getValue(sensor), "parentValue");
+    }
+    
+    @Test
+    public void testCanStoreChildThenParentSensor() throws Exception {
+        AttributeSensor<String> sensor = Sensors.newStringSensor("a", "");
+        AttributeSensor<String> childSensor = Sensors.newStringSensor("a.b", "");
+        
+        map.update(childSensor, "childValue");
+        map.update(sensor, "parentValue");
+        
+        assertEquals(map.getValue(childSensor), "childValue");
+        assertEquals(map.getValue(sensor), "parentValue");
+    }
+    
+    @Test
+    public void testConcurrentModifyAttributeCalls() throws Exception {
+        AttributeSensor<Integer> sensor = Sensors.newIntegerSensor("a", "");
+        
+        Function<Integer, Maybe<Integer>> modifier = new Function<Integer, Maybe<Integer>>() {
+            @Override public Maybe<Integer> apply(Integer input) {
+                return Maybe.of((input == null) ? 1 : input + 1);
+            }
+        };
+        
+        List<Future<?>> futures = Lists.newArrayList();
+        
+        for (int i = 0; i < NUM_TASKS; i++) {
+            Future<?> future = executor.submit(newModifyAttributeCallable(map, sensor, modifier));
+            futures.add(future);
+        }
+
+        for (Future<?> future : futures) {
+            future.get();
+        }
+
+        assertEquals(map.getValue(sensor), Integer.valueOf(NUM_TASKS));
+    }
+    
+    @Test
+    public void testModifyAttributeReturningAbsentDoesNotEmit() throws Exception {
+        AttributeSensor<Integer> sensor = Sensors.newIntegerSensor("a", "");
+        AttributeSensor<Integer> childSensor = Sensors.newIntegerSensor("a.b", "");
+        
+        final RecordingSensorEventListener<Object> listener = new RecordingSensorEventListener<>();
+        entity.subscribe(entity, sensor, listener);
+        
+        map.modify(childSensor, Functions.constant(Maybe.<Integer>absent()));
+        
+        Asserts.succeedsContinually(new Runnable() {
+            @Override public void run() {
+                assertTrue(Iterables.isEmpty(listener.getEvents()), "events="+listener.getEvents());
+            }});
+    }
+    
+    protected <T> Runnable newUpdateMapRunnable(final AttributeMap map, final AttributeSensor<T> attribute, final T val) {
+        return new Runnable() {
+            @Override public void run() {
+                map.update(attribute, val);
+            }
+        };
+    }
+    
+    protected <T> Callable<T> newGetAttributeCallable(final AttributeMap map, final AttributeSensor<T> attribute) {
+        return new Callable<T>() {
+            @Override public T call() {
+                return map.getValue(attribute);
+            }
+        };
+    }
+    
+    protected <T> Callable<T> newModifyAttributeCallable(final AttributeMap map, final AttributeSensor<T> attribute, final Function<? super T, Maybe<T>> modifier) {
+        return new Callable<T>() {
+            @Override public T call() {
+                return map.modify(attribute, modifier);
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/entity/AttributeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/AttributeTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/AttributeTest.java
new file mode 100644
index 0000000..614a275
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/AttributeTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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 org.apache.brooklyn.core.entity;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.core.test.entity.TestEntityImpl;
+import org.apache.brooklyn.sensor.core.BasicAttributeSensor;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class AttributeTest {
+    static AttributeSensor<String> COLOR = new BasicAttributeSensor<String>(String.class, "my.color");
+
+    TestEntityImpl e;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        e = new TestEntityImpl();
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown(){
+        // nothing to tear down; entity was not managed (i.e. had no management context)
+    }
+
+    @Test
+    public void canGetAndSetAttribute() {
+        e.setAttribute(COLOR, "red");
+        assertEquals(e.getAttribute(COLOR), "red");
+    }
+    
+    @Test
+    public void missingAttributeIsNull() {
+        assertEquals(e.getAttribute(COLOR), null);
+    }
+    
+    @Test
+    public void canGetAttributeByNameParts() {
+        // Initially null
+        assertNull(e.getAttributeByNameParts(COLOR.getNameParts()));
+        
+        // Once set, returns val
+        e.setAttribute(COLOR, "red");
+        assertEquals(e.getAttributeByNameParts(COLOR.getNameParts()), "red");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/entity/ConfigEntityInheritanceTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/ConfigEntityInheritanceTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/ConfigEntityInheritanceTest.java
new file mode 100644
index 0000000..2a8ae20
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/ConfigEntityInheritanceTest.java
@@ -0,0 +1,190 @@
+/*
+ * 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 org.apache.brooklyn.core.entity;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.config.ConfigInheritance;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.internal.ConfigMapTest.MyOtherEntity;
+import org.apache.brooklyn.core.test.entity.TestApplication;
+import org.apache.brooklyn.sensor.core.AttributeSensorAndConfigKey;
+import org.apache.brooklyn.sensor.core.BasicAttributeSensorAndConfigKey.IntegerAttributeSensorAndConfigKey;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * There is a bug where:
+ *    class XI extends SI implements X
+ *    class SI implements S  
+ *    interface X extends Y
+ *    config C is declared on S and overwritten at Y
+ */
+public class ConfigEntityInheritanceTest {
+
+    private TestApplication app;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() {
+        app = TestApplication.Factory.newManagedInstanceForTests();
+        Entities.startManagement(app);
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+    }
+
+    protected void checkKeys(Entity entity2, Integer value) {
+        Assert.assertEquals(entity2.getConfig(MyOtherEntity.INT_KEY), value);
+        Assert.assertEquals(entity2.getConfig(MyOtherEntity.SENSOR_AND_CONFIG_KEY), value);
+    }
+
+    @Test
+    public void testConfigKeysIncludesHasConfigKeys() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MyOtherEntity.class)), 1);
+    }
+    
+    @Test
+    public void testConfigKeysIncludesHasConfigKeysInheritsOverwritten() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MyOtherEntityOverwriting.class)), 2);
+    }
+    @Test
+    public void testConfigKeysIncludesHasConfigKeysInheritsOverwrittenThenInherited() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MyOtherEntityOverwritingThenInheriting.class)), 2);
+    }
+    
+    public static class MyOtherEntityOverwriting extends MyOtherEntity {
+        public static final ConfigKey<Integer> INT_KEY = ConfigKeys.newConfigKeyWithDefault(MyOtherEntity.INT_KEY, 2);
+        public static final IntegerAttributeSensorAndConfigKey SENSOR_AND_CONFIG_KEY = 
+                new IntegerAttributeSensorAndConfigKey(MyOtherEntity.SENSOR_AND_CONFIG_KEY, 2);
+    }
+    public static class MyOtherEntityOverwritingThenInheriting extends MyOtherEntityOverwriting {
+    }
+
+    // --------------------
+    
+    @Test
+    public void testConfigKeysHere() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MyEntityHere.class)), 3);
+    }
+    @Test
+    public void testConfigKeysSub() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MySubEntityHere.class)), 4);
+    }
+    @Test
+    public void testConfigKeysSubExtended() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MySubEntityHere.class)), 4);
+    }
+    @Test
+    public void testConfigKeysSubInheriting() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MySubEntityHereInheriting.class)), 4);
+    }
+    @Test
+    public void testConfigKeysHereSubRight() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MySubEntityHereLeft.class)), 4);
+    }
+    @Test
+    public void testConfigKeysSubLeft() throws Exception {
+        checkKeys(app.addChild(EntitySpec.create(MySubEntityHereRight.class)), 4);
+    }
+    @Test
+    public void testConfigKeysExtAndImplIntTwoRight() throws Exception {
+        // this mirrors the bug observed in kafka entities;
+        // the right-side interface normally dominates, but not when it is transitive
+        // (although we shouldn't rely on order in any case;
+        // new routines check whether one config key extends another and if so it takes the extending one)
+        checkKeys(app.addChild(EntitySpec.create(MyEntityHereExtendingAndImplementingInterfaceImplementingTwoRight.class)), 4);
+    }
+
+    public interface MyInterfaceDeclaring {
+        public static final ConfigKey<Integer> INT_KEY = 
+            ConfigKeys.newIntegerConfigKey("intKey", "int key", 3);
+        public static final AttributeSensorAndConfigKey<Integer,Integer> SENSOR_AND_CONFIG_KEY = 
+            new IntegerAttributeSensorAndConfigKey("sensorConfigKey", "sensor+config key", 3);
+    }
+    public interface MyInterfaceRedeclaringAndInheriting extends MyInterfaceDeclaring {
+        public static final ConfigKey<Integer> INT_KEY = ConfigKeys.newConfigKeyWithDefault(MyInterfaceDeclaring.INT_KEY, 4);
+        public static final IntegerAttributeSensorAndConfigKey SENSOR_AND_CONFIG_KEY = 
+                new IntegerAttributeSensorAndConfigKey(MyInterfaceDeclaring.SENSOR_AND_CONFIG_KEY, 4);
+    }
+
+    public interface MyInterfaceRedeclaring {
+        public static final ConfigKey<Integer> INT_KEY = ConfigKeys.newConfigKeyWithDefault(MyInterfaceDeclaring.INT_KEY, 4);
+        public static final IntegerAttributeSensorAndConfigKey SENSOR_AND_CONFIG_KEY = 
+                new IntegerAttributeSensorAndConfigKey(MyInterfaceDeclaring.SENSOR_AND_CONFIG_KEY, 4);
+    }
+    
+    public interface MyInterfaceRedeclaringThenExtending extends MyInterfaceRedeclaring {
+    }
+
+    public interface MyInterfaceExtendingLeft extends MyInterfaceRedeclaring, MyInterfaceDeclaring {
+    }
+
+    public interface MyInterfaceExtendingRight extends MyInterfaceDeclaring, MyInterfaceRedeclaring {
+    }
+
+    public static class MyEntityHere extends AbstractEntity implements MyInterfaceDeclaring {
+    }
+    
+    public static class MySubEntityHere extends MyEntityHere implements MyInterfaceRedeclaring {
+    }
+
+    public static class MySubEntityHereInheriting extends MyEntityHere implements MyInterfaceRedeclaringAndInheriting {
+    }
+
+    public static class MySubEntityHereExtended extends MyEntityHere implements MyInterfaceRedeclaringThenExtending {
+    }
+
+    public static class MySubEntityHereLeft extends MyEntityHere implements MyInterfaceRedeclaring, MyInterfaceDeclaring {
+    }
+
+    public static class MySubEntityHereRight extends MyEntityHere implements MyInterfaceDeclaring, MyInterfaceRedeclaring {
+    }
+    
+    public static class MyEntityHereExtendingAndImplementingInterfaceImplementingTwoRight extends MyEntityHere implements MyInterfaceExtendingRight {
+    }
+
+    // --------------------
+
+    @Test
+    public void testConfigKeysInheritance() throws Exception {
+        app.setConfig(MyEntityWithPartiallyHeritableConfig.HERITABLE, "heritable");
+        app.setConfig(MyEntityWithPartiallyHeritableConfig.UNINHERITABLE, "uninheritable");
+        app.setConfig(MyEntityWithPartiallyHeritableConfig.ALWAYS_HERITABLE, "always_heritable");
+        Entity child = app.addChild(EntitySpec.create(MyEntityWithPartiallyHeritableConfig.class));
+        
+        Assert.assertNotNull(child.getConfig(MyEntityWithPartiallyHeritableConfig.HERITABLE));
+        Assert.assertNull(child.getConfig(MyEntityWithPartiallyHeritableConfig.UNINHERITABLE), null);
+        Assert.assertNotNull(child.getConfig(MyEntityWithPartiallyHeritableConfig.ALWAYS_HERITABLE));
+    }
+    
+    public static class MyEntityWithPartiallyHeritableConfig extends AbstractEntity {
+        public static final ConfigKey<String> HERITABLE = ConfigKeys.builder(String.class, "herit.default").build();
+        public static final ConfigKey<String> UNINHERITABLE = ConfigKeys.builder(String.class, "herit.none").inheritance(ConfigInheritance.NONE).build();
+        // i find a strange joy in words where the prefix "in-" does not mean not, like inflammable 
+        public static final ConfigKey<String> ALWAYS_HERITABLE = ConfigKeys.builder(String.class, "herit.always").inheritance(ConfigInheritance.ALWAYS).build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/entity/DependentConfigurationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/DependentConfigurationTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/DependentConfigurationTest.java
new file mode 100644
index 0000000..2c681f3
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/DependentConfigurationTest.java
@@ -0,0 +1,413 @@
+/*
+ * 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 org.apache.brooklyn.core.entity;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
+import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.sensor.core.DependentConfiguration;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.task.BasicTask;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
+import org.apache.brooklyn.util.text.StringPredicates;
+import org.apache.brooklyn.util.time.Duration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Callables;
+
+/** Tests the standalone routines in dependent configuration.
+ * See e.g. LocalEntitiesTest for tests of attributeWhenReady etc.
+ */
+public class DependentConfigurationTest extends BrooklynAppUnitTestSupport {
+
+    private static final Logger log = LoggerFactory.getLogger(DependentConfigurationTest.class);
+    
+    public static final int SHORT_WAIT_MS = 100;
+    public static final int TIMEOUT_MS = 30*1000;
+    
+    private TestEntity entity;
+    private TestEntity entity2;
+
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        entity2 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+    }
+    
+    @Test
+    public void testTransform() throws Exception {
+        Task<Integer> t = DependentConfiguration.transform(
+                new BasicTask<Integer>(Callables.returning(2)), 
+                incrementerFunction());
+        submit(t);
+        assertEquals(t.get(TIMEOUT_MS, TimeUnit.MILLISECONDS), Integer.valueOf(3));
+    }
+
+    private Function<Integer, Integer> incrementerFunction() {
+        return new Function<Integer, Integer>() {
+            @Override public Integer apply(Integer val) {
+                return val + 1;
+            }};
+    }
+    
+    @Test
+    public void testFormatString() throws Exception {
+        Task<String> t = DependentConfiguration.formatString("%s://%s:%d/",
+                "http",
+                new BasicTask<String>(Callables.returning("localhost")), 
+                DependentConfiguration.transform(new BasicTask<Integer>(Callables.returning(8080)), incrementerFunction()));
+        submit(t);
+        Assert.assertEquals(t.get(TIMEOUT_MS, TimeUnit.MILLISECONDS), "http://localhost:8081/");
+    }
+
+    @Test
+    public void testAttributeWhenReady() throws Exception {
+        final Task<String> t = submit(DependentConfiguration.attributeWhenReady(entity, TestEntity.NAME));
+        assertNotDoneContinually(t);
+        
+        entity.setAttribute(TestEntity.NAME, "myval");
+        assertEquals(assertDoneEventually(t), "myval");
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithPredicate() throws Exception {
+        final Task<String> t = submit(DependentConfiguration.attributeWhenReady(entity, TestEntity.NAME, Predicates.equalTo("myval2")));
+        
+        entity.setAttribute(TestEntity.NAME, "myval");
+        assertNotDoneContinually(t);
+        
+        entity.setAttribute(TestEntity.NAME, "myval2");
+        assertEquals(assertDoneEventually(t), "myval2");
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithPostProcessing() throws Exception {
+        final Task<String> t = submit(DependentConfiguration.valueWhenAttributeReady(entity, TestEntity.SEQUENCE, Functions.toStringFunction()));
+        assertNotDoneContinually(t);
+        
+        entity.setAttribute(TestEntity.SEQUENCE, 1);
+        assertEquals(assertDoneEventually(t), "1");
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithPostProcessingWithBuilder() throws Exception {
+        final Task<String> t = submit(DependentConfiguration.builder()
+                .attributeWhenReady(entity, TestEntity.SEQUENCE)
+                .postProcess(Functions.toStringFunction())
+                .build());
+
+        assertNotDoneContinually(t);
+        
+        entity.setAttribute(TestEntity.SEQUENCE, 1);
+        assertEquals(assertDoneEventually(t), "1");
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithPostProcessingWithBuilderWaitingNow() throws Exception {
+        final Task<String> t = submit(new Callable<String>() {
+            public String call() {
+                return DependentConfiguration.builder()
+                        .attributeWhenReady(entity, TestEntity.SEQUENCE)
+                        .postProcess(Functions.toStringFunction())
+                        .runNow();
+            }});
+
+        assertNotDoneContinually(t);
+        
+        entity.setAttribute(TestEntity.SEQUENCE, 1);
+        assertEquals(assertDoneEventually(t), "1");
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithAbortHappyPath() throws Exception {
+        final Task<String> t = submit(DependentConfiguration.builder()
+                .attributeWhenReady(entity, TestEntity.NAME)
+                .abortIf(entity2, TestEntity.SEQUENCE, Predicates.equalTo(1))
+                .build());
+        assertNotDoneContinually(t);
+        
+        entity.setAttribute(TestEntity.NAME, "myval");
+        assertEquals(assertDoneEventually(t), "myval");
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithAbort() throws Exception {
+        final Task<String> t = submit(DependentConfiguration.builder()
+                .attributeWhenReady(entity, TestEntity.NAME)
+                .abortIf(entity2, TestEntity.SEQUENCE, Predicates.equalTo(1))
+                .build());
+
+        assertNotDoneContinually(t);
+
+        entity2.setAttribute(TestEntity.SEQUENCE, 321);
+        assertNotDoneContinually(t);
+
+        entity2.setAttribute(TestEntity.SEQUENCE, 1);
+        try {
+            assertDoneEventually(t);
+            fail();
+        } catch (Exception e) {
+            if (!e.toString().contains("Aborted waiting for ready")) throw e;
+        }
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithAbortWaitingNow() throws Exception {
+        final Task<String> t = submit(new Callable<String>() {
+            public String call() {
+                return DependentConfiguration.builder()
+                        .attributeWhenReady(entity, TestEntity.NAME)
+                        .abortIf(entity2, TestEntity.SEQUENCE, Predicates.equalTo(1))
+                        .runNow();
+            }});
+
+        assertNotDoneContinually(t);
+
+        entity2.setAttribute(TestEntity.SEQUENCE, 321);
+        assertNotDoneContinually(t);
+
+        entity2.setAttribute(TestEntity.SEQUENCE, 1);
+        try {
+            assertDoneEventually(t);
+            fail();
+        } catch (Exception e) {
+            if (!e.toString().contains("Aborted waiting for ready")) throw e;
+        }
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithAbortFailsWhenAbortConditionAlreadyHolds() throws Exception {
+        entity2.setAttribute(TestEntity.SEQUENCE, 1);
+        final Task<String> t = submit(DependentConfiguration.builder()
+                .attributeWhenReady(entity, TestEntity.NAME)
+                .abortIf(entity2, TestEntity.SEQUENCE, Predicates.equalTo(1))
+                .build());
+        try {
+            assertDoneEventually(t);
+            fail();
+        } catch (Exception e) {
+            if (!e.toString().contains("Aborted waiting for ready")) throw e;
+        }
+    }
+
+    @Test
+    public void testAttributeWhenReadyWithAbortFailsWhenAbortConditionAlreadyHoldsWaitingNow() throws Exception {
+        entity2.setAttribute(TestEntity.SEQUENCE, 1);
+        final Task<String> t = submit(new Callable<String>() {
+            public String call() {
+                return DependentConfiguration.builder()
+                        .attributeWhenReady(entity, TestEntity.NAME)
+                        .abortIf(entity2, TestEntity.SEQUENCE, Predicates.equalTo(1))
+                        .runNow();
+            }});
+        try {
+            assertDoneEventually(t);
+            fail();
+        } catch (Exception e) {
+            if (!e.toString().contains("Aborted waiting for ready")) throw e;
+        }
+    }
+
+    @Test
+    public void testAttributeWhenReadyRunNowWithoutPostProcess() throws Exception {
+        Task<String> t  = submit(new Callable<String>() {
+            @Override
+            public String call() throws Exception {
+                return DependentConfiguration.builder()
+                        .attributeWhenReady(entity, TestEntity.NAME)
+                        .runNow();
+            }
+        });
+        entity.setAttribute(TestEntity.NAME, "myentity");
+        assertDoneEventually(t);
+        assertEquals(t.get(), "myentity");
+    }
+
+    @Test
+    public void testAttributeWhenReadyAbortsWhenOnFireByDefault() {
+        log.info("starting test "+JavaClassNames.niceClassAndMethod());
+        final Task<String> t = submit(DependentConfiguration.builder()
+                .attributeWhenReady(entity, TestEntity.NAME)
+                .build());
+
+        ServiceStateLogic.setExpectedState(entity, Lifecycle.ON_FIRE);
+        EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+        
+        try {
+            assertDoneEventually(t);
+            fail("Should have failed already!");
+        } catch (Throwable e) {
+            if (e.toString().contains("Aborted waiting for ready")) 
+                return;
+            
+            log.warn("Did not abort as expected: "+e, e);
+            Entities.dumpInfo(entity);
+            
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    @Test(invocationCount=100, groups = "Integration")
+    public void testAttributeWhenReadyAbortsWhenOnfireByDefaultManyTimes() {
+        testAttributeWhenReadyAbortsWhenOnFireByDefault();
+    }
+    
+    @Test
+    public void testAttributeWhenReadyAbortsWhenAlreadyOnFireByDefault() throws Exception {
+        ServiceStateLogic.setExpectedState(entity, Lifecycle.ON_FIRE);
+        EntityTestUtils.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.ON_FIRE);
+        
+        final Task<String> t = submit(DependentConfiguration.builder()
+                .attributeWhenReady(entity, TestEntity.NAME)
+                .build());
+
+        try {
+            assertDoneEventually(t);
+            fail();
+        } catch (Exception e) {
+            if (!e.toString().contains("Aborted waiting for ready")) throw e;
+        }
+    }
+
+    @Test
+    public void testListAttributeWhenReadyFromMultipleEntities() throws Exception {
+        final Task<List<String>> t = submit(DependentConfiguration.builder()
+                .attributeWhenReadyFromMultiple(ImmutableList.of(entity, entity2), TestEntity.NAME)
+                .build());
+        assertNotDoneContinually(t);
+        
+        entity.setAttribute(TestEntity.NAME, "myval");
+        assertNotDoneContinually(t);
+        
+        entity2.setAttribute(TestEntity.NAME, "myval2");
+        assertEquals(ImmutableSet.copyOf(assertDoneEventually(t)), ImmutableSet.of("myval", "myval2"));
+    }
+
+    @Test
+    public void testListAttributeWhenReadyFromMultipleEntitiesWithLocalReadinessPredicate() throws Exception {
+        final Task<List<String>> t = submit(DependentConfiguration.builder()
+                .attributeWhenReadyFromMultiple(ImmutableList.of(entity, entity2), TestEntity.NAME, StringPredicates.startsWith("myval"))
+                .build());
+        
+        entity.setAttribute(TestEntity.NAME, "wrongval");
+        entity2.setAttribute(TestEntity.NAME, "wrongval2");
+        assertNotDoneContinually(t);
+        
+        entity.setAttribute(TestEntity.NAME, "myval");
+        assertNotDoneContinually(t);
+        entity2.setAttribute(TestEntity.NAME, "myval2");
+        assertEquals(ImmutableSet.copyOf(assertDoneEventually(t)), ImmutableSet.of("myval", "myval2"));
+    }
+
+    @Test
+    public void testListAttributeWhenReadyFromMultipleEntitiesWithGlobalPostProcessor() throws Exception {
+        final Task<String> t = submit(DependentConfiguration.builder()
+                .attributeWhenReadyFromMultiple(ImmutableList.of(entity, entity2), TestEntity.SEQUENCE)
+                .postProcessFromMultiple(new Function<List<Integer>, String>() {
+                        @Override public String apply(List<Integer> input) {
+                            if (input == null) {
+                                return null;
+                            } else {
+                                MutableList<Integer> inputCopy = MutableList.copyOf(input);
+                                Collections.sort(inputCopy);
+                                return Joiner.on(",").join(inputCopy);
+                            }
+                        }})
+                .build());
+        
+        entity.setAttribute(TestEntity.SEQUENCE, 1);
+        entity2.setAttribute(TestEntity.SEQUENCE, 2);
+        assertEquals(assertDoneEventually(t), "1,2");
+    }
+
+    private void assertNotDoneContinually(final Task<?> t) {
+        Asserts.succeedsContinually(ImmutableMap.of("timeout", SHORT_WAIT_MS), new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                if (t.isDone()) {
+                    fail("task unexpectedly done: t="+t+"; result="+t.get());
+                }
+                return null;
+            }
+        });
+    }
+    
+    private <T> T assertDoneEventually(final Task<T> t) throws Exception {
+        final AtomicReference<ExecutionException> exception = new AtomicReference<ExecutionException>();
+        T result = Asserts.succeedsEventually(MutableMap.of("timeout", Duration.FIVE_SECONDS), new Callable<T>() {
+            @Override public T call() throws InterruptedException, TimeoutException {
+                try {
+                    return t.get(Duration.ONE_SECOND);
+                } catch (ExecutionException e) {
+                    exception.set(e);
+                    return null;
+                } catch (InterruptedException e) {
+                    throw e;
+                } catch (TimeoutException e) {
+                    throw e;
+                }
+            }
+        });
+        if (exception.get() != null) {
+            throw exception.get();
+        }
+        return result;
+    }
+
+    
+    private <T> Task<T> submit(Task<T> task) {
+        return app.getExecutionContext().submit(task);
+    }
+    
+    private <T> Task<T> submit(Callable<T> job) {
+        return app.getExecutionContext().submit(new BasicTask<T>(job));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java
new file mode 100644
index 0000000..885eb45
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/DynamicEntityTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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 org.apache.brooklyn.core.entity;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import org.apache.brooklyn.api.entity.EntityInitializer;
+import org.apache.brooklyn.api.entity.EntityLocal;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.effector.core.EffectorTaskTest;
+import org.apache.brooklyn.entity.stock.BasicEntity;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.testng.annotations.Test;
+
+public class DynamicEntityTest extends BrooklynAppUnitTestSupport {
+
+    @Test
+    public void testEffectorAddedDuringInit() {
+        BasicEntity entity = app.createAndManageChild(EntitySpec.create(BasicEntity.class)
+                .addInitializer(new EntityInitializer() {
+                    public void apply(EntityLocal entity) {
+                        ((EntityInternal) entity).getMutableEntityType().addEffector(EffectorTaskTest.DOUBLE_1);
+                    }
+                }));
+        assertEquals(entity.invoke(EffectorTaskTest.DOUBLE_BODYLESS, MutableMap.of("numberToDouble", 5)).getUnchecked(), (Integer) 10);
+    }
+
+    @Test
+    public void testEffectorRemovedDuringInit() {
+        TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+                .addInitializer(new EntityInitializer() {
+                    @Override
+                    public void apply(EntityLocal entity) {
+                        ((EntityInternal) entity).getMutableEntityType().removeEffector(TestEntity.IDENTITY_EFFECTOR);
+                    }
+                }));
+        assertFalse(entity.getMutableEntityType().getEffectors().containsKey(TestEntity.IDENTITY_EFFECTOR.getName()));
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/c27cf1d0/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java
new file mode 100644
index 0000000..2a2cbc7
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntitiesTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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 org.apache.brooklyn.core.entity;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityAndAttribute;
+import org.apache.brooklyn.core.entity.EntityInitializers;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.location.core.SimulatedLocation;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class EntitiesTest extends BrooklynAppUnitTestSupport {
+
+    private static final int TIMEOUT_MS = 10*1000;
+    
+    private SimulatedLocation loc;
+    private TestEntity entity;
+    
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        loc = app.getManagementContext().getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        app.start(ImmutableList.of(loc));
+    }
+    
+    @Test
+    public void testDescendants() throws Exception {
+        Assert.assertEquals(Iterables.size(Entities.descendants(app)), 2);
+        Assert.assertEquals(Iterables.getOnlyElement(Entities.descendants(app, TestEntity.class)), entity);
+    }
+    
+    @Test
+    public void testAttributeSupplier() throws Exception {
+        entity.setAttribute(TestEntity.NAME, "myname");
+        assertEquals(Entities.attributeSupplier(entity, TestEntity.NAME).get(), "myname");
+    }
+    
+    @Test
+    public void testAttributeSupplierUsingTuple() throws Exception {
+        entity.setAttribute(TestEntity.NAME, "myname");
+        assertEquals(Entities.attributeSupplier(EntityAndAttribute.supplier(entity, TestEntity.NAME)).get(), "myname");
+    }
+    
+    @Test(groups="Integration") // takes 1 second
+    public void testAttributeSupplierWhenReady() throws Exception {
+        final AtomicReference<String> result = new AtomicReference<String>();
+        
+        final Thread t = new Thread(new Runnable() {
+            @Override public void run() {
+                result.set(Entities.attributeSupplierWhenReady(entity, TestEntity.NAME).get());
+                
+            }});
+        try {
+            t.start();
+            
+            // should block, waiting for value
+            Asserts.succeedsContinually(new Runnable() {
+                @Override public void run() {
+                    assertTrue(t.isAlive());
+                }
+            });
+            
+            entity.setAttribute(TestEntity.NAME, "myname");
+            t.join(TIMEOUT_MS);
+            assertFalse(t.isAlive());
+            assertEquals(result.get(), "myname");
+        } finally {
+            t.interrupt();
+        }
+        
+        // And now that it's set, the attribute-when-ready should return immediately
+        assertEquals(Entities.attributeSupplierWhenReady(entity, TestEntity.NAME).get(), "myname");
+    }
+    
+    @Test
+    public void testCreateGetContainsAndRemoveTags() throws Exception {
+        entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)
+            .tag(2)
+            .addInitializer(EntityInitializers.addingTags("foo")));
+        
+        entity.tags().addTag(app);
+        
+        Assert.assertTrue(entity.tags().containsTag(app));
+        Assert.assertTrue(entity.tags().containsTag("foo"));
+        Assert.assertTrue(entity.tags().containsTag(2));
+        Assert.assertFalse(entity.tags().containsTag("bar"));
+        
+        Assert.assertEquals(entity.tags().getTags(), MutableSet.of(app, "foo", 2));
+        
+        entity.tags().removeTag("foo");
+        Assert.assertFalse(entity.tags().containsTag("foo"));
+        
+        Assert.assertTrue(entity.tags().containsTag(entity.getParent()));
+        Assert.assertFalse(entity.tags().containsTag(entity));
+        
+        entity.tags().removeTag(2);
+        Assert.assertEquals(entity.tags().getTags(), MutableSet.of(app));
+    }
+    
+}