Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upDocument using a Mutex to sequentalise tests #43155
Comments
nrc
added
the
T-doc
label
Jul 10, 2017
This comment has been minimized.
This comment has been minimized.
|
I guess the trick is this: use std::sync::Mutex;
#[macro_use] extern crate lazy_static;
lazy_static! {
static ref TEST_MUTEX: Mutex<()> = Mutex::new(());
}
macro_rules! test {
(fn $name:ident() $body:block) => {
#[test]
fn $name() {
let _guard = $crate::TEST_MUTEX.lock().unwrap();
$body
}
}
}
test! { fn one() { println!("one"); } }
test! { fn two() { println!("two"); } }Where the preamble could certainly be put in a support crate. |
This comment has been minimized.
This comment has been minimized.
kriomant
commented
Jul 15, 2017
|
This approach has a problem: when one test fails with panic, remaining ones fail with |
This comment has been minimized.
This comment has been minimized.
|
Hmm, good point. I suppose an implementation like this can fix that: macro_rules! test {
(fn $name:ident() $body:block) => {
#[test]
fn $name() {
let guard = $crate::TEST_MUTEX.lock().unwrap();
if let Err(e) = panic::catch_unwind(|| { $body }) {
drop(guard);
panic::resume_unwind(e);
}
}
}
}Another reason to put this in a support crate (or the standard test harness) to avoid this and likely other traps. |
This comment has been minimized.
This comment has been minimized.
|
You don't need to do anything with |
This comment has been minimized.
This comment has been minimized.
|
@sfackler Does a poisoned mutex still... mutex? |
This comment has been minimized.
This comment has been minimized.
|
Yes - the guard object is still inside of the error - https://doc.rust-lang.org/std/sync/struct.PoisonError.html#method.into_inner |
This comment has been minimized.
This comment has been minimized.
kriomant
commented
Jul 16, 2017
|
Yes, problem can be worked around using |
This comment has been minimized.
This comment has been minimized.
|
I agree in general (that's why I made https://docs.rs/antidote), but here, we're not accessing anything in the mutex so you can just save off the |
Mark-Simulacrum
added
the
C-enhancement
label
Jul 28, 2017
This comment has been minimized.
This comment has been minimized.
marmistrz
commented
Jul 31, 2017
|
I couldn't agree more that we need something built-in. I tried adding the Mutex to my own tests, and this did not seem to work anyway. https://github.com/marmistrz/randmockery/blob/mutex/tests/test.rs Setting |
This comment has been minimized.
This comment has been minimized.
|
@marmistrz |
kennytm
referenced this issue
Aug 29, 2017
Open
Tests in `static_any_map.rs` are not atomic, may cause spurious failure. #1
This comment has been minimized.
This comment has been minimized.
|
I think I'm failing to understand why someone couldn't just use |
This comment has been minimized.
This comment has been minimized.
marmistrz
commented
Oct 28, 2017
|
@frewsxcv because the canonical, obvious way to run tests is And, possibly, only some tests need mutual exclusion (e.g. because they use some single, problematic POSIX API, like it's in nix in case of fork/wait) and the others can safely run in parallel. |
steveklabnik
added
the
P-low
label
Oct 31, 2017
This comment has been minimized.
This comment has been minimized.
|
Triage: marking as p-low. Seems like it's worth documenting, but not going to get to this any time soon. |
This comment has been minimized.
This comment has been minimized.
MasonRemaley
commented
Nov 7, 2017
•
|
I just ran into this when writing tests for some OpenGL context creation code--this solution isn't possible in doctests since they don't share state, correct? Worst case scenario I can just document that my library can only be tested via |
This comment has been minimized.
This comment has been minimized.
|
Each doctest is a separate process, so I'd expect there to be less issues with them running in parallel. |
This comment has been minimized.
This comment has been minimized.
MasonRemaley
commented
Nov 14, 2017
|
It did cause an issue in my case, because my tests interact with the platform's windowing system which is shared between all processes. I realized though that I have to have a note explaining this anyway though since other apps running on someone's machine could also mess with the windowing system, so I guess just documenting you need to use |
This comment has been minimized.
This comment has been minimized.
glennpratt
commented
Aug 25, 2018
|
I'm hitting this testing functions that parse environment variables to change various behaviors. A mutex would be really noisy to spread into all my tests when really just a few tests need to either run in sequence or run in a fork. Either way is quite a bit of boilerplate. I looked and it seems Rust didn't have many tests for std::env, which made me wonder if this was the reason (or maybe I just didn't look hard enough). In other languages I'd probably fork and pass the value back for assertions, but I gather there are concerns with forking from the test runner. And of course being able to serialize the result and pass it back is a fair amount of boilerplate in Rust just for a test case. |
This comment has been minimized.
This comment has been minimized.
0xpr03
commented
Sep 4, 2018
|
Hitting the same problem here. I'll have to re-parse my data multiple times, load everything into memory, disable parallel tests or drop test altogether. |
This comment has been minimized.
This comment has been minimized.
jeff-at-dwelo
commented
Dec 11, 2018
|
Hitting this issue trying to write integration tests against an MQTT server that does not like clients using the same credentials to open multiple connections. Having that macro boilerplate at the stop of my tests is super gross and apparently still failure prone. I don't understand. We had a working PR into rust-lang to fix this in code back in 1.20, and it was summarily dropped. What happened at that meeting? |
This comment has been minimized.
This comment has been minimized.
As the issue says, since this is possible without a new language feature, the new feature was not accepted. |
This comment has been minimized.
This comment has been minimized.
0xpr03
commented
Jan 8, 2019
•
In the light of recent calls to stop adding feature over feature to rust it makes sense. |
This comment has been minimized.
This comment has been minimized.
marmistrz
commented
Jan 9, 2019
|
This definitely doesn't belong to the language itself. How about adding a field in Cargo.toml which would have the same effect as |
This comment has been minimized.
This comment has been minimized.
|
@marmistrz It sounds like one goal of this hypothetical feature is to flag certain tests as a non-parallelizable, while the rest are. In which case it'd likely need to be some sort of attribute on an individual testcase or module |
This comment has been minimized.
This comment has been minimized.
|
lol, also I just realized I linked to a comment thinking it was someone else, but it's actually you |
This comment has been minimized.
This comment has been minimized.
0xpr03
commented
Jan 10, 2019
•
That is a pretty nice idea and would help a lot. Edit: Of course there's always the possibility to define a test.sh, mark all sequentials as |
This comment has been minimized.
This comment has been minimized.
yaymukund
commented
Mar 17, 2019
|
If anyone else stumbled into this thread searching for a solution, there's the |
nrc commentedJul 10, 2017
cc #42684
One can use a static Mutex to sequentialise tests, but this is not documented, afaik.