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
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn test_error_display_deserialization() {
101 let err = MigrationError::DeserializationError("invalid JSON".to_string());
102 let display = format!("{}", err);
103 assert!(display.contains("Failed to deserialize"));
104 assert!(display.contains("invalid JSON"));
105 }
106
107 #[test]
108 fn test_error_display_serialization() {
109 let err = MigrationError::SerializationError("invalid data".to_string());
110 let display = format!("{}", err);
111 assert!(display.contains("Failed to serialize"));
112 assert!(display.contains("invalid data"));
113 }
114
115 #[test]
116 fn test_error_display_entity_not_found() {
117 let err = MigrationError::EntityNotFound("user".to_string());
118 let display = format!("{}", err);
119 assert!(display.contains("Entity 'user' not found"));
120 }
121
122 #[test]
123 fn test_error_display_migration_path_not_defined() {
124 let err = MigrationError::MigrationPathNotDefined {
125 entity: "task".to_string(),
126 version: "2.0.0".to_string(),
127 };
128 let display = format!("{}", err);
129 assert!(display.contains("No migration path defined"));
130 assert!(display.contains("task"));
131 assert!(display.contains("2.0.0"));
132 }
133
134 #[test]
135 fn test_error_display_migration_step_failed() {
136 let err = MigrationError::MigrationStepFailed {
137 from: "1.0.0".to_string(),
138 to: "2.0.0".to_string(),
139 error: "field missing".to_string(),
140 };
141 let display = format!("{}", err);
142 assert!(display.contains("Migration failed"));
143 assert!(display.contains("1.0.0"));
144 assert!(display.contains("2.0.0"));
145 assert!(display.contains("field missing"));
146 }
147
148 #[test]
149 fn test_error_debug() {
150 let err = MigrationError::EntityNotFound("test".to_string());
151 let debug = format!("{:?}", err);
152 assert!(debug.contains("EntityNotFound"));
153 }
154
155 #[test]
156 fn test_error_is_std_error() {
157 let err = MigrationError::DeserializationError("test".to_string());
158 let _: &dyn std::error::Error = &err;
160 }
161
162 #[test]
163 fn test_error_display_circular_migration_path() {
164 let err = MigrationError::CircularMigrationPath {
165 entity: "task".to_string(),
166 path: "1.0.0 -> 2.0.0 -> 1.0.0".to_string(),
167 };
168 let display = format!("{}", err);
169 assert!(display.contains("Circular migration path"));
170 assert!(display.contains("task"));
171 assert!(display.contains("1.0.0 -> 2.0.0 -> 1.0.0"));
172 }
173
174 #[test]
175 fn test_error_display_invalid_version_order() {
176 let err = MigrationError::InvalidVersionOrder {
177 entity: "task".to_string(),
178 from: "2.0.0".to_string(),
179 to: "1.0.0".to_string(),
180 };
181 let display = format!("{}", err);
182 assert!(display.contains("Invalid version order"));
183 assert!(display.contains("task"));
184 assert!(display.contains("2.0.0"));
185 assert!(display.contains("1.0.0"));
186 assert!(display.contains("must increase"));
187 }
188}