summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serial_test_derive
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/serial_test_derive
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/serial_test_derive')
-rw-r--r--third_party/rust/serial_test_derive/.cargo-checksum.json1
-rw-r--r--third_party/rust/serial_test_derive/Cargo.toml44
-rw-r--r--third_party/rust/serial_test_derive/LICENSE19
-rw-r--r--third_party/rust/serial_test_derive/README.md51
-rw-r--r--third_party/rust/serial_test_derive/src/lib.rs414
-rw-r--r--third_party/rust/serial_test_derive/tests/broken/test_serial_async_before_wrapper.rs7
-rw-r--r--third_party/rust/serial_test_derive/tests/broken/test_serial_async_before_wrapper.stderr7
7 files changed, 543 insertions, 0 deletions
diff --git a/third_party/rust/serial_test_derive/.cargo-checksum.json b/third_party/rust/serial_test_derive/.cargo-checksum.json
new file mode 100644
index 0000000000..313de515d5
--- /dev/null
+++ b/third_party/rust/serial_test_derive/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"a02b6139f1d683aff6731643e41aaf0ffb5d8ea7e186f9e2bbdbcba5a4837f7d","LICENSE":"ac7e05bd11cc1cfc3f9452c1b9986a9b1d54e180fa88e44e69caf955f95dc8a6","README.md":"b6df6928aece5915ef3469e8384c3716a4fe58820fd1e8ab758c061bd5a499f0","src/lib.rs":"0881974b990368dd1fabcbb97b5f75e861f1acbf150f0fe740abf8a4576c80db","tests/broken/test_serial_async_before_wrapper.rs":"fc61e416a5ec885af93e2e846323ca5bc6ca7c2e7e315c26e1f7f035b029b96e","tests/broken/test_serial_async_before_wrapper.stderr":"139864bee445d9ef9d554d4c261c657dda8c864b402e1d6dd66bdde3037c3fe8"},"package":"2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8"} \ No newline at end of file
diff --git a/third_party/rust/serial_test_derive/Cargo.toml b/third_party/rust/serial_test_derive/Cargo.toml
new file mode 100644
index 0000000000..95fe5bcfe9
--- /dev/null
+++ b/third_party/rust/serial_test_derive/Cargo.toml
@@ -0,0 +1,44 @@
+# 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_derive"
+version = "0.6.0"
+authors = ["Tom Parker-Shemilt <palfrey@tevp.net>"]
+description = "Helper crate for serial_test"
+readme = "README.md"
+categories = ["development-tools::testing"]
+license = "MIT"
+repository = "https://github.com/palfrey/serial_test/"
+
+[lib]
+proc-macro = true
+[dependencies.proc-macro-error]
+version = "1"
+
+[dependencies.proc-macro2]
+version = "1.0"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.rustversion]
+version = "1.0"
+
+[dependencies.syn]
+version = "1.0"
+features = ["full"]
+[dev-dependencies.env_logger]
+version = ">= 0.7, <0.9"
+
+[dev-dependencies.trybuild]
+version = "1"
diff --git a/third_party/rust/serial_test_derive/LICENSE b/third_party/rust/serial_test_derive/LICENSE
new file mode 100644
index 0000000000..5a8adc1d4d
--- /dev/null
+++ b/third_party/rust/serial_test_derive/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_derive/README.md b/third_party/rust/serial_test_derive/README.md
new file mode 100644
index 0000000000..d379a1d2fd
--- /dev/null
+++ b/third_party/rust/serial_test_derive/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_derive/src/lib.rs b/third_party/rust/serial_test_derive/src/lib.rs
new file mode 100644
index 0000000000..3e827cb967
--- /dev/null
+++ b/third_party/rust/serial_test_derive/src/lib.rs
@@ -0,0 +1,414 @@
+//! # serial_test_derive
+//! Helper crate for [serial_test](../serial_test/index.html)
+
+#![cfg_attr(docsrs, feature(doc_cfg))]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+use proc_macro2::TokenTree;
+use proc_macro_error::{abort_call_site, proc_macro_error};
+use quote::{format_ident, quote, ToTokens, TokenStreamExt};
+use std::ops::Deref;
+
+/// Allows for the creation of serialised Rust tests
+/// ````
+/// #[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. If you want different subsets of tests to be serialised with each
+/// other, but not depend on other subsets, you can add an argument to [serial](macro@serial), and all calls
+/// with identical arguments will be called in serial. e.g.
+/// ````
+/// #[test]
+/// #[serial(something)]
+/// fn test_serial_one() {
+/// // Do things
+/// }
+///
+/// #[test]
+/// #[serial(something)]
+/// fn test_serial_another() {
+/// // Do things
+/// }
+///
+/// #[test]
+/// #[serial(other)]
+/// fn test_serial_third() {
+/// // Do things
+/// }
+///
+/// #[test]
+/// #[serial(other)]
+/// fn test_serial_fourth() {
+/// // Do things
+/// }
+/// ````
+/// `test_serial_one` and `test_serial_another` will be executed in serial, as will `test_serial_third` and `test_serial_fourth`
+/// but neither sequence will be blocked by the other
+///
+/// Nested serialised tests (i.e. a [serial](macro@serial) tagged test calling another) is supported
+#[proc_macro_attribute]
+#[proc_macro_error]
+pub fn serial(attr: TokenStream, input: TokenStream) -> TokenStream {
+ local_serial_core(attr.into(), input.into()).into()
+}
+
+/// Allows for the creation of file-serialised Rust tests
+/// ````
+/// #[test]
+/// #[file_serial]
+/// fn test_serial_one() {
+/// // Do things
+/// }
+///
+/// #[test]
+/// #[file_serial]
+/// fn test_serial_another() {
+/// // Do things
+/// }
+/// ````
+///
+/// Multiple tests with the [file_serial](macro@file_serial) attribute are guaranteed to run in serial, as per the [serial](macro@serial)
+/// attribute. 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, and [file_serial](macro@file_serial) does not support nested serialised tests, but otherwise acts
+/// like [serial](macro@serial).
+///
+/// It also supports an optional `path` arg e.g
+/// ````
+/// #[test]
+/// #[file_serial(key, "/tmp/foo")]
+/// fn test_serial_one() {
+/// // Do things
+/// }
+///
+/// #[test]
+/// #[file_serial(key, "/tmp/foo")]
+/// fn test_serial_another() {
+/// // Do things
+/// }
+/// ````
+/// Note that in this case you need to specify the `name` arg as well (as per [serial](macro@serial)). The path defaults to a reasonable temp directory for the OS if not specified.
+#[proc_macro_attribute]
+#[proc_macro_error]
+#[cfg_attr(docsrs, doc(cfg(feature = "file_locks")))]
+pub fn file_serial(attr: TokenStream, input: TokenStream) -> TokenStream {
+ fs_serial_core(attr.into(), input.into()).into()
+}
+
+// Based off of https://github.com/dtolnay/quote/issues/20#issuecomment-437341743
+struct QuoteOption<T>(Option<T>);
+
+impl<T: ToTokens> ToTokens for QuoteOption<T> {
+ fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+ tokens.append_all(match self.0 {
+ Some(ref t) => quote! { ::std::option::Option::Some(#t) },
+ None => quote! { ::std::option::Option::None },
+ });
+ }
+}
+
+fn get_raw_args(attr: proc_macro2::TokenStream) -> Vec<String> {
+ let mut attrs = attr.into_iter().collect::<Vec<TokenTree>>();
+ let mut raw_args: Vec<String> = Vec::new();
+ while !attrs.is_empty() {
+ match attrs.remove(0) {
+ TokenTree::Ident(id) => {
+ raw_args.push(id.to_string());
+ }
+ TokenTree::Literal(literal) => {
+ let string_literal = literal.to_string();
+ if !string_literal.starts_with('\"') || !string_literal.ends_with('\"') {
+ panic!("Expected a string literal, got '{}'", string_literal);
+ }
+ // Hacky way of getting a string without the enclosing quotes
+ raw_args.push(string_literal[1..string_literal.len() - 1].to_string());
+ }
+ x => {
+ panic!("Expected either strings or literals as args, not {}", x);
+ }
+ }
+ if !attrs.is_empty() {
+ match attrs.remove(0) {
+ TokenTree::Punct(p) if p.as_char() == ',' => {}
+ x => {
+ panic!("Expected , between args, not {}", x);
+ }
+ }
+ }
+ }
+ raw_args
+}
+
+fn local_serial_core(
+ attr: proc_macro2::TokenStream,
+ input: proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ let mut raw_args = get_raw_args(attr);
+ let key = match raw_args.len() {
+ 0 => "".to_string(),
+ 1 => raw_args.pop().unwrap(),
+ n => {
+ panic!(
+ "Expected either 0 or 1 arguments, got {}: {:?}",
+ n, raw_args
+ );
+ }
+ };
+ serial_setup(input, vec![Box::new(key)], "local")
+}
+
+fn fs_serial_core(
+ attr: proc_macro2::TokenStream,
+ input: proc_macro2::TokenStream,
+) -> proc_macro2::TokenStream {
+ let none_ident = Box::new(format_ident!("None"));
+ let mut args: Vec<Box<dyn quote::ToTokens>> = Vec::new();
+ let mut raw_args = get_raw_args(attr);
+ match raw_args.len() {
+ 0 => {
+ args.push(Box::new("".to_string()));
+ args.push(none_ident);
+ }
+ 1 => {
+ args.push(Box::new(raw_args.pop().unwrap()));
+ args.push(none_ident);
+ }
+ 2 => {
+ let key = raw_args.remove(0);
+ let path = raw_args.remove(0);
+ args.push(Box::new(key));
+ args.push(Box::new(QuoteOption(Some(path))));
+ }
+ n => {
+ panic!("Expected 0-2 arguments, got {}: {:?}", n, raw_args);
+ }
+ }
+ serial_setup(input, args, "fs")
+}
+
+fn serial_setup<T>(
+ input: proc_macro2::TokenStream,
+ args: Vec<Box<T>>,
+ prefix: &str,
+) -> proc_macro2::TokenStream
+where
+ T: quote::ToTokens + ?Sized,
+{
+ let ast: syn::ItemFn = syn::parse2(input).unwrap();
+ let asyncness = ast.sig.asyncness;
+ let name = ast.sig.ident;
+ let return_type = match ast.sig.output {
+ syn::ReturnType::Default => None,
+ syn::ReturnType::Type(_rarrow, ref box_type) => Some(box_type.deref()),
+ };
+ let block = ast.block;
+ let attrs: Vec<syn::Attribute> = ast
+ .attrs
+ .into_iter()
+ .filter(|at| {
+ if let Ok(m) = at.parse_meta() {
+ let path = m.path();
+ if asyncness.is_some()
+ && path.segments.len() == 2
+ && path.segments[1].ident == "test"
+ {
+ // We assume that any 2-part attribute with the second part as "test" on an async function
+ // is the "do this test with reactor" wrapper. This is true for actix, tokio and async_std.
+ abort_call_site!("Found async test attribute after serial, which will break");
+ }
+
+ // we skip ignore/should_panic because the test framework already deals with it
+ !(path.is_ident("ignore") || path.is_ident("should_panic"))
+ } else {
+ true
+ }
+ })
+ .collect();
+ if let Some(ret) = return_type {
+ match asyncness {
+ Some(_) => {
+ let fnname = format_ident!("{}_async_serial_core_with_return", prefix);
+ quote! {
+ #(#attrs)
+ *
+ async fn #name () -> #ret {
+ serial_test::#fnname(#(#args ),*, || async #block ).await;
+ }
+ }
+ }
+ None => {
+ let fnname = format_ident!("{}_serial_core_with_return", prefix);
+ quote! {
+ #(#attrs)
+ *
+ fn #name () -> #ret {
+ serial_test::#fnname(#(#args ),*, || #block )
+ }
+ }
+ }
+ }
+ } else {
+ match asyncness {
+ Some(_) => {
+ let fnname = format_ident!("{}_async_serial_core", prefix);
+ quote! {
+ #(#attrs)
+ *
+ async fn #name () {
+ serial_test::#fnname(#(#args ),*, || async #block ).await;
+ }
+ }
+ }
+ None => {
+ let fnname = format_ident!("{}_serial_core", prefix);
+ quote! {
+ #(#attrs)
+ *
+ fn #name () {
+ serial_test::#fnname(#(#args ),*, || #block );
+ }
+ }
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use proc_macro2::{Literal, Punct, Spacing};
+
+ use super::{format_ident, fs_serial_core, local_serial_core, quote, TokenTree};
+ use std::iter::FromIterator;
+
+ #[test]
+ fn test_serial() {
+ let attrs = proc_macro2::TokenStream::new();
+ let input = quote! {
+ #[test]
+ fn foo() {}
+ };
+ let stream = local_serial_core(attrs.into(), input);
+ let compare = quote! {
+ #[test]
+ fn foo () {
+ serial_test::local_serial_core("", || {} );
+ }
+ };
+ assert_eq!(format!("{}", compare), format!("{}", stream));
+ }
+
+ #[test]
+ fn test_stripped_attributes() {
+ let _ = env_logger::builder().is_test(true).try_init();
+ let attrs = proc_macro2::TokenStream::new();
+ let input = quote! {
+ #[test]
+ #[ignore]
+ #[should_panic(expected = "Testing panic")]
+ #[something_else]
+ fn foo() {}
+ };
+ let stream = local_serial_core(attrs.into(), input);
+ let compare = quote! {
+ #[test]
+ #[something_else]
+ fn foo () {
+ serial_test::local_serial_core("", || {} );
+ }
+ };
+ assert_eq!(format!("{}", compare), format!("{}", stream));
+ }
+
+ #[test]
+ fn test_serial_async() {
+ let attrs = proc_macro2::TokenStream::new();
+ let input = quote! {
+ async fn foo() {}
+ };
+ let stream = local_serial_core(attrs.into(), input);
+ let compare = quote! {
+ async fn foo () {
+ serial_test::local_async_serial_core("", || async {} ).await;
+ }
+ };
+ assert_eq!(format!("{}", compare), format!("{}", stream));
+ }
+
+ #[test]
+ fn test_serial_async_return() {
+ let attrs = proc_macro2::TokenStream::new();
+ let input = quote! {
+ async fn foo() -> Result<(), ()> { Ok(()) }
+ };
+ let stream = local_serial_core(attrs.into(), input);
+ let compare = quote! {
+ async fn foo () -> Result<(), ()> {
+ serial_test::local_async_serial_core_with_return("", || async { Ok(()) } ).await;
+ }
+ };
+ assert_eq!(format!("{}", compare), format!("{}", stream));
+ }
+
+ // 1.54 needed for https://github.com/rust-lang/rust/commit/9daf546b77dbeab7754a80d7336cd8d00c6746e4 change in note message
+ #[rustversion::since(1.54)]
+ #[test]
+ fn test_serial_async_before_wrapper() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/broken/test_serial_async_before_wrapper.rs");
+ }
+
+ #[test]
+ fn test_file_serial() {
+ let attrs = vec![TokenTree::Ident(format_ident!("foo"))];
+ let input = quote! {
+ #[test]
+ fn foo() {}
+ };
+ let stream = fs_serial_core(
+ proc_macro2::TokenStream::from_iter(attrs.into_iter()),
+ input,
+ );
+ let compare = quote! {
+ #[test]
+ fn foo () {
+ serial_test::fs_serial_core("foo", None, || {} );
+ }
+ };
+ assert_eq!(format!("{}", compare), format!("{}", stream));
+ }
+
+ #[test]
+ fn test_file_serial_with_path() {
+ let attrs = vec![
+ TokenTree::Ident(format_ident!("foo")),
+ TokenTree::Punct(Punct::new(',', Spacing::Alone)),
+ TokenTree::Literal(Literal::string("bar_path")),
+ ];
+ let input = quote! {
+ #[test]
+ fn foo() {}
+ };
+ let stream = fs_serial_core(
+ proc_macro2::TokenStream::from_iter(attrs.into_iter()),
+ input,
+ );
+ let compare = quote! {
+ #[test]
+ fn foo () {
+ serial_test::fs_serial_core("foo", ::std::option::Option::Some("bar_path"), || {} );
+ }
+ };
+ assert_eq!(format!("{}", compare), format!("{}", stream));
+ }
+}
diff --git a/third_party/rust/serial_test_derive/tests/broken/test_serial_async_before_wrapper.rs b/third_party/rust/serial_test_derive/tests/broken/test_serial_async_before_wrapper.rs
new file mode 100644
index 0000000000..690eccf591
--- /dev/null
+++ b/third_party/rust/serial_test_derive/tests/broken/test_serial_async_before_wrapper.rs
@@ -0,0 +1,7 @@
+use serial_test_derive::serial;
+
+#[serial]
+#[actix_rt::test]
+async fn test_async_serial_no_arg_actix() {}
+
+fn main() {} \ No newline at end of file
diff --git a/third_party/rust/serial_test_derive/tests/broken/test_serial_async_before_wrapper.stderr b/third_party/rust/serial_test_derive/tests/broken/test_serial_async_before_wrapper.stderr
new file mode 100644
index 0000000000..f37e867bba
--- /dev/null
+++ b/third_party/rust/serial_test_derive/tests/broken/test_serial_async_before_wrapper.stderr
@@ -0,0 +1,7 @@
+error: Found async test attribute after serial, which will break
+ --> tests/broken/test_serial_async_before_wrapper.rs:3:1
+ |
+3 | #[serial]
+ | ^^^^^^^^^
+ |
+ = note: this error originates in the attribute macro `serial` (in Nightly builds, run with -Z macro-backtrace for more info)