// Copyright 2010 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.android.stardroid.test.control; import com.google.android.stardroid.control.Clock; import com.google.android.stardroid.control.TimeTravelClock; import com.google.android.stardroid.control.TransitioningCompositeClock; import junit.framework.TestCase; import java.util.Date; /** * Tests for the {@link TransitioningCompositeClock}. * * @author John Taylor */ public class TransitioningCompositeClockTest extends TestCase { /** * A fake clock for which we can set the time. * * @author John Taylor */ private static class FakeClock implements Clock { private long time; @Override public long getTimeInMillisSinceEpoch() { return time; } public void setTimeInMillisSinceEpoch(long time) { this.time = time; } public void advanceTimeByMillis(long deltaTime) { time += deltaTime; } } public void testInterpolant() { double tol = 1e-3; assertEquals(0, TransitioningCompositeClock.interpolate(0, 10, 0), tol); assertEquals(1, TransitioningCompositeClock.interpolate(1, 10, 0), tol); assertEquals(10, TransitioningCompositeClock.interpolate(0, 10, 1), tol); assertEquals(5, TransitioningCompositeClock.interpolate(0, 10, 0.5), tol); // Test derivatives double epsilon = 1e-4; double dydx0 = (TransitioningCompositeClock.interpolate(0, 1, epsilon) - TransitioningCompositeClock.interpolate(0, 1, 0)) / epsilon; assertEquals(0.0, dydx0, tol); double dydx1 = (TransitioningCompositeClock.interpolate(0, 1, 1) - TransitioningCompositeClock.interpolate(0, 1, 1 - epsilon)) / epsilon; assertEquals(0.0, dydx1, tol); } public void testTransition() { TimeTravelClock timeTravelClock = new TimeTravelClock(); FakeClock fakeClock = new FakeClock(); TransitioningCompositeClock transitioningClock = new TransitioningCompositeClock( timeTravelClock, fakeClock); fakeClock.setTimeInMillisSinceEpoch(1000); // Transitioning clock starts in real time assertEquals(1000, transitioningClock.getTimeInMillisSinceEpoch()); fakeClock.setTimeInMillisSinceEpoch(2000); assertEquals(2000, transitioningClock.getTimeInMillisSinceEpoch()); Date timeTravelDate = new Date(5000); transitioningClock.goTimeTravel(timeTravelDate); // We shouldn't have budged assertEquals(2000, transitioningClock.getTimeInMillisSinceEpoch()); fakeClock.advanceTimeByMillis(TransitioningCompositeClock.TRANSITION_TIME_MILLIS / 2); // Half way there assertEquals(3500, transitioningClock.getTimeInMillisSinceEpoch()); fakeClock.advanceTimeByMillis(TransitioningCompositeClock.TRANSITION_TIME_MILLIS / 2); // All the way there assertEquals(5000, transitioningClock.getTimeInMillisSinceEpoch()); // Where we stay... fakeClock.advanceTimeByMillis(1000); assertEquals(5000, transitioningClock.getTimeInMillisSinceEpoch()); transitioningClock.returnToRealTime(); long destinationTime = fakeClock.getTimeInMillisSinceEpoch() + TransitioningCompositeClock.TRANSITION_TIME_MILLIS; // Shouldn't have moved yet assertEquals(5000, transitioningClock.getTimeInMillisSinceEpoch()); fakeClock.advanceTimeByMillis(TransitioningCompositeClock.TRANSITION_TIME_MILLIS / 2); // Half way there assertEquals((5000 + destinationTime) / 2, transitioningClock.getTimeInMillisSinceEpoch()); fakeClock.advanceTimeByMillis(TransitioningCompositeClock.TRANSITION_TIME_MILLIS / 2); // All the way there assertEquals(destinationTime, transitioningClock.getTimeInMillisSinceEpoch()); fakeClock.advanceTimeByMillis(1000); // Continue to advance in real time. assertEquals(fakeClock.getTimeInMillisSinceEpoch(), transitioningClock.getTimeInMillisSinceEpoch()); } }