Skip to content

Commit

Permalink
Put a time limit even on tests expected to hang
Browse files Browse the repository at this point in the history
Without this, in some cases when cargo-mutants is itself mutated or
buggy, test subprocesses can hang around forever, which is not useful.

With this change, they will eventually exit, but after long enough that
timeout handling can still be tested.
  • Loading branch information
sourcefrog committed Sep 20, 2022
1 parent 373de47 commit 9842c60
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 10 deletions.
5 changes: 4 additions & 1 deletion testdata/tree/already_hangs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use std::thread::sleep;
use std::time::Duration;

pub fn infinite_loop() {
for i in 0.. {
// Not really infinite, so that orphaned processes don't hang around forever.
// They shouldn't normally happen, but they might when cargo-mutants is itself
// being mutation tested, or has a bug, etc.
for i in 0..600 {
println!("{}", i);
sleep(Duration::from_secs(1));
}
Expand Down
6 changes: 6 additions & 0 deletions testdata/tree/hang_avoided_by_attr/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! An example of a function we should not mutate because it will hang.
use std::time::{Duration, Instant};

/// If mutated to return false, the program will spin forever.
///
/// Ideally and eventually, cargo-mutants should stop it after a timeout,
Expand All @@ -10,11 +12,15 @@ fn should_stop() -> bool {
}

pub fn controlled_loop() {
let start = Instant::now();
for i in 0.. {
println!("{}", i);
if should_stop() {
break;
}
if start.elapsed() > Duration::from_secs(60 * 5) {
panic!("timed out");
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions testdata/tree/hang_when_mutated/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! lets us test the case where that has not yet been fixed.
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{Duration, Instant};

static TRIGGER: AtomicBool = AtomicBool::new(false);

Expand All @@ -18,13 +19,20 @@ fn should_stop() -> bool {

/// Runs until `should_stop` returns true, and then returns the number
/// of iterations.
///
/// Also stops after a few minutes anyhow, so that if the timeouts are not
/// properly implemented, the child process doesn't hang around forever.
pub fn controlled_loop() -> usize {
let start = Instant::now();
for i in 1.. {
println!("{}", i);
if should_stop() {
return i;
}
std::thread::sleep(std::time::Duration::from_millis(100));
if start.elapsed() > Duration::from_secs(60 * 5) {
panic!("timed out");
}
}
unreachable!();
}
Expand Down
2 changes: 1 addition & 1 deletion tests/snapshots/cli__check_tree_with_mutants_skip.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ expression: stdout
Found 1 mutant to test
Copy source to scratch directory ... done
Unmutated baseline ... ok
src/lib.rs:12: replace controlled_loop with () ... ok
src/lib.rs:14: replace controlled_loop with () ... ok
1 mutant tested: 1 succeeded

8 changes: 4 additions & 4 deletions tests/snapshots/cli__list_mutants_in_all_trees_as_json.snap
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ expression: buf
{
"package": "cargo-mutants-testdata-hang-avoided-by-attr",
"file": "src/lib.rs",
"line": 12,
"line": 14,
"function": "controlled_loop",
"return_type": "",
"replacement": "()"
Expand All @@ -140,23 +140,23 @@ expression: buf
{
"package": "cargo-mutants-testdata-hang-when-mutated",
"file": "src/lib.rs",
"line": 11,
"line": 12,
"function": "should_stop",
"return_type": "-> bool",
"replacement": "true"
},
{
"package": "cargo-mutants-testdata-hang-when-mutated",
"file": "src/lib.rs",
"line": 11,
"line": 12,
"function": "should_stop",
"return_type": "-> bool",
"replacement": "false"
},
{
"package": "cargo-mutants-testdata-hang-when-mutated",
"file": "src/lib.rs",
"line": 21,
"line": 25,
"function": "controlled_loop",
"return_type": "-> usize",
"replacement": "Default::default()"
Expand Down
8 changes: 4 additions & 4 deletions tests/snapshots/cli__list_mutants_in_all_trees_as_text.snap
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ src/bin/factorial.rs:7: replace factorial -> u32 with Default::default()
## testdata/tree/hang_avoided_by_attr

```
src/lib.rs:12: replace controlled_loop with ()
src/lib.rs:14: replace controlled_loop with ()
```

## testdata/tree/hang_when_mutated

```
src/lib.rs:11: replace should_stop -> bool with true
src/lib.rs:11: replace should_stop -> bool with false
src/lib.rs:21: replace controlled_loop -> usize with Default::default()
src/lib.rs:12: replace should_stop -> bool with true
src/lib.rs:12: replace should_stop -> bool with false
src/lib.rs:25: replace controlled_loop -> usize with Default::default()
```

## testdata/tree/insta
Expand Down

0 comments on commit 9842c60

Please sign in to comment.