From 6ecdf5bb4b0132ce66670b4d46453aa022ea892c Mon Sep 17 00:00:00 2001 From: Jakob Schikowski Date: Tue, 9 Feb 2021 02:13:10 +0100 Subject: [PATCH 1/4] api: add Gen::set_size and Gen::from_seed The seed still can't be set by QuickCheck users, but the new Gen constructor is useful for other crates that use QuickCheck only for its Arbitrary trait. Closes #277 --- src/arbitrary.rs | 24 +++++++++++++++++++++--- src/tester.rs | 2 +- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/arbitrary.rs b/src/arbitrary.rs index 92f893b..26b0be8 100644 --- a/src/arbitrary.rs +++ b/src/arbitrary.rs @@ -39,15 +39,33 @@ pub struct Gen { } impl Gen { - /// Returns a `Gen` with the given size configuration. + pub(crate) const DEFAULT_SIZE: usize = 100; + + /// Returns a `Gen` with a random seed and the given size configuration. + pub fn new(size: usize) -> Gen { + Gen { rng: rand::rngs::SmallRng::from_entropy(), size: size } + } + + /// Returns a `Gen` with the given seed and a default size configuration. + /// + /// Two `Gen`s created with the same seed will generate the same values. Though the values + /// may vary between QuickCheck releases. + pub fn from_seed(seed: u64) -> Gen { + Gen { + rng: rand::rngs::SmallRng::seed_from_u64(seed), + size: Self::DEFAULT_SIZE, + } + } + + /// Sets the size configuration for this generator. /// /// The `size` parameter controls the size of random values generated. /// For example, it specifies the maximum length of a randomly generated /// vector, but is and should not be used to control the range of a /// randomly generated number. (Unless that number is used to control the /// size of a data structure.) - pub fn new(size: usize) -> Gen { - Gen { rng: rand::rngs::SmallRng::from_entropy(), size: size } + pub fn set_size(&mut self, size: usize) { + self.size = size; } /// Returns the size configured with this generator. diff --git a/src/tester.rs b/src/tester.rs index e2eaa20..e639973 100644 --- a/src/tester.rs +++ b/src/tester.rs @@ -33,7 +33,7 @@ fn qc_max_tests() -> u64 { } fn qc_gen_size() -> usize { - let default = 100; + let default = Gen::DEFAULT_SIZE; match env::var("QUICKCHECK_GENERATOR_SIZE") { Ok(val) => val.parse().unwrap_or(default), Err(_) => default, From 9eabf07af8b7a0f8b28f70de7ab16de7c30cd566 Mon Sep 17 00:00:00 2001 From: Julian Ganz Date: Sun, 9 May 2021 14:09:22 +0200 Subject: [PATCH 2/4] Enable generator to be seeded via the environment This change allows generators in a `QuickCheck` instance to be seeded via the environment. This allows reproducing tests by simply setting the environment variable, e.g. when performing an automated `git bisect`. If implementations of `Arbitrary` do not pull new entropy during generation of values, e.g. by using generators returned by `Gen::new`, that is. --- src/tester.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/tester.rs b/src/tester.rs index e639973..d077969 100644 --- a/src/tester.rs +++ b/src/tester.rs @@ -40,6 +40,10 @@ fn qc_gen_size() -> usize { } } +fn qc_seed() -> Option { + env::var("QUICKCHECK_SEED").ok().and_then(|v| v.parse().ok()) +} + fn qc_min_tests_passed() -> u64 { let default = 0; match env::var("QUICKCHECK_MIN_TESTS_PASSED") { @@ -59,7 +63,13 @@ impl QuickCheck { /// number of overall tests is set to `10000` and the generator is created /// with a size of `100`. pub fn new() -> QuickCheck { - let gen = Gen::new(qc_gen_size()); + let gen = if let Some(seed) = qc_seed() { + let mut g = Gen::from_seed(seed); + g.set_size(qc_gen_size()); + g + } else { + Gen::new(qc_gen_size()) + }; let tests = qc_tests(); let max_tests = cmp::max(tests, qc_max_tests()); let min_tests_passed = qc_min_tests_passed(); From b5d0483735d6eb5561337e8336d05aa9067e8798 Mon Sep 17 00:00:00 2001 From: Julian Ganz Date: Mon, 10 May 2021 09:19:40 +0200 Subject: [PATCH 3/4] Retrieve seed as hexadecimal number rather than decimal --- src/tester.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tester.rs b/src/tester.rs index d077969..4169fe9 100644 --- a/src/tester.rs +++ b/src/tester.rs @@ -41,7 +41,7 @@ fn qc_gen_size() -> usize { } fn qc_seed() -> Option { - env::var("QUICKCHECK_SEED").ok().and_then(|v| v.parse().ok()) + env::var("QUICKCHECK_SEED").ok().and_then(|v| u64::from_str_radix(v.as_ref(), 16).ok()) } fn qc_min_tests_passed() -> u64 { From 4ee3c0e20768f5f8f02e694c9c58d0737015dfc7 Mon Sep 17 00:00:00 2001 From: Julian Ganz Date: Sat, 29 May 2021 12:14:30 +0200 Subject: [PATCH 4/4] List all config params and env vars in doc of Quickcheck::new Previously, the configuration parameters were described in prose. Neither the minimum number of valid tests nor any description of the environment variables which could invluence these parameters were covered by the text. Naturally, neither was the recently introduced `QUICKCHECK_SEED`. This change replaces the prose with a list, which includes not only the defaults (where applicable) but also the environment variables consultet during initialization. --- src/tester.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/tester.rs b/src/tester.rs index 4169fe9..723cfbe 100644 --- a/src/tester.rs +++ b/src/tester.rs @@ -59,9 +59,19 @@ impl QuickCheck { /// You may also adjust the configuration, such as the number of tests to /// run. /// - /// By default, the maximum number of passed tests is set to `100`, the max - /// number of overall tests is set to `10000` and the generator is created - /// with a size of `100`. + /// The instance is initialized with the following configuration: + /// + /// * The maximum number of passed tests is initialized from the env var + /// `QUICKCHECK_TESTS`. This value defaults to `100`. + /// * The maximum number of overall tests is initialized from the env var + /// `QUICKCHECK_MAX_TESTS`. This value defaults to `10000`. + /// * The generator is initialized with a size specified in the env var + /// `QUICKCHECK_GENERATOR_SIZE`. The size defaults to `100`. + /// * If the env var `QUICKCHECK_SEED` is present and contains a + /// hexadecimal number, its value is used to seed the generator. + /// * The minimum number of valid tests which need to pass (i.e. excluding + /// discarded ones) is initialized from the env var + /// `QUICKCHECK_MIN_TESTS_PASSED`. This defaults to `0`. pub fn new() -> QuickCheck { let gen = if let Some(seed) = qc_seed() { let mut g = Gen::from_seed(seed);