#[cfg(feature = "std")]
use std::env;
#[cfg(feature = "std")]
use std::fmt;
#[cfg(feature = "std")]
use std::ffi::OsString;
#[cfg(feature = "std")]
use std::str::FromStr;
#[cfg(all(feature = "alloc", not(feature="std")))]
use alloc::boxed::Box;
#[cfg(feature = "std")]
use std::boxed::Box;
use test_runner::FailurePersistence;
#[cfg(feature = "std")]
use test_runner::FileFailurePersistence;
#[cfg(feature = "std")]
const CASES: &str = "PROPTEST_CASES";
#[cfg(feature = "std")]
const MAX_LOCAL_REJECTS: &str = "PROPTEST_MAX_LOCAL_REJECTS";
#[cfg(feature = "std")]
const MAX_GLOBAL_REJECTS: &str = "PROPTEST_MAX_GLOBAL_REJECTS";
#[cfg(feature = "std")]
const MAX_FLAT_MAP_REGENS: &str = "PROPTEST_MAX_FLAT_MAP_REGENS";
#[cfg(feature = "fork")]
const FORK: &str = "PROPTEST_FORK";
#[cfg(feature = "timeout")]
const TIMEOUT: &str = "PROPTEST_TIMEOUT";
#[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
) {
if let Some(src) = src.to_str() {
if let Ok(value) = src.parse() {
*dst = value;
} else {
eprintln!(
"proptest: The env-var {}={} can't be parsed as {}, \
using default of {}.", var, src, typ, *dst);
}
} else {
eprintln!(
"proptest: The env-var {} is not valid, using \
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))) {
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),
MAX_GLOBAL_REJECTS => parse_or_warn(
&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),
#[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),
_ => if var.starts_with("PROPTEST_") {
eprintln!("proptest: Ignoring unknown env-var {}.", var);
},
}
}
result
}
#[cfg(not(feature = "std"))]
fn contextualize_config(result: Config) -> Config { result }
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,
_non_exhaustive: (),
};
contextualize_config(result)
};
}
#[derive(Clone, Debug, PartialEq)]
pub struct Config {
pub cases: u32,
pub max_local_rejects: u32,
pub max_global_rejects: u32,
pub max_flat_map_regens: u32,
pub failure_persistence: Option<Box<FailurePersistence>>,
pub source_file: Option<&'static str>,
pub test_name: Option<&'static str>,
#[cfg(feature = "fork")]
pub fork: bool,
#[cfg(feature = "timeout")]
pub timeout: u32,
#[doc(hidden)]
pub _non_exhaustive: (),
}
impl Config {
pub fn with_cases(cases: u32) -> Self {
Self { cases, .. Config::default() }
}
pub fn with_source_file(source_file: &'static str) -> Self {
Self { source_file: Some(source_file), .. Config::default() }
}
pub fn clone_with_source_file(&self, source_file: &'static str) -> Self {
let mut result = self.clone();
result.source_file = Some(source_file);
result
}
pub fn fork(&self) -> bool {
self._fork() || self.timeout() > 0
}
#[cfg(feature = "fork")]
fn _fork(&self) -> bool {
self.fork
}
#[cfg(not(feature = "fork"))]
fn _fork(&self) -> bool {
false
}
#[cfg(feature = "timeout")]
pub fn timeout(&self) -> u32 {
self.timeout
}
#[cfg(not(feature = "timeout"))]
pub fn timeout(&self) -> u32 {
0
}
}
impl Default for Config {
fn default() -> Self {
DEFAULT_CONFIG.clone()
}
}