mod.rs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. //! Test automation.
  2. use std::{thread, mem};
  3. /// Magic trait for boxed `FnOnce`s.
  4. ///
  5. /// This is a temporary replacement as the trait from libstd is stabilized.
  6. trait FnBox {
  7. /// Call the closure.
  8. fn call_box(self: Box<Self>);
  9. }
  10. impl<F: FnOnce()> FnBox for F {
  11. fn call_box(self: Box<Self>) { (*self)() }
  12. }
  13. /// Like `std::thread::spawn`, but without the closure bounds.
  14. unsafe fn spawn_unsafe<'a, F: FnOnce() + Send + 'a>(func: F) -> thread::JoinHandle<()> {
  15. let closure: Box<FnBox + 'a> = Box::new(func);
  16. let closure: Box<FnBox + Send> = mem::transmute(closure);
  17. thread::spawn(move || closure.call_box())
  18. }
  19. /// Spawn three threads and `join` them.
  20. fn spawn_double<F: Fn() + Sync + Send>(func: F) {
  21. let handle;
  22. unsafe {
  23. handle = spawn_unsafe(|| func());
  24. }
  25. func();
  26. handle.join().unwrap();
  27. }
  28. /// "Multiply" a closure, by running it in multiple threads at the same time.
  29. ///
  30. /// This will test for memory leaks, as well as acid wrapping.
  31. #[allow(dead_code)]
  32. pub fn multiply<F: Fn() + Sync + Send + 'static>(func: F) {
  33. spawn_double(|| spawn_double(|| acid(|| func())));
  34. // TODO assert no leaks.
  35. }
  36. /// Wrap a block in acid tests.
  37. ///
  38. /// This performs a number of temporary allocations to try to detect inconsistency.
  39. ///
  40. /// The basic idea is that if the allocator is broken, it might allocate the same memory twice, or
  41. /// corrupt when allocating. Thus, we allocate some temporary segment and override it. This way we
  42. /// might be able to detect memory corruption through asserting memory consistency after the
  43. /// closure is completed.
  44. #[allow(dead_code)]
  45. pub fn acid<F: FnOnce()>(func: F) {
  46. let mut vec = vec!["something", "yep", "yup"];
  47. let mut _v = vec![Box::new(2), Box::new(5)];
  48. let mut bx = Box::new(2389);
  49. let abc = Box::new("abc");
  50. vec.shrink_to_fit();
  51. vec.extend(["lol", "lulz"].iter());
  52. vec.shrink_to_fit();
  53. vec.extend(["we", "are"].iter());
  54. func();
  55. *bx = 500;
  56. vec.push("heyaya");
  57. *bx = 55;
  58. assert_eq!(vec, ["something", "yep", "yup", "lol", "lulz", "we", "are", "heyaya"]);
  59. assert_eq!(*bx, 55);
  60. assert_eq!(*abc, "abc");
  61. }