Introduce mutation testing
Introduce mutation testing by way of mutagen [0] - Conditionally add the dev-dependency `mutagen` (using `do_mutate` flag) This flag is not very well named but `mutagen` and `mutate` are already taken? - Mutate all methods of the `U256` struct that do not require additional unit tests. Uses `cfg(all(test, do_mutate), mutate)` - I cannot workout why we need to check on `test` as well i.e., I don't understand why we cannot use `cfg(do_mutate, mutate)`? With this applied test can be run as usual with a stable toolchain. To run mutagen we use `RUSTFLAGS='--cfg=do_mutate' cargo +nightly mutagen`. [0] https://github.com/llogiq/mutagen
This commit is contained in:
parent
77aee43685
commit
2e79a0bdc4
|
@ -54,6 +54,9 @@ serde_derive = "1.0.103"
|
||||||
secp256k1 = { version = "0.24.0", features = [ "recovery", "rand-std" ] }
|
secp256k1 = { version = "0.24.0", features = [ "recovery", "rand-std" ] }
|
||||||
bincode = "1.3.1"
|
bincode = "1.3.1"
|
||||||
|
|
||||||
|
[target.'cfg(mutate)'.dev-dependencies]
|
||||||
|
mutagen = { git = "https://github.com/llogiq/mutagen" }
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "bip32"
|
name = "bip32"
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
use core::fmt::{self, LowerHex, UpperHex};
|
use core::fmt::{self, LowerHex, UpperHex};
|
||||||
use core::ops::{Add, Div, Mul, Not, Rem, Shl, Shr, Sub};
|
use core::ops::{Add, Div, Mul, Not, Rem, Shl, Shr, Sub};
|
||||||
|
|
||||||
|
#[cfg(all(test, mutate))]
|
||||||
|
use mutagen::mutate;
|
||||||
|
|
||||||
use crate::consensus::encode::{self, Decodable, Encodable};
|
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||||
#[cfg(doc)]
|
#[cfg(doc)]
|
||||||
use crate::consensus::Params;
|
use crate::consensus::Params;
|
||||||
|
@ -322,6 +325,7 @@ impl U256 {
|
||||||
const ONE: U256 = U256(0, 1);
|
const ONE: U256 = U256(0, 1);
|
||||||
|
|
||||||
/// Creates [`U256`] from a big-endian array of `u8`s.
|
/// Creates [`U256`] from a big-endian array of `u8`s.
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
fn from_be_bytes(a: [u8; 32]) -> U256 {
|
fn from_be_bytes(a: [u8; 32]) -> U256 {
|
||||||
let (high, low) = split_in_half(a);
|
let (high, low) = split_in_half(a);
|
||||||
let big = u128::from_be_bytes(high);
|
let big = u128::from_be_bytes(high);
|
||||||
|
@ -330,6 +334,7 @@ impl U256 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a [`U256`] from a little-endian array of `u8`s.
|
/// Creates a [`U256`] from a little-endian array of `u8`s.
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
fn from_le_bytes(a: [u8; 32]) -> U256 {
|
fn from_le_bytes(a: [u8; 32]) -> U256 {
|
||||||
let (high, low) = split_in_half(a);
|
let (high, low) = split_in_half(a);
|
||||||
let little = u128::from_le_bytes(high);
|
let little = u128::from_le_bytes(high);
|
||||||
|
@ -338,6 +343,7 @@ impl U256 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts `Self` to a big-endian array of `u8`s.
|
/// Converts `Self` to a big-endian array of `u8`s.
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
fn to_be_bytes(self) -> [u8; 32] {
|
fn to_be_bytes(self) -> [u8; 32] {
|
||||||
let mut out = [0; 32];
|
let mut out = [0; 32];
|
||||||
out[..16].copy_from_slice(&self.0.to_be_bytes());
|
out[..16].copy_from_slice(&self.0.to_be_bytes());
|
||||||
|
@ -346,6 +352,7 @@ impl U256 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts `Self` to a little-endian array of `u8`s.
|
/// Converts `Self` to a little-endian array of `u8`s.
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
fn to_le_bytes(self) -> [u8; 32] {
|
fn to_le_bytes(self) -> [u8; 32] {
|
||||||
let mut out = [0; 32];
|
let mut out = [0; 32];
|
||||||
out[..16].copy_from_slice(&self.1.to_le_bytes());
|
out[..16].copy_from_slice(&self.1.to_le_bytes());
|
||||||
|
@ -377,8 +384,10 @@ impl U256 {
|
||||||
ret.wrapping_inc()
|
ret.wrapping_inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
fn is_zero(&self) -> bool { self.0 == 0 && self.1 == 0 }
|
fn is_zero(&self) -> bool { self.0 == 0 && self.1 == 0 }
|
||||||
|
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
fn is_one(&self) -> bool { self.0 == 0 && self.1 == 1 }
|
fn is_one(&self) -> bool { self.0 == 0 && self.1 == 1 }
|
||||||
|
|
||||||
fn is_max(&self) -> bool { self.0 == u128::max_value() && self.1 == u128::max_value() }
|
fn is_max(&self) -> bool { self.0 == u128::max_value() && self.1 == u128::max_value() }
|
||||||
|
@ -571,6 +580,7 @@ impl U256 {
|
||||||
|
|
||||||
/// Returns `self` incremented by 1 wrapping around at the boundary of the type.
|
/// Returns `self` incremented by 1 wrapping around at the boundary of the type.
|
||||||
#[must_use = "this returns the result of the increment, without modifying the original"]
|
#[must_use = "this returns the result of the increment, without modifying the original"]
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
fn wrapping_inc(&self) -> U256 {
|
fn wrapping_inc(&self) -> U256 {
|
||||||
let mut ret = U256::ZERO;
|
let mut ret = U256::ZERO;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue