11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.util.concurrent; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Throwables; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.Thread.UncaughtExceptionHandler; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CountDownLatch; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutionException; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executor; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Future; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeoutException; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unit test for {@link AbstractExecutionThreadService}. 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Jesse Wilson 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class AbstractExecutionThreadServiceTest extends TestCase { 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final CountDownLatch enterRun = new CountDownLatch(1); 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final CountDownLatch exitRun = new CountDownLatch(1); 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Thread executionThread; 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Throwable thrownByExecutionThread; 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final Executor executor = new Executor() { 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void execute(Runnable command) { 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread = new Thread(command); 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void uncaughtException(Thread thread, Throwable e) { 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert thrownByExecutionThread = e; 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }); 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.start(); 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceStartStop() throws Exception { 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert WaitOnRunService service = new WaitOnRunService(); 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(service.startUpCalled); 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.start().get(); 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(service.startUpCalled); 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.RUNNING, service.state()); 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert enterRun.await(); // to avoid stopping the service until run() is invoked 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop().get(); 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(service.shutDownCalled); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.TERMINATED, service.state()); 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.join(); 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(thrownByExecutionThread); 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceStartStopIdempotence() throws Exception { 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert WaitOnRunService service = new WaitOnRunService(); 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.start(); 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.start(); 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.RUNNING, service.state()); 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.RUNNING, service.state()); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert enterRun.await(); // to avoid stopping the service until run() is invoked 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop(); 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop(); 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stopAndWait(); 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.TERMINATED, service.state()); 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stopAndWait(); 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.TERMINATED, service.state()); 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.RUNNING, service.start().get()); 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.RUNNING, service.startAndWait()); 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.TERMINATED, service.stop().get()); 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.TERMINATED, service.stopAndWait()); 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.join(); 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(thrownByExecutionThread); 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceExitingOnItsOwn() throws Exception { 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert WaitOnRunService service = new WaitOnRunService(); 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.expectedShutdownState = Service.State.RUNNING; 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.start().get(); 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(service.startUpCalled); 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.RUNNING, service.state()); 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert exitRun.countDown(); // the service will exit voluntarily 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.join(); 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(service.shutDownCalled); 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.TERMINATED, service.state()); 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertNull(thrownByExecutionThread); 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop().get(); // no-op 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.TERMINATED, service.state()); 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(service.shutDownCalled); 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class WaitOnRunService extends AbstractExecutionThreadService { 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean startUpCalled = false; 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean runCalled = false; 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean shutDownCalled = false; 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private State expectedShutdownState = State.STOPPING; 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void startUp() { 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(startUpCalled); 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(runCalled); 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(shutDownCalled); 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert startUpCalled = true; 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(State.STARTING, state()); 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void run() { 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(startUpCalled); 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(runCalled); 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(shutDownCalled); 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert runCalled = true; 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(State.RUNNING, state()); 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert enterRun.countDown(); 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert exitRun.await(); 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (InterruptedException e) { 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw Throwables.propagate(e); 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void shutDown() { 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(startUpCalled); 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(runCalled); 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(shutDownCalled); 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert shutDownCalled = true; 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(expectedShutdownState, state()); 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void triggerShutdown() { 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert exitRun.countDown(); 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Executor executor() { 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return executor; 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceThrowOnStartUp() throws Exception { 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ThrowOnStartUpService service = new ThrowOnStartUpService(); 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(service.startUpCalled); 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Future<Service.State> startupFuture = service.start(); 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert startupFuture.get(); 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ExecutionException expected) { 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals("kaboom!", expected.getCause().getMessage()); 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.join(); 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(service.startUpCalled); 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.FAILED, service.state()); 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(thrownByExecutionThread.getMessage().equals("kaboom!")); 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class ThrowOnStartUpService extends AbstractExecutionThreadService { 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean startUpCalled = false; 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void startUp() { 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert startUpCalled = true; 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException("kaboom!"); 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void run() { 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new AssertionError("run() should not be called"); 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Executor executor() { 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return executor; 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceThrowOnRun() throws Exception { 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ThrowOnRunService service = new ThrowOnRunService(); 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.start().get(); 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.join(); 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(service.shutDownCalled); 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.FAILED, service.state()); 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals("kaboom!", thrownByExecutionThread.getMessage()); 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceThrowOnRunAndThenAgainOnShutDown() throws Exception { 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ThrowOnRunService service = new ThrowOnRunService(); 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.throwOnShutDown = true; 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.start().get(); 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.join(); 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(service.shutDownCalled); 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.FAILED, service.state()); 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals("kaboom!", thrownByExecutionThread.getMessage()); 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class ThrowOnRunService extends AbstractExecutionThreadService { 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean shutDownCalled = false; 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean throwOnShutDown = false; 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void run() { 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException("kaboom!"); 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void shutDown() { 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert shutDownCalled = true; 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (throwOnShutDown) { 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException("double kaboom!"); 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Executor executor() { 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return executor; 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceThrowOnShutDown() throws Exception { 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ThrowOnShutDown service = new ThrowOnShutDown(); 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.start().get(); 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.RUNNING, service.state()); 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop(); 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert enterRun.countDown(); 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executionThread.join(); 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.FAILED, service.state()); 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals("kaboom!", thrownByExecutionThread.getMessage()); 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class ThrowOnShutDown extends AbstractExecutionThreadService { 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void run() { 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert enterRun.await(); 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (InterruptedException e) { 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw Throwables.propagate(e); 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void shutDown() { 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException("kaboom!"); 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Executor executor() { 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return executor; 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceTimeoutOnStartUp() throws Exception { 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TimeoutOnStartUp service = new TimeoutOnStartUp(); 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.start().get(1, TimeUnit.MILLISECONDS); 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (TimeoutException e) { 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(e.getMessage().contains(Service.State.STARTING.toString())); 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class TimeoutOnStartUp extends AbstractExecutionThreadService { 2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Executor executor() { 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Executor() { 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public void execute(Runnable command) { 2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void run() throws Exception { 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 303