Skip to main content

pattern_core/test_utils/
generators.rs

1//! Property-based test generators for patterns
2//!
3//! This module provides property-based test generators for patterns using proptest.
4//! Generators produce patterns with various structures (atomic, nested, deep, wide)
5//! suitable for property testing.
6
7#[cfg(test)]
8use proptest::prelude::*;
9
10#[cfg(test)]
11use crate::Pattern;
12
13/// Generate an arbitrary pattern with integer values
14///
15/// Generates patterns with:
16/// - Values between -100 and 100
17/// - Up to 10 elements per level
18/// - Up to 5 levels of nesting
19#[cfg(test)]
20pub fn arbitrary_pattern_i32() -> impl Strategy<Value = Pattern<i32>> {
21    let leaf = any::<i32>().prop_map(Pattern::point);
22
23    leaf.prop_recursive(
24        5,   // max_depth
25        256, // desired_size
26        10,  // max_elements per level
27        |inner| {
28            (any::<i32>(), prop::collection::vec(inner, 0..10))
29                .prop_map(|(value, elements)| Pattern::pattern(value, elements))
30        },
31    )
32}
33
34/// Generate an arbitrary pattern with string values
35///
36/// Generates patterns with:
37/// - String values (alphanumeric)
38/// - Up to 10 elements per level
39/// - Up to 5 levels of nesting
40#[cfg(test)]
41pub fn arbitrary_pattern_string() -> impl Strategy<Value = Pattern<String>> {
42    let leaf = "[a-zA-Z0-9]{1,10}".prop_map(|s: String| Pattern::point(s));
43
44    leaf.prop_recursive(
45        5,   // max_depth
46        256, // desired_size
47        10,  // max_elements per level
48        |inner| {
49            ("[a-zA-Z0-9]{1,10}", prop::collection::vec(inner, 0..10))
50                .prop_map(|(value, elements)| Pattern::pattern(value, elements))
51        },
52    )
53}
54
55/// Generate a pattern with Option values (for sequence testing)
56///
57/// Some values will be Some, others None, allowing testing of sequence operations
58#[cfg(test)]
59pub fn arbitrary_pattern_option() -> impl Strategy<Value = Pattern<Option<i32>>> {
60    let leaf = any::<Option<i32>>().prop_map(Pattern::point);
61
62    leaf.prop_recursive(
63        5,   // max_depth
64        256, // desired_size
65        10,  // max_elements per level
66        |inner| {
67            (any::<Option<i32>>(), prop::collection::vec(inner, 0..10))
68                .prop_map(|(value, elements)| Pattern::pattern(value, elements))
69        },
70    )
71}
72
73/// Generate a pattern with Result values (for sequence testing)
74///
75/// Some values will be Ok, others Err, allowing testing of sequence operations
76#[cfg(test)]
77pub fn arbitrary_pattern_result() -> impl Strategy<Value = Pattern<Result<i32, String>>> {
78    let leaf = any::<Result<i32, String>>().prop_map(Pattern::point);
79
80    leaf.prop_recursive(
81        5,   // max_depth
82        256, // desired_size
83        10,  // max_elements per level
84        |inner| {
85            (
86                any::<Result<i32, String>>(),
87                prop::collection::vec(inner, 0..10),
88            )
89                .prop_map(|(value, elements)| Pattern::pattern(value, elements))
90        },
91    )
92}
93
94/// Generate a small atomic pattern (for quick tests)
95#[cfg(test)]
96pub fn atomic_pattern_i32() -> impl Strategy<Value = Pattern<i32>> {
97    any::<i32>().prop_map(|v| Pattern::point(v))
98}
99
100/// Generate a shallow nested pattern (1-2 levels, for specific tests)
101#[cfg(test)]
102pub fn shallow_pattern_i32() -> impl Strategy<Value = Pattern<i32>> {
103    let leaf = any::<i32>().prop_map(|v| Pattern::point(v));
104
105    leaf.prop_recursive(
106        2,  // max_depth (shallow)
107        64, // desired_size (small)
108        5,  // max_elements per level
109        |inner| {
110            (any::<i32>(), prop::collection::vec(inner, 0..5))
111                .prop_map(|(value, elements)| Pattern::pattern(value, elements))
112        },
113    )
114}
115
116/// Generate a deep nested pattern (for stack safety tests)
117#[cfg(test)]
118pub fn deep_pattern_i32() -> impl Strategy<Value = Pattern<i32>> {
119    let leaf = any::<i32>().prop_map(|v| Pattern::point(v));
120
121    leaf.prop_recursive(
122        20,  // max_depth (deep!)
123        100, // desired_size
124        3,   // max_elements per level (fewer to keep depth high)
125        |inner| {
126            (any::<i32>(), prop::collection::vec(inner, 0..3))
127                .prop_map(|(value, elements)| Pattern::pattern(value, elements))
128        },
129    )
130}
131
132/// Generate a wide pattern (many siblings, for breadth tests)
133#[cfg(test)]
134pub fn wide_pattern_i32() -> impl Strategy<Value = Pattern<i32>> {
135    let leaf = any::<i32>().prop_map(|v| Pattern::point(v));
136
137    leaf.prop_recursive(
138        3,    // max_depth (shallow to keep wide)
139        1000, // desired_size (large)
140        50,   // max_elements per level (many siblings!)
141        |inner| {
142            (any::<i32>(), prop::collection::vec(inner, 0..50))
143                .prop_map(|(value, elements)| Pattern::pattern(value, elements))
144        },
145    )
146}