locktime: Add mutation testing
Add mutation testing to the `locktime` module and add unit tests to cover all mutants and ensure they are killed.
This commit is contained in:
parent
26c0da41b4
commit
ca471557a5
|
@ -14,6 +14,9 @@ use core::str::FromStr;
|
||||||
|
|
||||||
use bitcoin_internals::write_err;
|
use bitcoin_internals::write_err;
|
||||||
|
|
||||||
|
#[cfg(all(test, mutate))]
|
||||||
|
use mutagen::mutate;
|
||||||
|
|
||||||
use crate::consensus::encode::{self, Decodable, Encodable};
|
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||||
use crate::error::ParseIntError;
|
use crate::error::ParseIntError;
|
||||||
use crate::io::{self, Read, Write};
|
use crate::io::{self, Read, Write};
|
||||||
|
@ -198,6 +201,7 @@ impl LockTime {
|
||||||
/// }
|
/// }
|
||||||
/// ````
|
/// ````
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
pub fn is_satisfied_by(&self, height: Height, time: Time) -> bool {
|
pub fn is_satisfied_by(&self, height: Height, time: Time) -> bool {
|
||||||
use LockTime::*;
|
use LockTime::*;
|
||||||
|
|
||||||
|
@ -227,6 +231,7 @@ impl LockTime {
|
||||||
/// assert!(lock_time.is_implied_by(check));
|
/// assert!(lock_time.is_implied_by(check));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
pub fn is_implied_by(&self, other: LockTime) -> bool {
|
pub fn is_implied_by(&self, other: LockTime) -> bool {
|
||||||
use LockTime::*;
|
use LockTime::*;
|
||||||
|
|
||||||
|
@ -791,4 +796,90 @@ mod tests {
|
||||||
let result = Height::from_hex_str(hex);
|
let result = Height::from_hex_str(hex);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parses_correctly_to_height_or_time() {
|
||||||
|
let lock = LockTime::from_consensus(750_000);
|
||||||
|
|
||||||
|
assert!(lock.is_block_height());
|
||||||
|
assert!(!lock.is_block_time());
|
||||||
|
|
||||||
|
let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||||
|
let lock = LockTime::from_consensus(t);
|
||||||
|
|
||||||
|
assert!(!lock.is_block_height());
|
||||||
|
assert!(lock.is_block_time());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn satisfied_by_height() {
|
||||||
|
let lock = LockTime::from_consensus(750_000);
|
||||||
|
|
||||||
|
let height = Height::from_consensus(800_000).expect("failed to parse height");
|
||||||
|
|
||||||
|
let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||||
|
let time = Time::from_consensus(t).expect("invalid time value");
|
||||||
|
|
||||||
|
assert!(lock.is_satisfied_by(height, time))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn satisfied_by_time() {
|
||||||
|
let lock = LockTime::from_consensus(1053195600);
|
||||||
|
|
||||||
|
let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||||
|
let time = Time::from_consensus(t).expect("invalid time value");
|
||||||
|
|
||||||
|
let height = Height::from_consensus(800_000).expect("failed to parse height");
|
||||||
|
|
||||||
|
assert!(lock.is_satisfied_by(height, time))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn satisfied_by_same_height() {
|
||||||
|
let h = 750_000;
|
||||||
|
let lock = LockTime::from_consensus(h);
|
||||||
|
let height = Height::from_consensus(h).expect("failed to parse height");
|
||||||
|
|
||||||
|
let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||||
|
let time = Time::from_consensus(t).expect("invalid time value");
|
||||||
|
|
||||||
|
assert!(lock.is_satisfied_by(height, time))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn satisfied_by_same_time() {
|
||||||
|
let t: u32 = 1653195600; // May 22nd, 5am UTC.
|
||||||
|
let lock = LockTime::from_consensus(t);
|
||||||
|
let time = Time::from_consensus(t).expect("invalid time value");
|
||||||
|
|
||||||
|
let height = Height::from_consensus(800_000).expect("failed to parse height");
|
||||||
|
|
||||||
|
assert!(lock.is_satisfied_by(height, time))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn height_correctly_implies() {
|
||||||
|
let lock = LockTime::from_consensus(750_005);
|
||||||
|
|
||||||
|
assert!(!lock.is_implied_by(LockTime::from_consensus(750_004)));
|
||||||
|
assert!(lock.is_implied_by(LockTime::from_consensus(750_005)));
|
||||||
|
assert!(lock.is_implied_by(LockTime::from_consensus(750_006)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn time_correctly_implies() {
|
||||||
|
let t: u32 = 1700000005;
|
||||||
|
let lock = LockTime::from_consensus(t);
|
||||||
|
|
||||||
|
assert!(!lock.is_implied_by(LockTime::from_consensus(1700000004)));
|
||||||
|
assert!(lock.is_implied_by(LockTime::from_consensus(1700000005)));
|
||||||
|
assert!(lock.is_implied_by(LockTime::from_consensus(1700000006)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incorrect_units_do_not_imply() {
|
||||||
|
let lock = LockTime::from_consensus(750_005);
|
||||||
|
assert!(!lock.is_implied_by(LockTime::from_consensus(1700000004)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
|
#[cfg(all(test, mutate))]
|
||||||
|
use mutagen::mutate;
|
||||||
|
|
||||||
#[cfg(docsrs)]
|
#[cfg(docsrs)]
|
||||||
use crate::relative;
|
use crate::relative;
|
||||||
|
|
||||||
|
@ -53,6 +56,7 @@ impl LockTime {
|
||||||
/// assert!(lock.is_satisfied_by(current_height(), current_time()));
|
/// assert!(lock.is_satisfied_by(current_height(), current_time()));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
pub fn is_satisfied_by(&self, h: Height, t: Time) -> bool {
|
pub fn is_satisfied_by(&self, h: Height, t: Time) -> bool {
|
||||||
if let Ok(true) = self.is_satisfied_by_height(h) {
|
if let Ok(true) = self.is_satisfied_by_height(h) {
|
||||||
true
|
true
|
||||||
|
@ -94,6 +98,7 @@ impl LockTime {
|
||||||
/// assert!(satisfied);
|
/// assert!(satisfied);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
pub fn is_implied_by(&self, other: LockTime) -> bool {
|
pub fn is_implied_by(&self, other: LockTime) -> bool {
|
||||||
use LockTime::*;
|
use LockTime::*;
|
||||||
|
|
||||||
|
@ -121,6 +126,7 @@ impl LockTime {
|
||||||
/// assert!(lock.is_satisfied_by_height(Height::from(height+1)).expect("a height"));
|
/// assert!(lock.is_satisfied_by_height(Height::from(height+1)).expect("a height"));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
pub fn is_satisfied_by_height(&self, h: Height) -> Result<bool, Error> {
|
pub fn is_satisfied_by_height(&self, h: Height) -> Result<bool, Error> {
|
||||||
use LockTime::*;
|
use LockTime::*;
|
||||||
|
|
||||||
|
@ -147,6 +153,7 @@ impl LockTime {
|
||||||
/// assert!(lock.is_satisfied_by_time(Time::from_512_second_intervals(intervals + 10)).expect("a time"));
|
/// assert!(lock.is_satisfied_by_time(Time::from_512_second_intervals(intervals + 10)).expect("a time"));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
pub fn is_satisfied_by_time(&self, t: Time) -> Result<bool, Error> {
|
pub fn is_satisfied_by_time(&self, t: Time) -> Result<bool, Error> {
|
||||||
use LockTime::*;
|
use LockTime::*;
|
||||||
|
|
||||||
|
@ -294,3 +301,61 @@ impl std::error::Error for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn satisfied_by_height() {
|
||||||
|
let height = Height::from(10);
|
||||||
|
let time = Time::from_512_second_intervals(70);
|
||||||
|
|
||||||
|
let lock = LockTime::from(height);
|
||||||
|
|
||||||
|
assert!(!lock.is_satisfied_by(Height::from(9), time));
|
||||||
|
assert!(lock.is_satisfied_by(Height::from(10), time));
|
||||||
|
assert!(lock.is_satisfied_by(Height::from(11), time));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn satisfied_by_time() {
|
||||||
|
let height = Height::from(10);
|
||||||
|
let time = Time::from_512_second_intervals(70);
|
||||||
|
|
||||||
|
let lock = LockTime::from(time);
|
||||||
|
|
||||||
|
assert!(!lock.is_satisfied_by(height, Time::from_512_second_intervals(69)));
|
||||||
|
assert!(lock.is_satisfied_by(height, Time::from_512_second_intervals(70)));
|
||||||
|
assert!(lock.is_satisfied_by(height, Time::from_512_second_intervals(71)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn height_correctly_implies() {
|
||||||
|
let height = Height::from(10);
|
||||||
|
let lock = LockTime::from(height);
|
||||||
|
|
||||||
|
assert!(!lock.is_implied_by(LockTime::from(Height::from(9))));
|
||||||
|
assert!(lock.is_implied_by(LockTime::from(Height::from(10))));
|
||||||
|
assert!(lock.is_implied_by(LockTime::from(Height::from(11))));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn time_correctly_implies() {
|
||||||
|
let time = Time::from_512_second_intervals(70);
|
||||||
|
let lock = LockTime::from(time);
|
||||||
|
|
||||||
|
assert!(!lock.is_implied_by(LockTime::from(Time::from_512_second_intervals(69))));
|
||||||
|
assert!(lock.is_implied_by(LockTime::from(Time::from_512_second_intervals(70))));
|
||||||
|
assert!(lock.is_implied_by(LockTime::from(Time::from_512_second_intervals(71))));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn incorrect_units_do_not_imply() {
|
||||||
|
let time = Time::from_512_second_intervals(70);
|
||||||
|
let height = Height::from(10);
|
||||||
|
|
||||||
|
let lock = LockTime::from(time);
|
||||||
|
assert!(!lock.is_implied_by(LockTime::from(height)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue