1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45//! Support for property test usage.
67use std::any::Any;
8use std::fmt::Debug;
9use std::str::FromStr as _;
1011use proptest::test_runner::{FailurePersistence, PersistedSeed};
1213/// Persists all failed seeds to the source file.
14///
15/// Proptest generates nondeterministic tests in the sense that different seeds
16/// will be used in each run, this is intended because we expect the properties
17/// to hold for all possible inputs. So test flakes should be treated as test
18/// failures. This struct configures the containing proptest to log the seeds
19/// that caused test failures, please add all those seeds to the source file
20/// so that the test failure can be persisted.
21#[derive(Clone, Debug, PartialEq)]
22pub struct FailedSeeds(pub Vec<&'static str>);
2324impl FailurePersistence for FailedSeeds {
25fn load_persisted_failures2(&self, _source_file: Option<&'static str>) -> Vec<PersistedSeed> {
26let Self(seeds) = self;
27 seeds.iter().map(|s| PersistedSeed::from_str(s).expect("malformed seed")).collect()
28 }
2930fn save_persisted_failure2(
31&mut self,
32 source_file: Option<&'static str>,
33 seed: PersistedSeed,
34 shrunken_value: &dyn Debug,
35 ) {
36eprintln!("Test failed when: {:?}", shrunken_value);
37eprintln!("To reproduce this failure please add the following line:");
38// The `Display` and `FromStr` impl for `PersistedSeed` are inverse
39 // of each other.
40eprintln!("\"{}\"", seed);
41eprintln!("to the test config in file {}", source_file.expect("failed to get source file"));
42 }
4344fn box_clone(&self) -> Box<dyn FailurePersistence> {
45 Box::new(self.clone())
46 }
4748fn eq(&self, other: &dyn FailurePersistence) -> bool {
49 other.as_any().downcast_ref::<Self>().map_or(false, |x| x == self)
50 }
5152fn as_any(&self) -> &dyn Any {
53self
54}
55}
5657#[macro_export]
58macro_rules! failed_seeds_no_std {
59 ($($seed:literal),*) => {
60Some({
61use alloc::{boxed::Box, vec};
62 Box::new(proptest_support::FailedSeeds(vec![$($seed),*]))
63 })
64 }
65}
6667#[macro_export]
68macro_rules! failed_seeds {
69 ($($seed:literal),*) => {
70Some({
71 Box::new(proptest_support::FailedSeeds(vec![$($seed),*]))
72 })
73 }
74}