2019-08-10 00:07:57 +09:00
|
|
|
#![warn(rust_2018_idioms)]
|
2022-01-27 14:07:52 +00:00
|
|
|
#![cfg(feature = "sync")]
|
|
|
|
|
|
2023-07-27 18:57:19 +10:00
|
|
|
#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
|
2022-01-27 14:07:52 +00:00
|
|
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
2023-07-27 18:57:19 +10:00
|
|
|
#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
|
2022-01-27 14:07:52 +00:00
|
|
|
use wasm_bindgen_test::wasm_bindgen_test as maybe_tokio_test;
|
|
|
|
|
|
2023-07-27 18:57:19 +10:00
|
|
|
#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))]
|
2022-01-27 14:07:52 +00:00
|
|
|
use tokio::test as maybe_tokio_test;
|
2019-04-18 13:16:26 -04:00
|
|
|
|
2019-10-29 15:11:31 -07:00
|
|
|
use tokio::sync::Mutex;
|
2019-08-06 13:54:56 -07:00
|
|
|
use tokio_test::task::spawn;
|
2019-06-24 12:34:30 -07:00
|
|
|
use tokio_test::{assert_pending, assert_ready};
|
2019-04-18 13:16:26 -04:00
|
|
|
|
2019-10-29 15:11:31 -07:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
2019-04-18 13:16:26 -04:00
|
|
|
#[test]
|
|
|
|
|
fn straight_execution() {
|
2019-09-19 11:46:52 -04:00
|
|
|
let l = Mutex::new(100);
|
2019-04-18 13:16:26 -04:00
|
|
|
|
2019-08-06 13:54:56 -07:00
|
|
|
{
|
|
|
|
|
let mut t = spawn(l.lock());
|
|
|
|
|
let mut g = assert_ready!(t.poll());
|
2019-06-24 12:34:30 -07:00
|
|
|
assert_eq!(&*g, &100);
|
|
|
|
|
*g = 99;
|
2019-08-06 13:54:56 -07:00
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
let mut t = spawn(l.lock());
|
|
|
|
|
let mut g = assert_ready!(t.poll());
|
2019-06-24 12:34:30 -07:00
|
|
|
assert_eq!(&*g, &99);
|
|
|
|
|
*g = 98;
|
2019-08-06 13:54:56 -07:00
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
let mut t = spawn(l.lock());
|
2019-09-19 11:46:52 -04:00
|
|
|
let g = assert_ready!(t.poll());
|
2019-06-24 12:34:30 -07:00
|
|
|
assert_eq!(&*g, &98);
|
2019-08-06 13:54:56 -07:00
|
|
|
}
|
2019-04-18 13:16:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn readiness() {
|
2019-09-19 11:46:52 -04:00
|
|
|
let l1 = Arc::new(Mutex::new(100));
|
|
|
|
|
let l2 = Arc::clone(&l1);
|
2019-08-06 13:54:56 -07:00
|
|
|
let mut t1 = spawn(l1.lock());
|
|
|
|
|
let mut t2 = spawn(l2.lock());
|
2019-06-24 12:34:30 -07:00
|
|
|
|
2019-08-06 13:54:56 -07:00
|
|
|
let g = assert_ready!(t1.poll());
|
2019-04-18 13:16:26 -04:00
|
|
|
|
|
|
|
|
// We can't now acquire the lease since it's already held in g
|
2019-08-06 13:54:56 -07:00
|
|
|
assert_pending!(t2.poll());
|
2019-04-18 13:16:26 -04:00
|
|
|
|
|
|
|
|
// But once g unlocks, we can acquire it
|
|
|
|
|
drop(g);
|
2019-06-24 12:34:30 -07:00
|
|
|
assert!(t2.is_woken());
|
2022-08-09 14:44:29 +03:00
|
|
|
let _t2 = assert_ready!(t2.poll());
|
2019-04-18 13:16:26 -04:00
|
|
|
}
|
2019-06-25 13:42:35 -04:00
|
|
|
|
2019-08-06 13:54:56 -07:00
|
|
|
/*
|
2019-06-25 13:42:35 -04:00
|
|
|
#[test]
|
2019-06-30 08:48:53 -07:00
|
|
|
#[ignore]
|
2019-06-25 13:42:35 -04:00
|
|
|
fn lock() {
|
2019-09-19 11:46:52 -04:00
|
|
|
let mut lock = Mutex::new(false);
|
2019-06-25 13:42:35 -04:00
|
|
|
|
|
|
|
|
let mut lock2 = lock.clone();
|
|
|
|
|
std::thread::spawn(move || {
|
|
|
|
|
let l = lock2.lock();
|
|
|
|
|
pin_mut!(l);
|
|
|
|
|
|
|
|
|
|
let mut task = MockTask::new();
|
2019-06-26 11:32:41 -04:00
|
|
|
let mut g = assert_ready!(task.poll(&mut l));
|
2019-06-25 13:42:35 -04:00
|
|
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
|
|
|
|
*g = true;
|
|
|
|
|
drop(g);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
|
|
|
|
let mut task = MockTask::new();
|
|
|
|
|
let l = lock.lock();
|
|
|
|
|
pin_mut!(l);
|
|
|
|
|
|
2019-06-26 11:32:41 -04:00
|
|
|
assert_pending!(task.poll(&mut l));
|
|
|
|
|
|
2019-06-25 13:42:35 -04:00
|
|
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
|
|
|
|
assert!(task.is_woken());
|
2019-06-26 11:32:41 -04:00
|
|
|
let result = assert_ready!(task.poll(&mut l));
|
|
|
|
|
assert!(*result);
|
2019-06-25 13:42:35 -04:00
|
|
|
}
|
2019-08-06 13:54:56 -07:00
|
|
|
*/
|
2019-12-06 23:30:02 +01:00
|
|
|
|
|
|
|
|
/// Ensure a mutex is unlocked if a future holding the lock
|
|
|
|
|
/// is aborted prematurely.
|
2022-01-27 14:07:52 +00:00
|
|
|
#[tokio::test]
|
|
|
|
|
#[cfg(feature = "full")]
|
2019-12-06 23:30:02 +01:00
|
|
|
async fn aborted_future_1() {
|
2022-01-27 14:07:52 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
|
use tokio::time::{interval, timeout};
|
|
|
|
|
|
2019-12-06 23:30:02 +01:00
|
|
|
let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
|
|
|
|
|
{
|
|
|
|
|
let m2 = m1.clone();
|
|
|
|
|
// Try to lock mutex in a future that is aborted prematurely
|
|
|
|
|
timeout(Duration::from_millis(1u64), async move {
|
2020-11-23 10:42:50 -08:00
|
|
|
let iv = interval(Duration::from_millis(1000));
|
|
|
|
|
tokio::pin!(iv);
|
2022-08-09 14:44:29 +03:00
|
|
|
let _g = m2.lock().await;
|
2020-11-23 10:42:50 -08:00
|
|
|
iv.as_mut().tick().await;
|
|
|
|
|
iv.as_mut().tick().await;
|
2019-12-06 23:30:02 +01:00
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
.unwrap_err();
|
|
|
|
|
}
|
|
|
|
|
// This should succeed as there is no lock left for the mutex.
|
|
|
|
|
timeout(Duration::from_millis(1u64), async move {
|
2022-08-09 14:44:29 +03:00
|
|
|
let _g = m1.lock().await;
|
2019-12-06 23:30:02 +01:00
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
.expect("Mutex is locked");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// This test is similar to `aborted_future_1` but this time the
|
|
|
|
|
/// aborted future is waiting for the lock.
|
2022-01-27 14:07:52 +00:00
|
|
|
#[tokio::test]
|
|
|
|
|
#[cfg(feature = "full")]
|
2019-12-06 23:30:02 +01:00
|
|
|
async fn aborted_future_2() {
|
2022-01-27 14:07:52 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
|
use tokio::time::timeout;
|
|
|
|
|
|
2019-12-06 23:30:02 +01:00
|
|
|
let m1: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
|
|
|
|
|
{
|
|
|
|
|
// Lock mutex
|
|
|
|
|
let _lock = m1.lock().await;
|
|
|
|
|
{
|
|
|
|
|
let m2 = m1.clone();
|
|
|
|
|
// Try to lock mutex in a future that is aborted prematurely
|
|
|
|
|
timeout(Duration::from_millis(1u64), async move {
|
2022-08-09 14:44:29 +03:00
|
|
|
let _g = m2.lock().await;
|
2019-12-06 23:30:02 +01:00
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
.unwrap_err();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// This should succeed as there is no lock left for the mutex.
|
|
|
|
|
timeout(Duration::from_millis(1u64), async move {
|
2022-08-09 14:44:29 +03:00
|
|
|
let _g = m1.lock().await;
|
2019-12-06 23:30:02 +01:00
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
.expect("Mutex is locked");
|
|
|
|
|
}
|
2019-12-10 17:01:23 +01:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn try_lock() {
|
|
|
|
|
let m: Mutex<usize> = Mutex::new(0);
|
|
|
|
|
{
|
|
|
|
|
let g1 = m.try_lock();
|
2021-08-03 11:50:40 +03:00
|
|
|
assert!(g1.is_ok());
|
2019-12-10 17:01:23 +01:00
|
|
|
let g2 = m.try_lock();
|
2022-03-08 12:24:19 -08:00
|
|
|
assert!(g2.is_err());
|
2019-12-10 17:01:23 +01:00
|
|
|
}
|
|
|
|
|
let g3 = m.try_lock();
|
2021-08-03 11:50:40 +03:00
|
|
|
assert!(g3.is_ok());
|
2019-12-10 17:01:23 +01:00
|
|
|
}
|
2019-12-18 14:02:31 +08:00
|
|
|
|
2022-01-27 14:07:52 +00:00
|
|
|
#[maybe_tokio_test]
|
2019-12-18 14:02:31 +08:00
|
|
|
async fn debug_format() {
|
|
|
|
|
let s = "debug";
|
|
|
|
|
let m = Mutex::new(s.to_string());
|
|
|
|
|
assert_eq!(format!("{:?}", s), format!("{:?}", m.lock().await));
|
|
|
|
|
}
|
2020-07-31 22:00:23 +03:00
|
|
|
|
2022-01-27 14:07:52 +00:00
|
|
|
#[maybe_tokio_test]
|
2020-07-31 22:00:23 +03:00
|
|
|
async fn mutex_debug() {
|
|
|
|
|
let s = "data";
|
|
|
|
|
let m = Mutex::new(s.to_string());
|
|
|
|
|
assert_eq!(format!("{:?}", m), r#"Mutex { data: "data" }"#);
|
|
|
|
|
let _guard = m.lock().await;
|
|
|
|
|
assert_eq!(format!("{:?}", m), r#"Mutex { data: <locked> }"#)
|
|
|
|
|
}
|