# Copyright 2016 Google Inc. All Rights Reserved. # # 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. """Fake time, for testing.""" import six class FakeTime(object): """Fake time, for testing.""" def __init__(self, chronology): """The chronology is a generator that updates the world. Yield how many seconds of fake time elapse. Think of each yield as a "sleep". We read the very first value immediately, so that the world can be initialized in the chronology. Args: chronology: a generator that updates the state of the world and then sleeps via yielding. """ self._chronology = chronology # current fake time self._now = 0 # time at which to wake up the chronology self._next = six.advance_iterator(self._chronology) def sleep(self, seconds): """Sleep for this many fictitious seconds. The world will update accordingly. Args: seconds: how many seconds to pretend sleep for. Raises: IOError: for negative delays (matches time.sleep). BaseException: at the end of times, to detect infinite loop bugs and the like. """ if seconds < 0: # Chosen to match the behavior of time.sleep. raise IOError("Invalid argument") target = self._now + seconds if target < self._next: self._now = target return self._now = target for step in self._chronology: self._next += step if self._next > target: return raise BaseException("end of times") def now(self): """Returns the current fake time.""" return self._now