Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1388114

Browse files
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)

AltStyle によって変換されたページ (->オリジナル) /