Run with mutagen on travis. 2020-01-mutagen
authorMatt Corallo <git@bluematt.me>
Wed, 15 Jan 2020 20:08:45 +0000 (15:08 -0500)
committerMatt Corallo <git@bluematt.me>
Mon, 27 Jan 2020 16:50:50 +0000 (11:50 -0500)
Sadly our test coverage isn't very good and I had to hunt for
functions to mutate where we fail tests on every mutation mutagen
creates, but committing the framework is a start.

.travis.yml
lightning/Cargo.toml
lightning/src/lib.rs
lightning/src/ln/channel.rs

index 308c8d634d72debda99c692e549f8446a9c5a48f..2d51fc61f681de74752ef30de9bf1a82258e37f1 100644 (file)
@@ -1,7 +1,7 @@
 language: rust
 rust:
   - stable
-  - beta
+  - nightly
   - 1.22.0
   - 1.34.2
 cache: cargo
@@ -22,6 +22,14 @@ script:
      - if [ "$(rustup show | grep default | grep 1.22.0)" != "" ]; then RUSTFLAGS="-C link-dead-code" cargo test --verbose -p lightning; fi
      # Run lightning workspace fuzz tests for Rust 1.34.2
      - if [ "$(rustup show | grep default | grep 1.34.2)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; fi
+     # Run mutagen on nightly with TheBlueMatt's fork which exits with non-0 status
+     # if any mutations resulted in anything except test failures to prevent regressions.
+     - if [ "$(rustup show | grep default | grep nightly)" != "" ]; then
+           rm -rf mutagen && git clone https://github.com/TheBlueMatt/mutagen &&
+           cargo install --force --path mutagen/mutagen-runner &&
+           cd lightning &&
+           ~/.cargo/bin/cargo-mutagen --features mutation_testing; fi
+     # Generate codecov on stable
      - if [ "$(rustup show | grep default | grep stable)" != "" ]; then
            wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
            tar xzf master.tar.gz &&
index 341084fc393a7b0fc35822b1e67c0661f0ee42db..2e221888011b6174ae635c6837a413a319965524 100644 (file)
@@ -13,7 +13,6 @@ Still missing tons of error-handling. See GitHub issues for suggested projects i
 [features]
 # Supports tracking channels with a non-bitcoin chain hashes. Currently enables all kinds of fun DoS attacks.
 non_bitcoin_chain_hash_routing = []
-fuzztarget = ["secp256k1/fuzztarget", "bitcoin/fuzztarget", "bitcoin_hashes/fuzztarget"]
 # Unlog messages superior at targeted level.
 max_level_off = []
 max_level_error = []
@@ -21,10 +20,15 @@ max_level_warn = []
 max_level_info = []
 max_level_debug = []
 
+# Testing only features, don't enable these unless you want to run rust-lightning tests!
+fuzztarget = ["secp256k1/fuzztarget", "bitcoin/fuzztarget", "bitcoin_hashes/fuzztarget"]
+mutation_testing = ["mutagen"]
+
 [dependencies]
 bitcoin = "0.21"
 bitcoin_hashes = "0.7"
 secp256k1 = "0.15"
+mutagen = { git = "https://github.com/TheBlueMatt/mutagen", optional = true }
 
 [dev-dependencies.bitcoin]
 version = "0.21"
index 68924b57a36af64b7fc01b43efcb4733ca8f3dc7..631b66df9e8aa349caacfed227036e2ac661a9f8 100644 (file)
@@ -23,8 +23,15 @@ extern crate bitcoin_hashes;
 extern crate secp256k1;
 #[cfg(test)] extern crate rand;
 #[cfg(test)] extern crate hex;
+#[cfg(all(test, feature = "mutation_testing"))] extern crate mutagen;
 
 #[macro_use]
 pub mod util;
 pub mod chain;
 pub mod ln;
+
+#[cfg(all(
+               any(feature = "mutation_testing", feature = "fuzztarget"),
+               not(any(test, debug_assertions))
+               ))]
+const ERR: () = "You should never be building with feature = mutation_testing or feature = fuzztarget! They are used to compile with broken code for testing only!";
index 10a4abf51a1dc53b3e4b47d09ab2ab4303970a95..0af1b1fe2282a3e1bf5b8ae11ce3e1cd33ec2609 100644 (file)
@@ -36,6 +36,9 @@ use std::default::Default;
 use std::{cmp,mem,fmt};
 use std::sync::{Arc};
 
+#[cfg(all(test, feature = "mutation_testing"))]
+use mutagen::mutate;
+
 #[cfg(test)]
 pub struct ChannelValueStat {
        pub value_to_self_msat: u64,
@@ -2369,6 +2372,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                Ok(())
        }
 
+       #[cfg_attr(all(test, feature = "mutation_testing"), mutate)]
        fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK {
                let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number));
                let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), self.cur_local_commitment_transaction_number + 2);