// Copyright 2022 The ChromiumOS Authors // 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 timer driven by // that time. use std::time::Duration; use std::time::Instant; use crate::descriptor::AsRawDescriptor; use crate::Event; #[derive(Debug, Default, Copy, Clone)] pub struct Clock {} impl Clock { pub fn new() -> Self { Clock {} } pub fn now(&self) -> Instant { Instant::now() } } /// A fake clock that can be used in tests to give exact control over the time. /// For a code example, see the tests in base/src/timer.rs. #[derive(Debug)] pub struct FakeClock { epoch: Instant, ns_since_epoch: u64, deadlines: Vec<(u64, Event)>, } impl FakeClock { pub fn new() -> Self { FakeClock { epoch: Instant::now(), ns_since_epoch: 0, deadlines: Vec::new(), } } /// Get the current time, according to this clock. pub fn now(&self) -> Instant { self.epoch + Duration::from_nanos(self.ns_since_epoch) } /// Get the current time in ns, according to this clock. pub fn nanos(&self) -> u64 { self.ns_since_epoch } /// Register the event descriptor for a notification when self's time is |deadline_ns|. /// Drop any existing events registered to the same raw descriptor. pub fn add_event(&mut self, deadline_ns: u64, descriptor: Event) { self.deadlines.retain(|(_, old_descriptor)| { descriptor.as_raw_descriptor() != old_descriptor.as_raw_descriptor() }); self.deadlines.push((deadline_ns, descriptor)); } pub fn add_ns(&mut self, ns: u64) { self.ns_since_epoch += ns; let time = self.ns_since_epoch; self.deadlines.retain(|(ns, descriptor)| { let expired = *ns <= time; if expired { descriptor.signal().unwrap(); } !expired }); } } impl Default for FakeClock { fn default() -> Self { Self::new() } }