]> git.lizzy.rs Git - rust.git/blob - src/test/ui/no-stdio.rs
Rollup merge of #63356 - ali-raheem:issue#63183, r=KodrAus
[rust.git] / src / test / ui / no-stdio.rs
1 // run-pass
2 // ignore-android
3 // ignore-cloudabi no processes
4 // ignore-emscripten no processes
5 // ignore-sgx no processes
6
7 #![feature(rustc_private)]
8
9 extern crate libc;
10
11 use std::process::{Command, Stdio};
12 use std::env;
13 use std::io::{self, Read, Write};
14
15 #[cfg(unix)]
16 unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
17     let doit = |a| {
18         let r = libc::dup(a);
19         assert!(r >= 0);
20         return r
21     };
22     let a = doit(0);
23     let b = doit(1);
24     let c = doit(2);
25
26     assert!(libc::close(0) >= 0);
27     assert!(libc::close(1) >= 0);
28     assert!(libc::close(2) >= 0);
29
30     let r = f();
31
32     assert!(libc::dup2(a, 0) >= 0);
33     assert!(libc::dup2(b, 1) >= 0);
34     assert!(libc::dup2(c, 2) >= 0);
35
36     return r
37 }
38
39 #[cfg(windows)]
40 unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
41     type DWORD = u32;
42     type HANDLE = *mut u8;
43     type BOOL = i32;
44
45     const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
46     const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
47     const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
48     const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
49
50     extern "system" {
51         fn GetStdHandle(which: DWORD) -> HANDLE;
52         fn SetStdHandle(which: DWORD, handle: HANDLE) -> BOOL;
53     }
54
55     let doit = |id| {
56         let handle = GetStdHandle(id);
57         assert!(handle != INVALID_HANDLE_VALUE);
58         assert!(SetStdHandle(id, INVALID_HANDLE_VALUE) != 0);
59         return handle
60     };
61
62     let a = doit(STD_INPUT_HANDLE);
63     let b = doit(STD_OUTPUT_HANDLE);
64     let c = doit(STD_ERROR_HANDLE);
65
66     let r = f();
67
68     let doit = |id, handle| {
69         assert!(SetStdHandle(id, handle) != 0);
70     };
71     doit(STD_INPUT_HANDLE, a);
72     doit(STD_OUTPUT_HANDLE, b);
73     doit(STD_ERROR_HANDLE, c);
74
75     return r
76 }
77
78 fn main() {
79     if env::args().len() > 1 {
80         println!("test");
81         assert!(io::stdout().write(b"test\n").is_ok());
82         assert!(io::stderr().write(b"test\n").is_ok());
83         assert_eq!(io::stdin().read(&mut [0; 10]).unwrap(), 0);
84         return
85     }
86
87     // First, make sure reads/writes without stdio work if stdio itself is
88     // missing.
89     let (a, b, c) = unsafe {
90         without_stdio(|| {
91             let a = io::stdout().write(b"test\n");
92             let b = io::stderr().write(b"test\n");
93             let c = io::stdin().read(&mut [0; 10]);
94
95             (a, b, c)
96         })
97     };
98
99     assert_eq!(a.unwrap(), 5);
100     assert_eq!(b.unwrap(), 5);
101     assert_eq!(c.unwrap(), 0);
102
103     // Second, spawn a child and do some work with "null" descriptors to make
104     // sure it's ok
105     let me = env::current_exe().unwrap();
106     let status = Command::new(&me)
107                         .arg("next")
108                         .stdin(Stdio::null())
109                         .stdout(Stdio::null())
110                         .stderr(Stdio::null())
111                         .status().unwrap();
112     assert!(status.success(), "{:?} isn't a success", status);
113
114     // Finally, close everything then spawn a child to make sure everything is
115     // *still* ok.
116     let status = unsafe {
117         without_stdio(|| Command::new(&me).arg("next").status())
118     }.unwrap();
119     assert!(status.success(), "{:?} isn't a success", status);
120 }