]> git.proxmox.com Git - rustc.git/blame - src/test/run-pass/no-stdio.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / test / run-pass / no-stdio.rs
CommitLineData
7453a54e
SL
1// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
abe05a73 11// ignore-emscripten no processes
476ff2be 12// ignore-android
5bcae85e 13
7453a54e
SL
14#![feature(libc)]
15
16extern crate libc;
17
18use std::process::{Command, Stdio};
19use std::env;
20use std::io::{self, Read, Write};
21
22#[cfg(unix)]
23unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
24 let doit = |a| {
25 let r = libc::dup(a);
26 assert!(r >= 0);
27 return r
28 };
29 let a = doit(0);
30 let b = doit(1);
31 let c = doit(2);
32
33 assert!(libc::close(0) >= 0);
34 assert!(libc::close(1) >= 0);
35 assert!(libc::close(2) >= 0);
36
37 let r = f();
38
39 assert!(libc::dup2(a, 0) >= 0);
40 assert!(libc::dup2(b, 1) >= 0);
41 assert!(libc::dup2(c, 2) >= 0);
42
43 return r
44}
45
46#[cfg(windows)]
47unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
48 type DWORD = u32;
49 type HANDLE = *mut u8;
50 type BOOL = i32;
51
52 const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
53 const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
54 const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
55 const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
56
57 extern "system" {
58 fn GetStdHandle(which: DWORD) -> HANDLE;
59 fn SetStdHandle(which: DWORD, handle: HANDLE) -> BOOL;
60 }
61
62 let doit = |id| {
63 let handle = GetStdHandle(id);
64 assert!(handle != INVALID_HANDLE_VALUE);
65 assert!(SetStdHandle(id, INVALID_HANDLE_VALUE) != 0);
66 return handle
67 };
68
69 let a = doit(STD_INPUT_HANDLE);
70 let b = doit(STD_OUTPUT_HANDLE);
71 let c = doit(STD_ERROR_HANDLE);
72
73 let r = f();
74
75 let doit = |id, handle| {
76 assert!(SetStdHandle(id, handle) != 0);
77 };
78 doit(STD_INPUT_HANDLE, a);
79 doit(STD_OUTPUT_HANDLE, b);
80 doit(STD_ERROR_HANDLE, c);
81
82 return r
83}
84
85fn main() {
86 if env::args().len() > 1 {
87 println!("test");
88 assert!(io::stdout().write(b"test\n").is_ok());
89 assert!(io::stderr().write(b"test\n").is_ok());
90 assert_eq!(io::stdin().read(&mut [0; 10]).unwrap(), 0);
91 return
92 }
93
94 // First, make sure reads/writes without stdio work if stdio itself is
95 // missing.
96 let (a, b, c) = unsafe {
97 without_stdio(|| {
98 let a = io::stdout().write(b"test\n");
99 let b = io::stderr().write(b"test\n");
100 let c = io::stdin().read(&mut [0; 10]);
101
102 (a, b, c)
103 })
104 };
105
106 assert_eq!(a.unwrap(), 5);
107 assert_eq!(b.unwrap(), 5);
108 assert_eq!(c.unwrap(), 0);
109
110 // Second, spawn a child and do some work with "null" descriptors to make
111 // sure it's ok
112 let me = env::current_exe().unwrap();
113 let status = Command::new(&me)
114 .arg("next")
115 .stdin(Stdio::null())
116 .stdout(Stdio::null())
117 .stderr(Stdio::null())
118 .status().unwrap();
119 assert!(status.success(), "{:?} isn't a success", status);
120
121 // Finally, close everything then spawn a child to make sure everything is
122 // *still* ok.
123 let status = unsafe {
124 without_stdio(|| Command::new(&me).arg("next").status())
125 }.unwrap();
126 assert!(status.success(), "{:?} isn't a success", status);
127}