1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

// Copyright 2021 Conflux Foundation. All rights reserved.
// Conflux is free software and distributed under GNU General Public License.
// See http://www.gnu.org/licenses/

use proptest::{
    strategy::{Strategy, ValueTree},
    test_runner::{Config, TestRng, TestRunner},
};

/// Context for generating single values out of strategies.
///
/// Proptest is designed to be built around "value trees", which represent a
/// spectrum from complex values to simpler ones. But in some contexts, like
/// benchmarking or generating corpuses, one just wants a single value. This is
/// a convenience struct for that.
#[derive(Default)]
pub struct ValueGenerator {
    runner: TestRunner,
}

impl ValueGenerator {
    /// Creates a new value generator with the default RNG.
    pub fn new() -> Self { Default::default() }

    /// Creates a new value generator with provided RNG
    pub fn new_with_rng(rng: TestRng) -> Self {
        Self {
            runner: TestRunner::new_with_rng(Config::default(), rng),
        }
    }

    /// Creates a new value generator with a deterministic RNG.
    ///
    /// This generator has a hardcoded seed, so its results are predictable
    /// across test runs. However, a new proptest version may change the
    /// seed.
    pub fn deterministic() -> Self {
        Self {
            runner: TestRunner::deterministic(),
        }
    }

    /// Generates a single value for this strategy.
    ///
    /// Panics if generating the new value fails. The only situation in which
    /// this can happen is if generating the value causes too many internal
    /// rejects.
    pub fn generate<S: Strategy>(&mut self, strategy: S) -> S::Value {
        strategy
            .new_tree(&mut self.runner)
            .expect("creating a new value should succeed")
            .current()
    }
}