Kaynağa Gözat

Use proper clock mocking in the loopback example.

whitequark 7 yıl önce
ebeveyn
işleme
12f92be419
2 değiştirilmiş dosya ile 67 ekleme ve 12 silme
  1. 55 7
      examples/loopback.rs
  2. 12 5
      examples/utils.rs

+ 55 - 7
examples/loopback.rs

@@ -23,9 +23,60 @@ use smoltcp::iface::{ArpCache, SliceArpCache, EthernetInterface};
 use smoltcp::socket::{AsSocket, SocketSet};
 use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
 
+#[cfg(not(feature = "std"))]
+mod mock {
+    use core::cell::Cell;
+
+    #[derive(Debug)]
+    pub struct Clock(Cell<u64>);
+
+    impl Clock {
+        pub fn new() -> Clock {
+            Clock(Cell::new(0))
+        }
+
+        pub fn advance(&mut self, millis: u64) {
+            self.0.set(self.0.get() + millis)
+        }
+
+        pub fn elapsed(&self) -> u64 {
+            self.0.get()
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+mod mock {
+    use std::sync::Arc;
+    use std::sync::atomic::{Ordering, AtomicUsize};
+
+    // should be AtomicU64 but that's unstable
+    #[derive(Debug, Clone)]
+    pub struct Clock(Arc<AtomicUsize>);
+
+    impl Clock {
+        pub fn new() -> Clock {
+            Clock(Arc::new(AtomicUsize::new(0)))
+        }
+
+        pub fn advance(&self, millis: u64) {
+            self.0.fetch_add(millis as usize, Ordering::SeqCst);
+        }
+
+        pub fn elapsed(&self) -> u64 {
+            self.0.load(Ordering::SeqCst) as u64
+        }
+    }
+}
+
 fn main() {
+    let clock = mock::Clock::new();
+
     #[cfg(feature = "std")]
-    utils::setup_logging();
+    {
+        let clock = clock.clone();
+        utils::setup_logging_with_clock(move || clock.elapsed());
+    }
 
     let mut device = Loopback::new();
     #[cfg(feature = "std")]
@@ -68,8 +119,7 @@ fn main() {
     let mut did_listen  = false;
     let mut did_connect = false;
     let mut done = false;
-    let mut timestamp_ms = 0;
-    while !done && timestamp_ms < 500 {
+    while !done && clock.elapsed() < 10_000 {
         {
             let socket: &mut TcpSocket = socket_set.get_mut(server_handle).as_socket();
             if !socket.is_active() && !socket.is_listening() {
@@ -102,14 +152,12 @@ fn main() {
             }
         }
 
-        match iface.poll(&mut socket_set, timestamp_ms) {
+        match iface.poll(&mut socket_set, clock.elapsed()) {
             Ok(()) | Err(Error::Exhausted) => (),
             Err(e) => debug!("poll error: {}", e)
         }
 
-        const DELAY: u64 = 20;
-        debug!("{}ms pass", DELAY);
-        timestamp_ms += DELAY;
+        clock.advance(1);
     }
 
     if !done {

+ 12 - 5
examples/utils.rs

@@ -12,13 +12,12 @@ use smoltcp::phy::{Tracer, FaultInjector, TapInterface};
 use smoltcp::wire::EthernetFrame;
 use smoltcp::wire::PrettyPrinter;
 
-pub fn setup_logging() {
-    let startup_time = Instant::now();
+pub fn setup_logging_with_clock<F>(since_startup: F)
+        where F: Fn() -> u64 + Send + Sync + 'static {
     LogBuilder::new()
         .format(move |record: &LogRecord| {
-            let elapsed = Instant::now().duration_since(startup_time);
-            let timestamp = format!("[{:6}.{:03}s]",
-                                    elapsed.as_secs(), elapsed.subsec_nanos() / 1000000);
+            let elapsed = since_startup();
+            let timestamp = format!("[{:6}.{:03}s]", elapsed / 1000, elapsed % 1000);
             if record.target().ends_with("::utils") {
                 let mut message = format!("{}", record.args());
                 message.pop();
@@ -37,6 +36,14 @@ pub fn setup_logging() {
         .unwrap();
 }
 
+pub fn setup_logging() {
+    let startup_at = Instant::now();
+    setup_logging_with_clock(move  || {
+        let elapsed = Instant::now().duration_since(startup_at);
+        elapsed.as_secs() * 1000 + (elapsed.subsec_nanos() / 1000) as u64
+    })
+}
+
 pub fn trace_writer(printer: PrettyPrinter<EthernetFrame<&[u8]>>) {
     trace!("{}", printer)
 }