Skip to content

Commit dabbac1

Browse files
committed
std: working tests for low-level libuv open, write and close operations
1 parent a901b16 commit dabbac1

File tree

4 files changed

+174
-31
lines changed

4 files changed

+174
-31
lines changed

src/libstd/rt/uv/file.rs

Lines changed: 107 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
use prelude::*;
1212
use ptr::null;
1313
use libc::c_void;
14-
use rt::uv::{Request, NativeHandle, Loop, FsCallback,
15-
status_to_maybe_uv_error_with_loop};
14+
use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf,
15+
status_to_maybe_uv_error_with_loop,
16+
vec_to_uv_buf};//, vec_from_uv_buf};
1617
use rt::uv::uvll;
1718
use rt::uv::uvll::*;
1819
use path::Path;
@@ -30,6 +31,14 @@ pub enum UvFileFlag {
3031
O_CREAT,
3132
O_TRUNC
3233
}
34+
// just want enough to get 0644
35+
#[allow(non_camel_case_types)]
36+
pub enum UvFileMode {
37+
S_IWUSR,
38+
S_IRUSR,
39+
S_IRGRP,
40+
S_IROTH
41+
}
3342
pub fn map_flag(v: UvFileFlag) -> int {
3443
unsafe {
3544
match v {
@@ -41,9 +50,21 @@ pub fn map_flag(v: UvFileFlag) -> int {
4150
}
4251
}
4352
}
53+
pub fn map_mode(v: UvFileMode) -> int {
54+
unsafe {
55+
match v {
56+
S_IWUSR => uvll::get_S_IWUSR() as int,
57+
S_IRUSR => uvll::get_S_IRUSR() as int,
58+
S_IRGRP => uvll::get_S_IRGRP() as int,
59+
S_IROTH => uvll::get_S_IROTH() as int
60+
}
61+
}
62+
}
4463

4564
pub struct RequestData {
46-
complete_cb: Option<FsCallback>
65+
complete_cb: Option<FsCallback>,
66+
buf: Option<Buf>,
67+
raw_fd: Option<c_int>
4768
}
4869

4970
impl FsRequest {
@@ -58,7 +79,9 @@ impl FsRequest {
5879
pub fn install_req_data(&self, cb: Option<FsCallback>) {
5980
let fs_req = (self.native_handle()) as *uvll::uv_write_t;
6081
let data = ~RequestData {
61-
complete_cb: cb
82+
complete_cb: cb,
83+
buf: None,
84+
raw_fd: None
6285
};
6386
unsafe {
6487
let data = transmute::<~RequestData, *c_void>(data);
@@ -86,10 +109,10 @@ impl FsRequest {
86109

87110
fn cleanup_and_delete(self) {
88111
unsafe {
89-
uvll::fs_req_cleanup(self.native_handle());
90-
let data = uvll::get_data_for_uv_handle(self.native_handle());
112+
let data = uvll::get_data_for_req(self.native_handle());
91113
let _data = transmute::<*c_void, ~RequestData>(data);
92-
uvll::set_data_for_uv_handle(self.native_handle(), null::<()>());
114+
uvll::set_data_for_req(self.native_handle(), null::<()>());
115+
uvll::fs_req_cleanup(self.native_handle());
93116
free_req(self.native_handle() as *c_void)
94117
}
95118
}
@@ -121,10 +144,24 @@ impl FileDescriptor {
121144
uvll::fs_open(loop_.native_handle(),
122145
req.native_handle(), p, flags, mode, complete_cb) as int
123146
})
147+
}
124148

149+
pub fn write(&self, loop_: Loop, buf: ~[u8], offset: i64, cb: FsCallback)
150+
-> int {
151+
let mut req = FsRequest::new(Some(cb));
152+
let len = buf.len();
153+
let buf = vec_to_uv_buf(buf);
154+
let base_ptr = buf.base as *c_void;
155+
req.get_req_data().buf = Some(buf);
156+
req.get_req_data().raw_fd = Some(self.native_handle());
157+
unsafe {
158+
uvll::fs_write(loop_.native_handle(), req.native_handle(),
159+
self.native_handle(), base_ptr,
160+
len, offset, complete_cb) as int
161+
}
125162
}
126163

127-
fn close(self, loop_: Loop, cb: FsCallback) -> int {
164+
pub fn close(self, loop_: Loop, cb: FsCallback) -> int {
128165
let req = FsRequest::new(Some(cb));
129166
unsafe {
130167
uvll::fs_close(loop_.native_handle(), req.native_handle(),
@@ -170,17 +207,22 @@ mod test {
170207
//use rt::test::*;
171208
use unstable::run_in_bare_thread;
172209
use path::Path;
173-
use rt::uv::Loop;
210+
use rt::uv::{Loop};//, slice_to_uv_buf};
174211

175212
// this is equiv to touch, i guess?
176213
fn file_test_touch_impl() {
177214
debug!("hello?")
178215
do run_in_bare_thread {
179216
debug!("In bare thread")
180-
let loop_ = Loop::new();
217+
let mut loop_ = Loop::new();
181218
let flags = map_flag(O_RDWR) |
182-
map_flag(O_CREAT) | map_flag(O_TRUNC);
183-
do FileDescriptor::open(loop_, Path("./foo.txt"), flags, 0644)
219+
map_flag(O_CREAT);
220+
// 0644
221+
let mode = map_mode(S_IWUSR) |
222+
map_mode(S_IRUSR) |
223+
map_mode(S_IRGRP) |
224+
map_mode(S_IROTH);
225+
do FileDescriptor::open(loop_, Path("./foo.txt"), flags, mode)
184226
|req, uverr| {
185227
let loop_ = req.get_loop();
186228
assert!(uverr.is_none());
@@ -189,11 +231,64 @@ mod test {
189231
assert!(uverr.is_none());
190232
};
191233
};
234+
loop_.run();
192235
}
193236
}
194237

195238
#[test]
196239
fn file_test_touch() {
197240
file_test_touch_impl();
198241
}
242+
243+
fn file_test_tee_impl() {
244+
debug!("hello?")
245+
do run_in_bare_thread {
246+
debug!("In bare thread")
247+
let mut loop_ = Loop::new();
248+
let flags = map_flag(O_RDWR) |
249+
map_flag(O_CREAT);
250+
// 0644
251+
let mode = map_mode(S_IWUSR) |
252+
map_mode(S_IRUSR) |
253+
map_mode(S_IRGRP) |
254+
map_mode(S_IROTH);
255+
do FileDescriptor::open(loop_, Path("./file_tee_test.txt"), flags, mode)
256+
|req, uverr| {
257+
let loop_ = req.get_loop();
258+
assert!(uverr.is_none());
259+
let fd = FileDescriptor::from_open_req(req);
260+
let msg: ~[u8] = "hello world".as_bytes().to_owned();
261+
let raw_fd = fd.native_handle();
262+
do fd.write(loop_, msg, -1) |_, uverr| {
263+
let fd = FileDescriptor(raw_fd);
264+
do fd.close(loop_) |_, _| {
265+
assert!(uverr.is_none());
266+
};
267+
};
268+
};
269+
loop_.run();
270+
}
271+
}
272+
273+
#[test]
274+
fn file_test_tee() {
275+
file_test_tee_impl();
276+
}
277+
278+
fn naive_print(input: ~str) {
279+
do run_in_bare_thread {
280+
let mut loop_ = Loop::new();
281+
let stdout = FileDescriptor(1);
282+
let msg = input.as_bytes().to_owned();
283+
do stdout.write(loop_, msg, -1) |_, uverr| {
284+
assert!(uverr.is_none());
285+
};
286+
loop_.run();
287+
}
288+
}
289+
290+
#[test]
291+
fn file_test_println() {
292+
naive_print(~"oh yeah.\n");
293+
}
199294
}

src/libstd/rt/uv/uvll.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,10 @@ pub unsafe fn fs_open(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, flags:
621621
cb: *u8) -> c_int {
622622
rust_uv_fs_open(loop_ptr, req, path, flags as c_int, mode as c_int, cb)
623623
}
624+
pub unsafe fn fs_write(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void,
625+
len: uint, offset: i64, cb: *u8) -> c_int {
626+
rust_uv_fs_write(loop_ptr, req, fd, buf, len as c_uint, offset, cb)
627+
}
624628
pub unsafe fn fs_close(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int,
625629
cb: *u8) -> c_int {
626630
rust_uv_fs_close(loop_ptr, req, fd, cb)
@@ -630,21 +634,15 @@ pub unsafe fn fs_req_cleanup(req: *uv_fs_t) {
630634
}
631635

632636
// data access helpers
633-
pub unsafe fn get_O_RDONLY() -> c_int {
634-
rust_uv_get_O_RDONLY()
635-
}
636-
pub unsafe fn get_O_WRONLY() -> c_int {
637-
rust_uv_get_O_WRONLY()
638-
}
639-
pub unsafe fn get_O_RDWR() -> c_int {
640-
rust_uv_get_O_RDWR()
641-
}
642-
pub unsafe fn get_O_CREAT() -> c_int {
643-
rust_uv_get_O_CREAT()
644-
}
645-
pub unsafe fn get_O_TRUNC() -> c_int {
646-
rust_uv_get_O_TRUNC()
647-
}
637+
pub unsafe fn get_O_RDONLY() -> c_int { rust_uv_get_O_RDONLY() }
638+
pub unsafe fn get_O_WRONLY() -> c_int { rust_uv_get_O_WRONLY() }
639+
pub unsafe fn get_O_RDWR() -> c_int { rust_uv_get_O_RDWR() }
640+
pub unsafe fn get_O_CREAT() -> c_int { rust_uv_get_O_CREAT() }
641+
pub unsafe fn get_O_TRUNC() -> c_int { rust_uv_get_O_TRUNC() }
642+
pub unsafe fn get_S_IWUSR() -> c_int { rust_uv_get_S_IWUSR() }
643+
pub unsafe fn get_S_IRUSR() -> c_int { rust_uv_get_S_IRUSR() }
644+
pub unsafe fn get_S_IRGRP() -> c_int { rust_uv_get_S_IRGRP() }
645+
pub unsafe fn get_S_IROTH() -> c_int { rust_uv_get_S_IROTH() }
648646
pub unsafe fn get_result_from_fs_req(req: *uv_fs_t) -> c_int {
649647
rust_uv_get_result_from_fs_req(req)
650648
}
@@ -819,6 +817,8 @@ extern {
819817
fn rust_uv_timer_stop(handle: *uv_timer_t) -> c_int;
820818
fn rust_uv_fs_open(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
821819
flags: c_int, mode: c_int, cb: *u8) -> c_int;
820+
fn rust_uv_fs_write(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int,
821+
buf: *c_void, len: c_uint, offset: i64, cb: *u8) -> c_int;
822822
fn rust_uv_fs_close(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int,
823823
cb: *u8) -> c_int;
824824
fn rust_uv_fs_req_cleanup(req: *uv_fs_t);
@@ -827,6 +827,10 @@ extern {
827827
fn rust_uv_get_O_RDWR() -> c_int;
828828
fn rust_uv_get_O_CREAT() -> c_int;
829829
fn rust_uv_get_O_TRUNC() -> c_int;
830+
fn rust_uv_get_S_IWUSR() -> c_int;
831+
fn rust_uv_get_S_IRUSR() -> c_int;
832+
fn rust_uv_get_S_IRGRP() -> c_int;
833+
fn rust_uv_get_S_IROTH() -> c_int;
830834
fn rust_uv_get_result_from_fs_req(req: *uv_fs_t) -> c_int;
831835
fn rust_uv_get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t;
832836

src/rt/rust_uv.cpp

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,13 @@
1818
#include <signal.h>
1919
#endif
2020

21+
#include <fcntl.h>
2122
#include "uv.h"
2223

2324
#include "rust_globals.h"
2425

2526
extern "C" void*
2627
rust_uv_loop_new() {
27-
// XXX libuv doesn't always ignore SIGPIPE even though we don't need it.
28-
#ifndef __WIN32__
29-
signal(SIGPIPE, SIG_IGN);
30-
#endif
3128
return (void*)uv_loop_new();
3229
}
3330

@@ -517,3 +514,45 @@ extern "C" uintptr_t
517514
rust_uv_req_type_max() {
518515
return UV_REQ_TYPE_MAX;
519516
}
517+
518+
extern "C" int
519+
rust_uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
520+
int mode, uv_fs_cb cb) {
521+
return uv_fs_open(loop, req, path, flags, mode, cb);
522+
}
523+
extern "C" int
524+
rust_uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
525+
return uv_fs_close(loop, req, fd, cb);
526+
}
527+
extern "C" void
528+
rust_uv_fs_req_cleanup(uv_fs_t* req) {
529+
uv_fs_req_cleanup(req);
530+
}
531+
extern "C" int
532+
rust_uv_get_O_RDONLY() {
533+
return O_RDONLY;
534+
}
535+
extern "C" int
536+
rust_uv_get_O_WRONLY() {
537+
return O_WRONLY;
538+
}
539+
extern "C" int
540+
rust_uv_get_O_RDWR() {
541+
return O_RDWR;
542+
}
543+
extern "C" int
544+
rust_uv_get_O_CREAT() {
545+
return O_CREAT;
546+
}
547+
extern "C" int
548+
rust_uv_get_O_TRUNC() {
549+
return O_TRUNC;
550+
}
551+
extern "C" int
552+
rust_uv_get_result_from_fs_req(uv_fs_t* req) {
553+
return req->result;
554+
}
555+
extern "C" uv_loop_t*
556+
rust_uv_get_loop_from_fs_req(uv_fs_t* req) {
557+
return req->loop;
558+
}

src/rt/rustrt.def.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,17 @@ rust_uv_idle_init
109109
rust_uv_idle_start
110110
rust_uv_idle_stop
111111
rust_uv_fs_open
112+
rust_uv_fs_write
112113
rust_uv_fs_close
113114
rust_uv_get_O_RDONLY
114115
rust_uv_get_O_WRONLY
115116
rust_uv_get_O_RDWR
116117
rust_uv_get_O_CREAT
117118
rust_uv_get_O_TRUNC
119+
rust_uv_get_S_IRUSR
120+
rust_uv_get_S_IWUSR
121+
rust_uv_get_S_IROTH
122+
rust_uv_get_S_IRGRP
118123
rust_uv_get_result_from_fs_req
119124
rust_uv_get_loop_from_fs_req
120125
rust_uv_fs_req_cleanup

0 commit comments

Comments
 (0)