diff options
author | Miriam Zimmerman <mutexlox@google.com> | 2019-01-15 16:22:07 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-01-24 00:51:49 -0800 |
commit | d3144f7a52608d5295dd5bf8edc4f3d76ae4ad82 (patch) | |
tree | 9003b21dca3304b4663d73c288fb8b180eff151a /sys_util/src/clock.rs | |
parent | 39f93db2a4434d7c4126005024cc2f085af3bb43 (diff) | |
download | crosvm-d3144f7a52608d5295dd5bf8edc4f3d76ae4ad82.tar crosvm-d3144f7a52608d5295dd5bf8edc4f3d76ae4ad82.tar.gz crosvm-d3144f7a52608d5295dd5bf8edc4f3d76ae4ad82.tar.bz2 crosvm-d3144f7a52608d5295dd5bf8edc4f3d76ae4ad82.tar.lz crosvm-d3144f7a52608d5295dd5bf8edc4f3d76ae4ad82.tar.xz crosvm-d3144f7a52608d5295dd5bf8edc4f3d76ae4ad82.tar.zst crosvm-d3144f7a52608d5295dd5bf8edc4f3d76ae4ad82.zip |
Add FakeClock and FakeTimerFd for use in tests.
Together, these allow tests to create a FakeTimerFd that they can trigger at a particular point in the test code, without having to rely on sleep()s or other racy methods. BUG=None TEST=Unit tests for FakeTimerFd + dependent CL. Change-Id: I14381272a6d75bebcdedb0a329a017a2131a3482 Reviewed-on: https://chromium-review.googlesource.com/1413830 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Tested-by: Miriam Zimmerman <mutexlox@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: David Tolnay <dtolnay@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'sys_util/src/clock.rs')
-rw-r--r-- | sys_util/src/clock.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/sys_util/src/clock.rs b/sys_util/src/clock.rs new file mode 100644 index 0000000..5f6ce0c --- /dev/null +++ b/sys_util/src/clock.rs @@ -0,0 +1,84 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Utility file to provide a fake clock object representing current time, and a timerfd driven by +// that time. + +use std::time::{Duration, Instant}; +use std::os::unix::io::AsRawFd; +use EventFd; + +#[derive(Debug, Copy, Clone)] +pub struct Clock(Instant); +impl Clock { + pub fn new() -> Self { + Clock(Instant::now()) + } + + pub fn now(&self) -> Self { + Clock(Instant::now()) + } + + pub fn duration_since(&self, earlier: &Self) -> Duration { + self.0.duration_since(earlier.0) + } +} + +const NS_PER_SEC : u64 = 1_000_000_000; +/// A fake clock that can be used in tests to give exact control over the time. +/// For a code example, see the tests in sys_util/src/timerfd.rs. +#[derive(Debug)] +pub struct FakeClock { + ns_since_epoch: u64, + deadlines: Vec<(u64, EventFd)>, +} + +impl FakeClock { + pub fn new() -> Self { + FakeClock { + ns_since_epoch: 1547163599 * NS_PER_SEC, + deadlines: Vec::new(), + } + } + + /// Get the current time, according to this clock. + pub fn now(&self) -> Self { + FakeClock { + ns_since_epoch: self.ns_since_epoch, + deadlines: Vec::new(), + } + } + + /// Get the current time in ns, according to this clock. + pub fn nanos(&self) -> u64 { + self.ns_since_epoch + } + + /// Get the duration since |earlier|, assuming that earlier < self. + pub fn duration_since(&self, earlier: &Self) -> Duration { + let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch; + Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32) + } + + /// Register the event fd for a notification when self's time is |deadline_ns|. + /// Drop any existing events registered to the same raw fd. + pub fn add_event_fd(&mut self, deadline_ns: u64, fd: EventFd) { + self.deadlines.retain(|&(_, ref old_fd)| { + fd.as_raw_fd() != old_fd.as_raw_fd() + }); + self.deadlines.push((deadline_ns, fd)); + } + + pub fn add_ns(&mut self, ns: u64) { + self.ns_since_epoch += ns; + let time = self.ns_since_epoch; + self.deadlines.retain(|&(ns, ref fd)| { + let expired = ns <= time; + if expired { + fd.write(1).unwrap(); + } + !expired + }); + } +} |