1 // run-pass 2 // ignore-emscripten no processes 3 // ignore-sgx no processes 4 5 use std::env; 6 use std::io::prelude::*; 7 use std::process::Command; 8 use std::thread; 9 10 const THREADS: usize = 20; 11 const WRITES: usize = 100; 12 const WRITE_SIZE: usize = 1024 * 32; 13 main()14fn main() { 15 let args = env::args().collect::<Vec<_>>(); 16 if args.len() == 1 { 17 parent(); 18 } else { 19 child(); 20 } 21 } 22 parent()23fn parent() { 24 let me = env::current_exe().unwrap(); 25 let mut cmd = Command::new(me); 26 cmd.arg("run-the-test"); 27 let output = cmd.output().unwrap(); 28 assert!(output.status.success()); 29 assert_eq!(output.stderr.len(), 0); 30 assert_eq!(output.stdout.len(), WRITES * THREADS * WRITE_SIZE); 31 for byte in output.stdout.iter() { 32 assert_eq!(*byte, b'a'); 33 } 34 } 35 child()36fn child() { 37 let threads = (0..THREADS).map(|_| { 38 thread::spawn(|| { 39 let buf = [b'a'; WRITE_SIZE]; 40 for _ in 0..WRITES { 41 write_all(&buf); 42 } 43 }) 44 }).collect::<Vec<_>>(); 45 46 for thread in threads { 47 thread.join().unwrap(); 48 } 49 } 50 51 #[cfg(unix)] write_all(buf: &[u8])52fn write_all(buf: &[u8]) { 53 use std::fs::File; 54 use std::mem; 55 use std::os::unix::prelude::*; 56 57 let mut file = unsafe { File::from_raw_fd(1) }; 58 let res = file.write_all(buf); 59 mem::forget(file); 60 res.unwrap(); 61 } 62 63 #[cfg(windows)] write_all(buf: &[u8])64fn write_all(buf: &[u8]) { 65 use std::fs::File; 66 use std::mem; 67 use std::os::windows::raw::*; 68 use std::os::windows::prelude::*; 69 70 const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32; 71 72 extern "system" { 73 fn GetStdHandle(handle: u32) -> HANDLE; 74 } 75 76 let mut file = unsafe { 77 let handle = GetStdHandle(STD_OUTPUT_HANDLE); 78 assert!(!handle.is_null()); 79 File::from_raw_handle(handle) 80 }; 81 let res = file.write_all(buf); 82 mem::forget(file); 83 res.unwrap(); 84 } 85