]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/test.rs
Convert most code to new inner attribute syntax.
[rust.git] / src / libstd / io / test.rs
1 // Copyright 2013 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
11 /*! Various utility functions useful for writing I/O tests */
12
13 #![macro_escape]
14
15 use libc;
16 use os;
17 use prelude::*;
18 use std::io::net::ip::*;
19 use sync::atomics::{AtomicUint, INIT_ATOMIC_UINT, Relaxed};
20
21 macro_rules! iotest (
22     { fn $name:ident() $b:block $(#[$a:meta])* } => (
23         mod $name {
24             #[allow(unused_imports)];
25
26             use super::super::*;
27             use super::*;
28             use io;
29             use prelude::*;
30             use io::*;
31             use io::fs::*;
32             use io::test::*;
33             use io::net::tcp::*;
34             use io::net::ip::*;
35             use io::net::udp::*;
36             #[cfg(unix)]
37             use io::net::unix::*;
38             use io::timer::*;
39             use io::process::*;
40             use unstable::running_on_valgrind;
41             use str;
42             use util;
43
44             fn f() $b
45
46             $(#[$a])* #[test] fn green() { f() }
47             $(#[$a])* #[test] fn native() {
48                 use native;
49                 let (tx, rx) = channel();
50                 native::task::spawn(proc() { tx.send(f()) });
51                 rx.recv();
52             }
53         }
54     )
55 )
56
57 /// Get a port number, starting at 9600, for use in tests
58 pub fn next_test_port() -> u16 {
59     static mut next_offset: AtomicUint = INIT_ATOMIC_UINT;
60     unsafe {
61         base_port() + next_offset.fetch_add(1, Relaxed) as u16
62     }
63 }
64
65 /// Get a temporary path which could be the location of a unix socket
66 pub fn next_test_unix() -> Path {
67     static mut COUNT: AtomicUint = INIT_ATOMIC_UINT;
68     // base port and pid are an attempt to be unique between multiple
69     // test-runners of different configurations running on one
70     // buildbot, the count is to be unique within this executable.
71     let string = format!("rust-test-unix-path-{}-{}-{}",
72                          base_port(),
73                          unsafe {libc::getpid()},
74                          unsafe {COUNT.fetch_add(1, Relaxed)});
75     if cfg!(unix) {
76         os::tmpdir().join(string)
77     } else {
78         Path::new(r"\\.\pipe\" + string)
79     }
80 }
81
82 /// Get a unique IPv4 localhost:port pair starting at 9600
83 pub fn next_test_ip4() -> SocketAddr {
84     SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: next_test_port() }
85 }
86
87 /// Get a unique IPv6 localhost:port pair starting at 9600
88 pub fn next_test_ip6() -> SocketAddr {
89     SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1), port: next_test_port() }
90 }
91
92 /*
93 XXX: Welcome to MegaHack City.
94
95 The bots run multiple builds at the same time, and these builds
96 all want to use ports. This function figures out which workspace
97 it is running in and assigns a port range based on it.
98 */
99 fn base_port() -> u16 {
100
101     let base = 9600u16;
102     let range = 1000u16;
103
104     let bases = [
105         ("32-opt", base + range * 1),
106         ("32-nopt", base + range * 2),
107         ("64-opt", base + range * 3),
108         ("64-nopt", base + range * 4),
109         ("64-opt-vg", base + range * 5),
110         ("all-opt", base + range * 6),
111         ("snap3", base + range * 7),
112         ("dist", base + range * 8)
113     ];
114
115     // FIXME (#9639): This needs to handle non-utf8 paths
116     let path = os::getcwd();
117     let path_s = path.as_str().unwrap();
118
119     let mut final_base = base;
120
121     for &(dir, base) in bases.iter() {
122         if path_s.contains(dir) {
123             final_base = base;
124             break;
125         }
126     }
127
128     return final_base;
129 }
130
131 /// Raises the file descriptor limit when running tests if necessary
132 pub fn raise_fd_limit() {
133     unsafe { darwin_fd_limit::raise_fd_limit() }
134 }
135
136 #[cfg(target_os="macos")]
137 #[allow(non_camel_case_types)]
138 mod darwin_fd_limit {
139     /*!
140      * darwin_fd_limit exists to work around an issue where launchctl on Mac OS X defaults the
141      * rlimit maxfiles to 256/unlimited. The default soft limit of 256 ends up being far too low
142      * for our multithreaded scheduler testing, depending on the number of cores available.
143      *
144      * This fixes issue #7772.
145      */
146
147     use libc;
148     type rlim_t = libc::uint64_t;
149     struct rlimit {
150         rlim_cur: rlim_t,
151         rlim_max: rlim_t
152     }
153     extern {
154         // name probably doesn't need to be mut, but the C function doesn't specify const
155         fn sysctl(name: *mut libc::c_int, namelen: libc::c_uint,
156                   oldp: *mut libc::c_void, oldlenp: *mut libc::size_t,
157                   newp: *mut libc::c_void, newlen: libc::size_t) -> libc::c_int;
158         fn getrlimit(resource: libc::c_int, rlp: *mut rlimit) -> libc::c_int;
159         fn setrlimit(resource: libc::c_int, rlp: *rlimit) -> libc::c_int;
160     }
161     static CTL_KERN: libc::c_int = 1;
162     static KERN_MAXFILESPERPROC: libc::c_int = 29;
163     static RLIMIT_NOFILE: libc::c_int = 8;
164
165     pub unsafe fn raise_fd_limit() {
166         // The strategy here is to fetch the current resource limits, read the kern.maxfilesperproc
167         // sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value.
168         use ptr::mut_null;
169         use mem::size_of_val;
170         use os::last_os_error;
171
172         // Fetch the kern.maxfilesperproc value
173         let mut mib: [libc::c_int, ..2] = [CTL_KERN, KERN_MAXFILESPERPROC];
174         let mut maxfiles: libc::c_int = 0;
175         let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
176         if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size,
177                   mut_null(), 0) != 0 {
178             let err = last_os_error();
179             fail!("raise_fd_limit: error calling sysctl: {}", err);
180         }
181
182         // Fetch the current resource limits
183         let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0};
184         if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 {
185             let err = last_os_error();
186             fail!("raise_fd_limit: error calling getrlimit: {}", err);
187         }
188
189         // Bump the soft limit to the smaller of kern.maxfilesperproc and the hard limit
190         rlim.rlim_cur = ::cmp::min(maxfiles as rlim_t, rlim.rlim_max);
191
192         // Set our newly-increased resource limit
193         if setrlimit(RLIMIT_NOFILE, &rlim) != 0 {
194             let err = last_os_error();
195             fail!("raise_fd_limit: error calling setrlimit: {}", err);
196         }
197     }
198 }
199
200 #[cfg(not(target_os="macos"))]
201 mod darwin_fd_limit {
202     pub unsafe fn raise_fd_limit() {}
203 }