| // ignore-cloudabi no processes | 
 | // ignore-emscripten no processes | 
 |  | 
 | use std::env; | 
 | use std::io::prelude::*; | 
 | use std::process::Command; | 
 | use std::thread; | 
 |  | 
 | const THREADS: usize = 20; | 
 | const WRITES: usize = 100; | 
 | const WRITE_SIZE: usize = 1024 * 32; | 
 |  | 
 | fn main() { | 
 |     let args = env::args().collect::<Vec<_>>(); | 
 |     if args.len() == 1 { | 
 |         parent(); | 
 |     } else { | 
 |         child(); | 
 |     } | 
 | } | 
 |  | 
 | fn parent() { | 
 |     let me = env::current_exe().unwrap(); | 
 |     let mut cmd = Command::new(me); | 
 |     cmd.arg("run-the-test"); | 
 |     let output = cmd.output().unwrap(); | 
 |     assert!(output.status.success()); | 
 |     assert_eq!(output.stderr.len(), 0); | 
 |     assert_eq!(output.stdout.len(), WRITES * THREADS * WRITE_SIZE); | 
 |     for byte in output.stdout.iter() { | 
 |         assert_eq!(*byte, b'a'); | 
 |     } | 
 | } | 
 |  | 
 | fn child() { | 
 |     let threads = (0..THREADS).map(|_| { | 
 |         thread::spawn(|| { | 
 |             let buf = [b'a'; WRITE_SIZE]; | 
 |             for _ in 0..WRITES { | 
 |                 write_all(&buf); | 
 |             } | 
 |         }) | 
 |     }).collect::<Vec<_>>(); | 
 |  | 
 |     for thread in threads { | 
 |         thread.join().unwrap(); | 
 |     } | 
 | } | 
 |  | 
 | #[cfg(unix)] | 
 | fn write_all(buf: &[u8]) { | 
 |     use std::fs::File; | 
 |     use std::mem; | 
 |     use std::os::unix::prelude::*; | 
 |  | 
 |     let mut file = unsafe { File::from_raw_fd(1) }; | 
 |     let res = file.write_all(buf); | 
 |     mem::forget(file); | 
 |     res.unwrap(); | 
 | } | 
 |  | 
 | #[cfg(windows)] | 
 | fn write_all(buf: &[u8]) { | 
 |     use std::fs::File; | 
 |     use std::mem; | 
 |     use std::os::windows::raw::*; | 
 |     use std::os::windows::prelude::*; | 
 |  | 
 |     const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32; | 
 |  | 
 |     extern "system" { | 
 |         fn GetStdHandle(handle: u32) -> HANDLE; | 
 |     } | 
 |  | 
 |     let mut file = unsafe { | 
 |         let handle = GetStdHandle(STD_OUTPUT_HANDLE); | 
 |         assert!(!handle.is_null()); | 
 |         File::from_raw_handle(handle) | 
 |     }; | 
 |     let res = file.write_all(buf); | 
 |     mem::forget(file); | 
 |     res.unwrap(); | 
 | } |