modules/graphics/src/test/java/test/javafx/concurrent/ScheduledServiceTest.java

Print this page
rev 9250 : 8134762: Refactor Javafx graphics module tests for clear separation of tests
Reviewed-by:


   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.concurrent;
  27 
  28 import javafx.concurrent.mocks.EpicFailTask;
  29 import javafx.concurrent.mocks.SimpleTask;
  30 import javafx.event.EventHandler;
  31 import javafx.util.Callback;
  32 import javafx.util.Duration;
  33 import java.util.TimerTask;
  34 import java.util.concurrent.atomic.AtomicBoolean;
  35 import java.util.concurrent.atomic.AtomicInteger;





  36 import org.junit.Test;
  37 import static org.junit.Assert.assertEquals;
  38 import static org.junit.Assert.assertFalse;
  39 import static org.junit.Assert.assertNull;
  40 import static org.junit.Assert.assertTrue;
  41 
  42 /**
  43  * Tests for the ScheduledService.
  44  */
  45 public class ScheduledServiceTest extends ServiceTestBase {
  46     private static final Callback<Void, AbstractTask> EPIC_FAIL_FACTORY = param -> new EpicFailTask();
  47 
  48     /**
  49      * The service that we're going to test. Because a ScheduledService
  50      * in its default configuration will run forever and because for the
  51      * sake of testing we've essentially caused ScheduledServiceTest to
  52      * run as though it is single threaded, we have to make sure that each
  53      * individual iteration is paused and doesn't occur without an explicit
  54      * call. So in the test code you can call start(), and then read the wall
  55      * clock time, and then call iterate() to cause the scheduled service to


  60     private ScheduledServiceMock s;
  61 
  62     /**
  63      * If specified by the test BEFORE the service is started, then this
  64      * task will be used by the service. Defaults to SimpleTask if null.
  65      */
  66     private Callback<Void,AbstractTask> taskFactory = null;
  67 
  68     /**
  69      * A fake "wall clock" time, to keep track of how much
  70      * time was spent executing a task, and how much time was
  71      * spent in the delay. We fake out the delay by overriding the
  72      * "schedule" method in ScheduledServiceMock, and we fake out
  73      * the task execution time by using a custom task which, when
  74      * executed, will add to the wall clock time.
  75      */
  76     private long wallClock;
  77 
  78     @Override protected TestServiceFactory setupServiceFactory() {
  79         return new TestServiceFactory() {
  80             @Override protected AbstractTask createTestTask() {
  81                 return taskFactory == null ? new SimpleTask() : taskFactory.call(null);
  82             }
  83 
  84             @Override protected Service<String> createService() {
  85                 return new ScheduledServiceMock(this);
  86             }
  87         };
  88     }
  89 
  90     @Override public void setup() {
  91         super.setup();
  92         s = (ScheduledServiceMock) service;
  93         wallClock = 0;
  94     }
  95 
  96     /**************************************************************************************************
  97      * Big pile of tests for making sure setting the cumulative period works in a predictable manner  *
  98      * regardless of what kind of output comes from the back-off algorithm, also taking into          *
  99      * account the maximum cumulative period value.                                                   *
 100      *************************************************************************************************/
 101 
 102     @Test public void setCumulativePeriod_MaxIsInfinity_TwoSeconds() {
 103         s.setCumulativePeriod(Duration.seconds(2));
 104         assertEquals(Duration.seconds(2), s.getCumulativePeriod());
 105     }
 106 
 107     @Test public void setCumulativePeriod_MaxIsInfinity_Negative() {
 108         s.setCumulativePeriod(Duration.seconds(-2));
 109         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 110     }
 111 
 112     @Test public void setCumulativePeriod_MaxIsInfinity_NegativeInfinity() {
 113         s.setCumulativePeriod(Duration.seconds(Double.NEGATIVE_INFINITY));
 114         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 115     }
 116 
 117     @Test public void setCumulativePeriod_MaxIsInfinity_NaN() {
 118         s.setCumulativePeriod(Duration.seconds(Double.NaN));
 119         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 120     }
 121 
 122     @Test public void setCumulativePeriod_MaxIsInfinity_PositiveInfinity() {
 123         s.setCumulativePeriod(Duration.seconds(Double.POSITIVE_INFINITY));
 124         assertEquals(Duration.INDEFINITE, s.getCumulativePeriod());
 125     }
 126 
 127     @Test public void setCumulativePeriod_MaxIsInfinity_MAX_VALUE() {
 128         s.setCumulativePeriod(Duration.millis(Double.MAX_VALUE));
 129         assertEquals(Duration.millis(Double.MAX_VALUE), s.getCumulativePeriod());
 130     }
 131 
 132     @Test public void setCumulativePeriod_MaxIsNaN_TwoSeconds() {
 133         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 134         s.setCumulativePeriod(Duration.seconds(2));
 135         assertEquals(Duration.seconds(2), s.getCumulativePeriod());
 136     }
 137 
 138     @Test public void setCumulativePeriod_MaxIsNaN_Negative() {
 139         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 140         s.setCumulativePeriod(Duration.seconds(-2));
 141         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 142     }
 143 
 144     @Test public void setCumulativePeriod_MaxIsNaN_NegativeInfinity() {
 145         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 146         s.setCumulativePeriod(Duration.seconds(Double.NEGATIVE_INFINITY));
 147         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 148     }
 149 
 150     @Test public void setCumulativePeriod_MaxIsNaN_NaN() {
 151         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 152         s.setCumulativePeriod(Duration.seconds(Double.NaN));
 153         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 154     }
 155 
 156     @Test public void setCumulativePeriod_MaxIsNaN_PositiveInfinity() {
 157         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 158         s.setCumulativePeriod(Duration.seconds(Double.POSITIVE_INFINITY));
 159         assertEquals(Duration.INDEFINITE, s.getCumulativePeriod());
 160     }
 161 
 162     @Test public void setCumulativePeriod_MaxIsNaN_MAX_VALUE() {
 163         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 164         s.setCumulativePeriod(Duration.millis(Double.MAX_VALUE));
 165         assertEquals(Duration.millis(Double.MAX_VALUE), s.getCumulativePeriod());
 166     }
 167 
 168     @Test public void setCumulativePeriod_MaxIsNull_TwoSeconds() {
 169         s.setMaximumCumulativePeriod(null);
 170         s.setCumulativePeriod(Duration.seconds(2));
 171         assertEquals(Duration.seconds(2), s.getCumulativePeriod());
 172     }
 173 
 174     @Test public void setCumulativePeriod_MaxIsNull_Negative() {
 175         s.setMaximumCumulativePeriod(null);
 176         s.setCumulativePeriod(Duration.seconds(-2));
 177         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 178     }
 179 
 180     @Test public void setCumulativePeriod_MaxIsNull_NegativeInfinity() {
 181         s.setMaximumCumulativePeriod(null);
 182         s.setCumulativePeriod(Duration.seconds(Double.NEGATIVE_INFINITY));
 183         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 184     }
 185 
 186     @Test public void setCumulativePeriod_MaxIsNull_NaN() {
 187         s.setMaximumCumulativePeriod(null);
 188         s.setCumulativePeriod(Duration.seconds(Double.NaN));
 189         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 190     }
 191 
 192     @Test public void setCumulativePeriod_MaxIsNull_PositiveInfinity() {
 193         s.setMaximumCumulativePeriod(null);
 194         s.setCumulativePeriod(Duration.seconds(Double.POSITIVE_INFINITY));
 195         assertEquals(Duration.INDEFINITE, s.getCumulativePeriod());
 196     }
 197 
 198     @Test public void setCumulativePeriod_MaxIsNull_MAX_VALUE() {
 199         s.setMaximumCumulativePeriod(null);
 200         s.setCumulativePeriod(Duration.millis(Double.MAX_VALUE));
 201         assertEquals(Duration.millis(Double.MAX_VALUE), s.getCumulativePeriod());
 202     }
 203 
 204     @Test public void setCumulativePeriod_MaxIs10_TwoSeconds() {
 205         s.setMaximumCumulativePeriod(Duration.seconds(10));
 206         s.setCumulativePeriod(Duration.seconds(2));
 207         assertEquals(Duration.seconds(2), s.getCumulativePeriod());
 208     }
 209 
 210     @Test public void setCumulativePeriod_MaxIs10_TenSeconds() {
 211         s.setMaximumCumulativePeriod(Duration.seconds(10));
 212         s.setCumulativePeriod(Duration.seconds(10));
 213         assertEquals(Duration.seconds(10), s.getCumulativePeriod());
 214     }
 215 
 216     @Test public void setCumulativePeriod_MaxIs10_TwelveSeconds() {
 217         s.setMaximumCumulativePeriod(Duration.seconds(10));
 218         s.setCumulativePeriod(Duration.seconds(12));
 219         assertEquals(Duration.seconds(10), s.getCumulativePeriod());
 220     }
 221 
 222     @Test public void setCumulativePeriod_MaxIs10_Negative() {
 223         s.setMaximumCumulativePeriod(Duration.seconds(10));
 224         s.setCumulativePeriod(Duration.seconds(-2));
 225         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 226     }
 227 
 228     @Test public void setCumulativePeriod_MaxIs10_NegativeInfinity() {
 229         s.setMaximumCumulativePeriod(Duration.seconds(10));
 230         s.setCumulativePeriod(Duration.seconds(Double.NEGATIVE_INFINITY));
 231         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 232     }
 233 
 234     @Test public void setCumulativePeriod_MaxIs10_NaN() {
 235         s.setMaximumCumulativePeriod(Duration.seconds(10));
 236         s.setCumulativePeriod(Duration.seconds(Double.NaN));
 237         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 238     }
 239 
 240     @Test public void setCumulativePeriod_MaxIs10_PositiveInfinity() {
 241         s.setMaximumCumulativePeriod(Duration.seconds(10));
 242         s.setCumulativePeriod(Duration.seconds(Double.POSITIVE_INFINITY));
 243         assertEquals(Duration.seconds(10), s.getCumulativePeriod());
 244     }
 245 
 246     @Test public void setCumulativePeriod_MaxIs10_MAX_VALUE() {
 247         s.setMaximumCumulativePeriod(Duration.seconds(10));
 248         s.setCumulativePeriod(Duration.millis(Double.MAX_VALUE));
 249         assertEquals(Duration.seconds(10), s.getCumulativePeriod());
 250     }
 251 
 252     @Test public void setCumulativePeriod_MaxIs0_TwoSeconds() {
 253         s.setMaximumCumulativePeriod(Duration.ZERO);
 254         s.setCumulativePeriod(Duration.seconds(2));
 255         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 256     }
 257 
 258     @Test public void setCumulativePeriod_MaxIs0_TenSeconds() {
 259         s.setMaximumCumulativePeriod(Duration.ZERO);
 260         s.setCumulativePeriod(Duration.seconds(10));
 261         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 262     }
 263 
 264     @Test public void setCumulativePeriod_MaxIs0_TwelveSeconds() {
 265         s.setMaximumCumulativePeriod(Duration.ZERO);
 266         s.setCumulativePeriod(Duration.seconds(12));
 267         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 268     }
 269 
 270     @Test public void setCumulativePeriod_MaxIs0_Negative() {
 271         s.setMaximumCumulativePeriod(Duration.ZERO);
 272         s.setCumulativePeriod(Duration.seconds(-2));
 273         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 274     }
 275 
 276     @Test public void setCumulativePeriod_MaxIs0_NegativeInfinity() {
 277         s.setMaximumCumulativePeriod(Duration.ZERO);
 278         s.setCumulativePeriod(Duration.seconds(Double.NEGATIVE_INFINITY));
 279         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 280     }
 281 
 282     @Test public void setCumulativePeriod_MaxIs0_NaN() {
 283         s.setMaximumCumulativePeriod(Duration.ZERO);
 284         s.setCumulativePeriod(Duration.seconds(Double.NaN));
 285         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 286     }
 287 
 288     @Test public void setCumulativePeriod_MaxIs0_PositiveInfinity() {
 289         s.setMaximumCumulativePeriod(Duration.ZERO);
 290         s.setCumulativePeriod(Duration.seconds(Double.POSITIVE_INFINITY));
 291         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 292     }
 293 
 294     @Test public void setCumulativePeriod_MaxIs0_MAX_VALUE() {
 295         s.setMaximumCumulativePeriod(Duration.ZERO);
 296         s.setCumulativePeriod(Duration.millis(Double.MAX_VALUE));
 297         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 298     }
 299 
 300     @Test public void setCumulativePeriod_MaxIsNegative_TwoSeconds() {
 301         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 302         s.setCumulativePeriod(Duration.seconds(2));
 303         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 304     }
 305 
 306     @Test public void setCumulativePeriod_MaxIsNegative_TenSeconds() {
 307         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 308         s.setCumulativePeriod(Duration.seconds(10));
 309         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 310     }
 311 
 312     @Test public void setCumulativePeriod_MaxIsNegative_TwelveSeconds() {
 313         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 314         s.setCumulativePeriod(Duration.seconds(12));
 315         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 316     }
 317 
 318     @Test public void setCumulativePeriod_MaxIsNegative_Negative() {
 319         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 320         s.setCumulativePeriod(Duration.seconds(-2));
 321         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 322     }
 323 
 324     @Test public void setCumulativePeriod_MaxIsNegative_NegativeInfinity() {
 325         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 326         s.setCumulativePeriod(Duration.seconds(Double.NEGATIVE_INFINITY));
 327         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 328     }
 329 
 330     @Test public void setCumulativePeriod_MaxIsNegative_NaN() {
 331         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 332         s.setCumulativePeriod(Duration.seconds(Double.NaN));
 333         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 334     }
 335 
 336     @Test public void setCumulativePeriod_MaxIsNegative_PositiveInfinity() {
 337         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 338         s.setCumulativePeriod(Duration.seconds(Double.POSITIVE_INFINITY));
 339         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 340     }
 341 
 342     @Test public void setCumulativePeriod_MaxIsNegative_MAX_VALUE() {
 343         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 344         s.setCumulativePeriod(Duration.millis(Double.MAX_VALUE));
 345         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 346     }
 347 
 348     // TODO I think Duration boundary condition checking is wrong. It doesn't use isInfinite, but checks
 349     // directly with POSITIVE_INFINITY, neglecting to check NEGATIVE_INFINITY.
 350 
 351     // DELAY
 352     // Test that:
 353     //     delay (positive, unknown, zero) works the first time
 354     //     delay is not used on the next iteration
 355     //     delay works on restart
 356     //     delay works on reset / start
 357 
 358     @Test public void delayIsHonored_Positive() throws InterruptedException {
 359         s.setDelay(Duration.seconds(1));
 360         s.start();
 361         assertEquals(1000, wallClock);
 362     }
 363 
 364     @Test public void delayIsHonored_Unknown() throws InterruptedException {


 807         s.setOnReady(event -> onReadyCalled.set(true));
 808         s.setOnScheduled(event -> onScheduledCalled.set(true));
 809         s.setOnCancelled(event -> onCancelledCalled.set(true));
 810 
 811         s.start();
 812         assertFalse(s.isRunning());
 813         assertEquals(Worker.State.CANCELLED, s.getState());
 814         assertTrue(onReadyCalled.get());
 815         assertTrue(onScheduledCalled.get());
 816         assertTrue(onCancelledCalled.get());
 817     }
 818 
 819     /**
 820      * Allows us to monkey with how the threading works for the sake of testing.
 821      * Basically, you just call start() in order to go through an entire first
 822      * iteration, and a call to iterate() causes it to go through a subsequent
 823      * iteration. At the end of each iteration, you are in the SCHEDULED state,
 824      * unless failures occurred while running the task that caused the service
 825      * to finally enter the FAILED state.
 826      */
 827     private final class ScheduledServiceMock extends ScheduledService<String> {
 828         private TestServiceFactory factory;
 829         private Task<String> nextTask = null;
 830 
 831         ScheduledServiceMock(TestServiceFactory f) {
 832             this.factory = f;
 833         }
 834 
 835         @Override protected Task<String> createTask() {
 836             factory.currentTask = factory.createTestTask();
 837             factory.currentTask.test = factory.test;
 838             return factory.currentTask;
 839         }
 840 
 841         @Override void checkThread() { }
 842 
 843         @Override void schedule(TimerTask task, long delay) {
 844             wallClock += delay;
 845             task.run();
 846         }
 847 
 848         @Override protected void executeTask(Task<String> task) {
 849             nextTask = task;
 850             if (isFreshStart()) iterate();
 851         }
 852 
 853         @Override long clock() {
 854             return wallClock;
 855         }
 856 
 857         @Override boolean isFxApplicationThread() {
 858             return Thread.currentThread() == factory.appThread;
 859         }
 860 
 861         void iterate() {
 862             assert nextTask != null;
 863             Task<String> task = nextTask;
 864             nextTask = null;
 865 
 866             super.executeTask(task);
 867             handleEvents();
 868         }
 869     }
 870 }


   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.javafx.concurrent;
  27 
  28 import test.javafx.concurrent.mocks.EpicFailTask;
  29 import test.javafx.concurrent.mocks.SimpleTask;

  30 import javafx.util.Callback;
  31 import javafx.util.Duration;
  32 import java.util.TimerTask;
  33 import java.util.concurrent.atomic.AtomicBoolean;
  34 import java.util.concurrent.atomic.AtomicInteger;
  35 import javafx.concurrent.ScheduledService;
  36 import javafx.concurrent.ScheduledServiceShim;
  37 import javafx.concurrent.Service;
  38 import javafx.concurrent.Task;
  39 import javafx.concurrent.Worker;
  40 import org.junit.Test;
  41 import static org.junit.Assert.assertEquals;
  42 import static org.junit.Assert.assertFalse;
  43 import static org.junit.Assert.assertNull;
  44 import static org.junit.Assert.assertTrue;
  45 
  46 /**
  47  * Tests for the ScheduledService.
  48  */
  49 public class ScheduledServiceTest extends ServiceTestBase {
  50     private static final Callback<Void, AbstractTask> EPIC_FAIL_FACTORY = param -> new EpicFailTask();
  51 
  52     /**
  53      * The service that we're going to test. Because a ScheduledService
  54      * in its default configuration will run forever and because for the
  55      * sake of testing we've essentially caused ScheduledServiceTest to
  56      * run as though it is single threaded, we have to make sure that each
  57      * individual iteration is paused and doesn't occur without an explicit
  58      * call. So in the test code you can call start(), and then read the wall
  59      * clock time, and then call iterate() to cause the scheduled service to


  64     private ScheduledServiceMock s;
  65 
  66     /**
  67      * If specified by the test BEFORE the service is started, then this
  68      * task will be used by the service. Defaults to SimpleTask if null.
  69      */
  70     private Callback<Void,AbstractTask> taskFactory = null;
  71 
  72     /**
  73      * A fake "wall clock" time, to keep track of how much
  74      * time was spent executing a task, and how much time was
  75      * spent in the delay. We fake out the delay by overriding the
  76      * "schedule" method in ScheduledServiceMock, and we fake out
  77      * the task execution time by using a custom task which, when
  78      * executed, will add to the wall clock time.
  79      */
  80     private long wallClock;
  81 
  82     @Override protected TestServiceFactory setupServiceFactory() {
  83         return new TestServiceFactory() {
  84             @Override public AbstractTask createTestTask() {
  85                 return taskFactory == null ? new SimpleTask() : taskFactory.call(null);
  86             }
  87 
  88             @Override public Service<String> createService() {
  89                 return new ScheduledServiceMock(this);
  90             }
  91         };
  92     }
  93 
  94     @Override public void setup() {
  95         super.setup();
  96         s = (ScheduledServiceMock) service;
  97         wallClock = 0;
  98     }
  99 
 100     /**************************************************************************************************
 101      * Big pile of tests for making sure setting the cumulative period works in a predictable manner  *
 102      * regardless of what kind of output comes from the back-off algorithm, also taking into          *
 103      * account the maximum cumulative period value.                                                   *
 104      *************************************************************************************************/
 105 
 106     @Test public void setCumulativePeriod_MaxIsInfinity_TwoSeconds() {
 107         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(2));
 108         assertEquals(Duration.seconds(2), s.getCumulativePeriod());
 109     }
 110 
 111     @Test public void setCumulativePeriod_MaxIsInfinity_Negative() {
 112         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(-2));
 113         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 114     }
 115 
 116     @Test public void setCumulativePeriod_MaxIsInfinity_NegativeInfinity() {
 117         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NEGATIVE_INFINITY));
 118         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 119     }
 120 
 121     @Test public void setCumulativePeriod_MaxIsInfinity_NaN() {
 122         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NaN));
 123         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 124     }
 125 
 126     @Test public void setCumulativePeriod_MaxIsInfinity_PositiveInfinity() {
 127         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.POSITIVE_INFINITY));
 128         assertEquals(Duration.INDEFINITE, s.getCumulativePeriod());
 129     }
 130 
 131     @Test public void setCumulativePeriod_MaxIsInfinity_MAX_VALUE() {
 132         ScheduledServiceShim.setCumulativePeriod(s, Duration.millis(Double.MAX_VALUE));
 133         assertEquals(Duration.millis(Double.MAX_VALUE), s.getCumulativePeriod());
 134     }
 135 
 136     @Test public void setCumulativePeriod_MaxIsNaN_TwoSeconds() {
 137         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 138         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(2));
 139         assertEquals(Duration.seconds(2), s.getCumulativePeriod());
 140     }
 141 
 142     @Test public void setCumulativePeriod_MaxIsNaN_Negative() {
 143         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 144         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(-2));
 145         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 146     }
 147 
 148     @Test public void setCumulativePeriod_MaxIsNaN_NegativeInfinity() {
 149         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 150         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NEGATIVE_INFINITY));
 151         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 152     }
 153 
 154     @Test public void setCumulativePeriod_MaxIsNaN_NaN() {
 155         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 156         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NaN));
 157         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 158     }
 159 
 160     @Test public void setCumulativePeriod_MaxIsNaN_PositiveInfinity() {
 161         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 162         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.POSITIVE_INFINITY));
 163         assertEquals(Duration.INDEFINITE, s.getCumulativePeriod());
 164     }
 165 
 166     @Test public void setCumulativePeriod_MaxIsNaN_MAX_VALUE() {
 167         s.setMaximumCumulativePeriod(Duration.UNKNOWN);
 168         ScheduledServiceShim.setCumulativePeriod(s, Duration.millis(Double.MAX_VALUE));
 169         assertEquals(Duration.millis(Double.MAX_VALUE), s.getCumulativePeriod());
 170     }
 171 
 172     @Test public void setCumulativePeriod_MaxIsNull_TwoSeconds() {
 173         s.setMaximumCumulativePeriod(null);
 174         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(2));
 175         assertEquals(Duration.seconds(2), s.getCumulativePeriod());
 176     }
 177 
 178     @Test public void setCumulativePeriod_MaxIsNull_Negative() {
 179         s.setMaximumCumulativePeriod(null);
 180         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(-2));
 181         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 182     }
 183 
 184     @Test public void setCumulativePeriod_MaxIsNull_NegativeInfinity() {
 185         s.setMaximumCumulativePeriod(null);
 186         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NEGATIVE_INFINITY));
 187         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 188     }
 189 
 190     @Test public void setCumulativePeriod_MaxIsNull_NaN() {
 191         s.setMaximumCumulativePeriod(null);
 192         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NaN));
 193         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 194     }
 195 
 196     @Test public void setCumulativePeriod_MaxIsNull_PositiveInfinity() {
 197         s.setMaximumCumulativePeriod(null);
 198         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.POSITIVE_INFINITY));
 199         assertEquals(Duration.INDEFINITE, s.getCumulativePeriod());
 200     }
 201 
 202     @Test public void setCumulativePeriod_MaxIsNull_MAX_VALUE() {
 203         s.setMaximumCumulativePeriod(null);
 204         ScheduledServiceShim.setCumulativePeriod(s, Duration.millis(Double.MAX_VALUE));
 205         assertEquals(Duration.millis(Double.MAX_VALUE), s.getCumulativePeriod());
 206     }
 207 
 208     @Test public void setCumulativePeriod_MaxIs10_TwoSeconds() {
 209         s.setMaximumCumulativePeriod(Duration.seconds(10));
 210         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(2));
 211         assertEquals(Duration.seconds(2), s.getCumulativePeriod());
 212     }
 213 
 214     @Test public void setCumulativePeriod_MaxIs10_TenSeconds() {
 215         s.setMaximumCumulativePeriod(Duration.seconds(10));
 216         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(10));
 217         assertEquals(Duration.seconds(10), s.getCumulativePeriod());
 218     }
 219 
 220     @Test public void setCumulativePeriod_MaxIs10_TwelveSeconds() {
 221         s.setMaximumCumulativePeriod(Duration.seconds(10));
 222         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(12));
 223         assertEquals(Duration.seconds(10), s.getCumulativePeriod());
 224     }
 225 
 226     @Test public void setCumulativePeriod_MaxIs10_Negative() {
 227         s.setMaximumCumulativePeriod(Duration.seconds(10));
 228         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(-2));
 229         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 230     }
 231 
 232     @Test public void setCumulativePeriod_MaxIs10_NegativeInfinity() {
 233         s.setMaximumCumulativePeriod(Duration.seconds(10));
 234         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NEGATIVE_INFINITY));
 235         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 236     }
 237 
 238     @Test public void setCumulativePeriod_MaxIs10_NaN() {
 239         s.setMaximumCumulativePeriod(Duration.seconds(10));
 240         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NaN));
 241         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 242     }
 243 
 244     @Test public void setCumulativePeriod_MaxIs10_PositiveInfinity() {
 245         s.setMaximumCumulativePeriod(Duration.seconds(10));
 246         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.POSITIVE_INFINITY));
 247         assertEquals(Duration.seconds(10), s.getCumulativePeriod());
 248     }
 249 
 250     @Test public void setCumulativePeriod_MaxIs10_MAX_VALUE() {
 251         s.setMaximumCumulativePeriod(Duration.seconds(10));
 252         ScheduledServiceShim.setCumulativePeriod(s, Duration.millis(Double.MAX_VALUE));
 253         assertEquals(Duration.seconds(10), s.getCumulativePeriod());
 254     }
 255 
 256     @Test public void setCumulativePeriod_MaxIs0_TwoSeconds() {
 257         s.setMaximumCumulativePeriod(Duration.ZERO);
 258         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(2));
 259         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 260     }
 261 
 262     @Test public void setCumulativePeriod_MaxIs0_TenSeconds() {
 263         s.setMaximumCumulativePeriod(Duration.ZERO);
 264         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(10));
 265         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 266     }
 267 
 268     @Test public void setCumulativePeriod_MaxIs0_TwelveSeconds() {
 269         s.setMaximumCumulativePeriod(Duration.ZERO);
 270         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(12));
 271         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 272     }
 273 
 274     @Test public void setCumulativePeriod_MaxIs0_Negative() {
 275         s.setMaximumCumulativePeriod(Duration.ZERO);
 276         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(-2));
 277         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 278     }
 279 
 280     @Test public void setCumulativePeriod_MaxIs0_NegativeInfinity() {
 281         s.setMaximumCumulativePeriod(Duration.ZERO);
 282         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NEGATIVE_INFINITY));
 283         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 284     }
 285 
 286     @Test public void setCumulativePeriod_MaxIs0_NaN() {
 287         s.setMaximumCumulativePeriod(Duration.ZERO);
 288         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NaN));
 289         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 290     }
 291 
 292     @Test public void setCumulativePeriod_MaxIs0_PositiveInfinity() {
 293         s.setMaximumCumulativePeriod(Duration.ZERO);
 294         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.POSITIVE_INFINITY));
 295         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 296     }
 297 
 298     @Test public void setCumulativePeriod_MaxIs0_MAX_VALUE() {
 299         s.setMaximumCumulativePeriod(Duration.ZERO);
 300         ScheduledServiceShim.setCumulativePeriod(s, Duration.millis(Double.MAX_VALUE));
 301         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 302     }
 303 
 304     @Test public void setCumulativePeriod_MaxIsNegative_TwoSeconds() {
 305         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 306         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(2));
 307         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 308     }
 309 
 310     @Test public void setCumulativePeriod_MaxIsNegative_TenSeconds() {
 311         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 312         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(10));
 313         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 314     }
 315 
 316     @Test public void setCumulativePeriod_MaxIsNegative_TwelveSeconds() {
 317         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 318         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(12));
 319         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 320     }
 321 
 322     @Test public void setCumulativePeriod_MaxIsNegative_Negative() {
 323         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 324         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(-2));
 325         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 326     }
 327 
 328     @Test public void setCumulativePeriod_MaxIsNegative_NegativeInfinity() {
 329         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 330         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NEGATIVE_INFINITY));
 331         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 332     }
 333 
 334     @Test public void setCumulativePeriod_MaxIsNegative_NaN() {
 335         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 336         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.NaN));
 337         assertEquals(Duration.UNKNOWN, s.getCumulativePeriod());
 338     }
 339 
 340     @Test public void setCumulativePeriod_MaxIsNegative_PositiveInfinity() {
 341         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 342         ScheduledServiceShim.setCumulativePeriod(s, Duration.seconds(Double.POSITIVE_INFINITY));
 343         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 344     }
 345 
 346     @Test public void setCumulativePeriod_MaxIsNegative_MAX_VALUE() {
 347         s.setMaximumCumulativePeriod(Duration.seconds(-1));
 348         ScheduledServiceShim.setCumulativePeriod(s, Duration.millis(Double.MAX_VALUE));
 349         assertEquals(Duration.ZERO, s.getCumulativePeriod());
 350     }
 351 
 352     // TODO I think Duration boundary condition checking is wrong. It doesn't use isInfinite, but checks
 353     // directly with POSITIVE_INFINITY, neglecting to check NEGATIVE_INFINITY.
 354 
 355     // DELAY
 356     // Test that:
 357     //     delay (positive, unknown, zero) works the first time
 358     //     delay is not used on the next iteration
 359     //     delay works on restart
 360     //     delay works on reset / start
 361 
 362     @Test public void delayIsHonored_Positive() throws InterruptedException {
 363         s.setDelay(Duration.seconds(1));
 364         s.start();
 365         assertEquals(1000, wallClock);
 366     }
 367 
 368     @Test public void delayIsHonored_Unknown() throws InterruptedException {


 811         s.setOnReady(event -> onReadyCalled.set(true));
 812         s.setOnScheduled(event -> onScheduledCalled.set(true));
 813         s.setOnCancelled(event -> onCancelledCalled.set(true));
 814 
 815         s.start();
 816         assertFalse(s.isRunning());
 817         assertEquals(Worker.State.CANCELLED, s.getState());
 818         assertTrue(onReadyCalled.get());
 819         assertTrue(onScheduledCalled.get());
 820         assertTrue(onCancelledCalled.get());
 821     }
 822 
 823     /**
 824      * Allows us to monkey with how the threading works for the sake of testing.
 825      * Basically, you just call start() in order to go through an entire first
 826      * iteration, and a call to iterate() causes it to go through a subsequent
 827      * iteration. At the end of each iteration, you are in the SCHEDULED state,
 828      * unless failures occurred while running the task that caused the service
 829      * to finally enter the FAILED state.
 830      */
 831     private final class ScheduledServiceMock extends ScheduledServiceShim<String> {
 832         private TestServiceFactory factory;
 833         private Task<String> nextTask = null;
 834 
 835         ScheduledServiceMock(TestServiceFactory f) {
 836             this.factory = f;
 837         }
 838 
 839         @Override protected Task<String> createTask() {
 840             factory.currentTask = factory.createTestTask();
 841             factory.currentTask.set_test(factory.test);
 842             return factory.currentTask;
 843         }
 844 
 845         @Override public void checkThread() { }
 846 
 847         @Override public void schedule(TimerTask task, long delay) {
 848             wallClock += delay;
 849             task.run();
 850         }
 851 
 852         @Override public void executeTask(Task<String> task) {
 853             nextTask = task;
 854             if (isFreshStart()) iterate();
 855         }
 856 
 857         @Override public long clock() {
 858             return wallClock;
 859         }
 860 
 861         @Override public boolean isFxApplicationThread() {
 862             return Thread.currentThread() == factory.appThread;
 863         }
 864 
 865         void iterate() {
 866             assert nextTask != null;
 867             Task<String> task = nextTask;
 868             nextTask = null;
 869 
 870             super.executeTask(task);
 871             handleEvents();
 872         }
 873     }
 874 }