• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Utility file to provide a fake clock object representing current time, and a timerfd driven by
6 // that time.
7 
8 use std::os::unix::io::AsRawFd;
9 use std::time::{Duration, Instant};
10 
11 use crate::EventFd;
12 
13 #[derive(Debug, Copy, Clone)]
14 pub struct Clock(Instant);
15 impl Clock {
new() -> Self16     pub fn new() -> Self {
17         Clock(Instant::now())
18     }
19 
now(&self) -> Self20     pub fn now(&self) -> Self {
21         Clock(Instant::now())
22     }
23 
duration_since(&self, earlier: &Self) -> Duration24     pub fn duration_since(&self, earlier: &Self) -> Duration {
25         self.0.duration_since(earlier.0)
26     }
27 }
28 
29 impl Default for Clock {
default() -> Self30     fn default() -> Self {
31         Self::new()
32     }
33 }
34 
35 const NS_PER_SEC: u64 = 1_000_000_000;
36 /// A fake clock that can be used in tests to give exact control over the time.
37 /// For a code example, see the tests in sys_util/src/timerfd.rs.
38 #[derive(Debug)]
39 pub struct FakeClock {
40     ns_since_epoch: u64,
41     deadlines: Vec<(u64, EventFd)>,
42 }
43 
44 impl FakeClock {
new() -> Self45     pub fn new() -> Self {
46         FakeClock {
47             ns_since_epoch: 1_547_163_599 * NS_PER_SEC,
48             deadlines: Vec::new(),
49         }
50     }
51 
52     /// Get the current time, according to this clock.
now(&self) -> Self53     pub fn now(&self) -> Self {
54         FakeClock {
55             ns_since_epoch: self.ns_since_epoch,
56             deadlines: Vec::new(),
57         }
58     }
59 
60     ///  Get the current time in ns, according to this clock.
nanos(&self) -> u6461     pub fn nanos(&self) -> u64 {
62         self.ns_since_epoch
63     }
64 
65     /// Get the duration since |earlier|, assuming that earlier < self.
duration_since(&self, earlier: &Self) -> Duration66     pub fn duration_since(&self, earlier: &Self) -> Duration {
67         let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch;
68         Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32)
69     }
70 
71     /// Register the event fd for a notification when self's time is |deadline_ns|.
72     /// Drop any existing events registered to the same raw fd.
add_event_fd(&mut self, deadline_ns: u64, fd: EventFd)73     pub fn add_event_fd(&mut self, deadline_ns: u64, fd: EventFd) {
74         self.deadlines
75             .retain(|(_, old_fd)| fd.as_raw_fd() != old_fd.as_raw_fd());
76         self.deadlines.push((deadline_ns, fd));
77     }
78 
add_ns(&mut self, ns: u64)79     pub fn add_ns(&mut self, ns: u64) {
80         self.ns_since_epoch += ns;
81         let time = self.ns_since_epoch;
82         self.deadlines.retain(|(ns, fd)| {
83             let expired = *ns <= time;
84             if expired {
85                 fd.write(1).unwrap();
86             }
87             !expired
88         });
89     }
90 }
91 
92 impl Default for FakeClock {
default() -> Self93     fn default() -> Self {
94         Self::new()
95     }
96 }
97