std: working tests for low-level libuv open, write and close operations
This commit is contained in:
parent
a901b16690
commit
dabbac1d6c
4 changed files with 175 additions and 32 deletions
|
@ -11,8 +11,9 @@
|
|||
use prelude::*;
|
||||
use ptr::null;
|
||||
use libc::c_void;
|
||||
use rt::uv::{Request, NativeHandle, Loop, FsCallback,
|
||||
status_to_maybe_uv_error_with_loop};
|
||||
use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf,
|
||||
status_to_maybe_uv_error_with_loop,
|
||||
vec_to_uv_buf};//, vec_from_uv_buf};
|
||||
use rt::uv::uvll;
|
||||
use rt::uv::uvll::*;
|
||||
use path::Path;
|
||||
|
@ -30,6 +31,14 @@ pub enum UvFileFlag {
|
|||
O_CREAT,
|
||||
O_TRUNC
|
||||
}
|
||||
// just want enough to get 0644
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum UvFileMode {
|
||||
S_IWUSR,
|
||||
S_IRUSR,
|
||||
S_IRGRP,
|
||||
S_IROTH
|
||||
}
|
||||
pub fn map_flag(v: UvFileFlag) -> int {
|
||||
unsafe {
|
||||
match v {
|
||||
|
@ -41,9 +50,21 @@ pub fn map_flag(v: UvFileFlag) -> int {
|
|||
}
|
||||
}
|
||||
}
|
||||
pub fn map_mode(v: UvFileMode) -> int {
|
||||
unsafe {
|
||||
match v {
|
||||
S_IWUSR => uvll::get_S_IWUSR() as int,
|
||||
S_IRUSR => uvll::get_S_IRUSR() as int,
|
||||
S_IRGRP => uvll::get_S_IRGRP() as int,
|
||||
S_IROTH => uvll::get_S_IROTH() as int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RequestData {
|
||||
complete_cb: Option<FsCallback>
|
||||
complete_cb: Option<FsCallback>,
|
||||
buf: Option<Buf>,
|
||||
raw_fd: Option<c_int>
|
||||
}
|
||||
|
||||
impl FsRequest {
|
||||
|
@ -58,7 +79,9 @@ impl FsRequest {
|
|||
pub fn install_req_data(&self, cb: Option<FsCallback>) {
|
||||
let fs_req = (self.native_handle()) as *uvll::uv_write_t;
|
||||
let data = ~RequestData {
|
||||
complete_cb: cb
|
||||
complete_cb: cb,
|
||||
buf: None,
|
||||
raw_fd: None
|
||||
};
|
||||
unsafe {
|
||||
let data = transmute::<~RequestData, *c_void>(data);
|
||||
|
@ -86,10 +109,10 @@ impl FsRequest {
|
|||
|
||||
fn cleanup_and_delete(self) {
|
||||
unsafe {
|
||||
uvll::fs_req_cleanup(self.native_handle());
|
||||
let data = uvll::get_data_for_uv_handle(self.native_handle());
|
||||
let data = uvll::get_data_for_req(self.native_handle());
|
||||
let _data = transmute::<*c_void, ~RequestData>(data);
|
||||
uvll::set_data_for_uv_handle(self.native_handle(), null::<()>());
|
||||
uvll::set_data_for_req(self.native_handle(), null::<()>());
|
||||
uvll::fs_req_cleanup(self.native_handle());
|
||||
free_req(self.native_handle() as *c_void)
|
||||
}
|
||||
}
|
||||
|
@ -121,10 +144,24 @@ impl FileDescriptor {
|
|||
uvll::fs_open(loop_.native_handle(),
|
||||
req.native_handle(), p, flags, mode, complete_cb) as int
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
fn close(self, loop_: Loop, cb: FsCallback) -> int {
|
||||
pub fn write(&self, loop_: Loop, buf: ~[u8], offset: i64, cb: FsCallback)
|
||||
-> int {
|
||||
let mut req = FsRequest::new(Some(cb));
|
||||
let len = buf.len();
|
||||
let buf = vec_to_uv_buf(buf);
|
||||
let base_ptr = buf.base as *c_void;
|
||||
req.get_req_data().buf = Some(buf);
|
||||
req.get_req_data().raw_fd = Some(self.native_handle());
|
||||
unsafe {
|
||||
uvll::fs_write(loop_.native_handle(), req.native_handle(),
|
||||
self.native_handle(), base_ptr,
|
||||
len, offset, complete_cb) as int
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(self, loop_: Loop, cb: FsCallback) -> int {
|
||||
let req = FsRequest::new(Some(cb));
|
||||
unsafe {
|
||||
uvll::fs_close(loop_.native_handle(), req.native_handle(),
|
||||
|
@ -170,17 +207,22 @@ mod test {
|
|||
//use rt::test::*;
|
||||
use unstable::run_in_bare_thread;
|
||||
use path::Path;
|
||||
use rt::uv::Loop;
|
||||
use rt::uv::{Loop};//, slice_to_uv_buf};
|
||||
|
||||
// this is equiv to touch, i guess?
|
||||
fn file_test_touch_impl() {
|
||||
debug!("hello?")
|
||||
do run_in_bare_thread {
|
||||
debug!("In bare thread")
|
||||
let loop_ = Loop::new();
|
||||
let mut loop_ = Loop::new();
|
||||
let flags = map_flag(O_RDWR) |
|
||||
map_flag(O_CREAT) | map_flag(O_TRUNC);
|
||||
do FileDescriptor::open(loop_, Path("./foo.txt"), flags, 0644)
|
||||
map_flag(O_CREAT);
|
||||
// 0644
|
||||
let mode = map_mode(S_IWUSR) |
|
||||
map_mode(S_IRUSR) |
|
||||
map_mode(S_IRGRP) |
|
||||
map_mode(S_IROTH);
|
||||
do FileDescriptor::open(loop_, Path("./foo.txt"), flags, mode)
|
||||
|req, uverr| {
|
||||
let loop_ = req.get_loop();
|
||||
assert!(uverr.is_none());
|
||||
|
@ -189,6 +231,7 @@ mod test {
|
|||
assert!(uverr.is_none());
|
||||
};
|
||||
};
|
||||
loop_.run();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,4 +239,56 @@ mod test {
|
|||
fn file_test_touch() {
|
||||
file_test_touch_impl();
|
||||
}
|
||||
|
||||
fn file_test_tee_impl() {
|
||||
debug!("hello?")
|
||||
do run_in_bare_thread {
|
||||
debug!("In bare thread")
|
||||
let mut loop_ = Loop::new();
|
||||
let flags = map_flag(O_RDWR) |
|
||||
map_flag(O_CREAT);
|
||||
// 0644
|
||||
let mode = map_mode(S_IWUSR) |
|
||||
map_mode(S_IRUSR) |
|
||||
map_mode(S_IRGRP) |
|
||||
map_mode(S_IROTH);
|
||||
do FileDescriptor::open(loop_, Path("./file_tee_test.txt"), flags, mode)
|
||||
|req, uverr| {
|
||||
let loop_ = req.get_loop();
|
||||
assert!(uverr.is_none());
|
||||
let fd = FileDescriptor::from_open_req(req);
|
||||
let msg: ~[u8] = "hello world".as_bytes().to_owned();
|
||||
let raw_fd = fd.native_handle();
|
||||
do fd.write(loop_, msg, -1) |_, uverr| {
|
||||
let fd = FileDescriptor(raw_fd);
|
||||
do fd.close(loop_) |_, _| {
|
||||
assert!(uverr.is_none());
|
||||
};
|
||||
};
|
||||
};
|
||||
loop_.run();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_tee() {
|
||||
file_test_tee_impl();
|
||||
}
|
||||
|
||||
fn naive_print(input: ~str) {
|
||||
do run_in_bare_thread {
|
||||
let mut loop_ = Loop::new();
|
||||
let stdout = FileDescriptor(1);
|
||||
let msg = input.as_bytes().to_owned();
|
||||
do stdout.write(loop_, msg, -1) |_, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
};
|
||||
loop_.run();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_println() {
|
||||
naive_print(~"oh yeah.\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -621,6 +621,10 @@ pub unsafe fn fs_open(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, flags:
|
|||
cb: *u8) -> c_int {
|
||||
rust_uv_fs_open(loop_ptr, req, path, flags as c_int, mode as c_int, cb)
|
||||
}
|
||||
pub unsafe fn fs_write(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void,
|
||||
len: uint, offset: i64, cb: *u8) -> c_int {
|
||||
rust_uv_fs_write(loop_ptr, req, fd, buf, len as c_uint, offset, cb)
|
||||
}
|
||||
pub unsafe fn fs_close(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int,
|
||||
cb: *u8) -> c_int {
|
||||
rust_uv_fs_close(loop_ptr, req, fd, cb)
|
||||
|
@ -630,21 +634,15 @@ pub unsafe fn fs_req_cleanup(req: *uv_fs_t) {
|
|||
}
|
||||
|
||||
// data access helpers
|
||||
pub unsafe fn get_O_RDONLY() -> c_int {
|
||||
rust_uv_get_O_RDONLY()
|
||||
}
|
||||
pub unsafe fn get_O_WRONLY() -> c_int {
|
||||
rust_uv_get_O_WRONLY()
|
||||
}
|
||||
pub unsafe fn get_O_RDWR() -> c_int {
|
||||
rust_uv_get_O_RDWR()
|
||||
}
|
||||
pub unsafe fn get_O_CREAT() -> c_int {
|
||||
rust_uv_get_O_CREAT()
|
||||
}
|
||||
pub unsafe fn get_O_TRUNC() -> c_int {
|
||||
rust_uv_get_O_TRUNC()
|
||||
}
|
||||
pub unsafe fn get_O_RDONLY() -> c_int { rust_uv_get_O_RDONLY() }
|
||||
pub unsafe fn get_O_WRONLY() -> c_int { rust_uv_get_O_WRONLY() }
|
||||
pub unsafe fn get_O_RDWR() -> c_int { rust_uv_get_O_RDWR() }
|
||||
pub unsafe fn get_O_CREAT() -> c_int { rust_uv_get_O_CREAT() }
|
||||
pub unsafe fn get_O_TRUNC() -> c_int { rust_uv_get_O_TRUNC() }
|
||||
pub unsafe fn get_S_IWUSR() -> c_int { rust_uv_get_S_IWUSR() }
|
||||
pub unsafe fn get_S_IRUSR() -> c_int { rust_uv_get_S_IRUSR() }
|
||||
pub unsafe fn get_S_IRGRP() -> c_int { rust_uv_get_S_IRGRP() }
|
||||
pub unsafe fn get_S_IROTH() -> c_int { rust_uv_get_S_IROTH() }
|
||||
pub unsafe fn get_result_from_fs_req(req: *uv_fs_t) -> c_int {
|
||||
rust_uv_get_result_from_fs_req(req)
|
||||
}
|
||||
|
@ -819,6 +817,8 @@ extern {
|
|||
fn rust_uv_timer_stop(handle: *uv_timer_t) -> c_int;
|
||||
fn rust_uv_fs_open(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
|
||||
flags: c_int, mode: c_int, cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_write(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int,
|
||||
buf: *c_void, len: c_uint, offset: i64, cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_close(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int,
|
||||
cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_req_cleanup(req: *uv_fs_t);
|
||||
|
@ -827,6 +827,10 @@ extern {
|
|||
fn rust_uv_get_O_RDWR() -> c_int;
|
||||
fn rust_uv_get_O_CREAT() -> c_int;
|
||||
fn rust_uv_get_O_TRUNC() -> c_int;
|
||||
fn rust_uv_get_S_IWUSR() -> c_int;
|
||||
fn rust_uv_get_S_IRUSR() -> c_int;
|
||||
fn rust_uv_get_S_IRGRP() -> c_int;
|
||||
fn rust_uv_get_S_IROTH() -> c_int;
|
||||
fn rust_uv_get_result_from_fs_req(req: *uv_fs_t) -> c_int;
|
||||
fn rust_uv_get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t;
|
||||
|
||||
|
|
|
@ -18,16 +18,13 @@
|
|||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "uv.h"
|
||||
|
||||
#include "rust_globals.h"
|
||||
|
||||
extern "C" void*
|
||||
rust_uv_loop_new() {
|
||||
// XXX libuv doesn't always ignore SIGPIPE even though we don't need it.
|
||||
#ifndef __WIN32__
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
return (void*)uv_loop_new();
|
||||
}
|
||||
|
||||
|
@ -517,3 +514,45 @@ extern "C" uintptr_t
|
|||
rust_uv_req_type_max() {
|
||||
return UV_REQ_TYPE_MAX;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
rust_uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
|
||||
int mode, uv_fs_cb cb) {
|
||||
return uv_fs_open(loop, req, path, flags, mode, cb);
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
|
||||
return uv_fs_close(loop, req, fd, cb);
|
||||
}
|
||||
extern "C" void
|
||||
rust_uv_fs_req_cleanup(uv_fs_t* req) {
|
||||
uv_fs_req_cleanup(req);
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_get_O_RDONLY() {
|
||||
return O_RDONLY;
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_get_O_WRONLY() {
|
||||
return O_WRONLY;
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_get_O_RDWR() {
|
||||
return O_RDWR;
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_get_O_CREAT() {
|
||||
return O_CREAT;
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_get_O_TRUNC() {
|
||||
return O_TRUNC;
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_get_result_from_fs_req(uv_fs_t* req) {
|
||||
return req->result;
|
||||
}
|
||||
extern "C" uv_loop_t*
|
||||
rust_uv_get_loop_from_fs_req(uv_fs_t* req) {
|
||||
return req->loop;
|
||||
}
|
||||
|
|
|
@ -109,12 +109,17 @@ rust_uv_idle_init
|
|||
rust_uv_idle_start
|
||||
rust_uv_idle_stop
|
||||
rust_uv_fs_open
|
||||
rust_uv_fs_write
|
||||
rust_uv_fs_close
|
||||
rust_uv_get_O_RDONLY
|
||||
rust_uv_get_O_WRONLY
|
||||
rust_uv_get_O_RDWR
|
||||
rust_uv_get_O_CREAT
|
||||
rust_uv_get_O_TRUNC
|
||||
rust_uv_get_S_IRUSR
|
||||
rust_uv_get_S_IWUSR
|
||||
rust_uv_get_S_IROTH
|
||||
rust_uv_get_S_IRGRP
|
||||
rust_uv_get_result_from_fs_req
|
||||
rust_uv_get_loop_from_fs_req
|
||||
rust_uv_fs_req_cleanup
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue