summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serial_test
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/serial_test')
-rw-r--r--third_party/rust/serial_test/.cargo-checksum.json1
-rw-r--r--third_party/rust/serial_test/Cargo.toml46
-rw-r--r--third_party/rust/serial_test/LICENSE19
-rw-r--r--third_party/rust/serial_test/README.md51
-rw-r--r--third_party/rust/serial_test/src/code_lock.rs72
-rw-r--r--third_party/rust/serial_test/src/file_lock.rs86
-rw-r--r--third_party/rust/serial_test/src/lib.rs60
-rw-r--r--third_party/rust/serial_test/src/rwlock.rs30
-rw-r--r--third_party/rust/serial_test/tests/tests.rs8
9 files changed, 373 insertions, 0 deletions
diff --git a/third_party/rust/serial_test/.cargo-checksum.json b/third_party/rust/serial_test/.cargo-checksum.json
new file mode 100644
index 0000000000..e02e1074db
--- /dev/null
+++ b/third_party/rust/serial_test/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"3eaed30d780757b28e3db22c8dc2ae302f94b8ef7be4c3452c171a3fa1f66c0b","LICENSE":"ac7e05bd11cc1cfc3f9452c1b9986a9b1d54e180fa88e44e69caf955f95dc8a6","README.md":"b6df6928aece5915ef3469e8384c3716a4fe58820fd1e8ab758c061bd5a499f0","src/code_lock.rs":"775bc592dc9f09aaef90d6455b0ed584fc571224611de4497f5ab0136abc4e78","src/file_lock.rs":"e4c954278a467674648ee43c1b10d0013201358d7c4bbc8cc3678b5af17b9848","src/lib.rs":"6462996f756ee44b47562462a1c5148672c90a6dfc1c093319e583b08b1d251a","src/rwlock.rs":"51c99268a9bb86c601373dbb84f549cd7694ffab151b72ee789d73c149bbf5c7","tests/tests.rs":"242fd98c91c8c42e39a0795a40f44fc11451be54b3196dc4487796f929322bc8"},"package":"e5bcc41d18f7a1d50525d080fd3e953be87c4f9f1a974f3c21798ca00d54ec15"} \ No newline at end of file
diff --git a/third_party/rust/serial_test/Cargo.toml b/third_party/rust/serial_test/Cargo.toml
new file mode 100644
index 0000000000..1f46e3cc66
--- /dev/null
+++ b/third_party/rust/serial_test/Cargo.toml
@@ -0,0 +1,46 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "serial_test"
+version = "0.6.0"
+authors = ["Tom Parker-Shemilt <palfrey@tevp.net>"]
+description = "Allows for the creation of serialised Rust tests"
+readme = "README.md"
+keywords = ["sequential"]
+categories = ["development-tools::testing"]
+license = "MIT"
+repository = "https://github.com/palfrey/serial_test/"
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg", "docsrs"]
+[dependencies.document-features]
+version = "0.2"
+optional = true
+
+[dependencies.fslock]
+version = "0.2"
+optional = true
+
+[dependencies.lazy_static]
+version = "1.2"
+
+[dependencies.parking_lot]
+version = ">= 0.10, < 0.12"
+
+[dependencies.serial_test_derive]
+version = "~0.6.0"
+
+[features]
+default = []
+docsrs = ["document-features"]
+file_locks = ["fslock"]
diff --git a/third_party/rust/serial_test/LICENSE b/third_party/rust/serial_test/LICENSE
new file mode 100644
index 0000000000..5a8adc1d4d
--- /dev/null
+++ b/third_party/rust/serial_test/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018 Tom Parker-Shemilt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE. \ No newline at end of file
diff --git a/third_party/rust/serial_test/README.md b/third_party/rust/serial_test/README.md
new file mode 100644
index 0000000000..d379a1d2fd
--- /dev/null
+++ b/third_party/rust/serial_test/README.md
@@ -0,0 +1,51 @@
+# serial_test
+[![Version](https://img.shields.io/crates/v/serial_test.svg)](https://crates.io/crates/serial_test)
+[![Downloads](https://img.shields.io/crates/d/serial_test)](https://crates.io/crates/serial_test)
+[![Docs](https://docs.rs/serial_test/badge.svg)](https://docs.rs/serial_test/)
+[![MIT license](https://img.shields.io/crates/l/serial_test.svg)](./LICENSE)
+[![Build Status](https://github.com/palfrey/serial_test/workflows/Continuous%20integration/badge.svg?branch=main)](https://github.com/palfrey/serial_test/actions)
+[![MSRV: 1.39.0](https://flat.badgen.net/badge/MSRV/1.39.0/purple)](https://blog.rust-lang.org/2019/11/07/Rust-1.39.0.html)
+
+`serial_test` allows for the creation of serialised Rust tests using the `serial` attribute
+e.g.
+```rust
+#[test]
+#[serial]
+fn test_serial_one() {
+ // Do things
+}
+
+#[test]
+#[serial]
+fn test_serial_another() {
+ // Do things
+}
+
+#[tokio::test]
+#[serial]
+async fn test_serial_another() {
+ // Do things asynchronously
+}
+```
+Multiple tests with the `serial` attribute are guaranteed to be executed in serial. Ordering of the tests is not guaranteed however.
+Tests without the `serial` attribute may run at any time, including in parallel to tests marked as `serial`. Note that if you're using
+an async test reactor attribute (e.g. `tokio::test` or `actix_rt::test`) then they should be listed *before* `serial`, otherwise we
+don't get an async function and things break. There's now an error for this case to improve debugging.
+
+## Usage
+We require at least Rust 1.39 for [async/await](https://blog.rust-lang.org/2019/11/07/Async-await-stable.html) support
+
+Add to your Cargo.toml
+```toml
+[dev-dependencies]
+serial_test = "*"
+```
+
+plus `use serial_test::serial;` (for Rust 2018) or
+```rust
+#[macro_use]
+extern crate serial_test;
+```
+for earlier versions.
+
+You can then either add `#[serial]` or `#[serial(some_text)]` to tests as required.
diff --git a/third_party/rust/serial_test/src/code_lock.rs b/third_party/rust/serial_test/src/code_lock.rs
new file mode 100644
index 0000000000..a09b2f8d1e
--- /dev/null
+++ b/third_party/rust/serial_test/src/code_lock.rs
@@ -0,0 +1,72 @@
+use lazy_static::lazy_static;
+use parking_lot::ReentrantMutex;
+use std::collections::HashMap;
+use std::ops::{Deref, DerefMut};
+use std::sync::{Arc, RwLock};
+
+lazy_static! {
+ static ref LOCKS: Arc<RwLock<HashMap<String, ReentrantMutex<()>>>> =
+ Arc::new(RwLock::new(HashMap::new()));
+}
+
+fn check_new_key(name: &str) {
+ // Check if a new key is needed. Just need a read lock, which can be done in sync with everyone else
+ let new_key = {
+ let unlock = LOCKS.read().unwrap();
+ !unlock.deref().contains_key(name)
+ };
+ if new_key {
+ // This is the rare path, which avoids the multi-writer situation mostly
+ LOCKS
+ .write()
+ .unwrap()
+ .deref_mut()
+ .insert(name.to_string(), ReentrantMutex::new(()));
+ }
+}
+
+#[doc(hidden)]
+pub fn local_serial_core_with_return<E>(
+ name: &str,
+ function: fn() -> Result<(), E>,
+) -> Result<(), E> {
+ check_new_key(name);
+
+ let unlock = LOCKS.read().unwrap();
+ // _guard needs to be named to avoid being instant dropped
+ let _guard = unlock.deref()[name].lock();
+ function()
+}
+
+#[doc(hidden)]
+pub fn local_serial_core(name: &str, function: fn()) {
+ check_new_key(name);
+
+ let unlock = LOCKS.read().unwrap();
+ // _guard needs to be named to avoid being instant dropped
+ let _guard = unlock.deref()[name].lock();
+ function();
+}
+
+#[doc(hidden)]
+pub async fn local_async_serial_core_with_return<E>(
+ name: &str,
+ fut: impl std::future::Future<Output = Result<(), E>>,
+) -> Result<(), E> {
+ check_new_key(name);
+
+ let unlock = LOCKS.read().unwrap();
+ // _guard needs to be named to avoid being instant dropped
+ let _guard = unlock.deref()[name].lock();
+ fut.await
+}
+
+#[doc(hidden)]
+pub async fn local_async_serial_core(name: &str, fut: impl std::future::Future<Output = ()>) {
+ check_new_key(name);
+
+ let unlock = LOCKS.read().unwrap();
+ // _guard needs to be named to avoid being instant dropped
+ let _guard = unlock.deref()[name].lock();
+ fut.await;
+}
diff --git a/third_party/rust/serial_test/src/file_lock.rs b/third_party/rust/serial_test/src/file_lock.rs
new file mode 100644
index 0000000000..20cd99eddb
--- /dev/null
+++ b/third_party/rust/serial_test/src/file_lock.rs
@@ -0,0 +1,86 @@
+use fslock::LockFile;
+use std::{env, fs, path::Path};
+
+struct Lock {
+ lockfile: LockFile,
+}
+
+impl Lock {
+ fn unlock(self: &mut Lock) {
+ self.lockfile.unlock().unwrap();
+ println!("Unlock");
+ }
+}
+
+fn do_lock(path: &str) -> Lock {
+ if !Path::new(path).exists() {
+ fs::write(path, "").unwrap_or_else(|_| panic!("Lock file path was {:?}", path))
+ }
+ let mut lockfile = LockFile::open(path).unwrap();
+ println!("Waiting on {:?}", path);
+ lockfile.lock().unwrap();
+ println!("Locked for {:?}", path);
+ Lock { lockfile }
+}
+
+fn path_for_name(name: &str) -> String {
+ let mut pathbuf = env::temp_dir();
+ pathbuf.push(format!("serial-test-{}", name));
+ pathbuf.into_os_string().into_string().unwrap()
+}
+
+fn make_lock_for_name_and_path(name: &str, path: Option<&str>) -> Lock {
+ if let Some(opt_path) = path {
+ do_lock(opt_path)
+ } else {
+ let default_path = path_for_name(name);
+ do_lock(&default_path)
+ }
+}
+
+#[doc(hidden)]
+pub fn fs_serial_core(name: &str, path: Option<&str>, function: fn()) {
+ let mut lock = make_lock_for_name_and_path(name, path);
+ function();
+ lock.unlock();
+}
+
+#[doc(hidden)]
+pub fn fs_serial_core_with_return<E>(
+ name: &str,
+ path: Option<&str>,
+ function: fn() -> Result<(), E>,
+) -> Result<(), E> {
+ let mut lock = make_lock_for_name_and_path(name, path);
+ let ret = function();
+ lock.unlock();
+ ret
+}
+
+#[doc(hidden)]
+pub async fn fs_async_serial_core_with_return<E>(
+ name: &str,
+ path: Option<&str>,
+ fut: impl std::future::Future<Output = Result<(), E>>,
+) -> Result<(), E> {
+ let mut lock = make_lock_for_name_and_path(name, path);
+ let ret = fut.await;
+ lock.unlock();
+ ret
+}
+
+#[doc(hidden)]
+pub async fn fs_async_serial_core(
+ name: &str,
+ path: Option<&str>,
+ fut: impl std::future::Future<Output = ()>,
+) {
+ let mut lock = make_lock_for_name_and_path(name, path);
+ fut.await;
+ lock.unlock();
+}
+
+#[test]
+fn test_serial() {
+ fs_serial_core("test", None, || {});
+}
diff --git a/third_party/rust/serial_test/src/lib.rs b/third_party/rust/serial_test/src/lib.rs
new file mode 100644
index 0000000000..e83eec042d
--- /dev/null
+++ b/third_party/rust/serial_test/src/lib.rs
@@ -0,0 +1,60 @@
+#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
+
+//! # serial_test
+//! `serial_test` allows for the creation of serialised Rust tests using the [serial](macro@serial) attribute
+//! e.g.
+//! ````
+//! #[test]
+//! #[serial]
+//! fn test_serial_one() {
+//! // Do things
+//! }
+//!
+//! #[test]
+//! #[serial]
+//! fn test_serial_another() {
+//! // Do things
+//! }
+//! ````
+//! Multiple tests with the [serial](macro@serial) attribute are guaranteed to be executed in serial. Ordering
+//! of the tests is not guaranteed however.
+//!
+//! For cases like doctests and integration tests where the tests are run as separate processes, we also support
+//! [file_serial](macro@file_serial), with similar properties but based off file locking. Note that there are no
+//! guarantees about one test with [serial](macro@serial) and another with [file_serial](macro@file_serial)
+//! as they lock using different methods.
+//! ````
+//! #[test]
+//! #[file_serial]
+//! fn test_serial_three() {
+//! // Do things
+//! }
+//! ````
+//!
+//! ## Feature flags
+#![cfg_attr(
+ feature = "docsrs",
+ cfg_attr(doc, doc = ::document_features::document_features!())
+)]
+
+mod code_lock;
+#[cfg(feature = "file_locks")]
+mod file_lock;
+
+pub use code_lock::{
+ local_async_serial_core, local_async_serial_core_with_return, local_serial_core,
+ local_serial_core_with_return,
+};
+
+#[cfg(feature = "file_locks")]
+pub use file_lock::{
+ fs_async_serial_core, fs_async_serial_core_with_return, fs_serial_core,
+ fs_serial_core_with_return,
+};
+
+// Re-export #[serial/file_serial].
+#[allow(unused_imports)]
+pub use serial_test_derive::serial;
+
+#[cfg(feature = "file_locks")]
+pub use serial_test_derive::file_serial;
diff --git a/third_party/rust/serial_test/src/rwlock.rs b/third_party/rust/serial_test/src/rwlock.rs
new file mode 100644
index 0000000000..42c1a99707
--- /dev/null
+++ b/third_party/rust/serial_test/src/rwlock.rs
@@ -0,0 +1,30 @@
+use std::sync::{ Arc, Mutex, Condvar};
+
+// LockState can be in several possible states:
+
+// 1. 0 readers, false upgradeable_reader, false writer. No-one has any locks, anyone can acquire anything (initial state)
+// 2. 1+ readers, false upgradeable_reader, false writer - readers. writer cannot be acquired, but upgradeable_reader can be
+// 3. 1+ readers, true upgradeable_reader, false writer - bunch of readers, and one thread that could upgrade to writer, but not yet
+// 4. 0 readers, true upgradeable_reader, false writer - upgradeable_reader thread can upgrade to writer
+// 5. 0 readers, false upgradeable_reader, true writer - writer only. Nothing else can be acquired.
+
+struct LockState {
+ readers: u32,
+ upgradeable_reader: bool,
+ writer: bool
+}
+
+struct Locks(Arc<(Mutex<LockState>, Condvar)>);
+
+impl Locks {
+ pub fn new() -> Locks {
+ Locks(Arc::new((Mutex::new(
+ LockState {
+ readers: 0,
+ upgradeable_reader: false,
+ writer: false
+ }), Condvar::new())))
+ }
+
+ pub fn read() ->
+} \ No newline at end of file
diff --git a/third_party/rust/serial_test/tests/tests.rs b/third_party/rust/serial_test/tests/tests.rs
new file mode 100644
index 0000000000..add8b10dec
--- /dev/null
+++ b/third_party/rust/serial_test/tests/tests.rs
@@ -0,0 +1,8 @@
+use serial_test::local_serial_core;
+
+#[test]
+fn test_empty_serial_call() {
+ local_serial_core("beta", || {
+ println!("Bar");
+ });
+}