testtools 0.1.3

Helpers for eliminating boilerplate code in tests
Documentation
//! Threading tools.

use std::{io, thread::JoinHandle, time::Instant};

/// The `AutoJoin` is a thin wrapper around [`JoinHandle`] that will
/// automatically join the thread when dropped.
pub struct AutoJoin<T> {
  jh: Option<JoinHandle<T>>
}

impl<T> AutoJoin<T> {
  pub fn join(mut self) -> std::thread::Result<T> {
    if let Some(jh) = self.jh.take() {
      jh.join()
    } else {
      Err(Box::new(io::Error::new(
        io::ErrorKind::NotFound,
        "already consumed"
      )))
    }
  }
}

impl<T> Drop for AutoJoin<T> {
  fn drop(&mut self) {
    if let Some(jh) = self.jh.take() {
      let _ = jh.join();
    }
  }
}

/// Spawn a thread with its [`JoinHandle`] wrapped in a [`AutoJoin`].
pub fn spawn_autojoin<F, T>(f: F) -> AutoJoin<T>
where
  F: FnOnce() -> T,
  F: Send + 'static,
  T: Send + 'static
{
  AutoJoin {
    jh: Some(std::thread::spawn(f))
  }
}


/// Time execution of a closure, and panic if the measured time is lower than
/// the expected runtime.
///
/// `edur` is the expected duration.
pub fn expect_runtime<F>(edur: std::time::Duration, f: F)
where
  F: FnOnce()
{
  let start = Instant::now();

  f();

  let dur = Instant::now() - start;

  assert!(dur > edur);
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :