From 4bcb5c4dc88ee41ee0b65939d7928242ff1cfcaa Mon Sep 17 00:00:00 2001 From: Muhan Song Date: Fri, 29 Sep 2023 15:17:28 +0800 Subject: [PATCH] docs: add semaphore example Signed-off-by: Muhan Song --- tokio/src/sync/semaphore.rs | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tokio/src/sync/semaphore.rs b/tokio/src/sync/semaphore.rs index 08a86f4b9f7..ed48300e95c 100644 --- a/tokio/src/sync/semaphore.rs +++ b/tokio/src/sync/semaphore.rs @@ -210,6 +210,55 @@ use std::sync::Arc; /// } /// ``` /// +/// ## Ensure Tests with Mutual Dependencies Run Sequentially +/// +/// By default, Rust runs tests concurrently. However, in some scenarios, concurrent execution might lead to test interference. +/// For example, multiple tests might communicate with the same database, necessitating sequential execution to prevent data conflicts. +/// +/// Consider the following scenario: +/// 1. `test_insert`: Inserts a key-value pair into the database, then retrieves the value using the same key to verify the insertion. +/// 2. `test_update`: After insertion, this test updates the key's value to a new one and verifies if the value has been accurately updated. +/// 3. `test_others`: This is a non-interfering test that can run concurrently with other tests. +/// +/// For this example, it's essential that `test_insert` and `test_update` run sequentially, though their execution order is inconsequential. +/// Leveraging a semaphore with a single permit elegantly addresses this challenge. +/// +/// ``` +/// #[cfg(test)] +/// mod tests { +/// use tokio::sync::Semaphore; +/// // only one permit can be acquired +/// static PERMIT: Semaphore = Semaphore::const_new(1); +/// // initilization of database +/// static DB: database = database::setup(); +/// #[tokio::test] +/// async fn test_insert() { +/// // acquire permit first +/// let permit = PERMIT.acquire().await.unwrap(); +/// let (key, value) = ("name", 0); +/// DB.insert((key, value)).await; +/// assert_eq!(DB.get(key), value); +/// // undo the modification +/// DB.delete(key).await; +/// // permit dropped here +/// } +/// #[tokio::test] +/// async fn test_update() { +/// let permit = PERMIT.acquire().await.unwrap(); +/// let (key, value) = ("name", 0); +/// DB.insert((key, value)).await; +/// let new_value = 1; +/// // update new value at the same key +/// DB.update((key, new_value)).await; +/// assert_eq!(DB.get(key).await, new_value); +/// DB.delete(key).await; +/// } +/// #[tokio::test] +/// async fn test_other() { +/// // this test can simualtenously run with test_insert and test_update. +/// } +/// } +/// ``` /// [`PollSemaphore`]: https://docs.rs/tokio-util/latest/tokio_util/sync/struct.PollSemaphore.html /// [`Semaphore::acquire_owned`]: crate::sync::Semaphore::acquire_owned #[derive(Debug)]