1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   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.animation;
  27 
  28 import com.sun.javafx.animation.TickCalculation;
  29 import javafx.animation.Animation.Status;
  30 import javafx.animation.AnimationShim;
  31 import javafx.animation.Interpolator;
  32 import javafx.animation.SequentialTransition;
  33 import javafx.animation.SequentialTransitionShim;
  34 import javafx.animation.Transition;
  35 import javafx.animation.TransitionShim;
  36 import javafx.beans.property.LongProperty;
  37 import javafx.beans.property.SimpleLongProperty;
  38 import javafx.util.Duration;
  39 import org.junit.Before;
  40 import org.junit.Test;
  41 import static org.junit.Assert.*;
  42 
  43 public class SequentialTransitionPlayTest {
  44 
  45     public static final double TICK_MILLIS = TickCalculation.toMillis(100);
  46     public static final long TICK_STEP = Math.round(TICK_MILLIS);
  47 
  48     LongProperty xProperty = new SimpleLongProperty();
  49     LongProperty yProperty = new SimpleLongProperty();
  50     AbstractMasterTimerMock amt;
  51     SequentialTransition st;
  52     Transition child1X;
  53     Transition child1Y;
  54     Transition childByX;
  55     Transition childByX2;
  56 
  57     @Before
  58     public void setUp() {
  59         amt = new AbstractMasterTimerMock();
  60         st = SequentialTransitionShim.getSequentialTransition(amt);
  61         child1X = new TransitionShim() {
  62             {
  63                 setCycleDuration(Duration.minutes(1));
  64                 setInterpolator(Interpolator.LINEAR);
  65             }
  66 
  67             @Override
  68             protected void interpolate(double d) {
  69                 xProperty.set(Math.round(d * 60000));
  70             }
  71         };
  72         child1Y = new TransitionShim() {
  73             {
  74                 setCycleDuration(Duration.seconds(10));
  75                 setInterpolator(Interpolator.LINEAR);
  76             }
  77 
  78             @Override
  79             protected void interpolate(double d) {
  80                 yProperty.set(Math.round(d * 10000));
  81             }
  82         };
  83         childByX = createByXChild();
  84         childByX2 = createByXChild();
  85     }
  86 
  87     private Transition createByXChild() {
  88         return new TransitionShim() {
  89             {
  90                 setCycleDuration(Duration.seconds(1));
  91                 setInterpolator(Interpolator.LINEAR);
  92             }
  93 
  94             long lastX;
  95 
  96             @Override
  97             protected void interpolate(double frac) {
  98                 xProperty.set(Math.round(lastX + frac * 1000));
  99             }
 100 
 101             @Override
 102             public void sync(boolean forceSync) {
 103                 super.sync(forceSync);
 104                 if (forceSync) {
 105                     lastX = xProperty.get();
 106                 }
 107             }
 108 
 109 
 110         };
 111     }
 112 
 113     @Test
 114     public void testSimplePlay() {
 115         st.getChildren().addAll(child1X, child1Y);
 116 
 117         st.play();
 118         assertEquals(Status.RUNNING, st.getStatus());
 119         assertEquals(Status.STOPPED, child1X.getStatus());
 120         assertEquals(Status.STOPPED, child1Y.getStatus());
 121 
 122         amt.pulse();
 123         assertEquals(TickCalculation.toDuration(100), st.getCurrentTime());
 124         assertEquals(TickCalculation.toDuration(100), child1X.getCurrentTime());
 125         assertEquals(Duration.ZERO, child1Y.getCurrentTime());
 126         assertEquals(Math.round(TICK_MILLIS), xProperty.get());
 127         assertEquals(0, yProperty.get());
 128 
 129         assertEquals(Status.RUNNING, st.getStatus());
 130         assertEquals(Status.RUNNING, child1X.getStatus());
 131         assertEquals(Status.STOPPED, child1Y.getStatus());
 132 
 133         st.jumpTo(Duration.minutes(1).subtract(TickCalculation.toDuration(100)));
 134 
 135         assertEquals(Status.RUNNING, st.getStatus());
 136         assertEquals(Status.RUNNING, child1X.getStatus());
 137         assertEquals(Status.STOPPED, child1Y.getStatus());
 138         assertEquals(60000 - Math.round(TICK_MILLIS), xProperty.get());
 139         assertEquals(0, yProperty.get());
 140 
 141         amt.pulse();
 142         assertEquals(Status.RUNNING, st.getStatus());
 143         assertEquals(Status.STOPPED, child1X.getStatus());
 144         assertEquals(Status.STOPPED, child1Y.getStatus());
 145         assertEquals(60000, xProperty.get());
 146         assertEquals(0, yProperty.get());
 147 
 148         amt.pulse();
 149 
 150         assertEquals(Status.RUNNING, st.getStatus());
 151         assertEquals(Status.STOPPED, child1X.getStatus());
 152         assertEquals(Status.RUNNING, child1Y.getStatus());
 153         assertEquals(60000, xProperty.get());
 154         assertEquals(Math.round(TICK_MILLIS), yProperty.get());
 155 
 156         st.jumpTo(Duration.minutes(1).add(Duration.seconds(10)).subtract(TickCalculation.toDuration(100)));
 157 
 158         assertEquals(Status.RUNNING, st.getStatus());
 159         assertEquals(Status.STOPPED, child1X.getStatus());
 160         assertEquals(Status.RUNNING, child1Y.getStatus());
 161         assertEquals(60000, xProperty.get());
 162         assertEquals(10000 - Math.round(TICK_MILLIS), yProperty.get());
 163 
 164         amt.pulse();
 165 
 166         assertEquals(Status.STOPPED, st.getStatus());
 167         assertEquals(Status.STOPPED, child1X.getStatus());
 168         assertEquals(Status.STOPPED, child1Y.getStatus());
 169         assertEquals(60000, xProperty.get());
 170         assertEquals(10000, yProperty.get());
 171     }
 172 
 173 
 174     @Test
 175     public void testSimplePlayReversed() {
 176         st.getChildren().addAll(child1X, child1Y);
 177         st.setRate(-1.0);
 178         st.jumpTo(Duration.seconds(70));
 179 
 180         st.play();
 181         assertEquals(Status.RUNNING, st.getStatus());
 182         assertEquals(Status.STOPPED, child1X.getStatus());
 183         assertEquals(Status.STOPPED, child1Y.getStatus());
 184         assertEquals(Duration.seconds(70), st.getCurrentTime());
 185         assertEquals(Duration.seconds(60), child1X.getCurrentTime());
 186         assertEquals(Duration.seconds(10), child1Y.getCurrentTime());
 187 
 188         amt.pulse();
 189         assertEquals(Duration.seconds(70).subtract(TickCalculation.toDuration(100)), st.getCurrentTime());
 190         assertEquals(Duration.seconds(60), child1X.getCurrentTime());
 191         assertEquals(Duration.seconds(10).subtract(TickCalculation.toDuration(100)), child1Y.getCurrentTime());
 192         assertEquals(60000, xProperty.get());
 193         assertEquals(10000 - Math.round(TICK_MILLIS), yProperty.get());
 194 
 195         assertEquals(Status.RUNNING, st.getStatus());
 196         assertEquals(Status.STOPPED, child1X.getStatus());
 197         assertEquals(Status.RUNNING, child1Y.getStatus());
 198 
 199         st.jumpTo(Duration.minutes(1).add(TickCalculation.toDuration(100)));
 200 
 201         assertEquals(Status.RUNNING, st.getStatus());
 202         assertEquals(Status.STOPPED, child1X.getStatus());
 203         assertEquals(Status.RUNNING, child1Y.getStatus());
 204         assertEquals(60000, xProperty.get());
 205         assertEquals(Math.round(TICK_MILLIS), yProperty.get());
 206 
 207         amt.pulse();
 208         assertEquals(Status.RUNNING, st.getStatus());
 209         assertEquals(Status.STOPPED, child1X.getStatus());
 210         assertEquals(Status.STOPPED, child1Y.getStatus());
 211         assertEquals(60000, xProperty.get());
 212         assertEquals(0, yProperty.get());
 213 
 214         amt.pulse();
 215 
 216         assertEquals(Status.RUNNING, st.getStatus());
 217         assertEquals(Status.RUNNING, child1X.getStatus());
 218         assertEquals(Status.STOPPED, child1Y.getStatus());
 219         assertEquals(60000 - Math.round(TICK_MILLIS), xProperty.get());
 220         assertEquals(0, yProperty.get());
 221 
 222         st.jumpTo(TickCalculation.toDuration(100));
 223 
 224         assertEquals(Status.RUNNING, st.getStatus());
 225         assertEquals(Status.RUNNING, child1X.getStatus());
 226         assertEquals(Status.STOPPED, child1Y.getStatus());
 227         assertEquals(Math.round(TICK_MILLIS), xProperty.get());
 228         assertEquals(0, yProperty.get());
 229 
 230         amt.pulse();
 231 
 232         assertEquals(Status.STOPPED, st.getStatus());
 233         assertEquals(Status.STOPPED, child1X.getStatus());
 234         assertEquals(Status.STOPPED, child1Y.getStatus());
 235         assertEquals(0, xProperty.get());
 236         assertEquals(0, yProperty.get());
 237     }
 238 
 239     @Test
 240     public void testPauseAndJump() {
 241         st.getChildren().addAll(child1X, child1Y);
 242 
 243         st.play();
 244         st.jumpTo(Duration.seconds(10));
 245         st.pause();
 246         assertEquals(Status.PAUSED, st.getStatus());
 247         assertEquals(Status.PAUSED, child1X.getStatus());
 248         assertEquals(Status.STOPPED, child1Y.getStatus());
 249         assertEquals(10000, xProperty.get());
 250         assertEquals(0, yProperty.get());
 251 
 252         amt.pulse();
 253         assertEquals(Duration.seconds(10), st.getCurrentTime());
 254         assertEquals(Duration.seconds(10), child1X.getCurrentTime());
 255         assertEquals(Duration.ZERO, child1Y.getCurrentTime());
 256         assertEquals(10000, xProperty.get());
 257         assertEquals(0, yProperty.get());
 258 
 259         st.play();
 260         st.jumpTo(Duration.seconds(50));
 261         assertEquals(Status.RUNNING, st.getStatus());
 262         assertEquals(Status.RUNNING, child1X.getStatus());
 263         assertEquals(Status.STOPPED, child1Y.getStatus());
 264         assertEquals(Duration.seconds(50), st.getCurrentTime());
 265         assertEquals(Duration.seconds(50), child1X.getCurrentTime());
 266         assertEquals(Duration.seconds(0), child1Y.getCurrentTime());
 267         assertEquals(50000, xProperty.get());
 268         assertEquals(0, yProperty.get());
 269 
 270         amt.pulse();
 271         assertEquals(Status.RUNNING, st.getStatus());
 272         assertEquals(Status.RUNNING, child1X.getStatus());
 273         assertEquals(Status.STOPPED, child1Y.getStatus());
 274         assertEquals(50000 + Math.round(TickCalculation.toMillis(100)), xProperty.get());
 275         assertEquals(0, yProperty.get());
 276 
 277         st.pause();
 278         st.jumpTo(Duration.seconds(65));
 279         assertEquals(Duration.seconds(65), st.getCurrentTime());
 280         assertEquals(Duration.seconds(60), child1X.getCurrentTime());
 281         assertEquals(Duration.seconds(5), child1Y.getCurrentTime());
 282         assertEquals(Status.PAUSED, st.getStatus());
 283         assertEquals(Status.STOPPED, child1X.getStatus());
 284         assertEquals(Status.PAUSED, child1Y.getStatus());
 285         assertEquals(60000, xProperty.get());
 286         assertEquals(5000, yProperty.get());
 287 
 288         amt.pulse();
 289         assertEquals(Status.PAUSED, st.getStatus());
 290         assertEquals(Status.STOPPED, child1X.getStatus());
 291         assertEquals(Status.PAUSED, child1Y.getStatus());
 292         assertEquals(60000, xProperty.get());
 293         assertEquals(5000, yProperty.get());
 294 
 295         st.play();
 296         st.jumpTo(Duration.minutes(1).add(Duration.seconds(10)).subtract(TickCalculation.toDuration(100)));
 297         assertEquals(Duration.seconds(70).subtract(TickCalculation.toDuration(100)), st.getCurrentTime());
 298         assertEquals(Duration.seconds(60), child1X.getCurrentTime());
 299         assertEquals(Duration.seconds(10).subtract(TickCalculation.toDuration(100)), child1Y.getCurrentTime());
 300         assertEquals(Status.RUNNING, st.getStatus());
 301         assertEquals(Status.STOPPED, child1X.getStatus());
 302         assertEquals(Status.RUNNING, child1Y.getStatus());
 303         assertEquals(60000, xProperty.get());
 304         assertEquals(10000 - Math.round(TickCalculation.toMillis(100)), yProperty.get());
 305 
 306 
 307         amt.pulse();
 308         assertEquals(Duration.seconds(70), st.getCurrentTime());
 309         assertEquals(Duration.seconds(60), child1X.getCurrentTime());
 310         assertEquals(Duration.seconds(10), child1Y.getCurrentTime());
 311         assertEquals(Status.STOPPED, st.getStatus());
 312         assertEquals(Status.STOPPED, child1X.getStatus());
 313         assertEquals(Status.STOPPED, child1Y.getStatus());
 314         assertEquals(60000, xProperty.get());
 315         assertEquals(10000, yProperty.get());
 316     }
 317 
 318     @Test
 319     public void testPauseAndJumpReversed1() {
 320         st.getChildren().addAll(child1X, child1Y);
 321         st.setRate(-1.0);
 322 
 323         st.jumpTo(Duration.seconds(70));
 324         st.play();
 325         amt.pulse();
 326         assertEquals(Status.RUNNING, st.getStatus());
 327         assertEquals(Status.STOPPED, child1X.getStatus());
 328         assertEquals(Status.RUNNING, child1Y.getStatus());
 329         assertEquals(60000, xProperty.get());
 330         assertEquals(10000 - Math.round(TickCalculation.toMillis(100)), yProperty.get());
 331 
 332         st.pause();
 333         st.jumpTo(Duration.minutes(1).add(Duration.seconds(5)).add(TickCalculation.toDuration(100)));
 334         assertEquals(Status.PAUSED, st.getStatus());
 335         assertEquals(Status.STOPPED, child1X.getStatus());
 336         assertEquals(Status.PAUSED, child1Y.getStatus());
 337         assertEquals(Duration.seconds(65).add(TickCalculation.toDuration(100)), st.getCurrentTime());
 338         assertEquals(60000, xProperty.get());
 339         assertEquals(5000 + Math.round(TickCalculation.toMillis(100)), yProperty.get());
 340 
 341         st.play();
 342         amt.pulse();
 343         assertEquals(Status.RUNNING, st.getStatus());
 344         assertEquals(Status.STOPPED, child1X.getStatus());
 345         assertEquals(Status.RUNNING, child1Y.getStatus());
 346         assertEquals(60000, xProperty.get());
 347         assertEquals(5000, yProperty.get());
 348 
 349         st.pause();
 350         st.jumpTo(Duration.seconds(10));
 351         assertEquals(Status.PAUSED, st.getStatus());
 352         assertEquals(Status.PAUSED, child1X.getStatus());
 353         assertEquals(Status.STOPPED, child1Y.getStatus());
 354         assertEquals(10000, xProperty.get());
 355         assertEquals(0, yProperty.get());
 356 
 357         st.play();
 358         amt.pulse();
 359         assertEquals(Status.RUNNING, st.getStatus());
 360         assertEquals(Status.RUNNING, child1X.getStatus());
 361         assertEquals(Status.STOPPED, child1Y.getStatus());
 362         assertEquals(10000 - Math.round(TickCalculation.toMillis(100)), xProperty.get());
 363         assertEquals(0, yProperty.get());
 364 
 365         st.pause();
 366         st.jumpTo(Duration.seconds(0).add(TickCalculation.toDuration(100)));
 367         assertEquals(TickCalculation.toDuration(100), st.getCurrentTime());
 368         assertEquals(TickCalculation.toDuration(100), child1X.getCurrentTime());
 369         assertEquals(Duration.seconds(0), child1Y.getCurrentTime());
 370         assertEquals(Status.PAUSED, st.getStatus());
 371         assertEquals(Status.PAUSED, child1X.getStatus());
 372         assertEquals(Status.STOPPED, child1Y.getStatus());
 373         assertEquals(Math.round(TickCalculation.toMillis(100)), xProperty.get());
 374         assertEquals(0, yProperty.get());
 375 
 376         st.play();
 377         assertEquals(Status.RUNNING, st.getStatus());
 378         assertEquals(Status.RUNNING, child1X.getStatus());
 379         assertEquals(Status.STOPPED, child1Y.getStatus());
 380         assertEquals(Math.round(TickCalculation.toMillis(100)), xProperty.get());
 381         assertEquals(0, yProperty.get());
 382 
 383         amt.pulse();
 384         assertEquals(Duration.seconds(0), st.getCurrentTime());
 385         assertEquals(Duration.seconds(0), child1X.getCurrentTime());
 386         assertEquals(Duration.seconds(0), child1Y.getCurrentTime());
 387         assertEquals(Status.STOPPED, st.getStatus());
 388         assertEquals(Status.STOPPED, child1X.getStatus());
 389         assertEquals(Status.STOPPED, child1Y.getStatus());
 390         assertEquals(0, xProperty.get());
 391         assertEquals(0, yProperty.get());
 392     }
 393 
 394     @Test
 395     public void testPauseAndJumpReversed2() {
 396         st.getChildren().addAll(child1X, child1Y);
 397         st.setRate(-1.0);
 398 
 399         st.jumpTo(Duration.seconds(70));
 400         st.play();
 401         amt.pulse();
 402         assertEquals(Status.RUNNING, st.getStatus());
 403         assertEquals(Status.STOPPED, child1X.getStatus());
 404         assertEquals(Status.RUNNING, child1Y.getStatus());
 405         assertEquals(60000, xProperty.get());
 406         assertEquals(10000 - Math.round(TickCalculation.toMillis(100)), yProperty.get());
 407 
 408         st.pause();
 409         st.jumpTo(Duration.seconds(50));
 410         assertEquals(Status.PAUSED, st.getStatus());
 411         assertEquals(Status.PAUSED, child1X.getStatus());
 412         assertEquals(Status.STOPPED, child1Y.getStatus());
 413         assertEquals(Duration.seconds(50), st.getCurrentTime());
 414         assertEquals(50000, xProperty.get());
 415         assertEquals(0, yProperty.get());
 416 
 417         st.play();
 418         amt.pulse();
 419         assertEquals(Status.RUNNING, st.getStatus());
 420         assertEquals(Status.RUNNING, child1X.getStatus());
 421         assertEquals(Status.STOPPED, child1Y.getStatus());
 422         assertEquals(50000 - Math.round(TickCalculation.toMillis(100)), xProperty.get());
 423         assertEquals(0, yProperty.get());
 424 
 425         st.pause();
 426         st.jumpTo(Duration.minutes(1).add(Duration.seconds(5)).add(TickCalculation.toDuration(100)));
 427         assertEquals(Status.PAUSED, st.getStatus());
 428         assertEquals(Status.STOPPED, child1X.getStatus());
 429         assertEquals(Status.PAUSED, child1Y.getStatus());
 430         assertEquals(60000, xProperty.get());
 431         assertEquals(5000 + Math.round(TickCalculation.toMillis(100)), yProperty.get());
 432 
 433         st.play();
 434         amt.pulse();
 435         assertEquals(Status.RUNNING, st.getStatus());
 436         assertEquals(Status.STOPPED, child1X.getStatus());
 437         assertEquals(Status.RUNNING, child1Y.getStatus());
 438         assertEquals(60000, xProperty.get());
 439         assertEquals(5000, yProperty.get());
 440     }
 441 
 442     @Test
 443     public void testPauseAndJumpAutoReverse() {
 444         st.getChildren().addAll(child1X, child1Y);
 445         st.setAutoReverse(true);
 446         st.setCycleCount(2);
 447 
 448         st.jumpTo(Duration.minutes(1).add(Duration.seconds(10)).subtract(TickCalculation.toDuration(100)));
 449         st.play();
 450         assertEquals(Status.RUNNING, st.getStatus());
 451         assertEquals(Status.STOPPED, child1X.getStatus());
 452         assertEquals(Status.RUNNING, child1Y.getStatus());
 453         assertEquals(60000, xProperty.get());
 454         assertEquals(10000 - Math.round(TickCalculation.toMillis(100)), yProperty.get());
 455 
 456         amt.pulse();
 457         assertEquals(Duration.seconds(70), st.getCurrentTime());
 458         assertEquals(Duration.seconds(60), child1X.getCurrentTime());
 459         assertEquals(Duration.seconds(10), child1Y.getCurrentTime());
 460         assertEquals(60000, xProperty.get());
 461         assertEquals(10000, yProperty.get());
 462 
 463         st.pause();
 464         st.jumpTo(Duration.minutes(1).add(Duration.seconds(10)).add(TickCalculation.toDuration(100)));
 465         assertEquals(Status.PAUSED, st.getStatus());
 466         assertEquals(Status.STOPPED, child1X.getStatus());
 467         assertEquals(Status.PAUSED, child1Y.getStatus());
 468         assertEquals(Duration.seconds(70).subtract(TickCalculation.toDuration(100)), st.getCurrentTime());
 469         assertEquals(60000, xProperty.get());
 470         assertEquals(10000 - Math.round(TickCalculation.toMillis(100)), yProperty.get());
 471 
 472         st.play();
 473         amt.pulse();
 474         assertEquals(Status.RUNNING, st.getStatus());
 475         assertEquals(Status.STOPPED, child1X.getStatus());
 476         assertEquals(Status.RUNNING, child1Y.getStatus());
 477         assertEquals(60000, xProperty.get());
 478         assertEquals(10000 - Math.round(TickCalculation.toMillis(2 * 100)), yProperty.get());
 479 
 480         st.pause();
 481         st.jumpTo(Duration.seconds(100));
 482         assertEquals(Duration.seconds(40), st.getCurrentTime());
 483         assertEquals(Duration.seconds(40), child1X.getCurrentTime());
 484         assertEquals(Duration.seconds(0), child1Y.getCurrentTime());
 485         assertEquals(Status.PAUSED, st.getStatus());
 486         assertEquals(Status.PAUSED, child1X.getStatus());
 487         assertEquals(Status.STOPPED, child1Y.getStatus());
 488         assertEquals(40000, xProperty.get());
 489         assertEquals(0, yProperty.get());
 490 
 491         st.play();
 492         amt.pulse();
 493         assertEquals(Status.RUNNING, st.getStatus());
 494         assertEquals(Status.RUNNING, child1X.getStatus());
 495         assertEquals(Status.STOPPED, child1Y.getStatus());
 496         assertEquals(40000  - Math.round(TickCalculation.toMillis(100)), xProperty.get());
 497         assertEquals(0, yProperty.get());
 498 
 499         st.pause();
 500         st.jumpTo(Duration.minutes(2).add(Duration.seconds(20)).subtract(TickCalculation.toDuration(100)));
 501         assertEquals(TickCalculation.toDuration(100), st.getCurrentTime());
 502         assertEquals(TickCalculation.toDuration(100), child1X.getCurrentTime());
 503         assertEquals(Duration.seconds(0), child1Y.getCurrentTime());
 504         assertEquals(Status.PAUSED, st.getStatus());
 505         assertEquals(Status.PAUSED, child1X.getStatus());
 506         assertEquals(Status.STOPPED, child1Y.getStatus());
 507         assertEquals(Math.round(TickCalculation.toMillis(100)), xProperty.get());
 508         assertEquals(0, yProperty.get());
 509 
 510         st.play();
 511         assertEquals(Status.RUNNING, st.getStatus());
 512         assertEquals(Status.RUNNING, child1X.getStatus());
 513         assertEquals(Status.STOPPED, child1Y.getStatus());
 514         assertEquals(Math.round(TickCalculation.toMillis(100)), xProperty.get());
 515         assertEquals(0, yProperty.get());
 516 
 517         amt.pulse();
 518         assertEquals(Duration.seconds(0), st.getCurrentTime());
 519         assertEquals(Duration.seconds(0), child1X.getCurrentTime());
 520         assertEquals(Duration.seconds(0), child1Y.getCurrentTime());
 521         assertEquals(Status.STOPPED, st.getStatus());
 522         assertEquals(Status.STOPPED, child1X.getStatus());
 523         assertEquals(Status.STOPPED, child1Y.getStatus());
 524         assertEquals(0, xProperty.get());
 525         assertEquals(0, yProperty.get());
 526     }
 527 
 528     @Test
 529     public void testJumpAndPlay() {
 530         st.getChildren().addAll(child1X, child1Y);
 531 
 532         st.jumpTo(Duration.seconds(65));
 533         st.play();
 534 
 535         assertEquals(Status.RUNNING, st.getStatus());
 536         assertEquals(Status.STOPPED, child1X.getStatus());
 537         assertEquals(Status.RUNNING, child1Y.getStatus());
 538         assertEquals(60000, xProperty.get());
 539         assertEquals(5000, yProperty.get());
 540 
 541 
 542         amt.pulse();
 543         assertEquals(Status.RUNNING, st.getStatus());
 544         assertEquals(Status.STOPPED, child1X.getStatus());
 545         assertEquals(Status.RUNNING, child1Y.getStatus());
 546         assertEquals(60000, xProperty.get());
 547         assertEquals(5000 + Math.round(TICK_MILLIS), yProperty.get());
 548 
 549     }
 550 
 551     @Test
 552     public void testJumpAndPlayReversed() {
 553         st.getChildren().addAll(child1X, child1Y);
 554         st.setRate(-1.0);
 555 
 556         st.jumpTo(Duration.seconds(65));
 557         st.play();
 558 
 559         assertEquals(Status.RUNNING, st.getStatus());
 560         assertEquals(Status.STOPPED, child1X.getStatus());
 561         assertEquals(Status.RUNNING, child1Y.getStatus());
 562         assertEquals(60000, xProperty.get());
 563         assertEquals(5000, yProperty.get());
 564 
 565 
 566         amt.pulse();
 567         assertEquals(Status.RUNNING, st.getStatus());
 568         assertEquals(Status.STOPPED, child1X.getStatus());
 569         assertEquals(Status.RUNNING, child1Y.getStatus());
 570         assertEquals(60000, xProperty.get());
 571         assertEquals(5000 - Math.round(TICK_MILLIS), yProperty.get());
 572 
 573     }
 574 
 575 
 576     @Test
 577     public void testCycle() {
 578         st.getChildren().addAll(child1X, child1Y);
 579         st.setCycleCount(2);
 580 
 581         st.play();
 582 
 583         assertEquals(Status.RUNNING, st.getStatus());
 584         assertEquals(Status.STOPPED, child1X.getStatus());
 585         assertEquals(Status.STOPPED, child1Y.getStatus());
 586         assertEquals(0, xProperty.get());
 587         assertEquals(0, yProperty.get());
 588 
 589         st.jumpTo(Duration.minutes(1).add(Duration.seconds(10)).subtract(TickCalculation.toDuration(100)));
 590 
 591         assertEquals(Status.RUNNING, st.getStatus());
 592         assertEquals(Status.STOPPED, child1X.getStatus());
 593         assertEquals(Status.RUNNING, child1Y.getStatus());
 594         assertEquals(60000, xProperty.get());
 595         assertEquals(10000 - Math.round(TICK_MILLIS), yProperty.get());
 596 
 597         amt.pulse();
 598 
 599         assertEquals(Status.RUNNING, st.getStatus());
 600         assertEquals(Status.RUNNING, child1X.getStatus());
 601         assertEquals(Status.STOPPED, child1Y.getStatus());
 602         assertEquals(0, xProperty.get());
 603         assertEquals(0, yProperty.get());
 604 
 605         amt.pulse();
 606 
 607         assertEquals(TickCalculation.toDuration(100), st.getCurrentTime());
 608         assertEquals(TickCalculation.toDuration(100), child1X.getCurrentTime());
 609         assertEquals(Duration.ZERO, child1Y.getCurrentTime());
 610         assertEquals(Math.round(TICK_MILLIS), xProperty.get());
 611         assertEquals(0, yProperty.get());
 612 
 613         st.jumpTo(Duration.minutes(2).add(Duration.seconds(20)).subtract(TickCalculation.toDuration(100)));
 614 
 615         assertEquals(Status.RUNNING, st.getStatus());
 616         assertEquals(Status.STOPPED, child1X.getStatus());
 617         assertEquals(Status.RUNNING, child1Y.getStatus());
 618         assertEquals(60000, xProperty.get());
 619         assertEquals(10000 - Math.round(TICK_MILLIS), yProperty.get());
 620 
 621         amt.pulse();
 622 
 623         assertEquals(Status.STOPPED, st.getStatus());
 624         assertEquals(Status.STOPPED, child1X.getStatus());
 625         assertEquals(Status.STOPPED, child1Y.getStatus());
 626         assertEquals(60000, xProperty.get());
 627         assertEquals(10000, yProperty.get());
 628 
 629     }
 630 
 631     @Test
 632     public void testCycleReverse() {
 633         st.getChildren().addAll(child1X, child1Y);
 634         st.setCycleCount(-1);
 635         st.setRate(-1.0);
 636 
 637         st.play();
 638 
 639         assertEquals(Status.RUNNING, st.getStatus());
 640         assertEquals(Status.RUNNING, child1X.getStatus());
 641         assertEquals(Status.STOPPED, child1Y.getStatus());
 642         assertEquals(0, xProperty.get());
 643         assertEquals(0, yProperty.get());
 644 
 645         st.jumpTo(TickCalculation.toDuration(100));
 646 
 647         assertEquals(Status.RUNNING, st.getStatus());
 648         assertEquals(Status.RUNNING, child1X.getStatus());
 649         assertEquals(Status.STOPPED, child1Y.getStatus());
 650         assertEquals(Math.round(TICK_MILLIS), xProperty.get());
 651         assertEquals(0, yProperty.get());
 652 
 653         amt.pulse();
 654 
 655         assertEquals(Status.RUNNING, st.getStatus());
 656         assertEquals(Status.STOPPED, child1X.getStatus());
 657         assertEquals(Status.RUNNING, child1Y.getStatus());
 658         assertEquals(60000, xProperty.get());
 659         assertEquals(10000, yProperty.get());
 660 
 661         amt.pulse();
 662 
 663         assertEquals(Status.RUNNING, st.getStatus());
 664         assertEquals(Status.STOPPED, child1X.getStatus());
 665         assertEquals(Status.RUNNING, child1Y.getStatus());
 666         assertEquals(60000, xProperty.get());
 667         assertEquals(10000 - Math.round(TICK_MILLIS), yProperty.get());
 668 
 669         st.jumpTo(Duration.minutes(1).add(Duration.seconds(10)).subtract(TickCalculation.toDuration(100)));
 670 
 671         assertEquals(Status.RUNNING, st.getStatus());
 672         assertEquals(Status.STOPPED, child1X.getStatus());
 673         assertEquals(Status.RUNNING, child1Y.getStatus());
 674         assertEquals(60000, xProperty.get());
 675         assertEquals(10000 - Math.round(TICK_MILLIS), yProperty.get());
 676 
 677         amt.pulse();
 678 
 679         assertEquals(Status.RUNNING, st.getStatus());
 680         assertEquals(Status.STOPPED, child1X.getStatus());
 681         assertEquals(Status.RUNNING, child1Y.getStatus());
 682         assertEquals(60000, xProperty.get());
 683         assertEquals(10000 - Math.round(TickCalculation.toMillis(200)), yProperty.get());
 684 
 685     }
 686 
 687     @Test
 688     public void testJump() {
 689         st.getChildren().addAll(child1X, child1Y);
 690 
 691         assertEquals(Status.STOPPED, st.getStatus());
 692         assertEquals(Status.STOPPED, child1X.getStatus());
 693         assertEquals(Status.STOPPED, child1Y.getStatus());
 694         assertEquals(0, xProperty.get());
 695         assertEquals(0, yProperty.get());
 696 
 697         st.jumpTo(Duration.seconds(10));
 698 
 699         assertEquals(Status.STOPPED, st.getStatus());
 700         assertEquals(Status.STOPPED, child1X.getStatus());
 701         assertEquals(Status.STOPPED, child1Y.getStatus());
 702         assertEquals(0, xProperty.get());
 703         assertEquals(0, yProperty.get());
 704 
 705         st.play();
 706 
 707         assertEquals(Status.RUNNING, st.getStatus());
 708         assertEquals(Status.RUNNING, child1X.getStatus());  //Note: Not sure if we need to have also child1X running at this point
 709         assertEquals(Status.STOPPED, child1Y.getStatus());
 710         assertEquals(10000, xProperty.get());
 711         assertEquals(0, yProperty.get());
 712 
 713         amt.pulse();
 714 
 715         assertEquals(Status.RUNNING, st.getStatus());
 716         assertEquals(Status.RUNNING, child1X.getStatus());
 717         assertEquals(Status.STOPPED, child1Y.getStatus());
 718         assertEquals(10000 + Math.round(TICK_MILLIS), xProperty.get());
 719         assertEquals(0, yProperty.get());
 720 
 721         st.jumpTo(Duration.seconds(65));
 722 
 723         assertEquals(Status.RUNNING, st.getStatus());
 724         assertEquals(Status.STOPPED, child1X.getStatus());
 725         assertEquals(Status.RUNNING, child1Y.getStatus());
 726         assertEquals(60000, xProperty.get());
 727         assertEquals(5000, yProperty.get());
 728 
 729         st.jumpTo(Duration.seconds(10));
 730 
 731         assertEquals(Status.RUNNING, st.getStatus());
 732         assertEquals(Status.RUNNING, child1X.getStatus());
 733         assertEquals(Status.STOPPED, child1Y.getStatus());
 734         assertEquals(10000, xProperty.get());
 735         assertEquals(0, yProperty.get());
 736 
 737         st.stop();
 738 
 739         assertEquals(Status.STOPPED, st.getStatus());
 740         assertEquals(Status.STOPPED, child1X.getStatus());
 741         assertEquals(Status.STOPPED, child1Y.getStatus());
 742         assertEquals(10000, xProperty.get());
 743         assertEquals(0, yProperty.get());
 744 
 745     }
 746 
 747     @Test
 748     public void testAutoReverse() {
 749         st.getChildren().addAll(child1X, child1Y);
 750         st.setAutoReverse(true);
 751         st.setCycleCount(-1);
 752 
 753         st.play();
 754 
 755         for (int i = 0; i < TickCalculation.fromDuration(Duration.seconds(70)) / 100 - 1; ++i) {
 756             amt.pulse();
 757         }
 758 
 759         amt.pulse();
 760 
 761         assertEquals(Status.RUNNING, st.getStatus());
 762         assertEquals(Status.STOPPED, child1X.getStatus());
 763         assertEquals(Status.STOPPED, child1Y.getStatus());
 764 
 765         assertEquals(60000, xProperty.get());
 766         assertEquals(10000, yProperty.get());
 767 
 768         amt.pulse();
 769 
 770         assertEquals(Status.RUNNING, st.getStatus());
 771         assertEquals(Status.STOPPED, child1X.getStatus());
 772         assertEquals(Status.RUNNING, child1Y.getStatus());
 773 
 774         assertEquals(60000, xProperty.get());
 775         assertEquals(10000 - Math.round(TICK_MILLIS), yProperty.get());
 776 
 777     }
 778 
 779     @Test
 780     public void testAutoReverseWithJump() {
 781         st.getChildren().addAll(child1X, child1Y);
 782         st.setAutoReverse(true);
 783         st.setCycleCount(-1);
 784 
 785         st.play();
 786 
 787         st.jumpTo(Duration.seconds(70).subtract(TickCalculation.toDuration(100)));
 788 
 789         amt.pulse();
 790 
 791         assertEquals(Status.RUNNING, st.getStatus());
 792         assertEquals(Status.STOPPED, child1X.getStatus());
 793         assertEquals(Status.STOPPED, child1Y.getStatus());
 794 
 795         assertEquals(60000, xProperty.get());
 796         assertEquals(10000, yProperty.get());
 797 
 798         amt.pulse();
 799 
 800         assertEquals(Status.RUNNING, st.getStatus());
 801         assertEquals(Status.STOPPED, child1X.getStatus());
 802         assertEquals(Status.RUNNING, child1Y.getStatus());
 803 
 804         assertEquals(60000, xProperty.get());
 805         assertEquals(10000 - Math.round(TICK_MILLIS), yProperty.get());
 806 
 807     }
 808 
 809     @Test
 810     public void testChildWithDifferentRate() {
 811         st.getChildren().addAll(child1X, child1Y);
 812         child1X.setRate(2.0);
 813 
 814         st.play();
 815 
 816         amt.pulse();
 817 
 818         assertEquals(Math.round(TICK_MILLIS * 2), xProperty.get());
 819 
 820         st.jumpTo(Duration.seconds(30));
 821 
 822         assertEquals(60000, xProperty.get());
 823         assertEquals(0, yProperty.get());
 824 
 825         st.jumpTo(Duration.seconds(40));
 826 
 827         assertEquals(60000, xProperty.get());
 828         assertEquals(10000, yProperty.get());
 829 
 830 
 831         st.jumpTo(Duration.seconds(5));
 832         amt.pulse();
 833 
 834         st.setRate(-1.0);
 835 
 836         amt.pulse();
 837         amt.pulse();
 838 
 839         assertEquals(10000 - Math.round(TICK_MILLIS * 2), xProperty.get());
 840         assertEquals(0, yProperty.get());
 841 
 842         st.setRate(1.0);
 843 
 844         amt.pulse();
 845         amt.pulse();
 846 
 847         assertEquals(10000 + Math.round(TICK_MILLIS * 2), xProperty.get());
 848         assertEquals(0, yProperty.get());
 849 
 850     }
 851 
 852     @Test
 853     public void testToggleRate() {
 854         st.getChildren().addAll(child1X, child1Y);
 855 
 856         st.play();
 857 
 858         st.jumpTo(Duration.seconds(60));
 859 
 860         amt.pulse();
 861 
 862         assertEquals(Status.RUNNING, st.getStatus());
 863         assertEquals(Status.STOPPED, child1X.getStatus());
 864         assertEquals(Status.RUNNING, child1Y.getStatus());
 865 
 866         assertEquals(60000, xProperty.get());
 867         assertEquals(Math.round(TICK_MILLIS), yProperty.get());
 868 
 869         st.setRate(-1.0);
 870 
 871         amt.pulse();
 872         amt.pulse();
 873 
 874         assertEquals(Status.RUNNING, st.getStatus());
 875         assertEquals(Status.RUNNING, child1X.getStatus());
 876         assertEquals(Status.STOPPED, child1Y.getStatus());
 877 
 878         assertEquals(60000 - Math.round(TICK_MILLIS), xProperty.get());
 879         assertEquals(0, yProperty.get());
 880 
 881         st.setRate(1.0);
 882 
 883         amt.pulse();
 884         amt.pulse();
 885 
 886         assertEquals(Status.RUNNING, st.getStatus());
 887         assertEquals(Status.STOPPED, child1X.getStatus());
 888         assertEquals(Status.RUNNING, child1Y.getStatus());
 889 
 890         assertEquals(60000, xProperty.get());
 891         assertEquals(Math.round(TICK_MILLIS), yProperty.get());
 892 
 893     }
 894 
 895     @Test
 896     public void testToggleRate_2() {
 897         st.getChildren().addAll(child1X, child1Y);
 898 
 899         st.play();
 900 
 901         st.jumpTo(Duration.seconds(10));
 902 
 903         amt.pulse();
 904 
 905         assertEquals(Status.RUNNING, st.getStatus());
 906         assertEquals(Status.RUNNING, child1X.getStatus());
 907         assertEquals(Status.STOPPED, child1Y.getStatus());
 908 
 909         assertEquals(10000 + Math.round(TICK_MILLIS), xProperty.get());
 910         assertEquals(0, yProperty.get());
 911 
 912         st.setRate(-1.0);
 913 
 914         amt.pulse();
 915         amt.pulse();
 916 
 917         assertEquals(Status.RUNNING, st.getStatus());
 918         assertEquals(Status.RUNNING, child1X.getStatus());
 919         assertEquals(Status.STOPPED, child1Y.getStatus());
 920 
 921         assertEquals(10000 - Math.round(TICK_MILLIS), xProperty.get());
 922         assertEquals(0, yProperty.get());
 923 
 924         st.setRate(1.0);
 925 
 926         amt.pulse();
 927         amt.pulse();
 928 
 929         assertEquals(Status.RUNNING, st.getStatus());
 930         assertEquals(Status.RUNNING, child1X.getStatus());
 931         assertEquals(Status.STOPPED, child1Y.getStatus());
 932 
 933         assertEquals(10000 + Math.round(TICK_MILLIS), xProperty.get());
 934         assertEquals(0, yProperty.get());
 935 
 936     }
 937 
 938     @Test
 939     public void testPlayFromStartSynchronization() {
 940         st.getChildren().addAll(child1Y, childByX);
 941 
 942         st.play();
 943 
 944         assertEquals(0, yProperty.get());
 945         assertEquals(0, xProperty.get());
 946 
 947         st.jumpTo(Duration.seconds(11));
 948         amt.pulse();
 949 
 950         st.play();
 951         assertEquals(0, yProperty.get());
 952         assertEquals(1000, xProperty.get());
 953 
 954         st.jumpTo(Duration.seconds(11));
 955         amt.pulse();
 956 
 957 
 958         assertEquals(10000, yProperty.get());
 959         assertEquals(2000, xProperty.get());
 960 
 961     }
 962 
 963     @Test
 964     public void testCycleSynchronization() {
 965         st.getChildren().addAll(childByX, childByX2);
 966 
 967         st.play();
 968 
 969         assertEquals(0, xProperty.get());
 970 
 971         st.jumpTo(Duration.seconds(11));
 972         amt.pulse();
 973 
 974         st.play();
 975         assertEquals(2000, xProperty.get());
 976 
 977         st.jumpTo(Duration.seconds(11));
 978         amt.pulse();
 979 
 980         assertEquals(4000, xProperty.get());
 981 
 982     }
 983 
 984     @Test
 985     public void testJumpToDelay() {
 986         child1X.setDelay(Duration.seconds(2));
 987         st.getChildren().addAll(child1X);
 988 
 989         st.jumpTo(Duration.seconds(2).subtract(TickCalculation.toDuration(100)));
 990         st.play();
 991 
 992         assertEquals(Status.RUNNING, st.getStatus());
 993         assertEquals(Status.STOPPED, child1X.getStatus());
 994 
 995         amt.pulse(); amt.pulse();
 996 
 997         assertEquals(Math.round(TICK_MILLIS), xProperty.get(), 1e-10);
 998     }
 999 
1000     @Test
1001     public void testJumpToSecondDelay() {
1002         child1Y.setDelay(Duration.seconds(2));
1003         st.getChildren().addAll(child1X, child1Y);
1004 
1005         st.jumpTo(Duration.seconds(62).subtract(TickCalculation.toDuration(100)));
1006         st.play();
1007 
1008         assertEquals(Status.RUNNING, st.getStatus());
1009         assertEquals(Status.STOPPED, child1X.getStatus());
1010         assertEquals(Status.STOPPED, child1Y.getStatus());
1011 
1012         amt.pulse(); amt.pulse();
1013 
1014         assertEquals(Math.round(TICK_MILLIS), yProperty.get(), 1e-10);
1015     }
1016 
1017 }