/** * This covers a bug where if a listener was installed that would stop the manager if any service * fails and something failed during startup before service.start was called on all the services, * then awaitStopped would deadlock due to an IllegalStateException that was thrown when trying to * stop the timer(!). */ public void testFailStart_stopOthers() throws TimeoutException { Service a = new FailStartService(); Service b = new NoOpService(); final ServiceManager manager = new ServiceManager(asList(a, b)); manager.addListener(new Listener() { @Override public void failure(Service service) { manager.stopAsync(); }}); manager.startAsync(); manager.awaitStopped(10, TimeUnit.MILLISECONDS); }
/** * This covers a bug where if a listener was installed that would stop the manager if any service * fails and something failed during startup before service.start was called on all the services, * then awaitStopped would deadlock due to an IllegalStateException that was thrown when trying to * stop the timer(!). */ public void testFailStart_stopOthers() throws TimeoutException { Service a = new FailStartService(); Service b = new NoOpService(); final ServiceManager manager = new ServiceManager(asList(a, b)); manager.addListener( new Listener() { @Override public void failure(Service service) { manager.stopAsync(); } }); manager.startAsync(); manager.awaitStopped(10, TimeUnit.MILLISECONDS); }
/** * Tests that a ServiceManager can be fully shut down if one of its failure listeners is slow or * even permanently blocked. */ public void testListenerDeadlock() throws InterruptedException { final CountDownLatch failEnter = new CountDownLatch(1); final CountDownLatch failLeave = new CountDownLatch(1); final CountDownLatch afterStarted = new CountDownLatch(1); Service failRunService = new AbstractService() { @Override protected void doStart() { new Thread() { @Override public void run() { notifyStarted(); // We need to wait for the main thread to leave the ServiceManager.startAsync call to // ensure that the thread running the failure callbacks is not the main thread. Uninterruptibles.awaitUninterruptibly(afterStarted); notifyFailed(new Exception("boom")); } }.start(); } @Override protected void doStop() { notifyStopped(); } }; final ServiceManager manager = new ServiceManager( Arrays.asList(failRunService, new NoOpService())); manager.addListener(new ServiceManager.Listener() { @Override public void failure(Service service) { failEnter.countDown(); // block until after the service manager is shutdown Uninterruptibles.awaitUninterruptibly(failLeave); } }); manager.startAsync(); afterStarted.countDown(); // We do not call awaitHealthy because, due to races, that method may throw an exception. But // we really just want to wait for the thread to be in the failure callback so we wait for that // explicitly instead. failEnter.await(); assertFalse("State should be updated before calling listeners", manager.isHealthy()); // now we want to stop the services. Thread stoppingThread = new Thread() { @Override public void run() { manager.stopAsync().awaitStopped(); } }; stoppingThread.start(); // this should be super fast since the only non stopped service is a NoOpService stoppingThread.join(1000); assertFalse("stopAsync has deadlocked!.", stoppingThread.isAlive()); failLeave.countDown(); // release the background thread }
public void testNulls() { ServiceManager manager = new ServiceManager(Arrays.<Service>asList()); new NullPointerTester() .setDefault(ServiceManager.Listener.class, new RecordingListener()) .testAllPublicInstanceMethods(manager); }
/** * Tests that a ServiceManager can be fully shut down if one of its failure listeners is slow or * even permanently blocked. */ public void testListenerDeadlock() throws InterruptedException { final CountDownLatch failEnter = new CountDownLatch(1); final CountDownLatch failLeave = new CountDownLatch(1); final CountDownLatch afterStarted = new CountDownLatch(1); Service failRunService = new AbstractService() { @Override protected void doStart() { new Thread() { @Override public void run() { notifyStarted(); // We need to wait for the main thread to leave the ServiceManager.startAsync call // to // ensure that the thread running the failure callbacks is not the main thread. Uninterruptibles.awaitUninterruptibly(afterStarted); notifyFailed(new Exception("boom")); } }.start(); } @Override protected void doStop() { notifyStopped(); } }; final ServiceManager manager = new ServiceManager(Arrays.asList(failRunService, new NoOpService())); manager.addListener( new ServiceManager.Listener() { @Override public void failure(Service service) { failEnter.countDown(); // block until after the service manager is shutdown Uninterruptibles.awaitUninterruptibly(failLeave); } }); manager.startAsync(); afterStarted.countDown(); // We do not call awaitHealthy because, due to races, that method may throw an exception. But // we really just want to wait for the thread to be in the failure callback so we wait for that // explicitly instead. failEnter.await(); assertFalse("State should be updated before calling listeners", manager.isHealthy()); // now we want to stop the services. Thread stoppingThread = new Thread() { @Override public void run() { manager.stopAsync().awaitStopped(); } }; stoppingThread.start(); // this should be super fast since the only non stopped service is a NoOpService stoppingThread.join(1000); assertFalse("stopAsync has deadlocked!.", stoppingThread.isAlive()); failLeave.countDown(); // release the background thread }