Skip to content

Commit d733989

Browse files
author
Mark McCaskey
committed
Add wasi::poll_oneoff file read test
1 parent ec20e32 commit d733989

File tree

7 files changed

+172
-6
lines changed

7 files changed

+172
-6
lines changed

lib/wasi-tests/tests/wasitests/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mod mapdir;
1818
mod path_link;
1919
mod path_rename;
2020
mod path_symlink;
21+
mod poll_oneoff;
2122
mod quine;
2223
mod readlink;
2324
mod wasi_sees_virtual_root;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#[test]
2+
fn test_poll_oneoff() {
3+
assert_wasi_output!(
4+
"../../wasitests/poll_oneoff.wasm",
5+
"poll_oneoff",
6+
vec![],
7+
vec![(
8+
"hamlet".to_string(),
9+
::std::path::PathBuf::from("wasitests/test_fs/hamlet")
10+
),],
11+
vec![],
12+
"../../wasitests/poll_oneoff.out"
13+
);
14+
}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }
+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Args:
2+
// mapdir: hamlet:wasitests/test_fs/hamlet
3+
4+
use std::fs;
5+
use std::io::{Read, Seek, SeekFrom};
6+
#[cfg(target_os = "wasi")]
7+
use std::os::wasi::prelude::AsRawFd;
8+
use std::path::PathBuf;
9+
10+
#[cfg(target_os = "wasi")]
11+
#[link(wasm_import_module = "wasi_unstable")]
12+
extern "C" {
13+
fn poll_oneoff(subscriptons: u32, events: u32, nsubscriptons: u32, nevents: u32) -> u16;
14+
}
15+
16+
#[derive(Debug, Copy, Clone)]
17+
#[repr(C)]
18+
pub struct __wasi_event_t {
19+
pub userdata: u64,
20+
pub error: u16,
21+
pub type_: __wasi_eventtype_t,
22+
pub u: __wasi_event_u,
23+
}
24+
25+
impl Default for __wasi_event_t {
26+
fn default() -> Self {
27+
__wasi_event_t {
28+
userdata: 0,
29+
error: 0,
30+
type_: 0,
31+
u: __wasi_event_u {
32+
fd_readwrite: __wasi_event_fd_readwrite_t {
33+
nbytes: 0,
34+
flags: 0,
35+
},
36+
},
37+
}
38+
}
39+
}
40+
41+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
42+
#[repr(C)]
43+
pub struct __wasi_event_fd_readwrite_t {
44+
pub nbytes: u64,
45+
pub flags: u16,
46+
}
47+
48+
#[derive(Copy, Clone)]
49+
#[repr(C)]
50+
pub union __wasi_event_u {
51+
pub fd_readwrite: __wasi_event_fd_readwrite_t,
52+
}
53+
54+
impl std::fmt::Debug for __wasi_event_u {
55+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56+
write!(f, "__wasi_event_u {{ ")?;
57+
write!(f, "{:?} }}", unsafe { self.fd_readwrite })
58+
}
59+
}
60+
61+
pub type __wasi_eventtype_t = u8;
62+
pub const __WASI_EVENTTYPE_CLOCK: u8 = 0;
63+
pub const __WASI_EVENTTYPE_FD_READ: u8 = 1;
64+
pub const __WASI_EVENTTYPE_FD_WRITE: u8 = 2;
65+
66+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
67+
#[repr(C)]
68+
pub struct __wasi_subscription_clock_t {
69+
pub userdata: u64,
70+
pub clock_id: u32,
71+
pub timeout: u64,
72+
pub precision: u64,
73+
pub flags: u16,
74+
}
75+
76+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
77+
#[repr(C)]
78+
pub struct __wasi_subscription_fs_readwrite_t {
79+
pub fd: u32,
80+
}
81+
82+
#[derive(Copy, Clone)]
83+
#[repr(C)]
84+
pub union __wasi_subscription_u {
85+
clock: __wasi_subscription_clock_t,
86+
fd_readwrite: __wasi_subscription_fs_readwrite_t,
87+
}
88+
89+
#[derive(Copy, Clone)]
90+
#[repr(C)]
91+
pub struct __wasi_subscription_t {
92+
pub userdata: u64,
93+
pub type_: __wasi_eventtype_t,
94+
pub u: __wasi_subscription_u,
95+
}
96+
97+
#[cfg(target_os = "wasi")]
98+
fn poll_read(fds: &[u32]) -> Result<Vec<__wasi_event_t>, u16> {
99+
let mut in_ = fds
100+
.iter()
101+
.map(|n| __wasi_subscription_t {
102+
userdata: 0x123456,
103+
type_: __WASI_EVENTTYPE_FD_READ,
104+
u: __wasi_subscription_u {
105+
fd_readwrite: __wasi_subscription_fs_readwrite_t { fd: *n as u32 },
106+
},
107+
})
108+
.collect::<Vec<_>>();
109+
let mut out_ = vec![Default::default(); in_.len()];
110+
let mut nsubscriptions: u32 = 0;
111+
let result = unsafe {
112+
poll_oneoff(
113+
in_.as_ptr() as usize as u32,
114+
out_.as_mut_ptr() as usize as u32,
115+
in_.len() as u32,
116+
(&mut nsubscriptions as *mut u32) as usize as u32,
117+
)
118+
};
119+
120+
if result == 0 {
121+
Ok(out_)
122+
} else {
123+
Err(result)
124+
}
125+
}
126+
127+
fn main() {
128+
#[cfg(not(target_os = "wasi"))]
129+
let mut base = PathBuf::from("wasitests/test_fs");
130+
#[cfg(target_os = "wasi")]
131+
let mut base = PathBuf::from("/");
132+
133+
let path = base.join("hamlet/act4/scene1.txt");
134+
let mut file = fs::File::open(&path).expect("Could not open file");
135+
let mut buffer = [0u8; 64];
136+
137+
#[cfg(target_os = "wasi")]
138+
{
139+
let fds = vec![file.as_raw_fd()];
140+
let mut result = poll_read(fds.as_slice()).expect("First poll");
141+
while result[0].error != 0 {
142+
result = poll_read(fds.as_slice()).expect("subsequent polls");
143+
}
144+
println!("{:?}", result[0]);
145+
}
146+
#[cfg(not(target_os = "wasi"))]
147+
{
148+
println!("{}", "__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }");
149+
}
150+
}
80.5 KB
Binary file not shown.

lib/wasi/src/state/types.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/// types for use in the WASI filesystem
22
use crate::syscalls::types::*;
3+
#[cfg(unix)]
4+
use std::convert::TryInto;
35
use std::{
46
fs,
57
io::{self, Read, Seek, Write},
@@ -297,7 +299,7 @@ pub(crate) fn poll(
297299
selfs: &[&dyn WasiFile],
298300
events: &[PollEventSet],
299301
seen_events: &mut [PollEventSet],
300-
) -> Result<(), WasiFsError> {
302+
) -> Result<u32, WasiFsError> {
301303
if !(selfs.len() == events.len() && events.len() == seen_events.len()) {
302304
return Err(WasiFsError::InvalidInput);
303305
}
@@ -313,15 +315,16 @@ pub(crate) fn poll(
313315
.collect::<Vec<_>>();
314316
let result = unsafe { libc::poll(fds.as_mut_ptr(), selfs.len() as _, 1) };
315317

316-
if result != 0 {
318+
if result < 0 {
317319
// TODO: check errno and return value
318320
return Err(WasiFsError::IOError);
319321
}
320322
// convert result and write back values
321323
for (i, fd) in fds.into_iter().enumerate() {
322324
seen_events[i] = platform_poll_events_to_pollevent_set(fd.revents);
323325
}
324-
Ok(())
326+
// unwrap is safe because we check the error above
327+
Ok(result.try_into().unwrap())
325328
}
326329

327330
#[cfg(not(unix))]
@@ -451,7 +454,6 @@ impl WasiFile for HostFile {
451454

452455
#[cfg(unix)]
453456
fn bytes_available(&self) -> Result<usize, WasiFsError> {
454-
use std::convert::TryInto;
455457
use std::os::unix::io::AsRawFd;
456458
let host_fd = self.inner.as_raw_fd();
457459

@@ -737,7 +739,6 @@ impl WasiFile for Stdin {
737739

738740
#[cfg(unix)]
739741
fn bytes_available(&self) -> Result<usize, WasiFsError> {
740-
use std::convert::TryInto;
741742
use std::os::unix::io::AsRawFd;
742743
let host_fd = self.0.as_raw_fd();
743744

lib/wasi/src/syscalls/unix/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::state::{Kind, WasiFile, WasiFs};
21
use crate::syscalls::types::*;
32
use libc::{
43
clock_getres, clock_gettime, timespec, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,

0 commit comments

Comments
 (0)