View Javadoc
1   /*
2    * Copyright 2018 SPF4J.
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  package org.spf4j.base;
17  
18  import com.google.common.annotations.Beta;
19  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
20  import gnu.trove.iterator.TLongIterator;
21  import gnu.trove.list.array.TLongArrayList;
22  import java.util.function.LongSupplier;
23  import javax.annotation.Nonnull;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  /**
28   * @author Zoltan Farkas
29   */
30  @Beta
31  public final class TestTimeSource implements LongSupplier {
32  
33    private static final Logger LOG = LoggerFactory.getLogger(TestTimeSource.class);
34  
35    public static final TLongIterator SYSTEM_NANO_TIME_STREAM = new TLongIterator() {
36      @Override
37      public long next() {
38        return System.nanoTime();
39      }
40  
41      @Override
42      public boolean hasNext() {
43        return true;
44      }
45  
46      @Override
47      public void remove() {
48        throw new UnsupportedOperationException();
49      }
50    };
51  
52    private static volatile TLongIterator timeStream = SYSTEM_NANO_TIME_STREAM;
53  
54    public static void clear() {
55      timeStream = SYSTEM_NANO_TIME_STREAM;
56    }
57  
58    public static void setTimeStream(final TLongIterator stream) {
59      timeStream = stream;
60    }
61  
62    public static void setTimeStream(final long... times) {
63      timeStream = new TLongArrayList(times).iterator();
64    }
65  
66    public static long freezeTime() {
67      long nanoTime = TimeSource.nanoTime();
68      setTimeStream(new TLongIterator() {
69        @Override
70        public long next() {
71          return nanoTime;
72        }
73  
74        @Override
75        public boolean hasNext() {
76          return true;
77        }
78  
79        @Override
80        public void remove() {
81          throw new UnsupportedOperationException();
82        }
83      });
84      return nanoTime;
85    }
86  
87  
88    @Override
89    @Nonnull
90    @SuppressFBWarnings("CLI_CONSTANT_LIST_INDEX")
91    public long getAsLong() {
92      long nextTime;
93      if (timeStream.hasNext()) {
94        nextTime = timeStream.next();
95      } else {
96        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
97        throw new AssertionError("End of time reached at "
98                + (stackTrace.length > 2 ? stackTrace[2] : "unknown"));
99      }
100     if (LOG.isTraceEnabled()) {
101       StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
102       LOG.trace("nanoTime = {} at {}", nextTime, stackTrace.length > 2 ? stackTrace[2] : "unknown");
103     }
104     return nextTime;
105   }
106 
107 }