Github user aledsage commented on a diff in the pull request:

    https://github.com/apache/brooklyn-server/pull/443#discussion_r89775723
  
    --- Diff: 
core/src/test/java/org/apache/brooklyn/entity/group/DynamicClusterTest.java ---
    @@ -1225,4 +1235,93 @@ private void 
assertFirstAndNonFirstCounts(Collection<Entity> members, int expect
             assertEquals(found.size(), expectedNonFirstCount);
         }
     
    +    @DataProvider
    +    public Object[][] maxConcurrentCommandsTestProvider() {
    +        return new Object[][]{{1}, {2}, {3}};
    +    }
    +
    +    @Test(dataProvider = "maxConcurrentCommandsTestProvider")
    +    public void 
testEntitiesStartAndStopSequentiallyWhenMaxConcurrentCommandsIsOne(int 
maxConcurrentCommands) {
    +        EntitySpec<ThrowOnAsyncStartEntity> memberSpec = 
EntitySpec.create(ThrowOnAsyncStartEntity.class)
    +                .configure(ThrowOnAsyncStartEntity.MAX_CONCURRENCY, 
maxConcurrentCommands)
    +                .configure(ThrowOnAsyncStartEntity.COUNTER, new 
AtomicInteger());
    +        DynamicCluster cluster = 
app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
    +                .configure(DynamicCluster.MAX_CONCURRENT_CHILD_COMMANDS, 
maxConcurrentCommands)
    +                .configure(DynamicCluster.INITIAL_SIZE, 10)
    +                .configure(DynamicCluster.MEMBER_SPEC, memberSpec));
    +        app.start(ImmutableList.of(app.newSimulatedLocation()));
    +        
assertEquals(cluster.sensors().get(Attributes.SERVICE_STATE_ACTUAL), 
Lifecycle.RUNNING);
    +    }
    +
    +    @Test
    +    public void 
testFirstMemberStartsFirstWhenMaxConcurrentCommandsIsGiven() {
    +        final AtomicInteger counter = new AtomicInteger();
    +
    +        final DynamicCluster cluster = 
app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
    +                .configure(DynamicCluster.MAX_CONCURRENT_CHILD_COMMANDS, 1)
    +                .configure(DynamicCluster.INITIAL_SIZE, 10));
    +
    +        Task<Boolean> firstMemberUp = Tasks.<Boolean>builder()
    +                .body(new Callable<Boolean>() {
    +                    @Override
    +                    public Boolean call() throws Exception {
    +                        Task<Entity> first = 
DependentConfiguration.attributeWhenReady(cluster, DynamicCluster.FIRST);
    +                        
DynamicTasks.queueIfPossible(first).orSubmitAsync();
    +                        final Entity source = first.get();
    +                        final Task<Boolean> booleanTask = 
DependentConfiguration.attributeWhenReady(source, Attributes.SERVICE_UP);
    +                        
DynamicTasks.queueIfPossible(booleanTask).orSubmitAsync();
    +                        return booleanTask.get();
    +                    }
    +                })
    +                .build();
    +
    +        EntitySpec<ThrowOnAsyncStartEntity> firstMemberSpec = 
EntitySpec.create(ThrowOnAsyncStartEntity.class)
    +                .configure(ThrowOnAsyncStartEntity.COUNTER, counter)
    +                .configure(ThrowOnAsyncStartEntity.START_LATCH, true);
    +
    +        EntitySpec<ThrowOnAsyncStartEntity> memberSpec = 
EntitySpec.create(ThrowOnAsyncStartEntity.class)
    +                .configure(ThrowOnAsyncStartEntity.COUNTER, counter)
    +                .configure(ThrowOnAsyncStartEntity.START_LATCH, 
firstMemberUp);
    +
    +        cluster.config().set(DynamicCluster.FIRST_MEMBER_SPEC, 
firstMemberSpec);
    +        cluster.config().set(DynamicCluster.MEMBER_SPEC, memberSpec);
    +
    +        // app.start blocks so in the failure case this test would block 
forever.
    +        Thread t = new Thread() {
    +            @Override public void run() {
    +                app.start(ImmutableList.of(app.newSimulatedLocation()));
    +            }
    +        };
    +        t.start();
    +        try {
    +            EntityAsserts.assertAttributeEqualsEventually(cluster, 
Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
    +        } finally {
    +            if (t.isAlive()) {
    +                t.interrupt();
    +            }
    +            Entities.unmanage(cluster);
    +        }
    +    }
    +
    +    @ImplementedBy(ThrowOnAsyncStartEntityImpl.class)
    +    public interface ThrowOnAsyncStartEntity extends TestEntity {
    +        ConfigKey<Integer> MAX_CONCURRENCY = 
ConfigKeys.newConfigKey(Integer.class, "concurrency", "max concurrency", 1);
    +        ConfigKey<AtomicInteger> COUNTER = 
ConfigKeys.newConfigKey(AtomicInteger.class, "counter");
    +        ConfigKey<Boolean> START_LATCH = 
ConfigKeys.newConfigKey(Boolean.class, "startlatch");
    +    }
    +
    +    public static class ThrowOnAsyncStartEntityImpl extends TestEntityImpl 
implements ThrowOnAsyncStartEntity {
    +        private static final Logger LOG = 
LoggerFactory.getLogger(ThrowOnAsyncStartEntityImpl.class);
    +        @Override
    +        public void start(Collection<? extends Location> locs) {
    +            int count = config().get(COUNTER).incrementAndGet();
    +            LOG.debug("{} starting (first={})", new Object[]{this, 
sensors().get(AbstractGroup.FIRST_MEMBER)});
    +            config().get(START_LATCH);
    +            // Throw if more than one entity is starting at the same time 
as this.
    +            assertTrue(count <= config().get(MAX_CONCURRENCY), "expected " 
+ count + " <= " + config().get(MAX_CONCURRENCY));
    +            super.start(locs);
    +            config().get(COUNTER).decrementAndGet();
    --- End diff --
    
    Wrap in a try-finally block, to ensure the counter is deprecated? Probably 
not necessary for the existing tests, as they're not failing the start or 
interrupting. But still worth adding I think.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---

Reply via email to