e2.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(e1, "simulate failure")); assertTrue(inRestartLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@Test public void testReplacesFailedMember() throws Exception { final DynamicCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(TestEntity.class)) .configure(DynamicCluster.INITIAL_SIZE, 3)); app.start(ImmutableList.<Location>of(loc)); cluster.policies().add(PolicySpec.create(ServiceReplacer.class) .configure(ServiceReplacer.FAILURE_SENSOR_TO_MONITOR, HASensors.ENTITY_FAILED)); final Set<Entity> initialMembers = ImmutableSet.copyOf(cluster.getMembers()); final TestEntity e1 = (TestEntity) Iterables.get(initialMembers, 1); e1.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(e1, "simulate failure")); // Expect e1 to be replaced Asserts.succeedsEventually(new Runnable() { @Override public void run() { Set<Entity> newMembers = Sets.difference(ImmutableSet.copyOf(cluster.getMembers()), initialMembers); Set<Entity> removedMembers = Sets.difference(initialMembers, ImmutableSet.copyOf(cluster.getMembers())); assertEquals(removedMembers, ImmutableSet.of(e1)); assertEquals(newMembers.size(), 1); assertEquals(((TestEntity)Iterables.getOnlyElement(newMembers)).getCallHistory(), ImmutableList.of("start")); assertEquals(e1.getCallHistory(), ImmutableList.of("start", "stop")); assertFalse(Entities.isManaged(e1)); }}); }
@Test public void testServiceRestarterWorksAfterRebind() throws Exception { origEntity.policies().add(PolicySpec.create(ServiceRestarter.class) .configure(ServiceRestarter.FAILURE_SENSOR_TO_MONITOR, HASensors.ENTITY_FAILED)); TestApplication newApp = rebind(); final TestEntity newEntity = (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class)); newEntity.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(origEntity, "simulate failure")); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(newEntity.getCallHistory(), ImmutableList.of("restart")); }}); }
newApp.getManagementContext().getSubscriptionManager().subscribe(e1, HASensors.ENTITY_RECOVERED, eventListener); e1.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(e1, "simulate failure"));
final TestEntity e1 = (TestEntity) Iterables.get(initialMembers, 0); e1.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(e1, "simulate failure"));
@Test(groups={"Integration", "Broken"}) // has a 1 second wait public void testDoesNotOnFireWhenFailToReplaceMember() throws Exception { app.subscriptions().subscribe(null, ServiceReplacer.ENTITY_REPLACEMENT_FAILED, eventListener); final DynamicCluster cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class) .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(FailingEntity.class) .configure(FailingEntity.FAIL_ON_START_CONDITION, predicateOnlyTrueForCallAtOrAfter(2))) .configure(DynamicCluster.INITIAL_SIZE, 1) .configure(DynamicCluster.QUARANTINE_FAILED_ENTITIES, true)); app.start(ImmutableList.<Location>of(loc)); cluster.policies().add(PolicySpec.create(ServiceReplacer.class) .configure(ServiceReplacer.FAILURE_SENSOR_TO_MONITOR, HASensors.ENTITY_FAILED) .configure(ServiceReplacer.SET_ON_FIRE_ON_FAILURE, false)); final Set<Entity> initialMembers = ImmutableSet.copyOf(cluster.getMembers()); final TestEntity e1 = (TestEntity) Iterables.get(initialMembers, 0); e1.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(e1, "simulate failure")); // Configured to not mark cluster as on fire Asserts.succeedsContinually(new Runnable() { @Override public void run() { assertNotEquals(cluster.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE, "Unexpected ON_FIRE state"); }}); // And will have received notification event about it assertEventuallyHasEntityReplacementFailedEvent(cluster); }
@Test public void testPropagatesAllStaticSensors() { app.enrichers().add(Enrichers.builder() .propagatingAll() .from(entity) .build()); // all attributes propagated entity.sensors().set(TestEntity.NAME, "foo"); entity.sensors().set(TestEntity.SEQUENCE, 2); EntityAsserts.assertAttributeEqualsEventually(app, TestEntity.NAME, "foo"); EntityAsserts.assertAttributeEqualsEventually(app, TestEntity.SEQUENCE, 2); // notification-sensor propagated final AtomicReference<Integer> notif = new AtomicReference<Integer>(); app.subscriptions().subscribe(app, TestEntity.MY_NOTIF, new SensorEventListener<Integer>() { @Override public void onEvent(SensorEvent<Integer> event) { notif.set(event.getValue()); }}); entity.sensors().emit(TestEntity.MY_NOTIF, 7); Asserts.eventually(AtomicReferences.supplier(notif), Predicates.equalTo(7)); }
@Test public void testUnsubscribeRemovesAllSubscriptionsForThatEntity() throws Exception { policy.subscriptions().subscribe(entity, TestEntity.SEQUENCE, listener); policy.subscriptions().subscribe(entity, TestEntity.NAME, listener); policy.subscriptions().subscribe(entity, TestEntity.MY_NOTIF, listener); policy.subscriptions().subscribe(otherEntity, TestEntity.SEQUENCE, listener); policy.subscriptions().unsubscribe(entity); entity.sensors().set(TestEntity.SEQUENCE, 123); entity.sensors().set(TestEntity.NAME, "myname"); entity.sensors().emit(TestEntity.MY_NOTIF, 456); otherEntity.sensors().set(TestEntity.SEQUENCE, 789); Thread.sleep(SHORT_WAIT_MS); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(listener.getEvents(), ImmutableList.of( new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 789))); }}); }
@Test public void testPropagatesAllSensorsIncludesDynamicallyAdded() { AttributeSensor<String> dynamicAttribute = Sensors.newStringSensor("test.dynamicsensor.strattrib"); BasicNotificationSensor<String> dynamicNotificationSensor = new BasicNotificationSensor<String>(String.class, "test.dynamicsensor.strnotif"); app.enrichers().add(Enrichers.builder() .propagatingAll() .from(entity) .build()); entity.sensors().set(dynamicAttribute, "foo"); EntityAsserts.assertAttributeEqualsEventually(app, dynamicAttribute, "foo"); // notification-sensor propagated final AtomicReference<String> notif = new AtomicReference<String>(); app.subscriptions().subscribe(app, dynamicNotificationSensor, new SensorEventListener<String>() { @Override public void onEvent(SensorEvent<String> event) { notif.set(event.getValue()); }}); entity.sensors().emit(dynamicNotificationSensor, "mynotifval"); Asserts.eventually(AtomicReferences.supplier(notif), Predicates.equalTo("mynotifval")); }
@Test public void testUnsubscribeRemovesAllSubscriptionsForThatEntity() { loc.subscriptions().subscribe(observedEntity, TestEntity.SEQUENCE, listener); loc.subscriptions().subscribe(observedEntity, TestEntity.NAME, listener); loc.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener); loc.subscriptions().subscribe(otherEntity, TestEntity.SEQUENCE, listener); loc.subscriptions().unsubscribe(observedEntity); observedEntity.sensors().set(TestEntity.SEQUENCE, 123); observedEntity.sensors().set(TestEntity.NAME, "myname"); observedEntity.sensors().emit(TestEntity.MY_NOTIF, 123); otherEntity.sensors().set(TestEntity.SEQUENCE, 456); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(listener.getEvents(), ImmutableList.of( new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 456))); }}); }
@Test public void testSubscriptionReceivesEvents() { entity.subscriptions().subscribe(observedEntity, TestEntity.SEQUENCE, listener); entity.subscriptions().subscribe(observedEntity, TestEntity.NAME, listener); entity.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener); otherEntity.sensors().set(TestEntity.SEQUENCE, 123); observedEntity.sensors().set(TestEntity.SEQUENCE, 123); observedEntity.sensors().set(TestEntity.NAME, "myname"); observedEntity.sensors().emit(TestEntity.MY_NOTIF, 456); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(listener.getEvents(), ImmutableList.of( new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedEntity, 123), new BasicSensorEvent<String>(TestEntity.NAME, observedEntity, "myname"), new BasicSensorEvent<Integer>(TestEntity.MY_NOTIF, observedEntity, 456))); }}); }
@Test public void testSubscriptionReceivesEvents() { loc.subscriptions().subscribe(observedEntity, TestEntity.SEQUENCE, listener); loc.subscriptions().subscribe(observedEntity, TestEntity.NAME, listener); loc.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener); otherEntity.sensors().set(TestEntity.SEQUENCE, 123); observedEntity.sensors().set(TestEntity.SEQUENCE, 123); observedEntity.sensors().set(TestEntity.NAME, "myname"); observedEntity.sensors().emit(TestEntity.MY_NOTIF, 456); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(listener.getEvents(), ImmutableList.of( new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, observedEntity, 123), new BasicSensorEvent<String>(TestEntity.NAME, observedEntity, "myname"), new BasicSensorEvent<Integer>(TestEntity.MY_NOTIF, observedEntity, 456))); }}); }
@Test public void testSubscriptionReceivesEvents() throws Exception { policy.subscriptions().subscribe(entity, TestEntity.SEQUENCE, listener); policy.subscriptions().subscribe(entity, TestEntity.NAME, listener); policy.subscriptions().subscribe(entity, TestEntity.MY_NOTIF, listener); otherEntity.sensors().set(TestEntity.SEQUENCE, 456); entity.sensors().set(TestEntity.SEQUENCE, 123); entity.sensors().set(TestEntity.NAME, "myname"); entity.sensors().emit(TestEntity.MY_NOTIF, 789); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(listener.getEvents(), ImmutableList.of( new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, entity, 123), new BasicSensorEvent<String>(TestEntity.NAME, entity, "myname"), new BasicSensorEvent<Integer>(TestEntity.MY_NOTIF, entity, 789))); }}); }
@Test public void testUnsubscribeRemovesAllSubscriptionsForThatEntity() { entity.subscriptions().subscribe(observedEntity, TestEntity.SEQUENCE, listener); entity.subscriptions().subscribe(observedEntity, TestEntity.NAME, listener); entity.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener); entity.subscriptions().subscribe(otherEntity, TestEntity.SEQUENCE, listener); entity.subscriptions().unsubscribe(observedEntity); observedEntity.sensors().set(TestEntity.SEQUENCE, 123); observedEntity.sensors().set(TestEntity.NAME, "myname"); observedEntity.sensors().emit(TestEntity.MY_NOTIF, 123); otherEntity.sensors().set(TestEntity.SEQUENCE, 456); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(listener.getEvents(), ImmutableList.of( new BasicSensorEvent<Integer>(TestEntity.SEQUENCE, otherEntity, 456))); }}); }
@Test public void testEmitsFailureEventWhenRestarterFails() throws Exception { final FailingEntity e2 = app.createAndManageChild(EntitySpec.create(FailingEntity.class) .configure(FailingEntity.FAIL_ON_RESTART, true)); app.subscriptions().subscribe(e2, ServiceRestarter.ENTITY_RESTART_FAILED, eventListener); policy = e2.policies().add(PolicySpec.create(ServiceRestarter.class) .configure(ServiceRestarter.FAILURE_SENSOR_TO_MONITOR, HASensors.ENTITY_FAILED)); e2.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(e2, "simulate failure")); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(Iterables.getOnlyElement(events).getSensor(), ServiceRestarter.ENTITY_RESTART_FAILED, "events="+events); assertEquals(Iterables.getOnlyElement(events).getSource(), e2, "events="+events); assertEquals(((FailureDescriptor)Iterables.getOnlyElement(events).getValue()).getComponent(), e2, "events="+events); }}); assertEquals(e2.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE); }
@Test public void testSubscriptionReceivesEventsInOrder() { final int NUM_EVENTS = 100; loc.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener); for (int i = 0; i < NUM_EVENTS; i++) { observedEntity.sensors().emit(TestEntity.MY_NOTIF, i); } Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(Iterables.size(listener.getEvents()), NUM_EVENTS); for (int i = 0; i < NUM_EVENTS; i++) { assertEquals(Iterables.get(listener.getEvents(), i).getValue(), i); } }}); }
@Test public void testDoesNotSetOnFireOnFailure() throws Exception { final FailingEntity e2 = app.createAndManageChild(EntitySpec.create(FailingEntity.class) .configure(FailingEntity.SET_SERVICE_DOWN_ON_FAILURE, false) .configure(FailingEntity.FAIL_ON_RESTART, true)); app.subscriptions().subscribe(e2, ServiceRestarter.ENTITY_RESTART_FAILED, eventListener); policy = e2.policies().add(PolicySpec.create(ServiceRestarter.class) .configure(ServiceRestarter.FAILURE_SENSOR_TO_MONITOR, HASensors.ENTITY_FAILED) .configure(ServiceRestarter.SET_ON_FIRE_ON_FAILURE, false)); e2.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(e2, "simulate failure")); Asserts.succeedsContinually(new Runnable() { @Override public void run() { assertNotEquals(e2.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE); }}); }
@Test public void testSubscriptionReceivesEventsInOrder() { final int NUM_EVENTS = 100; entity.subscriptions().subscribe(observedEntity, TestEntity.MY_NOTIF, listener); for (int i = 0; i < NUM_EVENTS; i++) { observedEntity.sensors().emit(TestEntity.MY_NOTIF, i); } Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(Iterables.size(listener.getEvents()), NUM_EVENTS); for (int i = 0; i < NUM_EVENTS; i++) { assertEquals(Iterables.get(listener.getEvents(), i).getValue(), i); } }}); }
@Test(groups="Integration") // Has a 1 second wait public void testDoesNotRestartsWhenHealthy() throws Exception { policy = e1.policies().add(PolicySpec.create(ServiceRestarter.class) .configure(ServiceRestarter.FAILURE_SENSOR_TO_MONITOR, HASensors.ENTITY_FAILED)); e1.sensors().emit(HASensors.ENTITY_RECOVERED, new FailureDescriptor(e1, "not a failure")); Asserts.succeedsContinually(new Runnable() { @Override public void run() { assertEquals(e1.getCallHistory(), ImmutableList.of()); }}); }
@Test public void testRestartsOnFailure() throws Exception { policy = e1.policies().add(PolicySpec.create(ServiceRestarter.class) .configure(ServiceRestarter.FAILURE_SENSOR_TO_MONITOR, HASensors.ENTITY_FAILED)); e1.sensors().emit(HASensors.ENTITY_FAILED, new FailureDescriptor(e1, "simulate failure")); Asserts.succeedsEventually(new Runnable() { @Override public void run() { assertEquals(e1.getCallHistory(), ImmutableList.of("restart")); }}); }