Another round of test fixes from previous commits

This commit is contained in:
Alex Crichton 2013-11-07 20:13:25 -08:00
parent 3a3eefc5c3
commit 86a321b65d
19 changed files with 312 additions and 75 deletions

View File

@ -218,7 +218,7 @@ $$(LIBUV_MAKEFILE_$(1)): $$(LIBUV_DEPS)
ifdef CFG_WINDOWSY_$(1)
$$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS)
$$(Q)$$(MAKE) -C $$(S)src/libuv -f Makefile.mingw \
CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
CC="$$(CC) $$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \
AR="$$(AR_$(1))" \
V=$$(VERBOSE)
$$(Q)cp $$(S)src/libuv/libuv.a $$@

View File

@ -12,7 +12,7 @@ use std::c_str::CString;
use std::c_str;
use std::cast::transmute;
use std::cast;
use std::libc::{c_int, c_char, c_void, c_uint};
use std::libc::{c_int, c_char, c_void, size_t};
use std::libc;
use std::rt::BlockedTask;
use std::rt::io::{FileStat, IoError};
@ -20,6 +20,7 @@ use std::rt::io;
use std::rt::local::Local;
use std::rt::rtio;
use std::rt::sched::{Scheduler, SchedHandle};
use std::task;
use std::vec;
use super::{Loop, UvError, uv_error_to_io_error, wait_until_woken_after};
@ -79,7 +80,7 @@ impl FsRequest {
execute_nop(|req, cb| unsafe {
uvll::uv_fs_write(loop_.handle, req,
fd, vec::raw::to_ptr(buf) as *c_void,
buf.len() as c_uint, offset, cb)
buf.len() as size_t, offset, cb)
})
}
@ -89,7 +90,7 @@ impl FsRequest {
do execute(|req, cb| unsafe {
uvll::uv_fs_read(loop_.handle, req,
fd, vec::raw::to_ptr(buf) as *c_void,
buf.len() as c_uint, offset, cb)
buf.len() as size_t, offset, cb)
}).map |req| {
req.get_result() as int
}
@ -297,24 +298,26 @@ impl Drop for FsRequest {
fn execute(f: &fn(*uvll::uv_fs_t, uvll::uv_fs_cb) -> c_int)
-> Result<FsRequest, UvError>
{
let mut req = FsRequest {
fired: false,
req: unsafe { uvll::malloc_req(uvll::UV_FS) }
};
return match f(req.req, fs_cb) {
0 => {
req.fired = true;
let mut slot = None;
do wait_until_woken_after(&mut slot) {
unsafe { uvll::set_data_for_req(req.req, &slot) }
return do task::unkillable {
let mut req = FsRequest {
fired: false,
req: unsafe { uvll::malloc_req(uvll::UV_FS) }
};
match f(req.req, fs_cb) {
0 => {
req.fired = true;
let mut slot = None;
do wait_until_woken_after(&mut slot) {
unsafe { uvll::set_data_for_req(req.req, &slot) }
}
match req.get_result() {
n if n < 0 => Err(UvError(n)),
_ => Ok(req),
}
}
match req.get_result() {
n if n < 0 => Err(UvError(n)),
_ => Ok(req),
}
}
n => Err(UvError(n))
n => Err(UvError(n))
}
};
extern fn fs_cb(req: *uvll::uv_fs_t) {

View File

@ -126,6 +126,15 @@ mod test {
tube.recv();
}
#[test] #[should_fail]
fn smoke_fail() {
let tube = Tube::new();
let cb = ~MyCallback(tube.clone(), 1);
let mut idle = IdleWatcher::new(local_loop(), cb as ~Callback);
idle.resume();
fail!();
}
#[test]
fn fun_combinations_of_methods() {
let mut tube = Tube::new();

View File

@ -154,6 +154,26 @@ pub trait UvHandle<T> {
}
}
pub struct ForbidSwitch {
msg: &'static str,
sched: uint,
}
impl ForbidSwitch {
fn new(s: &'static str) -> ForbidSwitch {
ForbidSwitch {
msg: s, sched: Local::borrow(|s: &mut Scheduler| s.sched_id())
}
}
}
impl Drop for ForbidSwitch {
fn drop(&mut self) {
assert!(self.sched == Local::borrow(|s: &mut Scheduler| s.sched_id()),
"didnt want a scheduler switch: {}", self.msg);
}
}
pub struct ForbidUnwind {
msg: &'static str,
failing_before: bool,
@ -170,7 +190,7 @@ impl ForbidUnwind {
impl Drop for ForbidUnwind {
fn drop(&mut self) {
assert!(self.failing_before == task::failing(),
"failing sadface {}", self.msg);
"didnt want an unwind during: {}", self.msg);
}
}

View File

@ -1168,6 +1168,56 @@ mod test {
}
}
#[should_fail] #[test]
fn tcp_listener_fail_cleanup() {
let addr = next_test_ip4();
let w = TcpListener::bind(local_loop(), addr).unwrap();
let _w = w.listen().unwrap();
fail!();
}
#[should_fail] #[test]
fn tcp_stream_fail_cleanup() {
let (port, chan) = oneshot();
let chan = Cell::new(chan);
let addr = next_test_ip4();
do task::spawn_unlinked { // please no linked failure
let w = TcpListener::bind(local_loop(), addr).unwrap();
let mut w = w.listen().unwrap();
chan.take().send(());
w.accept();
}
port.recv();
let _w = TcpWatcher::connect(local_loop(), addr).unwrap();
fail!();
}
#[should_fail] #[test]
fn udp_listener_fail_cleanup() {
let addr = next_test_ip4();
let _w = UdpWatcher::bind(local_loop(), addr).unwrap();
fail!();
}
#[should_fail] #[test]
fn udp_fail_other_task() {
let addr = next_test_ip4();
let (port, chan) = oneshot();
let chan = Cell::new(chan);
// force the handle to be created on a different scheduler, failure in
// the original task will force a homing operation back to this
// scheduler.
do task::spawn_sched(task::SingleThreaded) {
let w = UdpWatcher::bind(local_loop(), addr).unwrap();
chan.take().send(w);
}
let _w = port.recv();
fail!();
}
#[should_fail]
#[test]
#[ignore(reason = "linked failure")]

View File

@ -238,3 +238,91 @@ impl RtioUnixAcceptor for PipeAcceptor {
impl HomingIO for PipeAcceptor {
fn home<'r>(&'r mut self) -> &'r mut SchedHandle { self.listener.home() }
}
#[cfg(test)]
mod tests {
use std::cell::Cell;
use std::comm::oneshot;
use std::rt::rtio::{RtioUnixListener, RtioUnixAcceptor, RtioPipe};
use std::rt::test::next_test_unix;
use std::task;
use super::*;
use super::super::local_loop;
#[test]
fn connect_err() {
match PipeWatcher::connect(local_loop(), &"path/to/nowhere".to_c_str()) {
Ok(*) => fail!(),
Err(*) => {}
}
}
#[test]
fn bind_err() {
match PipeListener::bind(local_loop(), &"path/to/nowhere".to_c_str()) {
Ok(*) => fail!(),
Err(e) => assert_eq!(e.name(), ~"EACCES"),
}
}
#[test]
fn bind() {
let p = next_test_unix().to_c_str();
match PipeListener::bind(local_loop(), &p) {
Ok(*) => {}
Err(*) => fail!(),
}
}
#[test] #[should_fail]
fn bind_fail() {
let p = next_test_unix().to_c_str();
let _w = PipeListener::bind(local_loop(), &p).unwrap();
fail!();
}
#[test]
fn connect() {
let path = next_test_unix();
let path2 = path.clone();
let (port, chan) = oneshot();
let chan = Cell::new(chan);
do spawn {
let p = PipeListener::bind(local_loop(), &path2.to_c_str()).unwrap();
let mut p = p.listen().unwrap();
chan.take().send(());
let mut client = p.accept().unwrap();
let mut buf = [0];
assert!(client.read(buf).unwrap() == 1);
assert_eq!(buf[0], 1);
assert!(client.write([2]).is_ok());
}
port.recv();
let mut c = PipeWatcher::connect(local_loop(), &path.to_c_str()).unwrap();
assert!(c.write([1]).is_ok());
let mut buf = [0];
assert!(c.read(buf).unwrap() == 1);
assert_eq!(buf[0], 2);
}
#[test] #[should_fail]
fn connect_fail() {
let path = next_test_unix();
let path2 = path.clone();
let (port, chan) = oneshot();
let chan = Cell::new(chan);
do task::spawn_unlinked { // plz no linked failure
let p = PipeListener::bind(local_loop(), &path2.to_c_str()).unwrap();
let mut p = p.listen().unwrap();
chan.take().send(());
p.accept();
}
port.recv();
let _c = PipeWatcher::connect(local_loop(), &path.to_c_str()).unwrap();
fail!()
}
}

View File

@ -77,23 +77,18 @@ impl Process {
};
let handle = UvHandle::alloc(None::<Process>, uvll::UV_PROCESS);
let process = ~Process {
handle: handle,
home: get_handle_to_current_scheduler!(),
to_wake: None,
exit_status: None,
term_signal: None,
};
match unsafe {
uvll::uv_spawn(loop_.handle, handle, &options)
} {
0 => {
let process = ~Process {
handle: handle,
home: get_handle_to_current_scheduler!(),
to_wake: None,
exit_status: None,
term_signal: None,
};
Ok(process.install())
}
err => {
unsafe { uvll::free_handle(handle) }
Err(UvError(err))
}
0 => Ok(process.install()),
err => Err(UvError(err)),
}
}
};

View File

@ -16,7 +16,7 @@ use std::rt::rtio::RtioTimer;
use std::rt::sched::{Scheduler, SchedHandle};
use uvll;
use super::{Loop, UvHandle, ForbidUnwind};
use super::{Loop, UvHandle, ForbidUnwind, ForbidSwitch};
use uvio::HomingIO;
pub struct TimerWatcher {
@ -100,7 +100,9 @@ impl RtioTimer for TimerWatcher {
}
}
extern fn timer_cb(handle: *uvll::uv_timer_t, _status: c_int) {
extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) {
let _f = ForbidSwitch::new("timer callback can't switch");
assert_eq!(status, 0);
let timer: &mut TimerWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
match timer.action.take_unwrap() {
@ -168,4 +170,76 @@ mod test {
timer.sleep(1);
timer.sleep(1);
}
#[test] #[should_fail]
fn oneshot_fail() {
let mut timer = TimerWatcher::new(local_loop());
let _port = timer.oneshot(1);
fail!();
}
#[test] #[should_fail]
fn period_fail() {
let mut timer = TimerWatcher::new(local_loop());
let _port = timer.period(1);
fail!();
}
#[test] #[should_fail]
fn normal_fail() {
let _timer = TimerWatcher::new(local_loop());
fail!();
}
#[test]
fn closing_channel_during_drop_doesnt_kill_everything() {
// see issue #10375
let mut timer = TimerWatcher::new(local_loop());
let timer_port = Cell::new(timer.period(1000));
do spawn {
timer_port.take().try_recv();
}
// when we drop the TimerWatcher we're going to destroy the channel,
// which must wake up the task on the other end
}
#[test]
fn sender_goes_away_oneshot() {
let port = {
let mut timer = TimerWatcher::new(local_loop());
timer.oneshot(1000)
};
assert_eq!(port.try_recv(), None);
}
#[test]
fn sender_goes_away_period() {
let port = {
let mut timer = TimerWatcher::new(local_loop());
timer.period(1000)
};
assert_eq!(port.try_recv(), None);
}
#[test]
fn receiver_goes_away_oneshot() {
let mut timer1 = TimerWatcher::new(local_loop());
timer1.oneshot(1);
let mut timer2 = TimerWatcher::new(local_loop());
// while sleeping, the prevous timer should fire and not have its
// callback do something terrible.
timer2.sleep(2);
}
#[test]
fn receiver_goes_away_period() {
let mut timer1 = TimerWatcher::new(local_loop());
timer1.period(1);
let mut timer2 = TimerWatcher::new(local_loop());
// while sleeping, the prevous timer should fire and not have its
// callback do something terrible.
timer2.sleep(2);
}
}

View File

@ -676,9 +676,9 @@ externfn!(fn uv_fs_open(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
externfn!(fn uv_fs_unlink(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
cb: uv_fs_cb) -> c_int)
externfn!(fn uv_fs_write(l: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void,
len: c_uint, offset: i64, cb: uv_fs_cb) -> c_int)
len: size_t, offset: i64, cb: uv_fs_cb) -> c_int)
externfn!(fn uv_fs_read(l: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void,
len: c_uint, offset: i64, cb: uv_fs_cb) -> c_int)
len: size_t, offset: i64, cb: uv_fs_cb) -> c_int)
externfn!(fn uv_fs_close(l: *uv_loop_t, req: *uv_fs_t, fd: c_int,
cb: uv_fs_cb) -> c_int)
externfn!(fn uv_fs_stat(l: *uv_loop_t, req: *uv_fs_t, path: *c_char,

View File

@ -423,7 +423,11 @@ pub fn ignore_io_error<T>(cb: &fn() -> T) -> T {
/// closure if no error occurred.
pub fn result<T>(cb: &fn() -> T) -> Result<T, IoError> {
let mut err = None;
let ret = io_error::cond.trap(|e| err = Some(e)).inside(cb);
let ret = io_error::cond.trap(|e| {
if err.is_none() {
err = Some(e);
}
}).inside(cb);
match err {
Some(e) => Err(e),
None => Ok(ret),

View File

@ -80,18 +80,20 @@ pub type fd_t = libc::c_int;
pub struct FileDesc {
priv fd: fd_t,
priv close_on_drop: bool,
}
impl FileDesc {
/// Create a `FileDesc` from an open C file descriptor.
///
/// The `FileDesc` will take ownership of the specified file descriptor and
/// close it upon destruction.
/// close it upon destruction if the `close_on_drop` flag is true, otherwise
/// it will not close the file descriptor when this `FileDesc` is dropped.
///
/// Note that all I/O operations done on this object will be *blocking*, but
/// they do not require the runtime to be active.
pub fn new(fd: fd_t) -> FileDesc {
FileDesc { fd: fd }
pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
FileDesc { fd: fd, close_on_drop: close_on_drop }
}
}
@ -137,7 +139,9 @@ impl Writer for FileDesc {
impl Drop for FileDesc {
#[fixed_stack_segment] #[inline(never)]
fn drop(&mut self) {
unsafe { libc::close(self.fd); }
if self.close_on_drop {
unsafe { libc::close(self.fd); }
}
}
}
@ -245,8 +249,8 @@ mod tests {
// opening or closing files.
unsafe {
let os::Pipe { input, out } = os::pipe();
let mut reader = FileDesc::new(input);
let mut writer = FileDesc::new(out);
let mut reader = FileDesc::new(input, true);
let mut writer = FileDesc::new(out, true);
writer.write(bytes!("test"));
let mut buf = [0u8, ..4];

View File

@ -105,9 +105,9 @@ impl Process {
Process {
pid: res.pid,
handle: res.handle,
input: in_pipe.map(|pipe| file::FileDesc::new(pipe.out)),
output: out_pipe.map(|pipe| file::FileDesc::new(pipe.input)),
error: err_pipe.map(|pipe| file::FileDesc::new(pipe.input)),
input: in_pipe.map(|pipe| file::FileDesc::new(pipe.out, true)),
output: out_pipe.map(|pipe| file::FileDesc::new(pipe.input, true)),
error: err_pipe.map(|pipe| file::FileDesc::new(pipe.input, true)),
exit_code: None,
}
}

View File

@ -36,10 +36,8 @@ pub struct StdIn {
impl StdIn {
/// Duplicates the stdin file descriptor, returning an io::Reader
#[fixed_stack_segment] #[inline(never)]
pub fn new() -> StdIn {
let fd = unsafe { libc::dup(libc::STDIN_FILENO) };
StdIn { fd: file::FileDesc::new(fd) }
StdIn { fd: file::FileDesc::new(libc::STDIN_FILENO, false) }
}
}
@ -54,10 +52,8 @@ pub struct StdOut {
impl StdOut {
/// Duplicates the specified file descriptor, returning an io::Writer
#[fixed_stack_segment] #[inline(never)]
pub fn new(fd: file::fd_t) -> StdOut {
let fd = unsafe { libc::dup(fd) };
StdOut { fd: file::FileDesc::new(fd) }
StdOut { fd: file::FileDesc::new(fd, false) }
}
}

View File

@ -160,11 +160,7 @@ mod test {
let port = timer.oneshot(100000000000);
timer.sleep(1); // this should invalidate the port
let port = Cell::new(port);
let ret = do task::try {
port.take().recv();
};
assert!(ret.is_err());
assert_eq!(port.try_recv(), None);
}
}

View File

@ -42,8 +42,7 @@ macro_rules! rtassert (
macro_rules! rtabort (
($msg:expr $($arg:tt)*) => ( {
::rt::util::abort(format!(concat!(file!(), ":", line!(), " ", $msg)
$($arg)*));
($($arg:tt)*) => ( {
::rt::util::abort(format!($($arg)*));
} )
)

View File

@ -436,13 +436,13 @@ mod tests {
}
fn writeclose(fd: c_int, s: &str) {
let mut writer = file::FileDesc::new(fd);
let mut writer = file::FileDesc::new(fd, true);
writer.write(s.as_bytes());
}
fn readclose(fd: c_int) -> ~str {
let mut res = ~[];
let mut reader = file::FileDesc::new(fd);
let mut reader = file::FileDesc::new(fd, true);
let mut buf = [0, ..1024];
loop {
match reader.read(buf) {

View File

@ -93,8 +93,7 @@ rust_sockaddr_size() {
extern "C" struct sockaddr*
rust_malloc_ip4_addr(char *name, int port) {
struct sockaddr_in *addr = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
memset(addr, 0, sizeof(struct sockaddr_in));
struct sockaddr_in *addr = (struct sockaddr_in*) calloc(1, rust_sockaddr_size());
assert(addr != NULL);
addr->sin_port = htons(port);
assert(uv_inet_pton(AF_INET, name, &addr->sin_addr) == 0);
@ -104,8 +103,7 @@ rust_malloc_ip4_addr(char *name, int port) {
extern "C" struct sockaddr*
rust_malloc_ip6_addr(char *name, int port) {
struct sockaddr_in6 *addr = (struct sockaddr_in6*) malloc(sizeof(struct sockaddr_in6));
memset(addr, 0, sizeof(struct sockaddr));
struct sockaddr_in6 *addr = (struct sockaddr_in6*) calloc(1, rust_sockaddr_size());
assert(addr != NULL);
addr->sin6_port = htons(port);
assert(uv_inet_pton(AF_INET6, name, &addr->sin6_addr) == 0);

View File

@ -67,7 +67,8 @@ pub fn main() {
call_that(|x, y| *x + *y - z);
call_cramped(|| 1, || unsafe {
cast::transmute(&100)
static a: uint = 100;
cast::transmute(&a)
});
// External functions

View File

@ -23,8 +23,8 @@
//
// See #9341
use std::rt::io;
use std::rt::io::process::{Process, ProcessConfig, CreatePipe, Ignored};
use std::rt::io::{Reader, Writer};
use std::str;
#[test]
@ -55,10 +55,10 @@ fn smoke_failure() {
cwd: None,
io: io,
};
let p = Process::new(args);
assert!(p.is_some());
let mut p = p.unwrap();
assert!(p.wait() != 0);
match io::result(|| Process::new(args)) {
Ok(*) => fail!(),
Err(*) => {}
}
}
#[test]