11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2011 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.util.concurrent.AbstractScheduledService.Scheduler; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.Service.State; 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CyclicBarrier; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutionException; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executors; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Future; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ScheduledExecutorService; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ScheduledFuture; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ScheduledThreadPoolExecutor; 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit; 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicBoolean; 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicInteger; 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unit test for {@link AbstractScheduledService}. 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Luke Sandberg 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class AbstractScheduledServiceTest extends TestCase { 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile Scheduler configuration = Scheduler.newFixedDelaySchedule(0, 10, TimeUnit.MILLISECONDS); 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile ScheduledFuture<?> future = null; 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile boolean atFixedRateCalled = false; 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile boolean withFixedDelayCalled = false; 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile boolean scheduleCalled = false; 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(10) { 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert long delay, TimeUnit unit) { 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return future = super.scheduleWithFixedDelay(command, initialDelay, delay, unit); 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testServiceStartStop() throws Exception { 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert NullService service = new NullService(); 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(future.isDone()); 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stopAndWait(); 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(future.isCancelled()); 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class NullService extends AbstractScheduledService { 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void runOneIteration() throws Exception { } 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void startUp() throws Exception { } 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void shutDown() throws Exception { } 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Scheduler scheduler() { return configuration; } 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected ScheduledExecutorService executor() { return executor; } 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testFailOnExceptionFromRun() throws Exception { 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestService service = new TestService(); 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runException = new Exception(); 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runFirstBarrier.await(); 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runSecondBarrier.await(); 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert future.get(); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ExecutionException e) { 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // An execution exception holds a runtime exception (from throwables.propogate) that holds our 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // original exception. 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(service.runException, e.getCause().getCause()); 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(service.state(), Service.State.FAILED); 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testFailOnExceptionFromStartUp() { 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestService service = new TestService(); 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startUpException = new Exception(); 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (UncheckedExecutionException e) { 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(service.startUpException, e.getCause()); 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0, service.numberOfTimesRunCalled.get()); 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.FAILED, service.state()); 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testFailOnExceptionFromShutDown() throws Exception { 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestService service = new TestService(); 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.shutDownException = new Exception(); 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runFirstBarrier.await(); 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListenableFuture<Service.State> stopHandle = service.stop(); 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runSecondBarrier.await(); 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stopHandle.get(); 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ExecutionException e) { 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(service.shutDownException, e.getCause()); 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(Service.State.FAILED, service.state()); 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testRunOneIterationCalledMultipleTimes() throws Exception { 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestService service = new TestService(); 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int i = 1; i < 10; i++) { 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runFirstBarrier.await(); 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(i, service.numberOfTimesRunCalled.get()); 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runSecondBarrier.await(); 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runFirstBarrier.await(); 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop(); 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runSecondBarrier.await(); 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stopAndWait(); 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testExecutorOnlyCalledOnce() throws Exception { 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestService service = new TestService(); 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // It should be called once during startup. 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, service.numberOfTimesExecutorCalled.get()); 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int i = 1; i < 10; i++) { 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runFirstBarrier.await(); 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(i, service.numberOfTimesRunCalled.get()); 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runSecondBarrier.await(); 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runFirstBarrier.await(); 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop(); 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runSecondBarrier.await(); 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stopAndWait(); 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Only called once overall. 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, service.numberOfTimesExecutorCalled.get()); 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSchedulerOnlyCalledOnce() throws Exception { 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestService service = new TestService(); 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // It should be called once during startup. 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, service.numberOfTimesSchedulerCalled.get()); 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int i = 1; i < 10; i++) { 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runFirstBarrier.await(); 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(i, service.numberOfTimesRunCalled.get()); 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runSecondBarrier.await(); 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runFirstBarrier.await(); 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop(); 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.runSecondBarrier.await(); 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stopAndWait(); 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Only called once overall. 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, service.numberOfTimesSchedulerCalled.get()); 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class TestService extends AbstractScheduledService { 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert CyclicBarrier runFirstBarrier = new CyclicBarrier(2); 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert CyclicBarrier runSecondBarrier = new CyclicBarrier(2); 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile boolean startUpCalled = false; 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile boolean shutDownCalled = false; 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger numberOfTimesRunCalled = new AtomicInteger(0); 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger numberOfTimesExecutorCalled = new AtomicInteger(0); 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AtomicInteger numberOfTimesSchedulerCalled = new AtomicInteger(0); 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile Exception runException = null; 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile Exception startUpException = null; 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile Exception shutDownException = null; 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void runOneIteration() throws Exception { 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(startUpCalled); 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(shutDownCalled); 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert numberOfTimesRunCalled.incrementAndGet(); 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(State.RUNNING, state()); 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert runFirstBarrier.await(); 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert runSecondBarrier.await(); 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (runException != null) { 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw runException; 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void startUp() throws Exception { 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(startUpCalled); 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(shutDownCalled); 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert startUpCalled = true; 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(State.STARTING, state()); 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (startUpException != null) { 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw startUpException; 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void shutDown() throws Exception { 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(startUpCalled); 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(shutDownCalled); 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert shutDownCalled = true; 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (shutDownException != null) { 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw shutDownException; 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected ScheduledExecutorService executor() { 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert numberOfTimesExecutorCalled.incrementAndGet(); 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return executor; 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Scheduler scheduler() { 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert numberOfTimesSchedulerCalled.incrementAndGet(); 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return configuration; 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static class SchedulerTest extends TestCase { 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // These constants are arbitrary and just used to make sure that the correct method is called 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // with the correct parameters. 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final int initialDelay = 10; 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final int delay = 20; 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final TimeUnit unit = TimeUnit.MILLISECONDS; 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Unique runnable object used for comparison. 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Runnable testRunnable = new Runnable() {@Override public void run() {}}; 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean called = false; 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void assertSingleCallWithCorrectParameters(Runnable command, long initialDelay, 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert long delay, TimeUnit unit) { 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(called); // only called once. 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert called = true; 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(SchedulerTest.initialDelay, initialDelay); 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(SchedulerTest.delay, delay); 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(SchedulerTest.unit, unit); 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(testRunnable, command); 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testFixedRateSchedule() { 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Scheduler schedule = Scheduler.newFixedRateSchedule(initialDelay, delay, unit); 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert schedule.schedule(null, new ScheduledThreadPoolExecutor(1) { 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert long period, TimeUnit unit) { 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertSingleCallWithCorrectParameters(command, initialDelay, delay, unit); 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }, testRunnable); 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(called); 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testFixedDelaySchedule() { 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Scheduler schedule = Scheduler.newFixedDelaySchedule(initialDelay, delay, unit); 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert schedule.schedule(null, new ScheduledThreadPoolExecutor(10) { 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert long delay, TimeUnit unit) { 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertSingleCallWithCorrectParameters(command, initialDelay, delay, unit); 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }, testRunnable); 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(called); 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private class TestCustomScheduler extends AbstractScheduledService.CustomScheduler { 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public AtomicInteger scheduleCounter = new AtomicInteger(0); 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Schedule getNextSchedule() throws Exception { 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert scheduleCounter.incrementAndGet(); 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Schedule(0, TimeUnit.SECONDS); 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testCustomSchedule_startStop() throws Exception { 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final CyclicBarrier firstBarrier = new CyclicBarrier(2); 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final CyclicBarrier secondBarrier = new CyclicBarrier(2); 2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final AtomicBoolean shouldWait = new AtomicBoolean(true); 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Runnable task = new Runnable() { 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public void run() { 2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (shouldWait.get()) { 2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert firstBarrier.await(); 2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert secondBarrier.await(); 2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (Exception e) { 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException(e); 3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestCustomScheduler scheduler = new TestCustomScheduler(); 3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Future<?> future = scheduler.schedule(null, Executors.newScheduledThreadPool(10), task); 3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert firstBarrier.await(); 3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, scheduler.scheduleCounter.get()); 3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert secondBarrier.await(); 3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert firstBarrier.await(); 3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(2, scheduler.scheduleCounter.get()); 3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert shouldWait.set(false); 3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert secondBarrier.await(); 3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert future.cancel(false); 3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testCustomSchedulerServiceStop() throws Exception { 3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestAbstractScheduledCustomService service = new TestAbstractScheduledCustomService(); 3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.firstBarrier.await(); 3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, service.numIterations.get()); 3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop(); 3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.secondBarrier.await(); 3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stopAndWait(); 3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Sleep for a while just to ensure that our task wasn't called again. 3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.sleep(unit.toMillis(3 * delay)); 3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(1, service.numIterations.get()); 3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testBig() throws Exception { 3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestAbstractScheduledCustomService service = new TestAbstractScheduledCustomService() { 3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Scheduler scheduler() { 3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new AbstractScheduledService.CustomScheduler(){ 3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Schedule getNextSchedule() throws Exception { 3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Explicitly yield to increase the probability of a pathological scheduling. 3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.yield(); 3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Schedule(0, TimeUnit.SECONDS); 3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.useBarriers = false; 3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.sleep(50); 3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.useBarriers = true; 3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.firstBarrier.await(); 3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int numIterations = service.numIterations.get(); 3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop(); 3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.secondBarrier.await(); 3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stopAndWait(); 3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(numIterations, service.numIterations.get()); 3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static class TestAbstractScheduledCustomService extends AbstractScheduledService { 3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final AtomicInteger numIterations = new AtomicInteger(0); 3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert volatile boolean useBarriers = true; 3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final CyclicBarrier firstBarrier = new CyclicBarrier(2); 3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final CyclicBarrier secondBarrier = new CyclicBarrier(2); 3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void runOneIteration() throws Exception { 3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert numIterations.incrementAndGet(); 3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (useBarriers) { 3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert firstBarrier.await(); 3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert secondBarrier.await(); 3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected ScheduledExecutorService executor() { 3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // use a bunch of threads so that weird overlapping schedules are more likely to happen. 3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Executors.newScheduledThreadPool(10); 3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void startUp() throws Exception { } 3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void shutDown() throws Exception { } 3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Scheduler scheduler() { 3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new CustomScheduler() { 3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Schedule getNextSchedule() throws Exception { 3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Schedule(delay, unit); 3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }}; 3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testCustomSchedulerFailure() throws Exception { 3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestFailingCustomScheduledService service = new TestFailingCustomScheduledService(); 3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.startAndWait(); 3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int i = 1; i < 4; i++) { 3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.firstBarrier.await(); 3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(i, service.numIterations.get()); 3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.secondBarrier.await(); 3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Thread.sleep(1000); 3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service.stop().get(100, TimeUnit.SECONDS); 3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ExecutionException e) { 3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(State.FAILED, service.state()); 3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static class TestFailingCustomScheduledService extends AbstractScheduledService { 4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final AtomicInteger numIterations = new AtomicInteger(0); 4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final CyclicBarrier firstBarrier = new CyclicBarrier(2); 4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final CyclicBarrier secondBarrier = new CyclicBarrier(2); 4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void runOneIteration() throws Exception { 4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert numIterations.incrementAndGet(); 4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert firstBarrier.await(); 4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert secondBarrier.await(); 4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected ScheduledExecutorService executor() { 4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // use a bunch of threads so that weird overlapping schedules are more likely to happen. 4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Executors.newScheduledThreadPool(10); 4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void startUp() throws Exception { } 4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void shutDown() throws Exception { } 4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected Scheduler scheduler() { 4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new CustomScheduler() { 4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Schedule getNextSchedule() throws Exception { 4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (numIterations.get() > 2) { 4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new IllegalStateException("Failed"); 4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new Schedule(delay, unit); 4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }}; 4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 435