perl_test_generators/
variable.rs1use proptest::prelude::*;
7
8static IDENT_START: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
10
11static IDENT_CONT: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789";
13
14fn identifier() -> impl Strategy<Value = String> {
16 prop_oneof![
17 Just("self".to_string()),
19 Just("class".to_string()),
20 (
22 prop::sample::select(IDENT_START),
23 prop::collection::vec(prop::sample::select(IDENT_CONT), 0..=11_usize),
24 )
25 .prop_map(|(first, rest)| {
26 let mut s = String::new();
27 s.push(first as char);
28 for b in rest {
29 s.push(b as char);
30 }
31 s
32 }),
33 ]
34}
35
36pub fn variable() -> impl Strategy<Value = String> {
42 prop_oneof![
43 Just("$_".to_string()),
45 Just("@_".to_string()),
46 Just("%ENV".to_string()),
47 Just("@ARGV".to_string()),
48 Just("$0".to_string()),
49 (1u32..=9).prop_map(|n| format!("${}", n)),
50 (prop_oneof![Just('$'), Just('@'), Just('%')], identifier())
52 .prop_map(|(sigil, name)| format!("{}{}", sigil, name)),
53 (prop_oneof![Just('$'), Just('@'), Just('%')], identifier(), identifier())
55 .prop_map(|(sigil, pkg, name)| format!("{}{}::{}", sigil, pkg, name)),
56 ]
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 proptest! {
64 #[test]
65 fn variable_starts_with_sigil(v in variable()) {
66 assert!(v.starts_with('$') || v.starts_with('@') || v.starts_with('%'));
67 }
68
69 #[test]
70 fn variable_body_is_valid(v in variable()) {
71 let body = &v[1..];
72 assert!(!body.is_empty(), "variable body must not be empty: {}", v);
73 }
74
75 #[test]
76 fn identifier_is_ascii(id in identifier()) {
77 prop_assert!(id.is_ascii(), "identifier must be ASCII: {}", id);
78 }
79 }
80}