-
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #119 from sourcefrog/return-error
Optionally return errors from functions returning Result
- Loading branch information
Showing
31 changed files
with
522 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# cargo-mutants configuration | ||
|
||
exclude_globs = [ "src/console.rs" ] | ||
error_values = ["::anyhow::anyhow!(\"mutated\")"] | ||
exclude_globs = ["src/console.rs"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# Skipping functions with an attribute | ||
|
||
To mark functions as skipped, so they are not mutated: | ||
|
||
1. Add a Cargo dependency on the [mutants](https://crates.io/crates/mutants) | ||
crate, version "0.0.3" or later. (This must be a regular `dependency` not a | ||
`dev-dependency`, because the annotation will be on non-test code.) | ||
|
||
2. Mark functions with `#[mutants::skip]` or other attributes containing | ||
`mutants::skip` (e.g. `#[cfg_attr(test, mutants::skip)]`). | ||
|
||
The `mutants` create is tiny and the attribute has no effect on the compiled | ||
code. It only flags the function for cargo-mutants. However, you can avoid the | ||
dependency by using the slightly longer `#[cfg_attr(test, mutants::skip)]` form. | ||
|
||
**Note:** Currently, `cargo-mutants` does not (yet) evaluate attributes like | ||
`cfg_attr`, it only looks for the sequence `mutants::skip` in the attribute. | ||
|
||
You may want to also add a comment explaining why the function is skipped. | ||
|
||
For example: | ||
|
||
```rust | ||
use std::time::{Duration, Instant}; | ||
|
||
/// Returns true if the program should stop | ||
#[cfg_attr(test, mutants::skip)] // Returning false would cause a hang | ||
fn should_stop() -> bool { | ||
true | ||
} | ||
|
||
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"); | ||
} | ||
} | ||
} | ||
|
||
mod test { | ||
#[test] | ||
fn controlled_loop_terminates() { | ||
super::controlled_loop() | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Generating error values | ||
|
||
cargo-mutants can be configured to generate mutants that return an error value from functions that return a Result. | ||
|
||
This will flag cases where no test fails if the function returns an error: that might happen if there are _only_ tests for the error cases and not for the Ok case. | ||
|
||
Since crates can choose to use any type for their error values, | ||
cargo-mutants must be told how to construct an appropriate error. | ||
|
||
The `--error` command line option and the `error_value` configuration option specify an error value to use. | ||
|
||
These options can be repeated or combined, which might be useful | ||
if there are multiple error types in the crate. On any one mutation site, probably only one of the error values will be viable, and cargo-mutants will discover that and use it. | ||
|
||
The error value can be any Rust expression that evaluates to a value of the error type. It should not include the `Err` wrapper, because cargo-mutants will add that. | ||
|
||
For example, if your crate uses `anyhow::Error` as its error type, you might use `--error '::anyhow::anyhow!("error")'`. | ||
|
||
If you have your own error type, you might use `--error 'crate::MyError::Generic'`. | ||
|
||
Since the correct error type is a property of the source tree, the configuration should typically go into `.cargo/mutants.toml` rather than being specified on the command line: | ||
|
||
```toml | ||
error_values = ["::anyhow::anyhow!(\"mutated\")"] | ||
``` | ||
|
||
To see only the mutants generated by this configuration, you | ||
can use a command like this: | ||
|
||
```sh | ||
cargo r mutants -F anyhow -vV -j4 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Generating mutants | ||
|
||
cargo mutants generates mutants by inspecting the existing | ||
source code and applying a set of rules to generate new code | ||
that is likely to compile but have different behavior. | ||
|
||
In the current release, the only mutation pattern is to | ||
replace function bodies with a value of the same type. | ||
This checks that the tests: | ||
|
||
1. Observe any side effects of the original function. | ||
2. Distinguish return values. | ||
|
||
More mutation rules will be added in future releases. | ||
|
||
| Return type | Mutation pattern | | ||
| ----------- | ---------------- | | ||
| `()` | `()` (return unit, with no side effects) | | ||
| `bool` | `true`, `false` | | ||
| `String` | `String::new()`, `"xyzzy".into()` | | ||
| `Result` | `Ok(Default::default())`, [and an error if configured](error-values.md) | | ||
| (any other) | `Default::default()` (and hope the type implements `Default`) | | ||
|
||
Some of these values may not be valid for all types: for example, returning | ||
`Default::default()` will work for many types, but not all. In this case the | ||
mutant is said to be "unviable": by default these are counted but not printed, | ||
although they can be shown with `--unviable`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,30 @@ | ||
# Parallelism | ||
|
||
The `--jobs` or `-j` option allows to test multiple mutants in parallel, by spawning several Cargo processes. This can give 25-50% performance improvements, depending on the tree under test and the hardware resources available. | ||
After the initial test of the unmutated tree, cargo-mutants can test multiple | ||
mutants in parallel. This can give significant performance improvements, | ||
depending on the tree under test and the hardware resources available. | ||
|
||
It's common that for some periods of its execution, a single Cargo build or test job can't use all the available CPU cores. Running multiple jobs in parallel makes use of resources that would otherwise be idle. | ||
Even though cargo builds, rustc, and Rust's test framework launch multiple | ||
processes or threads, they typically can't use all available CPU cores all the | ||
time, and many `cargo test` runs will end up using only one core waiting for the | ||
last task to complete. Running multiple jobs in parallel makes use of resources | ||
that would otherwise be idle. | ||
|
||
However, running many jobs simultaneously may also put high demands on the | ||
system's RAM (by running more compile/link/test tasks simultaneously), IO | ||
bandwidth, and cooling (by fully using all cores). | ||
By default, only one job is run at a time. | ||
|
||
The best setting will depend on many factors including the behavior of your program's test suite, the amount of memory on your system, and your system's behavior under high thermal load. | ||
To run more, use the `--jobs` or `-j` option, or set the `CARGO_MUTANTS_JOBS` | ||
environment variable. | ||
|
||
The default is currently to run only one job at a time. Setting this higher than the number of CPU cores is unlikely to be helpful. | ||
Setting this higher than the number of CPU cores is unlikely to be helpful. | ||
|
||
`-j 4` may be a good starting point, even if you have many more CPU cores. Start | ||
there and watch memory and CPU usage, and tune towards a setting where all cores | ||
are always utilized without memory usage going too high, and without thermal | ||
issues. | ||
The best setting will depend on many factors including the behavior of your | ||
program's test suite, the amount of memory on your system, and your system's | ||
behavior under high thermal load. | ||
|
||
Because tests may be slower with high parallelism, you may see some spurious timeouts, and you may need to set `--timeout` manually to allow enough safety margin. | ||
`-j 4` may be a good starting point. Start there and watch memory and CPU usage, | ||
and tune towards a setting where all cores are fully utilized without apparent | ||
thrashing, memory exhaustion, or thermal issues. | ||
|
||
Because tests may be slower with high parallelism, you may see some spurious | ||
timeouts, and you may need to set `--timeout` manually to allow enough safety | ||
margin. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.