Rewrite run_n_times to not be recursive but mutates arguments.
We reach a stack-overflow for n > 2000 otherwise. Mutation works well here and is a valid use-case.
This commit is contained in:
parent
1d72838f83
commit
038c5b2d34
|
@ -226,11 +226,12 @@ impl PropertyTest {
|
||||||
/// may stops earlier on failure; in which case a 'counterexample' is returned.
|
/// may stops earlier on failure; in which case a 'counterexample' is returned.
|
||||||
pub fn run<U>(self, seed: u32, n: usize) -> TestResult<U, PlutusData> {
|
pub fn run<U>(self, seed: u32, n: usize) -> TestResult<U, PlutusData> {
|
||||||
let mut labels = BTreeMap::new();
|
let mut labels = BTreeMap::new();
|
||||||
|
let mut remaining = n;
|
||||||
|
|
||||||
let (traces, counterexample, iterations) =
|
let (traces, counterexample, iterations) =
|
||||||
match self.run_n_times(n, Prng::from_seed(seed), None, &mut labels) {
|
match self.run_n_times(&mut remaining, Prng::from_seed(seed), &mut labels) {
|
||||||
Ok(None) => (Vec::new(), Ok(None), n),
|
Ok(None) => (Vec::new(), Ok(None), n),
|
||||||
Ok(Some((remaining, counterexample))) => (
|
Ok(Some(counterexample)) => (
|
||||||
self.eval(&counterexample.value)
|
self.eval(&counterexample.value)
|
||||||
.logs()
|
.logs()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -260,24 +261,19 @@ impl PropertyTest {
|
||||||
|
|
||||||
fn run_n_times<'a>(
|
fn run_n_times<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
remaining: usize,
|
remaining: &mut usize,
|
||||||
prng: Prng,
|
initial_prng: Prng,
|
||||||
counterexample: Option<(usize, Counterexample<'a>)>,
|
|
||||||
labels: &mut BTreeMap<String, usize>,
|
labels: &mut BTreeMap<String, usize>,
|
||||||
) -> Result<Option<(usize, Counterexample<'a>)>, FuzzerError> {
|
) -> Result<Option<Counterexample<'a>>, FuzzerError> {
|
||||||
// We short-circuit failures in case we have any. The counterexample is already simplified
|
let mut prng = initial_prng;
|
||||||
// at this point.
|
let mut counterexample = None;
|
||||||
if remaining > 0 && counterexample.is_none() {
|
|
||||||
let (next_prng, counterexample) = self.run_once(prng, labels)?;
|
while *remaining > 0 && counterexample.is_none() {
|
||||||
self.run_n_times(
|
(prng, counterexample) = self.run_once(prng, labels)?;
|
||||||
remaining - 1,
|
*remaining -= 1;
|
||||||
next_prng,
|
|
||||||
counterexample.map(|c| (remaining, c)),
|
|
||||||
labels,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Ok(counterexample)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(counterexample)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_once(
|
fn run_once(
|
||||||
|
@ -1418,13 +1414,9 @@ mod test {
|
||||||
impl PropertyTest {
|
impl PropertyTest {
|
||||||
fn expect_failure(&self) -> Counterexample {
|
fn expect_failure(&self) -> Counterexample {
|
||||||
let mut labels = BTreeMap::new();
|
let mut labels = BTreeMap::new();
|
||||||
match self.run_n_times(
|
let mut remaining = PropertyTest::DEFAULT_MAX_SUCCESS;
|
||||||
PropertyTest::DEFAULT_MAX_SUCCESS,
|
match self.run_n_times(&mut remaining, Prng::from_seed(42), &mut labels) {
|
||||||
Prng::from_seed(42),
|
Ok(Some(counterexample)) => counterexample,
|
||||||
None,
|
|
||||||
&mut labels,
|
|
||||||
) {
|
|
||||||
Ok(Some((_, counterexample))) => counterexample,
|
|
||||||
_ => panic!("expected property to fail but it didn't."),
|
_ => panic!("expected property to fail but it didn't."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue