version_migrate/
errors.rs1use thiserror::Error;
4
5#[derive(Error, Debug)]
7pub enum MigrationError {
8 #[error("Failed to deserialize: {0}")]
10 DeserializationError(String),
11
12 #[error("Failed to serialize: {0}")]
14 SerializationError(String),
15
16 #[error("Entity '{0}' not found")]
18 EntityNotFound(String),
19
20 #[error("No migration path defined for entity '{entity}' version '{version}'")]
22 MigrationPathNotDefined {
23 entity: String,
25 version: String,
27 },
28
29 #[error("Migration failed from '{from}' to '{to}': {error}")]
31 MigrationStepFailed {
32 from: String,
34 to: String,
36 error: String,
38 },
39
40 #[error("Circular migration path detected in entity '{entity}': {path}")]
42 CircularMigrationPath {
43 entity: String,
45 path: String,
47 },
48
49 #[error("Invalid version order in entity '{entity}': '{from}' -> '{to}' (versions must increase according to semver)")]
51 InvalidVersionOrder {
52 entity: String,
54 from: String,
56 to: String,
58 },
59
60 #[error("File I/O error at '{path}': {error}")]
62 IoError {
63 path: String,
65 error: String,
67 },
68
69 #[error("Failed to acquire file lock for '{path}': {error}")]
71 LockError {
72 path: String,
74 error: String,
76 },
77
78 #[error("Failed to parse TOML: {0}")]
80 TomlParseError(String),
81
82 #[error("Failed to serialize to TOML: {0}")]
84 TomlSerializeError(String),
85
86 #[error("Cannot determine home directory")]
88 HomeDirNotFound,
89
90 #[error("Failed to resolve path: {0}")]
92 PathResolution(String),
93
94 #[error("Failed to encode filename for ID '{id}': {reason}")]
96 FilenameEncoding {
97 id: String,
99 reason: String,
101 },
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn test_error_display_deserialization() {
110 let err = MigrationError::DeserializationError("invalid JSON".to_string());
111 let display = format!("{}", err);
112 assert!(display.contains("Failed to deserialize"));
113 assert!(display.contains("invalid JSON"));
114 }
115
116 #[test]
117 fn test_error_display_serialization() {
118 let err = MigrationError::SerializationError("invalid data".to_string());
119 let display = format!("{}", err);
120 assert!(display.contains("Failed to serialize"));
121 assert!(display.contains("invalid data"));
122 }
123
124 #[test]
125 fn test_error_display_entity_not_found() {
126 let err = MigrationError::EntityNotFound("user".to_string());
127 let display = format!("{}", err);
128 assert!(display.contains("Entity 'user' not found"));
129 }
130
131 #[test]
132 fn test_error_display_migration_path_not_defined() {
133 let err = MigrationError::MigrationPathNotDefined {
134 entity: "task".to_string(),
135 version: "2.0.0".to_string(),
136 };
137 let display = format!("{}", err);
138 assert!(display.contains("No migration path defined"));
139 assert!(display.contains("task"));
140 assert!(display.contains("2.0.0"));
141 }
142
143 #[test]
144 fn test_error_display_migration_step_failed() {
145 let err = MigrationError::MigrationStepFailed {
146 from: "1.0.0".to_string(),
147 to: "2.0.0".to_string(),
148 error: "field missing".to_string(),
149 };
150 let display = format!("{}", err);
151 assert!(display.contains("Migration failed"));
152 assert!(display.contains("1.0.0"));
153 assert!(display.contains("2.0.0"));
154 assert!(display.contains("field missing"));
155 }
156
157 #[test]
158 fn test_error_debug() {
159 let err = MigrationError::EntityNotFound("test".to_string());
160 let debug = format!("{:?}", err);
161 assert!(debug.contains("EntityNotFound"));
162 }
163
164 #[test]
165 fn test_error_is_std_error() {
166 let err = MigrationError::DeserializationError("test".to_string());
167 let _: &dyn std::error::Error = &err;
169 }
170
171 #[test]
172 fn test_error_display_circular_migration_path() {
173 let err = MigrationError::CircularMigrationPath {
174 entity: "task".to_string(),
175 path: "1.0.0 -> 2.0.0 -> 1.0.0".to_string(),
176 };
177 let display = format!("{}", err);
178 assert!(display.contains("Circular migration path"));
179 assert!(display.contains("task"));
180 assert!(display.contains("1.0.0 -> 2.0.0 -> 1.0.0"));
181 }
182
183 #[test]
184 fn test_error_display_invalid_version_order() {
185 let err = MigrationError::InvalidVersionOrder {
186 entity: "task".to_string(),
187 from: "2.0.0".to_string(),
188 to: "1.0.0".to_string(),
189 };
190 let display = format!("{}", err);
191 assert!(display.contains("Invalid version order"));
192 assert!(display.contains("task"));
193 assert!(display.contains("2.0.0"));
194 assert!(display.contains("1.0.0"));
195 assert!(display.contains("must increase"));
196 }
197}