mod.rs 2.3 KB

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