1use std::cmp;
2use std::env;
3use std::fmt::Debug;
4use std::panic;
56use crate::{
7 tester::Status::{Discard, Fail, Pass},
8Arbitrary, Gen,
9};
1011/// The main `QuickCheck` type for setting configuration and running
12/// `QuickCheck`.
13pub struct QuickCheck {
14 tests: u64,
15 max_tests: u64,
16 min_tests_passed: u64,
17 rng: Gen,
18}
1920fn qc_tests() -> u64 {
21let default = 100;
22match env::var("QUICKCHECK_TESTS") {
23Ok(val) => val.parse().unwrap_or(default),
24Err(_) => default,
25 }
26}
2728fn qc_max_tests() -> u64 {
29let default = 10_000;
30match env::var("QUICKCHECK_MAX_TESTS") {
31Ok(val) => val.parse().unwrap_or(default),
32Err(_) => default,
33 }
34}
3536fn qc_gen_size() -> usize {
37let default = 100;
38match env::var("QUICKCHECK_GENERATOR_SIZE") {
39Ok(val) => val.parse().unwrap_or(default),
40Err(_) => default,
41 }
42}
4344fn qc_min_tests_passed() -> u64 {
45let default = 0;
46match env::var("QUICKCHECK_MIN_TESTS_PASSED") {
47Ok(val) => val.parse().unwrap_or(default),
48Err(_) => default,
49 }
50}
5152impl Defaultfor QuickCheck {
53fn default() -> Self {
54Self::new()
55 }
56}
5758impl QuickCheck {
59/// Creates a new `QuickCheck` value.
60 ///
61 /// This can be used to run `QuickCheck` on things that implement
62 /// `Testable`. You may also adjust the configuration, such as the
63 /// number of tests to run.
64 ///
65 /// By default, the maximum number of passed tests is set to `100`, the max
66 /// number of overall tests is set to `10000` and the generator is created
67 /// with a size of `100`.
68pub fn new() -> QuickCheck {
69let rng = Gen::new(qc_gen_size());
70let tests = qc_tests();
71let max_tests = cmp::max(tests, qc_max_tests());
72let min_tests_passed = qc_min_tests_passed();
7374QuickCheck { tests, max_tests, min_tests_passed, rng }
75 }
7677/// Set the random number generator to be used by `QuickCheck`.
78pub fn rng(self, rng: Gen) -> QuickCheck {
79QuickCheck { rng, ..self }
80 }
8182/// Set the random number generator to be used by `QuickCheck`.
83 ///
84 /// This is **DEPRECATED**. Using this method on Rust 2024 or newer
85 /// requires the raw identifier syntax because `gen` is now a keyword.
86 /// Instead, prefer the [`QuickCheck::rng`] method.
87#[deprecated(since = "1.1.0", note = "use `set_rng` instead")]
88pub fn r#gen(self, rng: Gen) -> QuickCheck {
89self.rng(rng)
90 }
9192/// Set the number of tests to run.
93 ///
94 /// This actually refers to the maximum number of *passed* tests that
95 /// can occur. Namely, if a test causes a failure, future testing on that
96 /// property stops. Additionally, if tests are discarded, there may be
97 /// fewer than `tests` passed.
98pub fn tests(mut self, tests: u64) -> QuickCheck {
99self.tests = tests;
100self101 }
102103/// Set the maximum number of tests to run.
104 ///
105 /// The number of invocations of a property will never exceed this number.
106 /// This is necessary to cap the number of tests because `QuickCheck`
107 /// properties can discard tests.
108pub fn max_tests(mut self, max_tests: u64) -> QuickCheck {
109self.max_tests = max_tests;
110self111 }
112113/// Set the minimum number of tests that needs to pass.
114 ///
115 /// This actually refers to the minimum number of *valid* *passed* tests
116 /// that needs to pass for the property to be considered successful.
117pub fn min_tests_passed(mut self, min_tests_passed: u64) -> QuickCheck {
118self.min_tests_passed = min_tests_passed;
119self120 }
121122/// Tests a property and returns the result.
123 ///
124 /// The result returned is either the number of tests passed or a witness
125 /// of failure.
126 ///
127 /// (If you're using Rust's unit testing infrastructure, then you'll
128 /// want to use the `quickcheck` method, which will `panic!` on failure.)
129pub fn quicktest<A>(&mut self, f: A) -> Result<u64, TestResult>
130where
131A: Testable,
132 {
133let mut n_tests_passed = 0;
134for _ in 0..self.max_tests {
135if n_tests_passed >= self.tests {
136break;
137 }
138match f.result(&mut self.rng) {
139 TestResult { status: Pass, .. } => n_tests_passed += 1,
140 TestResult { status: Discard, .. } => continue,
141 r @ TestResult { status: Fail, .. } => return Err(r),
142 }
143 }
144Ok(n_tests_passed)
145 }
146147/// Tests a property and calls `panic!` on failure.
148 ///
149 /// The `panic!` message will include a (hopefully) minimal witness of
150 /// failure.
151 ///
152 /// It is appropriate to use this method with Rust's unit testing
153 /// infrastructure.
154 ///
155 /// Note that if the environment variable `RUST_LOG` is set to enable
156 /// `info` level log messages for the `quickcheck` crate, then this will
157 /// include output on how many `QuickCheck` tests were passed.
158 ///
159 /// # Example
160 ///
161 /// ```rust
162 /// use quickcheck::QuickCheck;
163 ///
164 /// fn prop_reverse_reverse() {
165 /// fn revrev(xs: Vec<usize>) -> bool {
166 /// let rev: Vec<_> = xs.clone().into_iter().rev().collect();
167 /// let revrev: Vec<_> = rev.into_iter().rev().collect();
168 /// xs == revrev
169 /// }
170 /// QuickCheck::new().quickcheck(revrev as fn(Vec<usize>) -> bool);
171 /// }
172 /// ```
173pub fn quickcheck<A>(&mut self, f: A)
174where
175A: Testable,
176 {
177// Ignore log init failures, implying it has already been done.
178let _ = crate::env_logger_init();
179180let n_tests_passed = match self.quicktest(f) {
181Ok(n_tests_passed) => n_tests_passed,
182Err(result) => { ::core::panicking::panic_display(&result.failed_msg()); }panic!("{}", result.failed_msg()),
183 };
184185if n_tests_passed >= self.min_tests_passed {
186{
{
let lvl = ::log::Level::Info;
if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level() {
::log::__private_api::log({ ::log::__private_api::GlobalLogger },
format_args!("(Passed {0} QuickCheck tests.)",
n_tests_passed), lvl,
&("quickcheck::tester", "quickcheck::tester",
::log::__private_api::loc()), ());
}
}
};info!("(Passed {} QuickCheck tests.)", n_tests_passed);
187 } else {
188{
::core::panicking::panic_fmt(format_args!("(Unable to generate enough tests, {0} not discarded.)",
n_tests_passed));
};panic!(
189"(Unable to generate enough tests, {} not discarded.)",
190 n_tests_passed
191 );
192 }
193 }
194}
195196/// Convenience function for running `QuickCheck`.
197///
198/// This is an alias for `QuickCheck::new().quickcheck(f)`.
199pub fn quickcheck<A: Testable>(f: A) {
200QuickCheck::new().quickcheck(f)
201}
202203/// Describes the status of a single instance of a test.
204///
205/// All testable things must be capable of producing a `TestResult`.
206#[derive(#[automatically_derived]
impl ::core::clone::Clone for TestResult {
#[inline]
fn clone(&self) -> TestResult {
TestResult {
status: ::core::clone::Clone::clone(&self.status),
arguments: ::core::clone::Clone::clone(&self.arguments),
err: ::core::clone::Clone::clone(&self.err),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for TestResult {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "TestResult",
"status", &self.status, "arguments", &self.arguments, "err",
&&self.err)
}
}Debug)]
207pub struct TestResult {
208 status: Status,
209 arguments: Option<Vec<String>>,
210 err: Option<String>,
211}
212213/// Whether a test has passed, failed or been discarded.
214#[derive(#[automatically_derived]
impl ::core::clone::Clone for Status {
#[inline]
fn clone(&self) -> Status {
match self {
Status::Pass => Status::Pass,
Status::Fail => Status::Fail,
Status::Discard => Status::Discard,
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Status {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Status::Pass => "Pass",
Status::Fail => "Fail",
Status::Discard => "Discard",
})
}
}Debug)]
215enum Status {
216 Pass,
217 Fail,
218 Discard,
219}
220221impl TestResult {
222/// Produces a test result that indicates the current test has passed.
223pub fn passed() -> TestResult {
224TestResult::from_bool(true)
225 }
226227/// Produces a test result that indicates the current test has failed.
228pub fn failed() -> TestResult {
229TestResult::from_bool(false)
230 }
231232/// Produces a test result that indicates failure from a runtime error.
233pub fn error<S: Into<String>>(msg: S) -> TestResult {
234let mut r = TestResult::from_bool(false);
235r.err = Some(msg.into());
236r237 }
238239/// Produces a test result that instructs `quickcheck` to ignore it.
240 /// This is useful for restricting the domain of your properties.
241 /// When a test is discarded, `quickcheck` will replace it with a
242 /// fresh one (up to a certain limit).
243pub fn discard() -> TestResult {
244TestResult { status: Discard, arguments: None, err: None }
245 }
246247/// Converts a `bool` to a `TestResult`. A `true` value indicates that
248 /// the test has passed and a `false` value indicates that the test
249 /// has failed.
250pub fn from_bool(b: bool) -> TestResult {
251TestResult {
252 status: if b { Pass } else { Fail },
253 arguments: None,
254 err: None,
255 }
256 }
257258/// Tests if a "procedure" fails when executed. The test passes only if
259 /// `f` generates a task failure during its execution.
260pub fn must_fail<T, F>(f: F) -> TestResult261where
262F: FnOnce() -> T,
263 F: 'static,
264 T: 'static,
265 {
266let f = panic::AssertUnwindSafe(f);
267TestResult::from_bool(panic::catch_unwind(f).is_err())
268 }
269270/// Returns `true` if and only if this test result describes a failing
271 /// test.
272pub fn is_failure(&self) -> bool {
273match self.status {
274Fail => true,
275Pass | Discard => false,
276 }
277 }
278279/// Returns `true` if and only if this test result describes a failing
280 /// test as a result of a run time error.
281pub fn is_error(&self) -> bool {
282self.is_failure() && self.err.is_some()
283 }
284285fn failed_msg(&self) -> String {
286let arguments_msg = match self.arguments {
287None => "No Arguments Provided".to_owned(),
288Some(ref args) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Arguments: ({0})",
args.join(", ")))
})format!("Arguments: ({})", args.join(", ")),
289 };
290match self.err {
291None => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("[quickcheck] TEST FAILED. {0}",
arguments_msg))
})format!("[quickcheck] TEST FAILED. {arguments_msg}"),
292Some(ref err) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("[quickcheck] TEST FAILED (runtime error). {0}\nError: {1}",
arguments_msg, err))
})format!(
293"[quickcheck] TEST FAILED (runtime error). {arguments_msg}\nError: {err}"
294),
295 }
296 }
297}
298299/// A shorter way of producing a `TestResult` from a `bool`.
300///
301/// # Example
302///
303/// ```rust
304/// use quickcheck::TestResult;
305///
306/// let result: TestResult = (2 > 1).into();
307/// assert!(!result.is_failure());
308/// ```
309impl From<bool> for TestResult {
310fn from(b: bool) -> TestResult {
311TestResult::from_bool(b)
312 }
313}
314315/// `Testable` describes types (e.g., a function) whose values can be
316/// tested.
317///
318/// Anything that can be tested must be capable of producing a `TestResult`
319/// given a random number generator. This is trivial for types like `bool`,
320/// which are just converted to either a passing or failing test result.
321///
322/// For functions, an implementation must generate random arguments
323/// and potentially shrink those arguments if they produce a failure.
324///
325/// It's unlikely that you'll have to implement this trait yourself.
326pub trait Testable: 'static {
327fn result(&self, _: &mut Gen) -> TestResult;
328}
329330impl Testablefor bool {
331fn result(&self, _: &mut Gen) -> TestResult {
332TestResult::from_bool(*self)
333 }
334}
335336impl Testablefor () {
337fn result(&self, _: &mut Gen) -> TestResult {
338TestResult::passed()
339 }
340}
341342impl Testablefor TestResult {
343fn result(&self, _: &mut Gen) -> TestResult {
344self.clone()
345 }
346}
347348impl<A, E> Testablefor Result<A, E>
349where
350A: Testable,
351 E: Debug + 'static,
352{
353fn result(&self, g: &mut Gen) -> TestResult {
354match *self {
355Ok(ref r) => r.result(g),
356Err(ref err) => TestResult::error(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", err))
})format!("{err:?}")),
357 }
358 }
359}
360361/// Return a vector of the debug formatting of each item in `args`
362fn debug_reprs(args: &[&dyn Debug]) -> Vec<String> {
363args.iter().map(|x| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", x))
})format!("{x:?}")).collect()
364}
365366macro_rules! testable_fn {
367 ($($name: ident),*) => {
368369impl<T: Testable,
370 $($name: Arbitrary + Debug),*> Testable for fn($($name),*) -> T {
371#[allow(non_snake_case)]
372fn result(&self, g: &mut Gen) -> TestResult {
373let self_ = *self;
374let a: ($($name,)*) = Arbitrary::arbitrary(g);
375let ( $($name,)* ) = a.clone();
376let mut r = safe(move || {self_($($name),*)}).result(g);
377378if r.is_failure() {
379let mut a = a.shrink();
380while let Some(t) = a.next() {
381let ($($name,)*) = t.clone();
382let mut r_new = safe(move || {self_($($name),*)}).result(g);
383if r_new.is_failure() {
384 {
385let ($(ref $name,)*) : ($($name,)*) = t;
386 r_new.arguments = Some(debug_reprs(&[$($name),*]));
387 }
388389// The shrunk value *does* witness a failure, so remember
390 // it for now
391r = r_new;
392393// ... and switch over to that value, i.e. try to shrink
394 // it further.
395a = t.shrink()
396 }
397 }
398 }
399400 r
401 }
402}}}
403404impl<T: Testable> Testable for fn() -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: () = Arbitrary::arbitrary(g);
let () = a.clone();
let mut r = safe(move || { self_() }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let () = t.clone();
let mut r_new = safe(move || { self_() }).result(g);
if r_new.is_failure() {
{
let (): () = t;
r_new.arguments = Some(debug_reprs(&[]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!();
405impl<T: Testable, A: Arbitrary + Debug> Testable for fn(A) -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: (A,) = Arbitrary::arbitrary(g);
let (A,) = a.clone();
let mut r = safe(move || { self_(A) }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let (A,) = t.clone();
let mut r_new = safe(move || { self_(A) }).result(g);
if r_new.is_failure() {
{
let (ref A,): (A,) = t;
r_new.arguments = Some(debug_reprs(&[A]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!(A);
406impl<T: Testable, A: Arbitrary + Debug, B: Arbitrary + Debug> Testable for
fn(A, B) -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: (A, B) = Arbitrary::arbitrary(g);
let (A, B) = a.clone();
let mut r = safe(move || { self_(A, B) }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let (A, B) = t.clone();
let mut r_new = safe(move || { self_(A, B) }).result(g);
if r_new.is_failure() {
{
let (ref A, ref B): (A, B) = t;
r_new.arguments = Some(debug_reprs(&[A, B]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!(A, B);
407impl<T: Testable, A: Arbitrary + Debug, B: Arbitrary + Debug, C: Arbitrary +
Debug> Testable for fn(A, B, C) -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: (A, B, C) = Arbitrary::arbitrary(g);
let (A, B, C) = a.clone();
let mut r = safe(move || { self_(A, B, C) }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let (A, B, C) = t.clone();
let mut r_new = safe(move || { self_(A, B, C) }).result(g);
if r_new.is_failure() {
{
let (ref A, ref B, ref C): (A, B, C) = t;
r_new.arguments = Some(debug_reprs(&[A, B, C]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!(A, B, C);
408impl<T: Testable, A: Arbitrary + Debug, B: Arbitrary + Debug, C: Arbitrary +
Debug, D: Arbitrary + Debug> Testable for fn(A, B, C, D) -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: (A, B, C, D) = Arbitrary::arbitrary(g);
let (A, B, C, D) = a.clone();
let mut r = safe(move || { self_(A, B, C, D) }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let (A, B, C, D) = t.clone();
let mut r_new = safe(move || { self_(A, B, C, D) }).result(g);
if r_new.is_failure() {
{
let (ref A, ref B, ref C, ref D): (A, B, C, D) = t;
r_new.arguments = Some(debug_reprs(&[A, B, C, D]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!(A, B, C, D);
409impl<T: Testable, A: Arbitrary + Debug, B: Arbitrary + Debug, C: Arbitrary +
Debug, D: Arbitrary + Debug, E: Arbitrary + Debug> Testable for
fn(A, B, C, D, E) -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: (A, B, C, D, E) = Arbitrary::arbitrary(g);
let (A, B, C, D, E) = a.clone();
let mut r = safe(move || { self_(A, B, C, D, E) }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let (A, B, C, D, E) = t.clone();
let mut r_new =
safe(move || { self_(A, B, C, D, E) }).result(g);
if r_new.is_failure() {
{
let (ref A, ref B, ref C, ref D, ref E): (A, B, C, D, E) =
t;
r_new.arguments = Some(debug_reprs(&[A, B, C, D, E]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!(A, B, C, D, E);
410impl<T: Testable, A: Arbitrary + Debug, B: Arbitrary + Debug, C: Arbitrary +
Debug, D: Arbitrary + Debug, E: Arbitrary + Debug, F: Arbitrary + Debug>
Testable for fn(A, B, C, D, E, F) -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: (A, B, C, D, E, F) = Arbitrary::arbitrary(g);
let (A, B, C, D, E, F) = a.clone();
let mut r = safe(move || { self_(A, B, C, D, E, F) }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let (A, B, C, D, E, F) = t.clone();
let mut r_new =
safe(move || { self_(A, B, C, D, E, F) }).result(g);
if r_new.is_failure() {
{
let (ref A, ref B, ref C, ref D, ref E, ref F):
(A, B, C, D, E, F) = t;
r_new.arguments = Some(debug_reprs(&[A, B, C, D, E, F]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!(A, B, C, D, E, F);
411impl<T: Testable, A: Arbitrary + Debug, B: Arbitrary + Debug, C: Arbitrary +
Debug, D: Arbitrary + Debug, E: Arbitrary + Debug, F: Arbitrary + Debug,
G: Arbitrary + Debug> Testable for fn(A, B, C, D, E, F, G) -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: (A, B, C, D, E, F, G) = Arbitrary::arbitrary(g);
let (A, B, C, D, E, F, G) = a.clone();
let mut r = safe(move || { self_(A, B, C, D, E, F, G) }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let (A, B, C, D, E, F, G) = t.clone();
let mut r_new =
safe(move || { self_(A, B, C, D, E, F, G) }).result(g);
if r_new.is_failure() {
{
let (ref A, ref B, ref C, ref D, ref E, ref F, ref G):
(A, B, C, D, E, F, G) = t;
r_new.arguments = Some(debug_reprs(&[A, B, C, D, E, F, G]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!(A, B, C, D, E, F, G);
412impl<T: Testable, A: Arbitrary + Debug, B: Arbitrary + Debug, C: Arbitrary +
Debug, D: Arbitrary + Debug, E: Arbitrary + Debug, F: Arbitrary + Debug,
G: Arbitrary + Debug, H: Arbitrary + Debug> Testable for
fn(A, B, C, D, E, F, G, H) -> T {
#[allow(non_snake_case)]
fn result(&self, g: &mut Gen) -> TestResult {
let self_ = *self;
let a: (A, B, C, D, E, F, G, H) = Arbitrary::arbitrary(g);
let (A, B, C, D, E, F, G, H) = a.clone();
let mut r = safe(move || { self_(A, B, C, D, E, F, G, H) }).result(g);
if r.is_failure() {
let mut a = a.shrink();
while let Some(t) = a.next() {
let (A, B, C, D, E, F, G, H) = t.clone();
let mut r_new =
safe(move || { self_(A, B, C, D, E, F, G, H) }).result(g);
if r_new.is_failure() {
{
let (ref A, ref B, ref C, ref D, ref E, ref F, ref G,
ref H): (A, B, C, D, E, F, G, H) = t;
r_new.arguments =
Some(debug_reprs(&[A, B, C, D, E, F, G, H]));
}
r = r_new;
a = t.shrink()
}
}
}
r
}
}testable_fn!(A, B, C, D, E, F, G, H);
413414fn safe<T, F>(fun: F) -> Result<T, String>
415where
416F: FnOnce() -> T,
417 F: 'static,
418 T: 'static,
419{
420 panic::catch_unwind(panic::AssertUnwindSafe(fun)).map_err(|any_err| {
421// Extract common types of panic payload:
422 // panic and assert produce &str or String
423if let Some(&s) = any_err.downcast_ref::<&str>() {
424s.to_owned()
425 } else if let Some(s) = any_err.downcast_ref::<String>() {
426s.to_owned()
427 } else {
428"UNABLE TO SHOW RESULT OF PANIC.".to_owned()
429 }
430 })
431}
432433#[cfg(test)]
434mod test {
435use crate::{Gen, QuickCheck};
436437#[test]
438fn shrinking_regression_issue_126() {
439fn thetest(vals: Vec<bool>) -> bool {
440 vals.iter().filter(|&v| *v).count() < 2
441}
442let failing_case = QuickCheck::new()
443 .quicktest(thetest as fn(vals: Vec<bool>) -> bool)
444 .unwrap_err();
445let expected_argument = format!("{:?}", [true, true]);
446assert_eq!(failing_case.arguments, Some(vec![expected_argument]));
447 }
448449#[test]
450fn size_for_small_types_issue_143() {
451fn t(_: i8) -> bool {
452true
453}
454 QuickCheck::new().rng(Gen::new(129)).quickcheck(t as fn(i8) -> bool);
455 }
456457#[test]
458fn regression_signed_shrinker_panic() {
459fn foo_can_shrink(v: i8) -> bool {
460let _ = crate::Arbitrary::shrink(&v).take(100).count();
461true
462}
463crate::quickcheck(foo_can_shrink as fn(i8) -> bool);
464 }
465}