1 #![expect(unsafe_op_in_unsafe_fn, reason = "old code, not worth updating yet")]
2
3 use std::collections::HashMap;
4 use std::mem::MaybeUninit;
5 use test_programs::preview1::{STDERR_FD, STDIN_FD, STDOUT_FD, assert_errno};
6
7 const TIMEOUT: u64 = 200_000_000u64; // 200 milliseconds, required to satisfy slow execution in CI
8 const CLOCK_ID: wasip1::Userdata = 0x0123_45678;
9 const STDIN_ID: wasip1::Userdata = 0x8765_43210;
10
poll_oneoff_impl( r#in: &[wasip1::Subscription], ) -> Result<Vec<wasip1::Event>, wasip1::Errno>11 unsafe fn poll_oneoff_impl(
12 r#in: &[wasip1::Subscription],
13 ) -> Result<Vec<wasip1::Event>, wasip1::Errno> {
14 let mut out: Vec<wasip1::Event> = Vec::new();
15 out.resize_with(r#in.len(), || {
16 MaybeUninit::<wasip1::Event>::zeroed().assume_init()
17 });
18 let size = wasip1::poll_oneoff(r#in.as_ptr(), out.as_mut_ptr(), r#in.len())?;
19 out.truncate(size);
20 Ok(out)
21 }
22
test_stdin_read()23 unsafe fn test_stdin_read() {
24 let clock = wasip1::SubscriptionClock {
25 id: wasip1::CLOCKID_MONOTONIC,
26 timeout: TIMEOUT,
27 precision: 0,
28 flags: 0,
29 };
30 let fd_readwrite = wasip1::SubscriptionFdReadwrite {
31 file_descriptor: STDIN_FD,
32 };
33 // Either stdin can be ready for reading, or this poll can timeout.
34 let r#in = [
35 wasip1::Subscription {
36 userdata: CLOCK_ID,
37 u: wasip1::SubscriptionU {
38 tag: wasip1::EVENTTYPE_CLOCK.raw(),
39 u: wasip1::SubscriptionUU { clock },
40 },
41 },
42 wasip1::Subscription {
43 userdata: STDIN_ID,
44 u: wasip1::SubscriptionU {
45 tag: wasip1::EVENTTYPE_FD_READ.raw(),
46 u: wasip1::SubscriptionUU {
47 fd_read: fd_readwrite,
48 },
49 },
50 },
51 ];
52 let out = poll_oneoff_impl(&r#in).unwrap();
53 // The result should be either a timeout, or that stdin is ready for reading.
54 // Both are valid behaviors that depend on the test environment.
55 assert!(out.len() >= 1, "stdin read should return at least 1 event");
56 for event in out {
57 if event.type_ == wasip1::EVENTTYPE_CLOCK {
58 assert_errno!(event.error, wasip1::ERRNO_SUCCESS);
59 assert_eq!(
60 event.userdata, CLOCK_ID,
61 "the event.userdata should contain CLOCK_ID",
62 );
63 } else if event.type_ == wasip1::EVENTTYPE_FD_READ {
64 assert_errno!(event.error, wasip1::ERRNO_SUCCESS);
65 assert_eq!(
66 event.userdata, STDIN_ID,
67 "the event.userdata should contain STDIN_ID",
68 );
69 } else {
70 panic!("unexpected event type {}", event.type_.raw());
71 }
72 }
73 }
74
writable_subs(h: &HashMap<u64, wasip1::Fd>) -> Vec<wasip1::Subscription>75 fn writable_subs(h: &HashMap<u64, wasip1::Fd>) -> Vec<wasip1::Subscription> {
76 h.iter()
77 .map(|(ud, fd)| wasip1::Subscription {
78 userdata: *ud,
79 u: wasip1::SubscriptionU {
80 tag: wasip1::EVENTTYPE_FD_WRITE.raw(),
81 u: wasip1::SubscriptionUU {
82 fd_write: wasip1::SubscriptionFdReadwrite {
83 file_descriptor: *fd,
84 },
85 },
86 },
87 })
88 .collect()
89 }
90
test_stdout_stderr_write()91 unsafe fn test_stdout_stderr_write() {
92 let mut writable: HashMap<u64, wasip1::Fd> =
93 [(1, STDOUT_FD), (2, STDERR_FD)].into_iter().collect();
94
95 let clock = wasip1::Subscription {
96 userdata: CLOCK_ID,
97 u: wasip1::SubscriptionU {
98 tag: wasip1::EVENTTYPE_CLOCK.raw(),
99 u: wasip1::SubscriptionUU {
100 clock: wasip1::SubscriptionClock {
101 id: wasip1::CLOCKID_MONOTONIC,
102 timeout: TIMEOUT,
103 precision: 0,
104 flags: 0,
105 },
106 },
107 },
108 };
109 let mut timed_out = false;
110 while !writable.is_empty() {
111 if timed_out {
112 panic!("timed out with the following pending subs: {writable:?}")
113 }
114 let mut subs = writable_subs(&writable);
115 subs.push(clock);
116 let out = poll_oneoff_impl(&subs).unwrap();
117 for event in out {
118 match event.userdata {
119 CLOCK_ID => timed_out = true,
120 ud => {
121 if let Some(_) = writable.remove(&ud) {
122 assert_eq!(event.type_, wasip1::EVENTTYPE_FD_WRITE);
123 assert_errno!(event.error, wasip1::ERRNO_SUCCESS);
124 } else {
125 panic!("Unknown userdata {ud}, pending sub: {writable:?}")
126 }
127 }
128 }
129 }
130 }
131 }
132
test_poll_oneoff()133 unsafe fn test_poll_oneoff() {
134 // NB we assume that stdin/stdout/stderr are valid and open
135 // for the duration of the test case
136 test_stdin_read();
137 test_stdout_stderr_write();
138 }
main()139 fn main() {
140 // Run the tests.
141 unsafe { test_poll_oneoff() }
142 }
143