use proptest::{ arbitrary::any, arbitrary::Arbitrary, strategy::Strategy, strategy::ValueTree, test_runner::TestRunner, }; use std::fmt::Debug; enum Op { Simplify, Complicate, } #[track_caller] pub fn assert_arbitrary(e: impl Strategy) { assert_eq_strategy(any::(), e); } #[track_caller] pub fn assert_eq_strategy( l: impl Strategy, r: impl Strategy, ) { let mut ops = vec![Op::Simplify]; for _ in 0..1000 { ops.push(Op::Simplify); ops.push(Op::Complicate); } assert_eq_strategy_ops(l, r, ops) } #[track_caller] fn assert_eq_strategy_ops( l: impl Strategy, r: impl Strategy, ops: Vec, ) { let mut l_runner = TestRunner::deterministic(); let mut r_runner = TestRunner::deterministic(); let mut r_tree = r .new_tree(&mut r_runner) .unwrap_or_else(|e| panic!("r.new_tree failed: {:?}", e)); let mut l_tree = l .new_tree(&mut l_runner) .unwrap_or_else(|e| panic!("l.new_tree failed: {:?}", e)); let mut step = 0; for op in ops { let l_value = l_tree.current(); let r_value = r_tree.current(); assert_eq!(l_value, r_value, "value: {step}"); step += 1; match op { Op::Simplify => assert_eq!(l_tree.simplify(), r_tree.simplify(), "step: {step}"), Op::Complicate => assert_eq!(l_tree.complicate(), r_tree.complicate(), "step: {step}"), } } }