• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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