//-
-// Copyright 2017, 2018 The proptest developers
+// Copyright 2017, 2018, 2019 The proptest developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std_facade::Box;
+use crate::std_facade::Box;
use core::u32;
#[cfg(feature = "std")]
use std::env;
#[cfg(feature = "std")]
-use std::fmt;
-#[cfg(feature = "std")]
use std::ffi::OsString;
#[cfg(feature = "std")]
+use std::fmt;
+#[cfg(feature = "std")]
use std::str::FromStr;
-use test_runner::FailurePersistence;
+use crate::test_runner::result_cache::{noop_result_cache, ResultCache};
+use crate::test_runner::rng::RngAlgorithm;
+use crate::test_runner::FailurePersistence;
#[cfg(feature = "std")]
-use test_runner::FileFailurePersistence;
-use test_runner::result_cache::{noop_result_cache, ResultCache};
+use crate::test_runner::FileFailurePersistence;
#[cfg(feature = "std")]
const CASES: &str = "PROPTEST_CASES";
const TIMEOUT: &str = "PROPTEST_TIMEOUT";
#[cfg(feature = "std")]
const VERBOSE: &str = "PROPTEST_VERBOSE";
+const RNG_ALGORITHM: &str = "PROPTEST_RNG_ALGORITHM";
#[cfg(feature = "std")]
fn contextualize_config(mut result: Config) -> Config {
- fn parse_or_warn<T : FromStr + fmt::Display>(
- src: &OsString, dst: &mut T, typ: &str, var: &str
+ fn parse_or_warn<T: FromStr + fmt::Display>(
+ src: &OsString,
+ dst: &mut T,
+ typ: &str,
+ var: &str,
) {
if let Some(src) = src.to_str() {
if let Ok(value) = src.parse() {
} else {
eprintln!(
"proptest: The env-var {}={} can't be parsed as {}, \
- using default of {}.", var, src, typ, *dst);
+ using default of {}.",
+ var, src, typ, *dst
+ );
}
} else {
eprintln!(
"proptest: The env-var {} is not valid, using \
- default of {}.", var, *dst);
+ default of {}.",
+ var, *dst
+ );
}
}
- result.failure_persistence = Some(Box::new(FileFailurePersistence::default()));
- for (var, value) in env::vars_os().filter_map(
- |(k,v)| k.into_string().ok().map(|k| (k,v))) {
+ result.failure_persistence =
+ Some(Box::new(FileFailurePersistence::default()));
+ for (var, value) in
+ env::vars_os().filter_map(|(k, v)| k.into_string().ok().map(|k| (k, v)))
+ {
match var.as_str() {
CASES => parse_or_warn(&value, &mut result.cases, "u32", CASES),
MAX_LOCAL_REJECTS => parse_or_warn(
- &value, &mut result.max_local_rejects,
- "u32", MAX_LOCAL_REJECTS),
+ &value,
+ &mut result.max_local_rejects,
+ "u32",
+ MAX_LOCAL_REJECTS,
+ ),
MAX_GLOBAL_REJECTS => parse_or_warn(
- &value, &mut result.max_global_rejects,
- "u32", MAX_GLOBAL_REJECTS),
+ &value,
+ &mut result.max_global_rejects,
+ "u32",
+ MAX_GLOBAL_REJECTS,
+ ),
MAX_FLAT_MAP_REGENS => parse_or_warn(
- &value, &mut result.max_flat_map_regens,
- "u32", MAX_FLAT_MAP_REGENS),
+ &value,
+ &mut result.max_flat_map_regens,
+ "u32",
+ MAX_FLAT_MAP_REGENS,
+ ),
#[cfg(feature = "fork")]
FORK => parse_or_warn(&value, &mut result.fork, "bool", FORK),
#[cfg(feature = "timeout")]
- TIMEOUT => parse_or_warn(
- &value, &mut result.timeout, "timeout", TIMEOUT),
+ TIMEOUT => {
+ parse_or_warn(&value, &mut result.timeout, "timeout", TIMEOUT)
+ }
MAX_SHRINK_TIME => parse_or_warn(
- &value, &mut result.max_shrink_time, "u32", MAX_SHRINK_TIME),
+ &value,
+ &mut result.max_shrink_time,
+ "u32",
+ MAX_SHRINK_TIME,
+ ),
MAX_SHRINK_ITERS => parse_or_warn(
- &value, &mut result.max_shrink_iters, "u32", MAX_SHRINK_ITERS),
- VERBOSE => parse_or_warn(
- &value, &mut result.verbose, "u32", VERBOSE),
-
- _ => if var.starts_with("PROPTEST_") {
- eprintln!("proptest: Ignoring unknown env-var {}.", var);
- },
+ &value,
+ &mut result.max_shrink_iters,
+ "u32",
+ MAX_SHRINK_ITERS,
+ ),
+ VERBOSE => {
+ parse_or_warn(&value, &mut result.verbose, "u32", VERBOSE)
+ }
+ RNG_ALGORITHM => parse_or_warn(
+ &value,
+ &mut result.rng_algorithm,
+ "RngAlgorithm",
+ RNG_ALGORITHM,
+ ),
+
+ _ => {
+ if var.starts_with("PROPTEST_") {
+ eprintln!("proptest: Ignoring unknown env-var {}.", var);
+ }
+ }
}
}
}
#[cfg(not(feature = "std"))]
-fn contextualize_config(result: Config) -> Config { result }
+fn contextualize_config(result: Config) -> Config {
+ result
+}
-/// The default config, computed by combining environment variables and
-/// defaults.
+fn default_default_config() -> Config {
+ Config {
+ cases: 256,
+ max_local_rejects: 65_536,
+ max_global_rejects: 1024,
+ max_flat_map_regens: 1_000_000,
+ failure_persistence: None,
+ source_file: None,
+ test_name: None,
+ #[cfg(feature = "fork")]
+ fork: false,
+ #[cfg(feature = "timeout")]
+ timeout: 0,
+ #[cfg(feature = "std")]
+ max_shrink_time: 0,
+ max_shrink_iters: u32::MAX,
+ result_cache: noop_result_cache,
+ #[cfg(feature = "std")]
+ verbose: 0,
+ rng_algorithm: RngAlgorithm::default(),
+ _non_exhaustive: (),
+ }
+}
+
+// The default config, computed by combining environment variables and
+// defaults.
+#[cfg(feature = "std")]
lazy_static! {
- static ref DEFAULT_CONFIG: Config = {
- let result = Config {
- cases: 256,
- max_local_rejects: 65_536,
- max_global_rejects: 1024,
- max_flat_map_regens: 1_000_000,
- failure_persistence: None,
- source_file: None,
- test_name: None,
- #[cfg(feature = "fork")]
- fork: false,
- #[cfg(feature = "timeout")]
- timeout: 0,
- #[cfg(feature = "std")]
- max_shrink_time: 0,
- max_shrink_iters: u32::MAX,
- result_cache: noop_result_cache,
- #[cfg(feature = "std")]
- verbose: 0,
- _non_exhaustive: (),
- };
-
- contextualize_config(result)
- };
+ static ref DEFAULT_CONFIG: Config =
+ { contextualize_config(default_default_config()) };
}
/// Configuration for how a proptest test should be run.
/// Give up on shrinking if more than this number of iterations of the test
/// code are run.
///
+ /// Setting this to `std::u32::MAX` causes the actual limit to be four
+ /// times the number of test cases.
+ ///
/// Setting this value to `0` disables shrinking altogether.
///
+ /// Note that the type of this field will change in a future version of
+ /// proptest to better accommodate its special values.
+ ///
/// The default is `std::u32::MAX`, which can be overridden by setting the
/// `PROPTEST_MAX_SHRINK_ITERS` environment variable.
pub max_shrink_iters: u32,
///
/// Caching incurs its own overhead, and may very well make your test run
/// more slowly.
- pub result_cache: fn () -> Box<dyn ResultCache>,
+ pub result_cache: fn() -> Box<dyn ResultCache>,
/// Set to non-zero values to cause proptest to emit human-targeted
/// messages to stderr as it runs.
#[cfg(feature = "std")]
pub verbose: u32,
+ /// The RNG algorithm to use when not using a user-provided RNG.
+ ///
+ /// The default is `RngAlgorithm::default()`, which can be overridden by
+ /// setting the `PROPTEST_RNG_ALGORITHM` environment variable to one of the following:
+ ///
+ /// - `xs` — `RngAlgorithm::XorShift`
+ /// - `cc` — `RngAlgorithm::ChaCha`
+ pub rng_algorithm: RngAlgorithm,
+
// Needs to be public so FRU syntax can be used.
#[doc(hidden)]
pub _non_exhaustive: (),
/// );
/// ```
pub fn with_cases(cases: u32) -> Self {
- Self { cases, .. Config::default() }
+ Self {
+ cases,
+ ..Config::default()
+ }
}
/// Constructs a `Config` only differing from the `default()` in the
/// );
/// ```
pub fn with_source_file(source_file: &'static str) -> Self {
- Self { source_file: Some(source_file), .. Config::default() }
+ Self {
+ source_file: Some(source_file),
+ ..Config::default()
+ }
}
/// Constructs a `Config` only differing from the provided Config instance, `self`,
0
}
+ /// Returns the configured limit on shrinking iterations.
+ ///
+ /// This takes into account the special "automatic" behaviour.
+ pub fn max_shrink_iters(&self) -> u32 {
+ if u32::MAX == self.max_shrink_iters {
+ self.cases.saturating_mul(4)
+ } else {
+ self.max_shrink_iters
+ }
+ }
+
// Used by macros to force the config to be owned without depending on
// certain traits being `use`d.
#[allow(missing_docs)]
}
}
+#[cfg(feature = "std")]
impl Default for Config {
fn default() -> Self {
DEFAULT_CONFIG.clone()
}
}
+
+#[cfg(not(feature = "std"))]
+impl Default for Config {
+ fn default() -> Self {
+ default_default_config()
+ }
+}