brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [09/24] incubator-brooklyn git commit: [BROOKLYN-162] Renaming package policy
Date Tue, 18 Aug 2015 11:06:07 GMT
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d30ff597/policy/src/test/java/brooklyn/policy/loadbalancing/LoadBalancingPolicyTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/loadbalancing/LoadBalancingPolicyTest.java b/policy/src/test/java/brooklyn/policy/loadbalancing/LoadBalancingPolicyTest.java
deleted file mode 100644
index 442e3b3..0000000
--- a/policy/src/test/java/brooklyn/policy/loadbalancing/LoadBalancingPolicyTest.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * 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.policy.loadbalancing;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-
-import org.apache.brooklyn.api.entity.basic.EntityLocal;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.test.Asserts;
-import brooklyn.util.collections.MutableMap;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
-public class LoadBalancingPolicyTest extends AbstractLoadBalancingPolicyTest {
-    
-    // Expect no balancing to occur as container A isn't above the high threshold.
-    @Test
-    public void testNoopWhenWithinThresholds() {
-        MockContainerEntity containerA = newContainer(app, "A", 10, 100);
-        MockContainerEntity containerB = newContainer(app, "B", 20, 60);
-        MockItemEntity item1 = newItem(app, containerA, "1", 10);
-        MockItemEntity item2 = newItem(app, containerA, "2", 10);
-        MockItemEntity item3 = newItem(app, containerA, "3", 10);
-        MockItemEntity item4 = newItem(app, containerA, "4", 10);
-
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4), 
-                ImmutableList.of(40d, 0d));
-    }
-    
-    @Test
-    public void testNoopWhenAlreadyBalanced() {
-        MockContainerEntity containerA = newContainer(app, "A", 20, 80);
-        MockContainerEntity containerB = newContainer(app, "B", 20, 80);
-        MockItemEntity item1 = newItem(app, containerA, "1", 10);
-        MockItemEntity item2 = newItem(app, containerA, "2", 30);
-        MockItemEntity item3 = newItem(app, containerB, "3", 20);
-        MockItemEntity item4 = newItem(app, containerB, "4", 20);
-
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4), 
-                ImmutableList.of(40d, 40d));
-        assertEquals(containerA.getBalanceableItems(), ImmutableSet.of(item1, item2));
-        assertEquals(containerB.getBalanceableItems(), ImmutableSet.of(item3, item4));
-    }
-    
-    // Expect 20 units of workload to be migrated from hot container (A) to cold (B).
-    @Test
-    public void testSimpleBalancing() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 25);
-        MockContainerEntity containerB = newContainer(app, "B", 20, 60);
-        MockItemEntity item1 = newItem(app, containerA, "1", 10);
-        MockItemEntity item2 = newItem(app, containerA, "2", 10);
-        MockItemEntity item3 = newItem(app, containerA, "3", 10);
-        MockItemEntity item4 = newItem(app, containerA, "4", 10);
-
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4), 
-                ImmutableList.of(20d, 20d));
-    }
-    
-    @Test
-    public void testSimpleBalancing2() {
-        MockContainerEntity containerA = newContainer(app, "A", 20, 40);
-        MockContainerEntity containerB = newContainer(app, "B", 20, 40);
-        MockItemEntity item1 = newItem(app, containerA, "1", 0);
-        MockItemEntity item2 = newItem(app, containerB, "2", 40);
-        MockItemEntity item3 = newItem(app, containerB, "3", 20);
-        MockItemEntity item4 = newItem(app, containerB, "4", 20);
-
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4), 
-                ImmutableList.of(40d, 40d));
-    }
-    
-//    @Test
-//    public void testAdjustedItemNotMoved() {
-//        MockBalancingModel pool = new MockBalancingModel(
-//                containers(
-//                        containerA, 20, 50,
-//                        containerB, 20, 50),
-//                items(
-//                        "item1", containerA, 0,
-//                        "item2", containerB, -40,
-//                        "item3", containerB, 20,
-//                        "item4", containerB, 20)
-//        );
-//        
-//        BalancingStrategy<String, String> policy = new BalancingStrategy<String, String>("Test", pool);
-//        policy.rebalance();
-//        
-//        assertEquals((Object)pool.getItemsForContainer(containerA), ImmutableSet.of("item1", "item3", "item4"), pool.itemDistributionToString());
-//        assertEquals((Object)pool.getItemsForContainer(containerB), ImmutableSet.of("item2"), pool.itemDistributionToString());
-//    }
-
-    @Test
-    public void testMultiMoveBalancing() {
-        MockContainerEntity containerA = newContainer(app, "A", 20, 50);
-        MockContainerEntity containerB = newContainer(app, "B", 20, 50);
-        MockItemEntity item1 = newItem(app, containerA, "1", 10);
-        MockItemEntity item2 = newItem(app, containerA, "2", 10);
-        MockItemEntity item3 = newItem(app, containerA, "3", 10);
-        MockItemEntity item4 = newItem(app, containerA, "4", 10);
-        MockItemEntity item5 = newItem(app, containerA, "5", 10);
-        MockItemEntity item6 = newItem(app, containerA, "6", 10);
-        MockItemEntity item7 = newItem(app, containerA, "7", 10);
-        MockItemEntity item8 = newItem(app, containerA, "8", 10);
-        MockItemEntity item9 = newItem(app, containerA, "9", 10);
-        MockItemEntity item10 = newItem(app, containerA, "10", 10);
-
-        // non-deterministic which items will be moved; but can assert how many (given they all have same workrate)
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4, item5, item6, item7, item8, item9, item10), 
-                ImmutableList.of(50d, 50d));
-        assertEquals(containerA.getBalanceableItems().size(), 5);
-        assertEquals(containerB.getBalanceableItems().size(), 5);
-    }
-    
-    @Test
-    public void testRebalanceWhenWorkratesChange() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 50);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 50);
-        MockItemEntity item1 = newItem(app, containerA, "1", 0);
-        MockItemEntity item2 = newItem(app, containerA, "2", 0);
-
-        ((EntityLocal)item1).setAttribute(MockItemEntity.TEST_METRIC, 40);
-        ((EntityLocal)item2).setAttribute(MockItemEntity.TEST_METRIC, 40);
-        
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2), 
-                ImmutableList.of(40d, 40d));
-    }
-    
-    // Expect no balancing to occur in hot pool (2 containers over-threshold at 40).
-    // On addition of new container, expect hot containers to offload 10 each.
-    @Test
-    public void testAddContainerWhenHot() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 30);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 30);
-        MockItemEntity item1 = newItem(app, containerA, "1", 10);
-        MockItemEntity item2 = newItem(app, containerA, "2", 10);
-        MockItemEntity item3 = newItem(app, containerA, "3", 10);
-        MockItemEntity item4 = newItem(app, containerA, "4", 10);
-        MockItemEntity item5 = newItem(app, containerB, "5", 10);
-        MockItemEntity item6 = newItem(app, containerB, "6", 10);
-        MockItemEntity item7 = newItem(app, containerB, "7", 10);
-        MockItemEntity item8 = newItem(app, containerB, "8", 10);
-        // Both containers are over-threshold at this point; should not rebalance.
-        
-        MockContainerEntity containerC = newAsyncContainer(app, "C", 10, 30, CONTAINER_STARTUP_DELAY_MS);
-        // New container allows hot ones to offload work.
-
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB, containerC), 
-                ImmutableList.of(item1, item2, item3, item4, item5, item6, item7, item8), 
-                ImmutableList.of(30d, 30d, 20d));
-    }
-
-    // On addition of new container, expect no rebalancing to occur as no existing container is hot.
-    @Test
-    public void testAddContainerWhenCold() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 50);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 50);
-        MockItemEntity item1 = newItem(app, containerA, "1", 10);
-        MockItemEntity item2 = newItem(app, containerA, "2", 10);
-        MockItemEntity item3 = newItem(app, containerA, "3", 10);
-        MockItemEntity item4 = newItem(app, containerA, "4", 10);
-        MockItemEntity item5 = newItem(app, containerB, "5", 10);
-        MockItemEntity item6 = newItem(app, containerB, "6", 10);
-        MockItemEntity item7 = newItem(app, containerB, "7", 10);
-        MockItemEntity item8 = newItem(app, containerB, "8", 10);
-        
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4, item5, item6, item7, item8), 
-                ImmutableList.of(40d, 40d));
-        
-        MockContainerEntity containerC = newAsyncContainer(app, "C", 10, 50, CONTAINER_STARTUP_DELAY_MS);
-
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB, containerC), 
-                ImmutableList.of(item1, item2, item3, item4, item5, item6, item7, item8), 
-                ImmutableList.of(40d, 40d, 0d));
-    }
-    
-    // Expect no balancing to occur in cool pool (2 containers under-threshold at 30).
-    // On addition of new item, expect over-threshold container (A) to offload 20 to B.
-    @Test
-    public void testAddItem() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 50);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 50);
-        MockItemEntity item1 = newItem(app, containerA, "1", 10);
-        MockItemEntity item2 = newItem(app, containerA, "2", 10);
-        MockItemEntity item3 = newItem(app, containerA, "3", 10);
-        MockItemEntity item4 = newItem(app, containerB, "4", 10);
-        MockItemEntity item5 = newItem(app, containerB, "5", 10);
-        MockItemEntity item6 = newItem(app, containerB, "6", 10);
-        
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4, item5, item6), 
-                ImmutableList.of(30d, 30d));
-        
-        newItem(app, containerA, "7", 40);
-        
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4, item5, item6), 
-                ImmutableList.of(50d, 50d));
-    }
-    
-    // FIXME Failed in build repeatedly (e.g. #1035), but couldn't reproduce locally yet with invocationCount=100
-    @Test(groups="WIP")
-    public void testRemoveContainerCausesRebalancing() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 30);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 30);
-        MockContainerEntity containerC = newContainer(app, "C", 10, 30);
-        MockItemEntity item1 = newItem(app, containerA, "1", 10);
-        MockItemEntity item2 = newItem(app, containerA, "2", 10);
-        MockItemEntity item3 = newItem(app, containerB, "3", 10);
-        MockItemEntity item4 = newItem(app, containerB, "4", 10);
-        MockItemEntity item5 = newItem(app, containerC, "5", 10);
-        MockItemEntity item6 = newItem(app, containerC, "6", 10);
-
-        Entities.unmanage(containerC);
-        item5.move(containerA);
-        item6.move(containerA);
-        
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4, item5, item6), 
-                ImmutableList.of(30d, 30d));
-    }
-
-    @Test
-    public void testRemoveItemCausesRebalancing() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 30);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 30);
-        MockItemEntity item1 = newItem(app, containerA, "1", 30);
-        MockItemEntity item2 = newItem(app, containerB, "2", 20);
-        MockItemEntity item3 = newItem(app, containerB, "3", 20);
-        
-        item1.stop();
-        Entities.unmanage(item1);
-        
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3), 
-                ImmutableList.of(20d, 20d));
-    }
-
-    @Test
-    public void testRebalancesAfterManualMove() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 50);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 50);
-        MockItemEntity item1 = newItem(app, containerA, "1", 20);
-        MockItemEntity item2 = newItem(app, containerA, "2", 20);
-        MockItemEntity item3 = newItem(app, containerB, "3", 20);
-        MockItemEntity item4 = newItem(app, containerB, "4", 20);
-
-        // Move everything onto containerA, and expect it to be automatically re-balanced
-        item3.move(containerA);
-        item4.move(containerA);
-
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3, item4), 
-                ImmutableList.of(40d, 40d));
-    }
-    
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    @Test
-    public void testModelIncludesItemsAndContainersStartedBeforePolicyCreated() {
-        pool.removePolicy(policy);
-        policy.destroy();
-        
-        // Set-up containers and items.
-        final MockContainerEntity containerA = newContainer(app, "A", 10, 100);
-        newItem(app, containerA, "1", 10);
-
-        policy = new LoadBalancingPolicy(MutableMap.of(), TEST_METRIC, model);
-        pool.addPolicy(policy);
-        
-        Asserts.succeedsEventually(MutableMap.of("timeout", TIMEOUT_MS), new Runnable() {
-            public void run() {
-                assertEquals(model.getContainerWorkrates(), ImmutableMap.of(containerA, 10d));
-            }
-        });
-    }
-    
-    @Test
-    public void testLockedItemsNotMoved() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 50);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 50);
-        MockItemEntity item1 = newLockedItem(app, containerA, "1", 40);
-        MockItemEntity item2 = newLockedItem(app, containerA, "2", 40);
-
-        assertWorkratesContinually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2), 
-                ImmutableList.of(80d, 0d));
-    }
-    
-    @Test
-    public void testLockedItemsContributeToOverloadedMeasurements() {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 50);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 50);
-        MockItemEntity item1 = newLockedItem(app, containerA, "1", 40);
-        MockItemEntity item2 = newItem(app, containerA, "2", 25);
-        MockItemEntity item3 = newItem(app, containerA, "3", 25);
-        
-        assertWorkratesEventually(
-                ImmutableList.of(containerA, containerB),
-                ImmutableList.of(item1, item2, item3), 
-                ImmutableList.of(40d, 50d));
-    }
-    
-    @Test
-    public void testOverloadedLockedItemsPreventMoreWorkEnteringContainer() throws Exception {
-        // Set-up containers and items.
-        MockContainerEntity containerA = newContainer(app, "A", 10, 50);
-        MockContainerEntity containerB = newContainer(app, "B", 10, 50);
-        MockItemEntity item1 = newLockedItem(app, containerA, "1", 50);
-        Thread.sleep(1); // increase chances of item1's workrate having been received first
-        MockItemEntity item2 = newItem(app, containerB, "2", 30);
-        MockItemEntity item3 = newItem(app, containerB, "3", 30);
-        
-        assertWorkratesContinually(
-                ImmutableList.of(containerA, containerB), 
-                ImmutableList.of(item1, item2, item3), 
-                ImmutableList.of(50d, 60d));
-    }
-    
-    @Test
-    public void testPolicyUpdatesModel() {
-        final MockContainerEntity containerA = newContainer(app, "A", 10, 20);
-        final MockContainerEntity containerB = newContainer(app, "B", 11, 21);
-        final MockItemEntity item1 = newItem(app, containerA, "1", 12);
-        final MockItemEntity item2 = newItem(app, containerB, "2", 13);
-        
-        Asserts.succeedsEventually(MutableMap.of("timeout", TIMEOUT_MS), new Runnable() {
-            public void run() {
-                assertEquals(model.getPoolSize(), 2);
-                assertEquals(model.getPoolContents(), ImmutableSet.of(containerA, containerB));
-                assertEquals(model.getItemWorkrate(item1), 12d);
-                assertEquals(model.getItemWorkrate(item2), 13d);
-                
-                assertEquals(model.getParentContainer(item1), containerA);
-                assertEquals(model.getParentContainer(item2), containerB);
-                assertEquals(model.getContainerWorkrates(), ImmutableMap.of(containerA, 12d, containerB, 13d));
-                
-                assertEquals(model.getPoolLowThreshold(), 10+11d);
-                assertEquals(model.getPoolHighThreshold(), 20+21d);
-                assertEquals(model.getCurrentPoolWorkrate(), 12+13d);
-                assertFalse(model.isHot());
-                assertFalse(model.isCold());
-            }
-        });
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d30ff597/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java b/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java
deleted file mode 100644
index 70d4b57..0000000
--- a/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntity.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.policy.loadbalancing;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Effector;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
-import org.apache.brooklyn.core.util.flags.SetFromFlag;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.annotation.EffectorParam;
-import brooklyn.entity.basic.AbstractGroup;
-import brooklyn.entity.basic.MethodEffector;
-import brooklyn.entity.trait.Startable;
-import brooklyn.event.basic.BasicConfigKey;
-
-@ImplementedBy(MockContainerEntityImpl.class)
-public interface MockContainerEntity extends AbstractGroup, BalanceableContainer<Movable>, Startable {
-
-    @SetFromFlag("membership")
-    public static final ConfigKey<String> MOCK_MEMBERSHIP = new BasicConfigKey<String>(
-            String.class, "mock.container.membership", "For testing ItemsInContainersGroup");
-
-    @SetFromFlag("delay")
-    public static final ConfigKey<Long> DELAY = new BasicConfigKey<Long>(
-            Long.class, "mock.container.delay", "", 0L);
-
-    public static final Effector<Void> OFFLOAD_AND_STOP = new MethodEffector<Void>(MockContainerEntity.class, "offloadAndStop");
-
-    public void lock();
-
-    public void unlock();
-
-    public int getWorkrate();
-
-    public Map<Entity, Double> getItemUsage();
-
-    public void addItem(Entity item);
-
-    public void removeItem(Entity item);
-
-    public void offloadAndStop(@EffectorParam(name="otherContianer") MockContainerEntity otherContainer);
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d30ff597/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntityImpl.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntityImpl.java b/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntityImpl.java
deleted file mode 100644
index 672addb..0000000
--- a/policy/src/test/java/brooklyn/policy/loadbalancing/MockContainerEntityImpl.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.policy.loadbalancing;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.event.AttributeSensor;
-import org.apache.brooklyn.api.location.Location;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.AbstractGroupImpl;
-import brooklyn.entity.basic.Attributes;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-
-public class MockContainerEntityImpl extends AbstractGroupImpl implements MockContainerEntity {
-
-    private static final Logger LOG = LoggerFactory.getLogger(MockContainerEntity.class);
-
-    volatile boolean offloading;
-    volatile boolean running;
-
-    ReentrantLock _lock = new ReentrantLock();
-
-    @Override
-    public <T> T setAttribute(AttributeSensor<T> attribute, T val) {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: container {} setting {} to {}", new Object[] {this, attribute, val});
-        return super.setAttribute(attribute, val);
-    }
-
-    @Override
-    public void lock() {
-        _lock.lock();
-        if (!running) {
-            _lock.unlock();
-            throw new IllegalStateException("Container lock "+this+"; it is not running");
-        }
-    }
-
-    @Override
-    public void unlock() {
-        _lock.unlock();
-    }
-
-    @Override
-    public int getWorkrate() {
-        int result = 0;
-        for (Entity member : getMembers()) {
-            Integer memberMetric = member.getAttribute(MockItemEntity.TEST_METRIC);
-            result += ((memberMetric != null) ? memberMetric : 0);
-        }
-        return result;
-    }
-
-    @Override
-    public Map<Entity, Double> getItemUsage() {
-        Map<Entity, Double> result = Maps.newLinkedHashMap();
-        for (Entity member : getMembers()) {
-            Map<Entity, Double> memberItemUsage = member.getAttribute(MockItemEntity.ITEM_USAGE_METRIC);
-            if (memberItemUsage != null) {
-                for (Map.Entry<Entity, Double> entry : memberItemUsage.entrySet()) {
-                    double val = (result.containsKey(entry.getKey()) ? result.get(entry.getKey()) : 0d);
-                    val += ((entry.getValue() != null) ? entry.getValue() : 0);
-                    result.put(entry.getKey(), val);
-                }
-            }
-        }
-        return result;
-    }
-    
-    @Override
-    public void addItem(Entity item) {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: adding item {} to container {}", item, this);
-        if (!running || offloading) throw new IllegalStateException("Container "+getDisplayName()+" is not running; cannot add item "+item);
-        addMember(item);
-        emit(BalanceableContainer.ITEM_ADDED, item);
-    }
-
-    @Override
-    public void removeItem(Entity item) {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: removing item {} from container {}", item, this);
-        if (!running) throw new IllegalStateException("Container "+getDisplayName()+" is not running; cannot remove item "+item);
-        removeMember(item);
-        emit(BalanceableContainer.ITEM_REMOVED, item);
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    @Override
-    public Set<Movable> getBalanceableItems() {
-        return (Set) Sets.newLinkedHashSet(getMembers());
-    }
-
-    public String toString() {
-        return "MockContainer["+getDisplayName()+"]";
-    }
-
-    private long getDelay() {
-        return getConfig(DELAY);
-    }
-    
-    @Override
-    public void start(Collection<? extends Location> locs) {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: starting container {}", this);
-        _lock.lock();
-        try {
-            Time.sleep(getDelay());
-            running = true;
-            addLocations(locs);
-            emit(Attributes.LOCATION_CHANGED, null);
-            setAttribute(SERVICE_UP, true);
-        } finally {
-            _lock.unlock();
-        }
-    }
-
-    @Override
-    public void stop() {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: stopping container {}", this);
-        _lock.lock();
-        try {
-            running = false;
-            Time.sleep(getDelay());
-            setAttribute(SERVICE_UP, false);
-        } finally {
-            _lock.unlock();
-        }
-    }
-
-    private void stopWithoutLock() {
-        running = false;
-        Time.sleep(getDelay());
-        setAttribute(SERVICE_UP, false);
-    }
-
-    public void offloadAndStop(final MockContainerEntity otherContainer) {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: offloading container {} to {} (items {})", new Object[] {this, otherContainer, getBalanceableItems()});
-        runWithLock(ImmutableList.of(this, otherContainer), new Runnable() {
-            public void run() {
-                offloading = false;
-                for (Movable item : getBalanceableItems()) {
-                    ((MockItemEntity)item).moveNonEffector(otherContainer);
-                }
-                if (LOG.isDebugEnabled()) LOG.debug("Mocks: stopping offloaded container {}", this);
-                stopWithoutLock();
-            }});
-    }
-
-    @Override
-    public void restart() {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: restarting {}", this);
-        throw new UnsupportedOperationException();
-    }
-
-    public static void runWithLock(List<MockContainerEntity> entitiesToLock, Runnable r) {
-        List<MockContainerEntity> entitiesToLockCopy = MutableList.copyOf(Iterables.filter(entitiesToLock, Predicates.notNull()));
-        List<MockContainerEntity> entitiesLocked = Lists.newArrayList();
-        Collections.sort(entitiesToLockCopy, new Comparator<MockContainerEntity>() {
-            public int compare(MockContainerEntity o1, MockContainerEntity o2) {
-                return o1.getId().compareTo(o2.getId());
-            }});
-
-        try {
-            for (MockContainerEntity it : entitiesToLockCopy) {
-                it.lock();
-                entitiesLocked.add(it);
-            }
-
-            r.run();
-
-        } finally {
-            for (MockContainerEntity it : entitiesLocked) {
-                it.unlock();
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d30ff597/policy/src/test/java/brooklyn/policy/loadbalancing/MockItemEntity.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/loadbalancing/MockItemEntity.java b/policy/src/test/java/brooklyn/policy/loadbalancing/MockItemEntity.java
deleted file mode 100644
index 9286072..0000000
--- a/policy/src/test/java/brooklyn/policy/loadbalancing/MockItemEntity.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.policy.loadbalancing;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
-import org.apache.brooklyn.api.event.AttributeSensor;
-
-import brooklyn.event.basic.Sensors;
-
-import com.google.common.reflect.TypeToken;
-
-@ImplementedBy(MockItemEntityImpl.class)
-public interface MockItemEntity extends Entity, Movable {
-
-    public static final AttributeSensor<Integer> TEST_METRIC = Sensors.newIntegerSensor(
-            "test.metric", "Dummy workrate for test entities");
-
-    @SuppressWarnings("serial")
-    public static final AttributeSensor<Map<Entity, Double>> ITEM_USAGE_METRIC = Sensors.newSensor(
-            new TypeToken<Map<Entity, Double>>() {}, "test.itemUsage.metric", "Dummy item usage for test entities");
-
-    public boolean isStopped();
-
-    public void moveNonEffector(Entity rawDestination);
-    
-    public void stop();
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d30ff597/policy/src/test/java/brooklyn/policy/loadbalancing/MockItemEntityImpl.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/loadbalancing/MockItemEntityImpl.java b/policy/src/test/java/brooklyn/policy/loadbalancing/MockItemEntityImpl.java
deleted file mode 100644
index ecc725e..0000000
--- a/policy/src/test/java/brooklyn/policy/loadbalancing/MockItemEntityImpl.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.policy.loadbalancing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.event.AttributeSensor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.util.collections.MutableList;
-
-
-public class MockItemEntityImpl extends AbstractEntity implements MockItemEntity {
-
-    private static final Logger LOG = LoggerFactory.getLogger(MockItemEntityImpl.class);
-    
-    public static AtomicInteger totalMoveCount = new AtomicInteger(0);
-    
-    public static AtomicLong lastMoveTime = new AtomicLong(-1);
-    
-    private volatile boolean stopped;
-    private volatile MockContainerEntity currentContainer;
-    
-    private final ReentrantLock _lock = new ReentrantLock();
-    
-    @Override
-    public String getContainerId() {
-        return (currentContainer == null) ? null : currentContainer.getId();
-    }
-
-    @Override
-    public boolean isStopped() {
-        return stopped;
-    }
-
-    @Override
-    public <T> T setAttribute(AttributeSensor<T> attribute, T val) {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: item {} setting {} to {}", new Object[] {this, attribute, val});
-        return super.setAttribute(attribute, val);
-    }
-
-    @Override
-    public void move(Entity destination) {
-        totalMoveCount.incrementAndGet();
-        lastMoveTime.set(System.currentTimeMillis());
-        moveNonEffector(destination);
-    }
-    
-    // only moves if the containers will accept us (otherwise we'd lose the item!)
-    @Override
-    public void moveNonEffector(Entity rawDestination) {
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: moving item {} from {} to {}", new Object[] {this, currentContainer, rawDestination});
-        checkNotNull(rawDestination);
-        final MockContainerEntity previousContainer = currentContainer;
-        final MockContainerEntity destination = (MockContainerEntity) rawDestination;
-        
-        MockContainerEntityImpl.runWithLock(MutableList.of(previousContainer, destination), new Runnable() { 
-            @Override public void run() {
-                _lock.lock();
-                try {
-                    if (stopped) throw new IllegalStateException("Item "+this+" is stopped; cannot move to "+destination);
-                    if (currentContainer != null) currentContainer.removeItem(MockItemEntityImpl.this);
-                    currentContainer = destination;
-                    destination.addItem(MockItemEntityImpl.this);
-                    setAttribute(CONTAINER, currentContainer);
-                } finally {
-                    _lock.unlock();
-                }
-        }});
-    }
-    
-    @Override
-    public void stop() {
-        // FIXME How best to indicate this has been entirely stopped, rather than just in-transit?
-        if (LOG.isDebugEnabled()) LOG.debug("Mocks: stopping item {} (was in container {})", this, currentContainer);
-        _lock.lock();
-        try {
-            if (currentContainer != null) currentContainer.removeItem(this);
-            currentContainer = null;
-            stopped = true;
-        } finally {
-            _lock.unlock();
-        }
-    }
-    
-    @Override
-    public String toString() {
-        return "MockItem["+getDisplayName()+"]";
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d30ff597/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java b/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java
new file mode 100644
index 0000000..83f7b33
--- /dev/null
+++ b/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java
@@ -0,0 +1,274 @@
+/*
+ * 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.policy.autoscaling;
+
+import static org.apache.brooklyn.policy.autoscaling.AutoScalerPolicyTest.currentSizeAsserter;
+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.proxying.EntitySpec;
+import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestCluster;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.event.basic.BasicNotificationSensor;
+import brooklyn.event.basic.Sensors;
+import brooklyn.test.Asserts;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+public class AutoScalerPolicyMetricTest {
+    
+    private static long TIMEOUT_MS = 10000;
+    private static long SHORT_WAIT_MS = 50;
+    
+    private static final AttributeSensor<Integer> MY_ATTRIBUTE = Sensors.newIntegerSensor("autoscaler.test.intAttrib");
+    TestApplication app;
+    TestCluster tc;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void before() {
+        app = TestApplication.Factory.newManagedInstanceForTests();
+        tc = app.createAndManageChild(EntitySpec.create(TestCluster.class)
+                .configure("initialSize", 1));
+    }
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+    }
+
+    @Test
+    public void testIncrementsSizeIffUpperBoundExceeded() {
+        tc.resize(1);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE).metricLowerBound(50).metricUpperBound(100).build();
+        tc.addPolicy(policy);
+
+        tc.setAttribute(MY_ATTRIBUTE, 100);
+        Asserts.succeedsContinually(ImmutableMap.of("timeout", SHORT_WAIT_MS), currentSizeAsserter(tc, 1));
+
+        tc.setAttribute(MY_ATTRIBUTE, 101);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 2));
+    }
+    
+    @Test
+    public void testDecrementsSizeIffLowerBoundExceeded() {
+        tc.resize(2);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE).metricLowerBound(50).metricUpperBound(100).build();
+        tc.addPolicy(policy);
+
+        tc.setAttribute(MY_ATTRIBUTE, 50);
+        Asserts.succeedsContinually(ImmutableMap.of("timeout", SHORT_WAIT_MS), currentSizeAsserter(tc, 2));
+
+        tc.setAttribute(MY_ATTRIBUTE, 49);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 1));
+    }
+    
+    @Test(groups="Integration")
+    public void testIncrementsSizeInProportionToMetric() {
+        tc.resize(5);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE).metricLowerBound(50).metricUpperBound(100).build();
+        tc.addPolicy(policy);
+        
+        // workload 200 so requires doubling size to 10 to handle: (200*5)/100 = 10
+        tc.setAttribute(MY_ATTRIBUTE, 200);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 10));
+        
+        // workload 5, requires 1 entity: (10*110)/100 = 11
+        tc.setAttribute(MY_ATTRIBUTE, 110);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 11));
+    }
+    
+    @Test(groups="Integration")
+    public void testDecrementsSizeInProportionToMetric() {
+        tc.resize(5);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE).metricLowerBound(50).metricUpperBound(100).build();
+        tc.addPolicy(policy);
+        
+        // workload can be handled by 4 servers, within its valid range: (49*5)/50 = 4.9
+        tc.setAttribute(MY_ATTRIBUTE, 49);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 4));
+        
+        // workload can be handled by 4 servers, within its valid range: (25*4)/50 = 2
+        tc.setAttribute(MY_ATTRIBUTE, 25);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 2));
+        
+        tc.setAttribute(MY_ATTRIBUTE, 0);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 1));
+    }
+    
+    @Test(groups="Integration")
+    public void testObeysMinAndMaxSize() {
+        tc.resize(4);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .minPoolSize(2).maxPoolSize(6)
+                .build();
+        tc.addPolicy(policy);
+
+        // Decreases to min-size only
+        tc.setAttribute(MY_ATTRIBUTE, 0);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 2));
+        
+        // Increases to max-size only
+        tc.setAttribute(MY_ATTRIBUTE, 100000);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 6));
+    }
+    
+    @Test(groups="Integration",invocationCount=20)
+    public void testWarnsWhenMaxCapReached() {
+        final List<MaxPoolSizeReachedEvent> maxReachedEvents = Lists.newCopyOnWriteArrayList();
+        tc.resize(1);
+        
+        BasicNotificationSensor<MaxPoolSizeReachedEvent> maxSizeReachedSensor = AutoScalerPolicy.DEFAULT_MAX_SIZE_REACHED_SENSOR;
+        
+        app.subscribe(tc, maxSizeReachedSensor, new SensorEventListener<MaxPoolSizeReachedEvent>() {
+                @Override public void onEvent(SensorEvent<MaxPoolSizeReachedEvent> event) {
+                    maxReachedEvents.add(event.getValue());
+                }});
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .maxPoolSize(6)
+                .maxSizeReachedSensor(maxSizeReachedSensor)
+                .build();
+        tc.addPolicy(policy);
+
+        // workload can be handled by 6 servers, so no need to notify: 6 <= (100*6)/50
+        tc.setAttribute(MY_ATTRIBUTE, 600);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 6));
+        assertTrue(maxReachedEvents.isEmpty());
+        
+        // Increases to above max capacity: would require (100000*6)/100 = 6000
+        tc.setAttribute(MY_ATTRIBUTE, 100000);
+        
+        // Assert our listener gets notified (once)
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new Runnable() {
+            public void run() {
+                assertEquals(maxReachedEvents.size(), 1);
+                assertEquals(maxReachedEvents.get(0).getMaxAllowed(), 6);
+                assertEquals(maxReachedEvents.get(0).getCurrentPoolSize(), 6);
+                assertEquals(maxReachedEvents.get(0).getCurrentUnbounded(), 6000);
+                assertEquals(maxReachedEvents.get(0).getMaxUnbounded(), 6000);
+                assertEquals(maxReachedEvents.get(0).getTimeWindow(), 0);
+            }});
+        Asserts.succeedsContinually(new Runnable() {
+                @Override public void run() {
+                    assertEquals(maxReachedEvents.size(), 1);
+                }});
+        currentSizeAsserter(tc, 6).run();
+    }
+    
+    @Test
+    public void testDestructionState() {
+        tc.resize(1);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE).metricLowerBound(50).metricUpperBound(100).build();
+        tc.addPolicy(policy);
+
+        policy.destroy();
+        assertTrue(policy.isDestroyed());
+        assertFalse(policy.isRunning());
+        
+        tc.setAttribute(MY_ATTRIBUTE, 100000);
+        Asserts.succeedsContinually(ImmutableMap.of("timeout", SHORT_WAIT_MS), currentSizeAsserter(tc, 1));
+        
+        // TODO Could assert all subscriptions have been de-registered as well, 
+        // but that requires exposing more things just for testing...
+    }
+    
+    @Test
+    public void testSuspendState() {
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE).metricLowerBound(50).metricUpperBound(100).build();
+        tc.addPolicy(policy);
+        
+        policy.suspend();
+        assertFalse(policy.isRunning());
+        assertFalse(policy.isDestroyed());
+        
+        policy.resume();
+        assertTrue(policy.isRunning());
+        assertFalse(policy.isDestroyed());
+    }
+
+    @Test
+    public void testPostSuspendActions() {
+        tc.resize(1);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE).metricLowerBound(50).metricUpperBound(100).build();
+        tc.addPolicy(policy);
+
+        policy.suspend();
+        
+        tc.setAttribute(MY_ATTRIBUTE, 100000);
+        Asserts.succeedsContinually(ImmutableMap.of("timeout", SHORT_WAIT_MS), currentSizeAsserter(tc, 1));
+    }
+    
+    @Test
+    public void testPostResumeActions() {
+        tc.resize(1);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE).metricLowerBound(50).metricUpperBound(100).build();
+        tc.addPolicy(policy);
+        
+        policy.suspend();
+        policy.resume();
+        tc.setAttribute(MY_ATTRIBUTE, 101);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 2));
+    }
+    
+    @Test
+    public void testSubscribesToMetricOnSpecifiedEntity() {
+        TestEntity entityWithMetric = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+        
+        tc.resize(1);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder()
+                .metric(TestEntity.SEQUENCE)
+                .entityWithMetric(entityWithMetric)
+                .metricLowerBound(50)
+                .metricUpperBound(100)
+                .build();
+        tc.addPolicy(policy);
+
+        // First confirm that tc is not being listened to for this entity
+        tc.setAttribute(TestEntity.SEQUENCE, 101);
+        Asserts.succeedsContinually(ImmutableMap.of("timeout", SHORT_WAIT_MS), currentSizeAsserter(tc, 1));
+
+        // Then confirm we listen to the correct "entityWithMetric"
+        entityWithMetric.setAttribute(TestEntity.SEQUENCE, 101);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 2));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d30ff597/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyRebindTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyRebindTest.java b/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyRebindTest.java
new file mode 100644
index 0000000..f8f200b
--- /dev/null
+++ b/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyRebindTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.policy.autoscaling;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.rebind.RebindTestFixtureWithApp;
+import brooklyn.event.basic.BasicNotificationSensor;
+import brooklyn.event.basic.Sensors;
+
+import org.apache.brooklyn.location.basic.SimulatedLocation;
+
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class AutoScalerPolicyRebindTest extends RebindTestFixtureWithApp {
+
+    public static BasicNotificationSensor<Map> POOL_HOT_SENSOR = new BasicNotificationSensor<Map>(
+            Map.class, "AutoScalerPolicyRebindTest.resizablepool.hot", "Pool is over-utilized; it has insufficient resource for current workload");
+    public static BasicNotificationSensor<Map> POOL_COLD_SENSOR = new BasicNotificationSensor<Map>(
+            Map.class, "AutoScalerPolicyRebindTest.resizablepool.cold", "Pool is under-utilized; it has too much resource for current workload");
+    public static BasicNotificationSensor<Map> POOL_OK_SENSOR = new BasicNotificationSensor<Map>(
+            Map.class, "AutoScalerPolicyRebindTest.resizablepool.cold", "Pool utilization is ok; the available resources are fine for the current workload");
+    public static BasicNotificationSensor<MaxPoolSizeReachedEvent> MAX_SIZE_REACHED_SENSOR = new BasicNotificationSensor<MaxPoolSizeReachedEvent>(
+            MaxPoolSizeReachedEvent.class, "AutoScalerPolicyRebindTest.maxSizeReached");
+    public static AttributeSensor<Integer> METRIC_SENSOR = Sensors.newIntegerSensor("AutoScalerPolicyRebindTest.metric");
+            
+    private DynamicCluster origCluster;
+    private SimulatedLocation origLoc;
+
+    @BeforeMethod(alwaysRun=true)
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        origLoc = origManagementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+        origCluster = origApp.createAndManageChild(EntitySpec.create(DynamicCluster.class)
+                .configure("memberSpec", EntitySpec.create(TestEntity.class)));
+    }
+    
+    @Test
+    public void testRestoresAutoScalerConfig() throws Exception {
+        origCluster.addPolicy(AutoScalerPolicy.builder()
+                .name("myname")
+                .metric(METRIC_SENSOR)
+                .entityWithMetric(origCluster)
+                .metricUpperBound(1)
+                .metricLowerBound(2)
+                .minPoolSize(0)
+                .maxPoolSize(3)
+                .minPeriodBetweenExecs(Duration.of(4, TimeUnit.MILLISECONDS))
+                .resizeUpStabilizationDelay(Duration.of(5, TimeUnit.MILLISECONDS))
+                .resizeDownStabilizationDelay(Duration.of(6, TimeUnit.MILLISECONDS))
+                .poolHotSensor(POOL_HOT_SENSOR)
+                .poolColdSensor(POOL_COLD_SENSOR)
+                .poolOkSensor(POOL_OK_SENSOR)
+                .maxSizeReachedSensor(MAX_SIZE_REACHED_SENSOR)
+                .maxReachedNotificationDelay(Duration.of(7, TimeUnit.MILLISECONDS))
+                .buildSpec());
+        
+        TestApplication newApp = rebind();
+        DynamicCluster newCluster = (DynamicCluster) Iterables.getOnlyElement(newApp.getChildren());
+        AutoScalerPolicy newPolicy = (AutoScalerPolicy) Iterables.getOnlyElement(newCluster.getPolicies());
+
+        assertEquals(newPolicy.getDisplayName(), "myname");
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.METRIC), METRIC_SENSOR);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.ENTITY_WITH_METRIC), newCluster);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.METRIC_UPPER_BOUND), 1);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.METRIC_LOWER_BOUND), 2);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.MIN_POOL_SIZE), (Integer)0);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.MAX_POOL_SIZE), (Integer)3);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.MIN_PERIOD_BETWEEN_EXECS), Duration.of(4, TimeUnit.MILLISECONDS));
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.RESIZE_UP_STABILIZATION_DELAY), Duration.of(5, TimeUnit.MILLISECONDS));
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.RESIZE_DOWN_STABILIZATION_DELAY), Duration.of(6, TimeUnit.MILLISECONDS));
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.POOL_HOT_SENSOR), POOL_HOT_SENSOR);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.POOL_COLD_SENSOR), POOL_COLD_SENSOR);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.POOL_OK_SENSOR), POOL_OK_SENSOR);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.MAX_SIZE_REACHED_SENSOR), MAX_SIZE_REACHED_SENSOR);
+        assertEquals(newPolicy.getConfig(AutoScalerPolicy.MAX_REACHED_NOTIFICATION_DELAY), Duration.of(7, TimeUnit.MILLISECONDS));
+    }
+    
+    @Test
+    public void testAutoScalerResizesAfterRebind() throws Exception {
+        origCluster.start(ImmutableList.of(origLoc));
+        origCluster.addPolicy(AutoScalerPolicy.builder()
+                .name("myname")
+                .metric(METRIC_SENSOR)
+                .entityWithMetric(origCluster)
+                .metricUpperBound(10)
+                .metricLowerBound(100)
+                .minPoolSize(1)
+                .maxPoolSize(3)
+                .buildSpec());
+        
+        TestApplication newApp = rebind();
+        DynamicCluster newCluster = (DynamicCluster) Iterables.getOnlyElement(newApp.getChildren());
+
+        assertEquals(newCluster.getCurrentSize(), (Integer)1);
+        
+        ((EntityInternal)newCluster).setAttribute(METRIC_SENSOR, 1000);
+        EntityTestUtils.assertGroupSizeEqualsEventually(newCluster, 3);
+        
+        ((EntityInternal)newCluster).setAttribute(METRIC_SENSOR, 1);
+        EntityTestUtils.assertGroupSizeEqualsEventually(newCluster, 1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d30ff597/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyReconfigurationTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyReconfigurationTest.java b/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyReconfigurationTest.java
new file mode 100644
index 0000000..f91adee
--- /dev/null
+++ b/policy/src/test/java/org/apache/brooklyn/policy/autoscaling/AutoScalerPolicyReconfigurationTest.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.policy.autoscaling;
+
+import static org.apache.brooklyn.policy.autoscaling.AutoScalerPolicyTest.currentSizeAsserter;
+
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestCluster;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.event.basic.Sensors;
+import brooklyn.test.Asserts;
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.ImmutableMap;
+
+public class AutoScalerPolicyReconfigurationTest {
+    
+    private static long TIMEOUT_MS = 10000;
+    
+    private static final AttributeSensor<Integer> MY_ATTRIBUTE = Sensors.newIntegerSensor("autoscaler.test.intAttrib");
+    TestApplication app;
+    TestCluster tc;
+    
+    @BeforeMethod(alwaysRun=true)
+    public void before() throws Exception {
+        app = TestApplication.Factory.newManagedInstanceForTests();
+        tc = app.createAndManageChild(EntitySpec.create(TestCluster.class)
+                .configure("initialSize", 1));
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (app != null) Entities.destroyAll(app.getManagementContext());
+    }
+
+    @Test
+    public void testIncreaseMinPoolSizeCausesImmediateGrowth() {
+        tc.resize(2);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .minPoolSize(2)
+                .build();
+        tc.addPolicy(policy);
+
+        policy.config().set(AutoScalerPolicy.MIN_POOL_SIZE, 3);
+        
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 3));
+    }
+    
+    @Test
+    public void testDecreaseMinPoolSizeAllowsSubsequentShrink() {
+        tc.resize(4);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .minPoolSize(2)
+                .build();
+        tc.addPolicy(policy);
+        
+        // 25*4 = 100 -> 2 nodes at 50 each
+        tc.setAttribute(MY_ATTRIBUTE, 25);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 2));
+
+        // Decreases to new min-size
+        policy.config().set(AutoScalerPolicy.MIN_POOL_SIZE, 1);
+        tc.setAttribute(MY_ATTRIBUTE, 0);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 1));
+    }
+    
+    @Test
+    public void testDecreaseMaxPoolSizeCausesImmediateShrink() {
+        tc.resize(6);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .maxPoolSize(6)
+                .build();
+        tc.addPolicy(policy);
+
+        policy.config().set(AutoScalerPolicy.MAX_POOL_SIZE, 4);
+        
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 4));
+    }
+    
+    @Test
+    public void testIncreaseMaxPoolSizeAllowsSubsequentGrowth() {
+        tc.resize(3);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .maxPoolSize(6)
+                .build();
+        tc.addPolicy(policy);
+
+        // 200*3 = 600 -> 6 nodes at 100 each
+        tc.setAttribute(MY_ATTRIBUTE, 200);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 6));
+        
+        policy.config().set(AutoScalerPolicy.MAX_POOL_SIZE, 8);
+        
+        // Increases to max-size only
+        tc.setAttribute(MY_ATTRIBUTE, 100000);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 8));
+    }
+    
+    @Test
+    public void testReconfigureMetricLowerBound() {
+        tc.resize(2);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .build();
+        tc.addPolicy(policy);
+
+        policy.config().set(AutoScalerPolicy.METRIC_LOWER_BOUND, 51);
+
+        tc.setAttribute(MY_ATTRIBUTE, 50);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 1));
+    }
+
+    @Test
+    public void testReconfigureMetricUpperBound() {
+        tc.resize(1);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .build();
+        tc.addPolicy(policy);
+
+        policy.config().set(AutoScalerPolicy.METRIC_UPPER_BOUND, 99);
+
+        tc.setAttribute(MY_ATTRIBUTE, 100);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 2));
+    }
+
+    @Test
+    public void testReconfigureResizeUpStabilizationDelay() {
+        tc.resize(1);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .resizeUpStabilizationDelay(Duration.TWO_MINUTES)
+                .build();
+        tc.addPolicy(policy);
+
+        policy.config().set(AutoScalerPolicy.RESIZE_UP_STABILIZATION_DELAY, Duration.ZERO);
+
+        tc.setAttribute(MY_ATTRIBUTE, 101);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 2));
+    }
+    
+    @Test
+    public void testReconfigureResizeDownStabilizationDelay() {
+        tc.resize(2);
+        
+        AutoScalerPolicy policy = new AutoScalerPolicy.Builder().metric(MY_ATTRIBUTE)
+                .metricLowerBound(50).metricUpperBound(100)
+                .resizeDownStabilizationDelay(Duration.TWO_MINUTES)
+                .build();
+        tc.addPolicy(policy);
+
+        policy.config().set(AutoScalerPolicy.RESIZE_DOWN_STABILIZATION_DELAY, Duration.ZERO);
+
+        tc.setAttribute(MY_ATTRIBUTE, 1);
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 1));
+    }
+}


Mime
View raw message