1use dtt::error::DateTimeError;
11use std::string::FromUtf8Error;
12use thiserror::Error;
13
14#[derive(Error, Debug)]
23#[non_exhaustive]
24pub enum SitemapError {
25 #[error("XML writing error: {0}")]
27 XmlWriteError(#[from] xml::writer::Error),
28
29 #[error("XML parsing error: {0}")]
31 XmlParseError(#[from] xml::reader::Error),
32
33 #[error("Date error: {0}")]
35 DateError(#[from] DateTimeError),
36
37 #[error("URL error: {0}")]
39 UrlError(#[from] url::ParseError),
40
41 #[error("I/O error: {0}")]
43 IoError(#[from] std::io::Error),
44
45 #[error("Encoding error: {0}")]
47 EncodingError(#[from] FromUtf8Error),
48
49 #[error("Invalid change frequency: {0}")]
51 InvalidChangeFreq(String),
52
53 #[error("Custom error: {0}")]
55 CustomError(String),
56
57 #[error("Sitemap size exceeds the maximum allowed (10MB)")]
59 SitemapTooLarge,
60
61 #[error("Number of URLs ({0}) exceeds the maximum allowed limit (50,000)")]
63 MaxUrlLimitExceeded(usize),
64}
65
66impl SitemapError {
67 pub fn context(&self) -> &'static str {
76 match self {
77 SitemapError::XmlWriteError(_) => "Error occurred while writing XML data",
78 SitemapError::XmlParseError(_) => "Error occurred while parsing XML data",
79 SitemapError::DateError(_) => "Error occurred while parsing or formatting dates",
80 SitemapError::UrlError(_) => "Error occurred while parsing URLs",
81 SitemapError::IoError(_) => "Error occurred during file or network operations",
82 SitemapError::EncodingError(_) => "Error occurred during UTF-8 string encoding or decoding",
83 SitemapError::InvalidChangeFreq(_) => "An invalid change frequency value was provided",
84 SitemapError::CustomError(_) => "An unexpected error occurred",
85 SitemapError::SitemapTooLarge => "The generated sitemap exceeds the maximum allowed size",
86 SitemapError::MaxUrlLimitExceeded(_) => "The number of URLs exceeds the maximum allowed limit",
87 }
88 }
89}
90
91pub type SitemapResult<T> = Result<T, SitemapError>;
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100 use std::io;
101 use xml::writer::{EventWriter, XmlEvent};
102
103 #[test]
104 fn test_error_creation_and_formatting() {
105 let mut writer = EventWriter::new(Vec::new());
107 let xml_write_result = writer.write(XmlEvent::end_element()); let xml_write_error = xml_write_result.unwrap_err();
109 let sitemap_error =
110 SitemapError::XmlWriteError(xml_write_error);
111 assert!(sitemap_error
112 .to_string()
113 .contains("XML writing error"));
114 assert_eq!(
115 sitemap_error.context(),
116 "Error occurred while writing XML data"
117 );
118
119 let custom_error =
120 SitemapError::CustomError("Test error".to_string());
121 assert_eq!(
122 custom_error.to_string(),
123 "Custom error: Test error"
124 );
125 }
126
127 #[test]
128 fn test_error_context() {
129 let url_error =
130 SitemapError::UrlError(url::ParseError::EmptyHost);
131 assert_eq!(
132 url_error.context(),
133 "Error occurred while parsing URLs"
134 );
135
136 let io_error = SitemapError::IoError(io::Error::new(
137 io::ErrorKind::Other,
138 "I/O Error",
139 ));
140 assert_eq!(
141 io_error.context(),
142 "Error occurred during file or network operations"
143 );
144
145 let invalid_change_freq =
146 SitemapError::InvalidChangeFreq("invalid".to_string());
147 assert_eq!(
148 invalid_change_freq.context(),
149 "An invalid change frequency value was provided"
150 );
151 }
152
153 #[test]
154 fn test_error_display() {
155 let date_error =
156 SitemapError::DateError(DateTimeError::InvalidFormat);
157 assert_eq!(
158 date_error.to_string(),
159 "Date error: Invalid date format"
160 );
161
162 let url_error =
163 SitemapError::UrlError(url::ParseError::EmptyHost);
164 assert_eq!(url_error.to_string(), "URL error: empty host");
165
166 let io_error = SitemapError::IoError(io::Error::new(
167 io::ErrorKind::Other,
168 "I/O Error",
169 ));
170 assert_eq!(io_error.to_string(), "I/O error: I/O Error");
171
172 let custom_error = SitemapError::CustomError(
173 "Custom error message".to_string(),
174 );
175 assert_eq!(
176 custom_error.to_string(),
177 "Custom error: Custom error message"
178 );
179
180 let sitemap_too_large = SitemapError::SitemapTooLarge;
181 assert_eq!(
182 sitemap_too_large.to_string(),
183 "Sitemap size exceeds the maximum allowed (10MB)"
184 );
185
186 let max_url_limit_exceeded =
187 SitemapError::MaxUrlLimitExceeded(60000);
188 assert_eq!(
189 max_url_limit_exceeded.to_string(),
190 "Number of URLs (60000) exceeds the maximum allowed limit (50,000)"
191 );
192 }
193
194 #[test]
195 fn test_result_type_alias() {
196 fn demo_function() -> SitemapResult<()> {
197 Err(SitemapError::CustomError("Test error".to_string()))
198 }
199
200 let result = demo_function();
201 assert!(result.is_err());
202 assert!(matches!(
203 result.unwrap_err(),
204 SitemapError::CustomError(_)
205 ));
206 }
207
208 #[test]
209 fn test_xml_parse_error() {
210 let xml = "<invalid>";
211 let reader = xml::reader::EventReader::from_str(xml);
212 let parse_result: Result<
213 Vec<xml::reader::XmlEvent>,
214 xml::reader::Error,
215 > = reader.into_iter().collect();
216 let xml_parse_error = parse_result.unwrap_err();
217 let sitemap_error =
218 SitemapError::XmlParseError(xml_parse_error);
219 assert!(sitemap_error
220 .to_string()
221 .contains("XML parsing error"));
222 assert_eq!(
223 sitemap_error.context(),
224 "Error occurred while parsing XML data"
225 );
226 }
227
228 #[test]
229 fn test_date_error() {
230 let date_error =
231 SitemapError::DateError(DateTimeError::InvalidFormat);
232 assert_eq!(
233 date_error.context(),
234 "Error occurred while parsing or formatting dates"
235 );
236 }
237
238 #[test]
239 fn test_encoding_error() {
240 let invalid_utf8 = vec![0xFF, 0xFE, 0xFD];
241 let encoding_error =
242 String::from_utf8(invalid_utf8).unwrap_err();
243 let sitemap_error = SitemapError::EncodingError(encoding_error);
244 assert!(sitemap_error.to_string().contains("Encoding error"));
245 assert_eq!(
246 sitemap_error.context(),
247 "Error occurred during UTF-8 string encoding or decoding"
248 );
249 }
250
251 #[test]
252 fn test_sitemap_size_errors() {
253 let sitemap_too_large = SitemapError::SitemapTooLarge;
254 assert_eq!(
255 sitemap_too_large.to_string(),
256 "Sitemap size exceeds the maximum allowed (10MB)"
257 );
258 assert_eq!(
259 sitemap_too_large.context(),
260 "The generated sitemap exceeds the maximum allowed size"
261 );
262
263 let max_url_limit_exceeded =
264 SitemapError::MaxUrlLimitExceeded(60000);
265 assert_eq!(
266 max_url_limit_exceeded.to_string(),
267 "Number of URLs (60000) exceeds the maximum allowed limit (50,000)"
268 );
269 assert_eq!(
270 max_url_limit_exceeded.context(),
271 "The number of URLs exceeds the maximum allowed limit"
272 );
273 }
274
275 #[test]
276 fn test_error_propagation() {
277 fn parse_url() -> SitemapResult<()> {
278 Err(SitemapError::UrlError(url::ParseError::EmptyHost))
279 }
280
281 fn handle_url() -> SitemapResult<()> {
282 parse_url()?;
283 Ok(())
284 }
285
286 let result = handle_url();
287 assert!(result.is_err());
288 assert!(matches!(
289 result.unwrap_err(),
290 SitemapError::UrlError(_)
291 ));
292 }
293
294 #[test]
295 fn test_url_parsing_errors() {
296 let empty_host =
297 SitemapError::UrlError(url::ParseError::EmptyHost);
298 assert_eq!(empty_host.to_string(), "URL error: empty host");
299
300 let invalid_port =
301 SitemapError::UrlError(url::ParseError::InvalidPort);
302 assert_eq!(
303 invalid_port.to_string(),
304 "URL error: invalid port number"
305 ); let relative_url = SitemapError::UrlError(
308 url::ParseError::RelativeUrlWithoutBase,
309 );
310 assert_eq!(
311 relative_url.to_string(),
312 "URL error: relative URL without a base"
313 );
314 }
315
316 #[test]
317 fn test_invalid_change_freq_edge_cases() {
318 let empty_string =
319 SitemapError::InvalidChangeFreq("".to_string());
320 assert_eq!(
321 empty_string.to_string(),
322 "Invalid change frequency: "
323 );
324
325 let long_string =
326 SitemapError::InvalidChangeFreq("a".repeat(1000));
327 assert!(long_string
328 .to_string()
329 .contains("Invalid change frequency"));
330 }
331
332 #[test]
333 fn test_max_url_limit_exceeded_edge_cases() {
334 let just_under_limit = SitemapError::MaxUrlLimitExceeded(49999);
335 assert_eq!(just_under_limit.to_string(), "Number of URLs (49999) exceeds the maximum allowed limit (50,000)");
336
337 let at_limit = SitemapError::MaxUrlLimitExceeded(50000);
338 assert_eq!(at_limit.to_string(), "Number of URLs (50000) exceeds the maximum allowed limit (50,000)");
339
340 let over_limit = SitemapError::MaxUrlLimitExceeded(50001);
341 assert_eq!(over_limit.to_string(), "Number of URLs (50001) exceeds the maximum allowed limit (50,000)");
342 }
343}