1use chopin_pg::error::PgError;
2
3#[derive(Debug)]
7pub enum OrmError {
8 Database(PgError),
10 RecordNotFound,
12 MultipleRecordsFound,
14 Extraction(String),
16 ModelError(String),
18 Validation(Vec<String>),
20}
21
22impl std::fmt::Display for OrmError {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 OrmError::Database(e) => write!(f, "Database error: {}", e),
26 OrmError::RecordNotFound => write!(f, "Record not found"),
27 OrmError::MultipleRecordsFound => write!(f, "Multiple records found"),
28 OrmError::Extraction(msg) => write!(f, "Extraction error: {}", msg),
29 OrmError::ModelError(msg) => write!(f, "Model error: {}", msg),
30 OrmError::Validation(errors) => {
31 write!(f, "Validation failed: {}", errors.join(", "))
32 }
33 }
34 }
35}
36
37impl std::error::Error for OrmError {
38 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
39 match self {
40 OrmError::Database(e) => Some(e),
41 _ => None,
42 }
43 }
44}
45
46impl From<PgError> for OrmError {
47 fn from(e: PgError) -> Self {
48 OrmError::Database(e)
49 }
50}
51
52impl From<String> for OrmError {
53 fn from(msg: String) -> Self {
54 OrmError::ModelError(msg)
55 }
56}
57
58impl From<&str> for OrmError {
59 fn from(msg: &str) -> Self {
60 OrmError::ModelError(msg.to_string())
61 }
62}
63
64pub type OrmResult<T> = Result<T, OrmError>;
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use chopin_pg::error::PgError;
70
71 #[test]
74 fn test_display_record_not_found() {
75 let s = OrmError::RecordNotFound.to_string();
76 assert!(
77 s.contains("not found") || s.contains("Record"),
78 "unexpected: {}",
79 s
80 );
81 }
82
83 #[test]
84 fn test_display_multiple_records_found() {
85 let s = OrmError::MultipleRecordsFound.to_string();
86 assert!(
87 s.contains("Multiple") || s.contains("multiple"),
88 "unexpected: {}",
89 s
90 );
91 }
92
93 #[test]
94 fn test_display_extraction() {
95 let s = OrmError::Extraction("bad type".to_string()).to_string();
96 assert!(s.contains("bad type"), "unexpected: {}", s);
97 }
98
99 #[test]
100 fn test_display_model_error() {
101 let s = OrmError::ModelError("invalid field".to_string()).to_string();
102 assert!(s.contains("invalid field"), "unexpected: {}", s);
103 }
104
105 #[test]
106 fn test_display_database() {
107 let pg_err = PgError::Protocol("test error".to_string());
108 let s = OrmError::Database(pg_err).to_string();
109 assert!(
110 s.contains("Database") || s.contains("test error"),
111 "unexpected: {}",
112 s
113 );
114 }
115
116 #[test]
119 fn test_source_database_is_some() {
120 use std::error::Error;
121 let e = OrmError::Database(PgError::Protocol("x".to_string()));
122 assert!(e.source().is_some());
123 }
124
125 #[test]
126 fn test_source_non_database_is_none() {
127 use std::error::Error;
128 assert!(OrmError::RecordNotFound.source().is_none());
129 assert!(OrmError::MultipleRecordsFound.source().is_none());
130 assert!(OrmError::Extraction("e".into()).source().is_none());
131 assert!(OrmError::ModelError("m".into()).source().is_none());
132 assert!(OrmError::Validation(vec!["v".into()]).source().is_none());
133 }
134
135 #[test]
138 fn test_from_pgerror() {
139 let pg_err = PgError::Protocol("from-test".to_string());
140 let orm_err: OrmError = pg_err.into();
141 assert!(matches!(orm_err, OrmError::Database(_)));
142 }
143
144 #[test]
145 fn test_from_string() {
146 let orm_err: OrmError = "test error".into();
147 assert!(matches!(orm_err, OrmError::ModelError(_)));
148 let orm_err: OrmError = String::from("test error").into();
149 assert!(matches!(orm_err, OrmError::ModelError(_)));
150 }
151
152 #[test]
155 fn test_debug_does_not_panic() {
156 let _ = format!("{:?}", OrmError::RecordNotFound);
157 let _ = format!("{:?}", OrmError::MultipleRecordsFound);
158 let _ = format!("{:?}", OrmError::Extraction("e".into()));
159 let _ = format!("{:?}", OrmError::ModelError("m".into()));
160 let _ = format!("{:?}", OrmError::Database(PgError::Protocol("x".into())));
161 let _ = format!("{:?}", OrmError::Validation(vec!["v".into()]));
162 }
163
164 #[test]
167 fn test_display_validation() {
168 let s = OrmError::Validation(vec!["field required".into(), "too short".into()]).to_string();
169 assert!(s.contains("field required"), "unexpected: {}", s);
170 assert!(s.contains("too short"), "unexpected: {}", s);
171 }
172
173 #[test]
174 fn test_validation_empty() {
175 let s = OrmError::Validation(vec![]).to_string();
176 assert!(s.contains("Validation failed"), "unexpected: {}", s);
177 }
178
179 #[test]
182 fn test_orm_result_ok() {
183 let r: OrmResult<i32> = Ok(7);
184 assert!(matches!(r, Ok(7)));
185 }
186
187 #[test]
188 fn test_orm_result_err() {
189 let r: OrmResult<i32> = Err(OrmError::RecordNotFound);
190 assert!(r.is_err());
191 }
192}