From 462c7a11309fb4828d69ca8df045155413497244 Mon Sep 17 00:00:00 2001 From: Shing Him Ng Date: Sun, 22 Dec 2024 15:48:30 -0600 Subject: [PATCH 1/3] Add weekly cargo-mutants workflow --- .cargo/mutants.toml | 27 ++++++++++++ .../workflows/cron-weekly-cargo-mutants.yml | 41 +++++++++++++++++++ .gitignore | 1 + 3 files changed, 69 insertions(+) create mode 100644 .cargo/mutants.toml create mode 100644 .github/workflows/cron-weekly-cargo-mutants.yml diff --git a/.cargo/mutants.toml b/.cargo/mutants.toml new file mode 100644 index 000000000..b6ed18c55 --- /dev/null +++ b/.cargo/mutants.toml @@ -0,0 +1,27 @@ +additional_cargo_args = ["--all-features"] +examine_globs = ["units/src/**/*.rs"] +exclude_globs = [ + "units/src/amount/verification.rs" # kani tests +] +exclude_re = [ + "impl Debug", + "impl Arbitrary", + "impl Display", + ".*Error", + # --------------------------------------------Crate-specific exclusions-------------------------------------------- + # Units + # src/amount/mod.rs + "parse_signed_to_satoshi", # Can't kill all mutants since there is no denomination smaller than Satoshi + "fmt_satoshi_in", # Related to formatting/display + "dec_width", # Replacing num /= 10 with num %=10 in a loop causes a timeout due to infinite loop + # src/fee_rate/serde.rs + "as_sat_per_kwu::opt::deserialize::.*", # Replaces return value with Ok(Default::default()), which is the same as Ok(None) + "as_sat_per_vb_floor::opt::deserialize::.*", # Replaces return value with Ok(Default::default()), which is the same as Ok(None) + "as_sat_per_vb_ceil::opt::deserialize::.*", # Replaces return value with Ok(Default::default()), which is the same as Ok(None) + # src/amount/serde.rs + "as_sat::opt::deserialize::>.*", # Replaces return value with Ok(Default::default()), which is the same as Ok(None) + "as_btc::opt::deserialize::>.*", # Replaces return value with Ok(Default::default()), which is the same as Ok(None) + "as_str::opt::deserialize::>.*", # Replaces return value with Ok(Default::default()), which is the same as Ok(None) + # src/locktime/relative.rs + "Time::to_consensus_u32" # It will replace | with ^, which will return the same value since the XOR is always taken against the u16 and an all-zero bitmask +] diff --git a/.github/workflows/cron-weekly-cargo-mutants.yml b/.github/workflows/cron-weekly-cargo-mutants.yml new file mode 100644 index 000000000..30896e402 --- /dev/null +++ b/.github/workflows/cron-weekly-cargo-mutants.yml @@ -0,0 +1,41 @@ +name: Weekly cargo-mutants +on: + schedule: + - cron: "0 0 * * 0" # runs weekly on Sunday at 00:00 + workflow_dispatch: # allows manual triggering +jobs: + cargo-mutants: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: taiki-e/install-action@v2 + with: + tool: cargo-mutants + - run: cargo mutants --in-place --no-shuffle + - uses: actions/upload-artifact@v4 + if: always() + with: + name: mutants.out + path: mutants.out + - name: Check for new mutants + if: always() + run: | + if [ -s mutants.out/missed.txt ]; then + echo "New missed mutants found" + gh issue create \ + --title "New Mutants Found" \ + --body "$(cat <> $GITHUB_ENV + else + echo "No new mutants found" + echo "create_issue=false" >> $GITHUB_ENV + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 6055dd863..48c9cedca 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ hashes/target # Test artifacts bitcoin/dep_test +mutants.out* # Fuzz artifacts hfuzz_target From 871fa08f6162727dcd51afa4ed02d8e2ead94246 Mon Sep 17 00:00:00 2001 From: Shing Him Ng Date: Wed, 15 Jan 2025 23:04:33 -0600 Subject: [PATCH 2/3] Fix typo in serde docs --- units/src/fee_rate/serde.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/units/src/fee_rate/serde.rs b/units/src/fee_rate/serde.rs index 496fee54d..1b1ad3364 100644 --- a/units/src/fee_rate/serde.rs +++ b/units/src/fee_rate/serde.rs @@ -171,7 +171,7 @@ pub mod as_sat_per_vb_ceil { //! Serialize and deserialize [`FeeRate`] denominated in satoshis per virtual byte. //! //! When serializing use ceil division to convert per kwu to per virtual byte. - //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb")]`. + //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_ceil")]`. use serde::{Deserialize, Deserializer, Serialize, Serializer}; From bfba2a85ddaad6b366a7502cbda1ff2462dfd4c7 Mon Sep 17 00:00:00 2001 From: Shing Him Ng Date: Wed, 15 Jan 2025 23:21:14 -0600 Subject: [PATCH 3/3] Kill remaining mutants --- units/src/amount/tests.rs | 2 ++ units/src/fee_rate/mod.rs | 3 --- units/src/locktime/relative.rs | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/units/src/amount/tests.rs b/units/src/amount/tests.rs index 42a9e3d3c..df1785e54 100644 --- a/units/src/amount/tests.rs +++ b/units/src/amount/tests.rs @@ -972,10 +972,12 @@ fn sum_amounts() { assert_eq!([].iter().sum::(), SignedAmount::ZERO); let amounts = [sat(42), sat(1337), sat(21)]; + assert_eq!(amounts.iter().sum::(), sat(1400)); let sum = amounts.into_iter().sum::(); assert_eq!(sum, sat(1400)); let amounts = [ssat(-42), ssat(1337), ssat(21)]; + assert_eq!(amounts.iter().sum::(), ssat(1316)); let sum = amounts.into_iter().sum::(); assert_eq!(sum, ssat(1316)); } diff --git a/units/src/fee_rate/mod.rs b/units/src/fee_rate/mod.rs index c0baeb9df..f9dca7b87 100644 --- a/units/src/fee_rate/mod.rs +++ b/units/src/fee_rate/mod.rs @@ -69,9 +69,6 @@ impl FeeRate { pub const fn to_sat_per_vb_floor(self) -> u64 { self.0 / (1000 / 4) } /// Converts to sat/vB rounding up. - /// TODO: cargo-mutants will try to replace - with /, which results in 1000 / 4 / 1 which is also 250. - /// Since we're addressing the mutants before introducing the cargo-mutants workflow, come back later - /// and skip this function in the mutants.toml config file pub const fn to_sat_per_vb_ceil(self) -> u64 { (self.0 + (1000 / 4 - 1)) / (1000 / 4) } /// Checked multiplication. diff --git a/units/src/locktime/relative.rs b/units/src/locktime/relative.rs index 7a25d4906..7f8b4413a 100644 --- a/units/src/locktime/relative.rs +++ b/units/src/locktime/relative.rs @@ -116,8 +116,6 @@ impl Time { /// Returns the `u32` value used to encode this locktime in an nSequence field or /// argument to `OP_CHECKSEQUENCEVERIFY`. - /// TODO: Skip this in cargo-mutants. It will replace | with ^, which will return the same - /// value since the XOR is always taken against the u16 and an all-zero bitmask #[inline] pub const fn to_consensus_u32(self) -> u32 { (1u32 << 22) | self.0 as u32 // cast safety: u32 is wider than u16 on all architectures