1 /* 2 * Copyright 2017, OpenCensus Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.opencensus.testing.common; 18 19 import com.google.common.math.LongMath; 20 import io.opencensus.common.Clock; 21 import io.opencensus.common.Duration; 22 import io.opencensus.common.Timestamp; 23 import javax.annotation.concurrent.GuardedBy; 24 import javax.annotation.concurrent.ThreadSafe; 25 26 /** 27 * A {@link Clock} that allows the time to be set for testing. 28 * 29 * @since 0.5 30 */ 31 @ThreadSafe 32 public final class TestClock extends Clock { 33 private static final int NUM_NANOS_PER_SECOND = 1000 * 1000 * 1000; 34 35 @GuardedBy("this") 36 private Timestamp currentTime = validateNanos(Timestamp.create(1493419949, 223123456)); 37 TestClock()38 private TestClock() {} 39 40 /** 41 * Creates a clock initialized to a constant non-zero time. {@code Timestamp.create(0, 0)} is not 42 * a good default, because it represents an invalid time. 43 * 44 * @return a clock initialized to a constant non-zero time. 45 * @since 0.5 46 */ create()47 public static TestClock create() { 48 return new TestClock(); 49 } 50 51 /** 52 * Creates a clock with the given time. 53 * 54 * @param time the initial time. 55 * @return a new {@code TestClock} with the given time. 56 * @since 0.5 57 */ create(Timestamp time)58 public static TestClock create(Timestamp time) { 59 TestClock clock = new TestClock(); 60 clock.setTime(time); 61 return clock; 62 } 63 64 /** 65 * Sets the time. 66 * 67 * @param time the new time. 68 * @since 0.5 69 */ setTime(Timestamp time)70 public synchronized void setTime(Timestamp time) { 71 currentTime = validateNanos(time); 72 } 73 74 /** 75 * Advances the time by a duration. 76 * 77 * @param duration the increase in time. 78 * @since 0.5 79 */ advanceTime(Duration duration)80 public synchronized void advanceTime(Duration duration) { 81 currentTime = validateNanos(currentTime.addDuration(duration)); 82 } 83 84 @Override now()85 public synchronized Timestamp now() { 86 return currentTime; 87 } 88 89 @Override nowNanos()90 public synchronized long nowNanos() { 91 return getNanos(currentTime); 92 } 93 validateNanos(Timestamp time)94 private static Timestamp validateNanos(Timestamp time) { 95 getNanos(time); 96 return time; 97 } 98 99 // Converts Timestamp into nanoseconds since time 0 and throws an exception if it overflows. getNanos(Timestamp time)100 private static long getNanos(Timestamp time) { 101 return LongMath.checkedAdd( 102 LongMath.checkedMultiply(time.getSeconds(), NUM_NANOS_PER_SECOND), time.getNanos()); 103 } 104 } 105