• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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 timer driven by
6 // that time.
7 
8 use std::time::{Duration, Instant};
9 
10 use super::Event;
11 use crate::descriptor::AsRawDescriptor;
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/timer.rs.
46 #[derive(Debug)]
47 pub struct FakeClock {
48     ns_since_epoch: u64,
49     deadlines: Vec<(u64, Event)>,
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 descriptor for a notification when self's time is |deadline_ns|.
94     /// Drop any existing events registered to the same raw descriptor.
add_event(&mut self, deadline_ns: u64, descriptor: Event)95     pub fn add_event(&mut self, deadline_ns: u64, descriptor: Event) {
96         self.deadlines.retain(|(_, old_descriptor)| {
97             descriptor.as_raw_descriptor() != old_descriptor.as_raw_descriptor()
98         });
99         self.deadlines.push((deadline_ns, descriptor));
100     }
101 
add_ns(&mut self, ns: u64)102     pub fn add_ns(&mut self, ns: u64) {
103         self.ns_since_epoch += ns;
104         let time = self.ns_since_epoch;
105         self.deadlines.retain(|(ns, descriptor)| {
106             let expired = *ns <= time;
107             if expired {
108                 descriptor.write(1).unwrap();
109             }
110             !expired
111         });
112     }
113 }
114 
115 impl Default for FakeClock {
default() -> Self116     fn default() -> Self {
117         Self::new()
118     }
119 }
120