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