• 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 
elapsed(&self) -> Duration28     pub fn elapsed(&self) -> Duration {
29         self.0.elapsed()
30     }
31 
checked_sub(&self, duration: Duration) -> Option<Self>32     pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
33         Some(Clock(self.0.checked_sub(duration)?))
34     }
35 }
36 
37 impl Default for Clock {
default() -> Self38     fn default() -> Self {
39         Self::new()
40     }
41 }
42 
43 const NS_PER_SEC: u64 = 1_000_000_000;
44 /// A fake clock that can be used in tests to give exact control over the time.
45 /// For a code example, see the tests in sys_util/src/timerfd.rs.
46 #[derive(Debug)]
47 pub struct FakeClock {
48     ns_since_epoch: u64,
49     deadlines: Vec<(u64, EventFd)>,
50 }
51 
52 impl FakeClock {
new() -> Self53     pub fn new() -> Self {
54         FakeClock {
55             ns_since_epoch: 1_547_163_599 * NS_PER_SEC,
56             deadlines: Vec::new(),
57         }
58     }
59 
60     /// Get the current time, according to this clock.
now(&self) -> Self61     pub fn now(&self) -> Self {
62         FakeClock {
63             ns_since_epoch: self.ns_since_epoch,
64             deadlines: Vec::new(),
65         }
66     }
67 
68     ///  Get the current time in ns, according to this clock.
nanos(&self) -> u6469     pub fn nanos(&self) -> u64 {
70         self.ns_since_epoch
71     }
72 
73     /// Get the duration since |earlier|, assuming that earlier < self.
duration_since(&self, earlier: &Self) -> Duration74     pub fn duration_since(&self, earlier: &Self) -> Duration {
75         let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch;
76         Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32)
77     }
78 
79     /// Get the time that has elapsed since this clock was made. Always returns 0 on a FakeClock.
elapsed(&self) -> Duration80     pub fn elapsed(&self) -> Duration {
81         self.now().duration_since(self)
82     }
83 
checked_sub(&self, duration: Duration) -> Option<Self>84     pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
85         Some(FakeClock {
86             ns_since_epoch: self
87                 .ns_since_epoch
88                 .checked_sub(duration.as_nanos() as u64)?,
89             deadlines: Vec::new(),
90         })
91     }
92 
93     /// Register the event fd for a notification when self's time is |deadline_ns|.
94     /// Drop any existing events registered to the same raw fd.
add_event_fd(&mut self, deadline_ns: u64, fd: EventFd)95     pub fn add_event_fd(&mut self, deadline_ns: u64, fd: EventFd) {
96         self.deadlines
97             .retain(|(_, old_fd)| fd.as_raw_fd() != old_fd.as_raw_fd());
98         self.deadlines.push((deadline_ns, fd));
99     }
100 
add_ns(&mut self, ns: u64)101     pub fn add_ns(&mut self, ns: u64) {
102         self.ns_since_epoch += ns;
103         let time = self.ns_since_epoch;
104         self.deadlines.retain(|(ns, fd)| {
105             let expired = *ns <= time;
106             if expired {
107                 fd.write(1).unwrap();
108             }
109             !expired
110         });
111     }
112 }
113 
114 impl Default for FakeClock {
default() -> Self115     fn default() -> Self {
116         Self::new()
117     }
118 }
119