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