protected void subscribeToServiceState() { stateListener = new RecordingSensorEventListener<Lifecycle>(); subscriptions().subscribe(this, SERVICE_STATE_ACTUAL, stateListener); upListener = new RecordingSensorEventListener<Boolean>(); subscriptions().subscribe(this, SERVICE_UP, upListener); processRunningListener = new RecordingSensorEventListener<Boolean>(); subscriptions().subscribe(this, SERVICE_PROCESS_IS_RUNNING, processRunningListener); }
@Override public void run() { listener.assertEventCount(1); }}); }
@Override public void run() { // TODO In tests, have seen duplicate "starting"; and always begins with "stopped"; and have // seen "on-fire" between stopping and stopped! Therefore not using // assertEqualsOrderIgnoringDuplicates. List<Lifecycle> states = ImmutableList.copyOf(listener.getEventValues()); assertContainsOrdered(states, ImmutableList.of(Lifecycle.RUNNING, Lifecycle.STOPPING, Lifecycle.STOPPED)); }}); }
@Test public void testAddingAndRemovingGroupEmitsNotification() throws Exception { final RecordingSensorEventListener<Group> groupAddedListener = new RecordingSensorEventListener<>(); final RecordingSensorEventListener<Group> groupRemovedListener = new RecordingSensorEventListener<>(); mgmt.getSubscriptionManager().subscribe(entity1, AbstractEntity.GROUP_ADDED, groupAddedListener); mgmt.getSubscriptionManager().subscribe(entity1, AbstractEntity.GROUP_REMOVED, groupRemovedListener); group.addMember(entity1); Asserts.succeedsEventually(new Runnable() { @Override public void run() { String msg = "events="+groupAddedListener.getEvents(); assertEquals(groupAddedListener.getEvents().size(), 1, msg); assertEquals(groupAddedListener.getEvents().get(0).getSource(), entity1, msg); assertEquals(groupAddedListener.getEvents().get(0).getSensor(), AbstractEntity.GROUP_ADDED, msg); }}); assertEquals(groupRemovedListener.getEvents().size(), 0, "events="+groupRemovedListener.getEvents()); group.removeMember(entity1); Asserts.succeedsEventually(new Runnable() { @Override public void run() { String msg = "events="+groupRemovedListener.getEvents(); assertEquals(groupRemovedListener.getEvents().size(), 1, msg); assertEquals(groupRemovedListener.getEvents().get(0).getSource(), entity1, msg); assertEquals(groupRemovedListener.getEvents().get(0).getSensor(), AbstractEntity.GROUP_REMOVED, msg); }}); assertEquals(groupAddedListener.getEvents().size(), 1, "events="+groupAddedListener.getEvents()); }
AttributeSensor<String> mySensor = Sensors.newStringSensor("mySensor"); RecordingSensorEventListener<String> listener = new RecordingSensorEventListener<>(); Application tmpApp = mgmt().getEntityManager().createEntity(EntitySpec.create(TestApplication.class)); tmpApp.subscriptions().subscribe(null, mySensor, listener); listener.assertHasEventEventually(Predicates.alwaysTrue());
@Test public void testUpdateMapEmitsEventOnChange() throws Exception { Entity entity = app.createAndManageChild(EntitySpec.create(BasicApplication.class) .enricher(EnricherSpec.create(UpdatingMap.class) .configure(UpdatingMap.SOURCE_SENSOR.getName(), mySensor.getName()) .configure(UpdatingMap.TARGET_SENSOR, mapSensor) .configure(UpdatingMap.KEY_IN_TARGET_SENSOR, "myKey") .configure(UpdatingMap.COMPUTING, Functions.forMap(MutableMap.of("v1", "valIsV1", "v2", "valIsV2"), "myDefault")))); EntityAsserts.assertAttributeEqualsEventually(entity, mapSensor, ImmutableMap.of("myKey", "myDefault")); RecordingSensorEventListener<Map<String, Object>> listener = new RecordingSensorEventListener<>(); app.subscriptions().subscribe(entity, mapSensor, listener); entity.sensors().set(mySensor, "v1"); EntityAsserts.assertAttributeEqualsEventually(entity, mapSensor, ImmutableMap.of("myKey", "valIsV1")); listener.assertHasEventEventually(Predicates.alwaysTrue()); assertEquals(Iterables.getOnlyElement(listener.getEventValues()), ImmutableMap.of("myKey", "valIsV1")); }
@Test(groups="Integration") public void testSetsServiceLifecycle() { ControlledDynamicWebAppCluster cluster = app.createAndManageChild( EntitySpec.create(ControlledDynamicWebAppCluster.class) .configure("initialSize", 1) .configure(ControlledDynamicWebAppCluster.MEMBER_SPEC, EntitySpec.create(TestJavaWebAppEntity.class)) ); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED); RecordingSensorEventListener<Lifecycle> listener = new RecordingSensorEventListener<Lifecycle>(true); app.subscriptions().subscribe(cluster, Attributes.SERVICE_STATE_ACTUAL, listener); app.start(locs); Asserts.eventually(Suppliers.ofInstance(listener.getEventValues()), CollectionFunctionals.sizeEquals(2)); assertEquals(listener.getEventValues(), ImmutableList.of(Lifecycle.STARTING, Lifecycle.RUNNING), "vals="+listener.getEventValues()); listener.clearEvents(); app.stop(); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STOPPED); Asserts.eventually(Suppliers.ofInstance(listener), CollectionFunctionals.sizeEquals(2)); assertEquals(listener.getEventValues(), ImmutableList.of(Lifecycle.STOPPING, Lifecycle.STOPPED), "vals="+listener.getEventValues()); }
protected Entity runTest(String catalogYaml, String appId) throws Exception { addCatalogItems(catalogYaml); String appYaml = Joiner.on("\n").join( "services:", "- type: " + appId); Entity app = createStartWaitAndLogApplication(appYaml); TestEntity entity = (TestEntity) Iterables.find(app.getChildren(), EntityPredicates.displayNameEqualTo("targetEntity")); assertHasEnricher(entity, ServiceFailureDetector.class); // Confirm ServiceFailureDetector triggers event RecordingSensorEventListener<Object> listener = subscribeToHaSensors(entity); ServiceNotUpLogic.updateNotUpIndicator(entity, INDICATOR_KEY_1, "Simulate a problem"); listener.assertHasEventEventually(SensorEventPredicates.sensorEqualTo(HASensors.ENTITY_FAILED)); listener.assertEventCount(1); listener.clearEvents(); ServiceNotUpLogic.clearNotUpIndicator(entity, INDICATOR_KEY_1); listener.assertHasEventEventually(SensorEventPredicates.sensorEqualTo(HASensors.ENTITY_RECOVERED)); listener.assertEventCount(1); return app; }
protected void runRebindWhenHealthy(String catalogYaml, String appId) throws Exception { addCatalogItems(catalogYaml); String appYaml = Joiner.on("\n").join( "services:", "- type: " + appId); createStartWaitAndLogApplication(appYaml); // Rebind StartableApplication newApp = rebind(); TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), EntityPredicates.displayNameEqualTo("targetEntity")); assertHasEnricher(newEntity, ServiceFailureDetector.class); // Confirm ServiceFailureDetector still functions RecordingSensorEventListener<Object> listener = subscribeToHaSensors(newEntity); ServiceNotUpLogic.updateNotUpIndicator(newEntity, INDICATOR_KEY_1, "Simulate a problem"); listener.assertHasEventEventually(SensorEventPredicates.sensorEqualTo(HASensors.ENTITY_FAILED)); listener.assertEventCount(1); }
@Test public void testContextEntityOnSubscriptionCallbackTask() { observedEntity.sensors().set(TestEntity.NAME, "myval"); entity.subscriptions().subscribe(ImmutableMap.of("notifyOfInitialValue", true), observedEntity, TestEntity.NAME, listener); // notify-of-initial-value should give us our entity assertListenerCalledOnceWithContextEntityEventually(listener, entity); listener.clearEvents(); // as should subsequent events observedEntity.sensors().set(TestEntity.NAME, "myval2"); assertListenerCalledOnceWithContextEntityEventually(listener, entity); listener.clearEvents(); // same for subscribing to children: context should be the subscriber entity.subscriptions().subscribeToChildren(observedEntity, TestEntity.SEQUENCE, listener); observedChildEntity.sensors().set(TestEntity.SEQUENCE, 123); assertListenerCalledOnceWithContextEntityEventually(listener, entity); }
@Override public void run() { assertHasEvent(filter); }}); }
@Test(groups="Integration") public void testSupressingDuplicates() throws Exception { AttributeSensor<String> mySensor = Sensors.newStringSensor("mysensor"); RecordingSensorEventListener<String> listener = new RecordingSensorEventListener<>(); app().subscriptions().subscribe(null, mySensor, listener); RecordingWinRmTool.setCustomResponse(".*mycommand.*", new RecordingWinRmTool.CustomResponse(0, "myval", "")); Entity entity = app().createAndManageChild(EntitySpec.create(TestEntity.class) .addInitializer(new WinRmCommandSensor<String>(ConfigBag.newInstance(ImmutableMap.of( HttpRequestSensor.SUPPRESS_DUPLICATES, true, WinRmCommandSensor.SENSOR_PERIOD, "1ms", WinRmCommandSensor.SENSOR_COMMAND, "mycommand", WinRmCommandSensor.SENSOR_NAME, mySensor.getName()))))); app().start(ImmutableList.of(loc)); EntityAsserts.assertAttributeEqualsEventually(entity, mySensor, "myval"); listener.assertHasEventEventually(Predicates.alwaysTrue()); Asserts.succeedsContinually(new Runnable() { @Override public void run() { listener.assertEventCount(1); }}); } }
/** This can be sensitive to order, e.g. if TestEntity set expected RUNNING before setting SERVICE_UP, * there would be a point when TestEntity is ON_FIRE. * <p> * There can also be issues if a cluster is resizing from/to 0 while in a RUNNING state. * To correct that, use {@link ServiceStateLogic#newEnricherFromChildrenUp()}. */ @Test public void testResizeFromZeroToOneDoesNotGoThroughFailing() throws Exception { final DynamicCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(TestEntity.class)) .configure(DynamicCluster.INITIAL_SIZE, 1)); RecordingSensorEventListener<Lifecycle> r = new RecordingSensorEventListener<>(); app.subscriptions().subscribe(cluster, Attributes.SERVICE_STATE_ACTUAL, r); cluster.start(ImmutableList.of(loc)); EntityAsserts.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); for (SensorEvent<Lifecycle> evt: r.getEvents()) { if (evt.getValue()==Lifecycle.ON_FIRE) Assert.fail("Should not have published " + Lifecycle.ON_FIRE + " during normal start up: " + r.getEvents()); } }
protected void runRebindWhenNotUp(String catalogYaml, String appId) throws Exception { addCatalogItems(catalogYaml); String appYaml = Joiner.on("\n").join( "services:", "- type: " + appId); Entity app = createStartWaitAndLogApplication(appYaml); // Make entity go on-fire TestEntity entity = (TestEntity) Iterables.find(app.getChildren(), EntityPredicates.displayNameEqualTo("targetEntity")); RecordingSensorEventListener<Object> listener = subscribeToHaSensors(entity); ServiceNotUpLogic.updateNotUpIndicator(entity, INDICATOR_KEY_1, "Simulating a problem"); listener.assertHasEventEventually(SensorEventPredicates.sensorEqualTo(HASensors.ENTITY_FAILED)); // Rebind StartableApplication newApp = rebind(); TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), EntityPredicates.displayNameEqualTo("targetEntity")); assertHasEnricher(newEntity, ServiceFailureDetector.class); // Confirm ServiceFailureDetector still functions RecordingSensorEventListener<Object> newListener = subscribeToHaSensors(newEntity); ServiceNotUpLogic.clearNotUpIndicator(newEntity, INDICATOR_KEY_1); newListener.assertHasEventEventually(SensorEventPredicates.sensorEqualTo(HASensors.ENTITY_RECOVERED)); newListener.assertEventCount(1); }
@Test(groups="Integration") // because takes a second public void testNotNotifiedDuplicateAddedLocations() throws Exception { final Location l = app.newSimulatedLocation(); final RecordingSensorEventListener<Object> addedEvents = new RecordingSensorEventListener<>(); final RecordingSensorEventListener<Object> removedEvents = new RecordingSensorEventListener<>(); app.subscriptions().subscribe(app, AbstractEntity.LOCATION_ADDED, addedEvents); app.subscriptions().subscribe(app, AbstractEntity.LOCATION_REMOVED, removedEvents); // Add first location app.addLocations(ImmutableList.of(l, l)); assertEventValuesEqualsEventually(addedEvents, ImmutableList.of(l)); assertEventValuesEquals(removedEvents, ImmutableList.of()); // Add second location app.addLocations(ImmutableList.of(l)); assertEventValuesEqualsContinually(addedEvents, ImmutableList.of(l)); assertEventValuesEquals(removedEvents, ImmutableList.of()); }
@Test(groups="Integration") @SuppressWarnings("deprecation") public void testHttpSensorSuppressingDuplicates() throws Exception { RecordingSensorEventListener<String> listener = new RecordingSensorEventListener<>(); entity.subscriptions().subscribe(entity, SENSOR_STRING, listener); HttpRequestSensor<Integer> sensor = new HttpRequestSensor<Integer>(ConfigBag.newInstance() .configure(HttpRequestSensor.SUPPRESS_DUPLICATES, true) .configure(HttpRequestSensor.SENSOR_PERIOD, Duration.millis(1)) .configure(HttpRequestSensor.SENSOR_NAME, SENSOR_STRING.getName()) .configure(HttpRequestSensor.SENSOR_TYPE, STRING_TARGET_TYPE) .configure(HttpRequestSensor.JSON_PATH, "$.myKey") .configure(HttpRequestSensor.SENSOR_URI, serverUrl + "/myKey/myValue")); sensor.apply((org.apache.brooklyn.api.entity.EntityLocal)entity); entity.sensors().set(Attributes.SERVICE_UP, true); EntityAsserts.assertAttributeEqualsEventually(entity, SENSOR_STRING, "myValue"); listener.assertHasEventEventually(Predicates.alwaysTrue()); Asserts.succeedsContinually(new Runnable() { @Override public void run() { listener.assertEventCount(1); }}); }
public void testTransformingSuppressDuplicates() { RecordingSensorEventListener<String> record = new RecordingSensorEventListener<>(); app.getManagementContext().getSubscriptionManager().subscribe(entity, STR2, record); entity.enrichers().add(Enrichers.builder() .transforming(STR1) .publishing(STR2) .computing(Functions.<String>identity()) .suppressDuplicates(true) .build()); entity.sensors().set(STR1, "myval"); Asserts.eventually(Suppliers.ofInstance(record), CollectionFunctionals.sizeEquals(1)); EntityAsserts.assertAttributeEquals(entity, STR2, "myval"); entity.sensors().set(STR1, "myval2"); entity.sensors().set(STR1, "myval2"); entity.sensors().set(STR1, "myval3"); EntityAsserts.assertAttributeEqualsContinually(entity, STR2, "myval3"); Asserts.assertThat(record.getEvents(), CollectionFunctionals.sizeEquals(3)); }
@Override public void run() { listener.assertEventCount(1); }}); }
private <T> List<T> getServiceStateEvents(RecordingSensorEventListener<T> listener) { if (stateListener == null) { return ImmutableList.of(); } else { return MutableList.copyOf(listener.getEventValues()).asUnmodifiable(); } }
protected static RecordingSensorEventListener<Object> subscribeToHaSensors(Entity entity) { RecordingSensorEventListener<Object> listener = new RecordingSensorEventListener<>(); entity.subscriptions().subscribe(entity, HASensors.ENTITY_RECOVERED, listener); entity.subscriptions().subscribe(entity, HASensors.ENTITY_FAILED, listener); return listener; } }