diff --git a/NEWS.md b/NEWS.md index 196d91fa..d02f5d46 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,8 @@ - Changed: No build timeouts by default. Previously, cargo-mutants set a default build timeout based on the baseline build, but experience showed that this would sometimes make builds flaky, because build times can be quite variable. If mutants cause builds to hang, then you can still set a timeout using `--build-timeout` or `--build-timeout-multiplier`. +- Fixed: Don't error if the `--in-diff` file is empty. + - Changed: cargo-mutants no longer passes `--cap-lints=allow` to rustc. This was previously done so that mutants would not unnecessarily be unviable due to triggering compiler warnings in trees configured to deny some lints, but it had the undesirable effect of disabling rustc's detection of long running const evaluations. If your tree treats some lints as errors then the previous behavior can be restored with `--cap-lints=true` (or the equivalent config option), or you can use `cfg_attr` and a feature flag to accept those warnings when testing under cargo-mutants. ## 24.5.0 diff --git a/book/src/lints.md b/book/src/lints.md index 739f1878..97a89017 100644 --- a/book/src/lints.md +++ b/book/src/lints.md @@ -6,7 +6,7 @@ For example, mutants that delete code are likely to cause some parameters to be There are a few possible solutions: -1. Define a feature flag for mutation testing, and use `cfg_attr` to enable strict warnings only when not testing mutants. +1. Define a feature flag for mutation testing, and use `cfg_attr` to enable strict warnings only when not testing mutants. 2. Use the `cargo mutants --cap-lints=true` command line option, or the `cap_lints = true` config option. `--cap_lints=true` also disables rustc's detection of long-running const expression evaluation, so may cause some builds to fail. If that happens in your tree, you can set a [build timeout](timeouts.md). diff --git a/src/in_diff.rs b/src/in_diff.rs index b7be4e98..755d32db 100644 --- a/src/in_diff.rs +++ b/src/in_diff.rs @@ -10,7 +10,7 @@ use camino::Utf8Path; use indoc::formatdoc; use itertools::Itertools; use patch::{Line, Patch}; -use tracing::{trace, warn}; +use tracing::{info, trace, warn}; use crate::mutate::Mutant; use crate::source::SourceFile; @@ -19,6 +19,10 @@ use crate::Result; /// Return only mutants to functions whose source was touched by this diff. pub fn diff_filter(mutants: Vec, diff_text: &str) -> Result> { // Flatten the error to a string because otherwise it references the diff, and can't be returned. + if diff_text.trim().is_empty() { + info!("diff file is empty; no mutants will match"); + return Ok(Vec::new()); + } let patches = Patch::from_multiple(diff_text).map_err(|err| anyhow!("Failed to parse diff: {err}"))?; check_diff_new_text_matches(&patches, &mutants)?; diff --git a/tests/in_diff.rs b/tests/in_diff.rs index 6f0af9cd..81a0eb51 100644 --- a/tests/in_diff.rs +++ b/tests/in_diff.rs @@ -4,6 +4,7 @@ use std::fs::read_to_string; use std::io::Write; use indoc::indoc; +use predicates::prelude::predicate; use similar::TextDiff; use tempfile::NamedTempFile; @@ -68,6 +69,22 @@ fn list_mutants_changed_in_diff1() { ); } +#[test] +fn empty_diff_is_not_an_error_and_matches_nothing() { + let diff_file = NamedTempFile::new().unwrap(); + let tmp = copy_of_testdata("diff1"); + run() + .args(["mutants", "--no-shuffle", "-d"]) + .arg(tmp.path()) + .arg("--in-diff") + .arg(diff_file.path()) + .arg("--list") + .assert() + .success() + .stdout("") + .stderr(predicate::str::contains("diff file is empty")); +} + /// If the text in the diff doesn't look like the tree then error out. #[test] fn mismatched_diff_causes_error() {