Skip to main content

perl_test_generators/
module.rs

1//! Generators for Perl module paths.
2//!
3//! Produces syntactically valid module names like `Foo`, `Foo::Bar`, `Foo::Bar::Baz`.
4
5use proptest::prelude::*;
6
7/// Single identifier segment (capitalized PascalCase or `UPPER_CASE`).
8fn module_segment() -> impl Strategy<Value = String> {
9    prop_oneof![
10        Just("Foo".to_string()),
11        Just("Bar".to_string()),
12        Just("Baz".to_string()),
13        Just("HTTP".to_string()),
14        Just("IO".to_string()),
15        (
16            prop::char::range('A', 'Z'),
17            prop::collection::vec(prop::char::range('a', 'z'), 0..=7_usize),
18        )
19            .prop_map(|(first, rest)| std::iter::once(first).chain(rest).collect::<String>()),
20    ]
21}
22
23/// Generate a full module path (1–5 segments joined by `::`).
24pub fn module_path() -> impl Strategy<Value = String> {
25    prop::collection::vec(module_segment(), 1..=5_usize).prop_map(|segs| segs.join("::"))
26}
27
28/// Generate module path segments as a `Vec<String>`.
29pub fn module_path_segments() -> impl Strategy<Value = Vec<String>> {
30    prop::collection::vec(module_segment(), 1..=5_usize)
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36
37    proptest! {
38        #[test]
39        fn module_path_no_empty_segments(path in module_path()) {
40            for seg in path.split("::") {
41                assert!(!seg.is_empty(), "empty segment in {}", path);
42            }
43        }
44
45        #[test]
46        fn module_path_starts_uppercase(path in module_path()) {
47            prop_assert!(!path.is_empty(), "module path must not be empty");
48            let first = path.chars().next().unwrap_or_default();
49            prop_assert!(first.is_ascii_uppercase(), "first char not uppercase: {}", path);
50        }
51
52        #[test]
53        fn segments_non_empty(segs in module_path_segments()) {
54            prop_assert!(!segs.is_empty());
55            for s in &segs {
56                prop_assert!(!s.is_empty());
57            }
58        }
59    }
60}