Skip to content

Commit 1388114

Browse files
committed
add tests for oneshot
This commit adds tests for the very basic new oneshot module. Most of the tests were taken/heavily inspired by tests from the `oneshot crate.
1 parent a0cc410 commit 1388114

File tree

2 files changed

+345
-0
lines changed

2 files changed

+345
-0
lines changed

library/std/tests/sync/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(lazy_get)]
22
#![feature(mapped_lock_guards)]
33
#![feature(mpmc_channel)]
4+
#![feature(oneshot_channel)]
45
#![feature(once_cell_try)]
56
#![feature(lock_value_accessors)]
67
#![feature(reentrant_lock)]
@@ -23,6 +24,8 @@ mod mutex;
2324
mod once;
2425
mod once_lock;
2526
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
27+
mod oneshot;
28+
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
2629
mod reentrant_lock;
2730
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))]
2831
mod rwlock;

library/std/tests/sync/oneshot.rs

Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
//! Inspired by tests from <https://github.com/faern/oneshot/blob/main/tests/sync.rs>
2+
3+
use std::sync::mpsc::RecvError;
4+
use std::sync::oneshot;
5+
use std::sync::oneshot::{RecvTimeoutError, TryRecvError};
6+
use std::time::{Duration, Instant};
7+
use std::{mem, thread};
8+
9+
#[test]
10+
fn send_before_try_recv() {
11+
let (sender, receiver) = oneshot::channel();
12+
13+
assert!(sender.send(19i128).is_ok());
14+
15+
match receiver.try_recv() {
16+
Ok(19) => {}
17+
_ => panic!("expected Ok(19)"),
18+
}
19+
}
20+
21+
#[test]
22+
fn send_before_recv() {
23+
let (sender, receiver) = oneshot::channel::<()>();
24+
25+
assert!(sender.send(()).is_ok());
26+
assert_eq!(receiver.recv(), Ok(()));
27+
28+
let (sender, receiver) = oneshot::channel::<u64>();
29+
30+
assert!(sender.send(42).is_ok());
31+
assert_eq!(receiver.recv(), Ok(42));
32+
33+
let (sender, receiver) = oneshot::channel::<[u8; 4096]>();
34+
35+
assert!(sender.send([0b10101010; 4096]).is_ok());
36+
assert!(receiver.recv().unwrap()[..] == [0b10101010; 4096][..]);
37+
}
38+
39+
#[test]
40+
fn sender_drop() {
41+
{
42+
let (sender, receiver) = oneshot::channel::<u128>();
43+
44+
mem::drop(sender);
45+
46+
match receiver.recv() {
47+
Err(RecvError) => {}
48+
_ => panic!("expected recv error"),
49+
}
50+
}
51+
52+
{
53+
let (sender, receiver) = oneshot::channel::<i32>();
54+
55+
mem::drop(sender);
56+
57+
match receiver.try_recv() {
58+
Err(TryRecvError::Disconnected) => {}
59+
_ => panic!("expected disconnected error"),
60+
}
61+
}
62+
{
63+
let (sender, receiver) = oneshot::channel::<i32>();
64+
65+
mem::drop(sender);
66+
67+
match receiver.recv_timeout(Duration::from_secs(1)) {
68+
Err(RecvTimeoutError::Disconnected) => {}
69+
_ => panic!("expected disconnected error"),
70+
}
71+
}
72+
}
73+
74+
#[test]
75+
fn send_never_deadline() {
76+
let (sender, receiver) = oneshot::channel::<i32>();
77+
78+
mem::drop(sender);
79+
80+
match receiver.recv_deadline(Instant::now()) {
81+
Err(RecvTimeoutError::Disconnected) => {}
82+
_ => panic!("expected disconnected error"),
83+
}
84+
}
85+
86+
#[test]
87+
fn send_before_recv_timeout() {
88+
let (sender, receiver) = oneshot::channel();
89+
90+
assert!(sender.send(22i128).is_ok());
91+
92+
let start = Instant::now();
93+
94+
let timeout = Duration::from_secs(1);
95+
match receiver.recv_timeout(timeout) {
96+
Ok(22) => {}
97+
_ => panic!("expected Ok(22)"),
98+
}
99+
100+
assert!(start.elapsed() < timeout);
101+
}
102+
103+
#[test]
104+
fn send_error() {
105+
let (sender, receiver) = oneshot::channel();
106+
107+
mem::drop(receiver);
108+
109+
let send_error = sender.send(32u128).unwrap_err();
110+
assert_eq!(send_error.0, 32);
111+
}
112+
113+
#[test]
114+
fn recv_before_send() {
115+
let (sender, receiver) = oneshot::channel();
116+
117+
let t1 = thread::spawn(move || {
118+
thread::sleep(Duration::from_millis(10));
119+
sender.send(9u128).unwrap();
120+
});
121+
let t2 = thread::spawn(move || {
122+
assert_eq!(receiver.recv(), Ok(9));
123+
});
124+
125+
t1.join().unwrap();
126+
t2.join().unwrap();
127+
}
128+
129+
#[test]
130+
fn recv_timeout_before_send() {
131+
let (sender, receiver) = oneshot::channel();
132+
133+
let t = thread::spawn(move || {
134+
thread::sleep(Duration::from_millis(100));
135+
sender.send(99u128).unwrap();
136+
});
137+
138+
match receiver.recv_timeout(Duration::from_secs(1)) {
139+
Ok(99) => {}
140+
_ => panic!("expected Ok(99)"),
141+
}
142+
143+
t.join().unwrap();
144+
}
145+
146+
#[test]
147+
fn recv_then_drop_sender() {
148+
let (sender, receiver) = oneshot::channel::<u128>();
149+
150+
let t1 = thread::spawn(move || match receiver.recv() {
151+
Err(RecvError) => {}
152+
_ => panic!("expected recv error"),
153+
});
154+
155+
let t2 = thread::spawn(move || {
156+
thread::sleep(Duration::from_millis(10));
157+
mem::drop(sender);
158+
});
159+
160+
t1.join().unwrap();
161+
t2.join().unwrap();
162+
}
163+
164+
#[test]
165+
fn drop_sender_then_recv() {
166+
let (sender, receiver) = oneshot::channel::<u128>();
167+
168+
let t1 = thread::spawn(move || {
169+
thread::sleep(Duration::from_millis(10));
170+
mem::drop(sender);
171+
});
172+
173+
let t2 = thread::spawn(move || match receiver.recv() {
174+
Err(RecvError) => {}
175+
_ => panic!("expected disconnected error"),
176+
});
177+
178+
t1.join().unwrap();
179+
t2.join().unwrap();
180+
}
181+
182+
#[test]
183+
fn try_recv_empty() {
184+
let (sender, receiver) = oneshot::channel::<u128>();
185+
match receiver.try_recv() {
186+
Err(TryRecvError::Empty(_)) => {}
187+
_ => panic!("expected empty error"),
188+
}
189+
mem::drop(sender);
190+
}
191+
192+
#[test]
193+
fn try_recv_then_drop_receiver() {
194+
let (sender, receiver) = oneshot::channel::<u128>();
195+
196+
let t1 = thread::spawn(move || {
197+
thread::sleep(Duration::from_millis(100));
198+
let _ = sender.send(42);
199+
});
200+
201+
let t2 = thread::spawn(move || match receiver.try_recv() {
202+
Ok(_) => {}
203+
Err(TryRecvError::Empty(r)) => {
204+
mem::drop(r);
205+
}
206+
Err(TryRecvError::Disconnected) => {}
207+
});
208+
209+
t2.join().unwrap();
210+
t1.join().unwrap();
211+
}
212+
213+
#[test]
214+
fn recv_no_time() {
215+
let (_sender, receiver) = oneshot::channel::<u128>();
216+
217+
let start = Instant::now();
218+
match receiver.recv_deadline(start) {
219+
Err(RecvTimeoutError::Timeout(_)) => {}
220+
_ => panic!("expected timeout error"),
221+
}
222+
223+
let (_sender, receiver) = oneshot::channel::<u128>();
224+
match receiver.recv_timeout(Duration::from_millis(0)) {
225+
Err(RecvTimeoutError::Timeout(_)) => {}
226+
_ => panic!("expected timeout error"),
227+
}
228+
}
229+
230+
#[test]
231+
fn recv_deadline_passed() {
232+
let (_sender, receiver) = oneshot::channel::<u128>();
233+
234+
let start = Instant::now();
235+
let timeout = Duration::from_millis(100);
236+
237+
match receiver.recv_deadline(start + timeout) {
238+
Err(RecvTimeoutError::Timeout(_)) => {}
239+
_ => panic!("expected timeout error"),
240+
}
241+
242+
assert!(start.elapsed() >= timeout);
243+
assert!(start.elapsed() < timeout * 3);
244+
}
245+
246+
#[test]
247+
fn recv_time_passed() {
248+
let (_sender, receiver) = oneshot::channel::<u128>();
249+
250+
let start = Instant::now();
251+
let timeout = Duration::from_millis(100);
252+
match receiver.recv_timeout(timeout) {
253+
Err(RecvTimeoutError::Timeout(_)) => {}
254+
_ => panic!("expected timeout error"),
255+
}
256+
assert!(start.elapsed() >= timeout);
257+
assert!(start.elapsed() < timeout * 3);
258+
}
259+
260+
#[test]
261+
fn non_send_type_can_be_used_on_same_thread() {
262+
use std::ptr;
263+
264+
#[derive(Debug, Eq, PartialEq)]
265+
struct NotSend(*mut ());
266+
267+
let (sender, receiver) = oneshot::channel();
268+
sender.send(NotSend(ptr::null_mut())).unwrap();
269+
let reply = receiver.try_recv().unwrap();
270+
assert_eq!(reply, NotSend(ptr::null_mut()));
271+
}
272+
273+
/// Helper for testing drop behavior (taken directly from the `oneshot` crate).
274+
struct DropCounter {
275+
count: std::rc::Rc<std::cell::RefCell<usize>>,
276+
}
277+
278+
impl DropCounter {
279+
fn new() -> (DropTracker, DropCounter) {
280+
let count = std::rc::Rc::new(std::cell::RefCell::new(0));
281+
(DropTracker { count: count.clone() }, DropCounter { count })
282+
}
283+
284+
fn count(&self) -> usize {
285+
*self.count.borrow()
286+
}
287+
}
288+
289+
struct DropTracker {
290+
count: std::rc::Rc<std::cell::RefCell<usize>>,
291+
}
292+
293+
impl Drop for DropTracker {
294+
fn drop(&mut self) {
295+
*self.count.borrow_mut() += 1;
296+
}
297+
}
298+
299+
#[test]
300+
fn message_in_channel_dropped_on_receiver_drop() {
301+
let (sender, receiver) = oneshot::channel();
302+
303+
let (message, counter) = DropCounter::new();
304+
assert_eq!(counter.count(), 0);
305+
306+
sender.send(message).unwrap();
307+
assert_eq!(counter.count(), 0);
308+
309+
mem::drop(receiver);
310+
assert_eq!(counter.count(), 1);
311+
}
312+
313+
#[test]
314+
fn send_error_drops_message_correctly() {
315+
let (sender, receiver) = oneshot::channel();
316+
mem::drop(receiver);
317+
318+
let (message, counter) = DropCounter::new();
319+
320+
let send_error = sender.send(message).unwrap_err();
321+
assert_eq!(counter.count(), 0);
322+
323+
mem::drop(send_error);
324+
assert_eq!(counter.count(), 1);
325+
}
326+
327+
#[test]
328+
fn send_error_drops_message_correctly_on_extract() {
329+
let (sender, receiver) = oneshot::channel();
330+
mem::drop(receiver);
331+
332+
let (message, counter) = DropCounter::new();
333+
334+
let send_error = sender.send(message).unwrap_err();
335+
assert_eq!(counter.count(), 0);
336+
337+
let message = send_error.0; // Access the inner value directly
338+
assert_eq!(counter.count(), 0);
339+
340+
mem::drop(message);
341+
assert_eq!(counter.count(), 1);
342+
}

0 commit comments

Comments
 (0)