@Test
  public void testAggregatingMembersEnricher() throws Exception {
    origApp.start(ImmutableList.of(origLoc));
    origCluster.resize(2);

    origApp.addEnricher(
        Enrichers.builder()
            .aggregating(METRIC1)
            .from(origCluster)
            .fromMembers()
            .computing(StringFunctions.joiner(","))
            .publishing(METRIC2)
            .build());

    TestApplication newApp = rebind();
    DynamicCluster newCluster =
        (DynamicCluster)
            Iterables.find(newApp.getChildren(), Predicates.instanceOf(DynamicCluster.class));

    int i = 1;
    for (Entity member : newCluster.getMembers()) {
      ((EntityInternal) member).setAttribute(METRIC1, "myval" + (i++));
    }
    EntityTestUtils.assertAttributeEventually(
        newApp,
        METRIC2,
        Predicates.or(Predicates.equalTo("myval1,myval2"), Predicates.equalTo("myval2,myval1")));
  }
  protected void runStopProcessAndRestart(Effector<?> restartEffector, Map<String, ?> args)
      throws Exception {
    LocalhostMachineProvisioningLocation loc = app.newLocalhostProvisioningLocation();
    SoftwareProcess entity = app.createAndManageChild(newEntitySpec());

    // Start the app
    app.start(ImmutableList.of(loc));
    EntityTestUtils.assertAttributeEqualsEventually(entity, SoftwareProcess.SERVICE_UP, true);
    EntityTestUtils.assertAttributeEqualsEventually(app, SoftwareProcess.SERVICE_UP, true);

    // Stop the process
    Entities.invokeEffector(
            app,
            entity,
            SoftwareProcess.STOP,
            ImmutableMap.of(
                StopSoftwareParameters.STOP_MACHINE_MODE.getName(),
                StopSoftwareParameters.StopMode.NEVER))
        .get();
    EntityTestUtils.assertAttributeEqualsEventually(entity, SoftwareProcess.SERVICE_UP, false);
    EntityTestUtils.assertAttributeEqualsEventually(
        entity, SoftwareProcess.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED);
    EntityTestUtils.assertAttributeEqualsEventually(
        entity, SoftwareProcess.SERVICE_PROCESS_IS_RUNNING, false);
    EntityTestUtils.assertAttributeEventually(
        entity,
        ServiceStateLogic.SERVICE_NOT_UP_INDICATORS,
        CollectionFunctionals.<String>mapSizeEquals(1));

    // Restart the process
    Entities.invokeEffector(app, entity, restartEffector, args).get();
    EntityTestUtils.assertAttributeEqualsEventually(entity, SoftwareProcess.SERVICE_UP, true);
    EntityTestUtils.assertAttributeEqualsEventually(
        entity, SoftwareProcess.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
    EntityTestUtils.assertAttributeEqualsEventually(
        entity, SoftwareProcess.SERVICE_PROCESS_IS_RUNNING, true);
    EntityTestUtils.assertAttributeEqualsEventually(
        entity, ServiceStateLogic.SERVICE_NOT_UP_INDICATORS, ImmutableMap.<String, Object>of());

    EntityTestUtils.assertAttributeEqualsEventually(app, SoftwareProcess.SERVICE_UP, true);
    EntityTestUtils.assertAttributeEqualsEventually(
        app, SoftwareProcess.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
  }
  @SuppressWarnings("unchecked")
  @Test
  public void testCombiningEnricher() throws Exception {
    origApp.addEnricher(
        Enrichers.builder()
            .combining(METRIC1, METRIC2)
            .from(origEntity)
            .computing(StringFunctions.joiner(","))
            .publishing(METRIC2)
            .build());

    TestApplication newApp = rebind();
    TestEntity newEntity =
        (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));

    newEntity.setAttribute(METRIC1, "myval");
    newEntity.setAttribute(METRIC2, "myval2");
    EntityTestUtils.assertAttributeEventually(
        newApp,
        METRIC2,
        Predicates.or(Predicates.equalTo("myval,myval2"), Predicates.equalTo("myval2,myval")));
  }