1mod adjectives;
2mod nouns;
3
4use rand::Rng;
5
6pub fn generate_random_name(random_suffix_length: Option<usize>) -> String {
24 generate_random_name_with_prefix(None, random_suffix_length)
25}
26
27pub fn generate_random_name_with_prefix(prefix: Option<&str>, random_suffix_length: Option<usize>) -> String {
45 let mut rng = rand::thread_rng();
46 let adjective = adjectives::ADJECTIVES[rng.gen_range(0..adjectives::ADJECTIVES.len())];
47 let noun = nouns::NOUNS[rng.gen_range(0..nouns::NOUNS.len())];
48
49 let base = match prefix {
50 Some(p) if !p.is_empty() => format!("{}-{}-{}", p, adjective, noun),
51 _ => format!("{}-{}", adjective, noun),
52 };
53
54 match random_suffix_length {
55 Some(length) if length > 0 => {
56 let random_chars: String = (0..length)
57 .map(|_| {
58 let chars = b"0123456789";
59 chars[rng.gen_range(0..chars.len())] as char
60 })
61 .collect();
62 format!("{}-{}", base, random_chars)
63 }
64 _ => base,
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn test_generates_valid_name() {
74 let name = generate_random_name(Some(5));
75 assert_eq!(name.matches('-').count(), 2);
76 }
77
78 #[test]
79 fn test_name_format() {
80 let name = generate_random_name(Some(5));
81 let parts: Vec<&str> = name.split('-').collect();
82 assert_eq!(parts.len(), 3);
83 assert!(!parts[0].is_empty()); assert!(!parts[1].is_empty()); assert_eq!(parts[2].len(), 5); }
87
88 #[test]
89 fn test_random_suffix_numeric() {
90 let name = generate_random_name(Some(5));
91 let parts: Vec<&str> = name.split('-').collect();
92 let suffix = parts[2];
93 assert!(suffix.chars().all(|c| c.is_ascii_digit()));
94 }
95
96 #[test]
97 fn test_adjective_from_list() {
98 let name = generate_random_name(Some(5));
99 let parts: Vec<&str> = name.split('-').collect();
100 let adjective = parts[0];
101 assert!(adjectives::ADJECTIVES.contains(&adjective));
102 }
103
104 #[test]
105 fn test_noun_from_list() {
106 let name = generate_random_name(Some(5));
107 let parts: Vec<&str> = name.split('-').collect();
108 let noun = parts[1];
109 assert!(nouns::NOUNS.contains(&noun));
110 }
111
112 #[test]
113 fn test_generates_different_names() {
114 let name1 = generate_random_name(Some(5));
115 let name2 = generate_random_name(Some(5));
116 assert_ne!(name1, name2);
118 }
119
120 #[test]
121 fn test_no_suffix() {
122 let name = generate_random_name(None);
123 assert_eq!(name.matches('-').count(), 1);
124 let parts: Vec<&str> = name.split('-').collect();
125 assert_eq!(parts.len(), 2);
126 }
127
128 #[test]
129 fn test_custom_suffix_length() {
130 let name = generate_random_name(Some(10));
131 let parts: Vec<&str> = name.split('-').collect();
132 assert_eq!(parts.len(), 3);
133 assert_eq!(parts[2].len(), 10);
134 }
135
136 #[test]
137 fn test_zero_suffix_length() {
138 let name = generate_random_name(Some(0));
139 assert_eq!(name.matches('-').count(), 1);
140 }
141
142 #[test]
143 fn test_no_trailing_dash() {
144 let name_no_suffix = generate_random_name(None);
145 assert!(!name_no_suffix.ends_with('-'));
146
147 let name_zero_suffix = generate_random_name(Some(0));
148 assert!(!name_zero_suffix.ends_with('-'));
149 }
150
151 #[test]
152 fn test_custom_prefix() {
153 let name = generate_random_name_with_prefix(Some("custom"), Some(5));
154 assert!(name.starts_with("custom-"));
155 let parts: Vec<&str> = name.split('-').collect();
156 assert_eq!(parts.len(), 4);
157 assert_eq!(parts[0], "custom");
158 }
159
160 #[test]
161 fn test_no_prefix() {
162 let name = generate_random_name_with_prefix(None, Some(5));
163 let parts: Vec<&str> = name.split('-').collect();
164 assert_eq!(parts.len(), 3);
165 assert!(adjectives::ADJECTIVES.contains(&parts[0]));
166 assert!(nouns::NOUNS.contains(&parts[1]));
167 assert_eq!(parts[2].len(), 5);
168 }
169
170 #[test]
171 fn test_empty_prefix() {
172 let name = generate_random_name_with_prefix(Some(""), None);
173 let parts: Vec<&str> = name.split('-').collect();
174 assert_eq!(parts.len(), 2);
175 assert!(adjectives::ADJECTIVES.contains(&parts[0]));
176 assert!(nouns::NOUNS.contains(&parts[1]));
177 }
178}