tauri_plugin_background_service/
error.rs1#[derive(Debug, thiserror::Error, Clone, serde::Serialize, serde::Deserialize)]
8#[non_exhaustive]
9pub enum ServiceError {
10 #[error("Service is already running")]
12 AlreadyRunning,
13
14 #[error("Service is not running")]
16 NotRunning,
17
18 #[error("Initialisation failed: {0}")]
20 Init(String),
21
22 #[error("Runtime error: {0}")]
24 Runtime(String),
25
26 #[error("Platform error: {0}")]
28 Platform(String),
29
30 #[cfg(mobile)]
32 #[error("Plugin invoke error: {0}")]
33 PluginInvoke(String),
34
35 #[cfg(feature = "desktop-service")]
37 #[error("Service installation failed: {0}")]
38 ServiceInstall(String),
39
40 #[cfg(feature = "desktop-service")]
42 #[error("Service uninstallation failed: {0}")]
43 ServiceUninstall(String),
44
45 #[cfg(feature = "desktop-service")]
47 #[error("IPC error: {0}")]
48 Ipc(String),
49}
50
51#[cfg(mobile)]
58impl From<tauri::plugin::mobile::PluginInvokeError> for ServiceError {
59 fn from(e: tauri::plugin::mobile::PluginInvokeError) -> Self {
60 Self::PluginInvoke(e.to_string())
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn display_already_running() {
70 assert_eq!(
71 ServiceError::AlreadyRunning.to_string(),
72 "Service is already running"
73 );
74 }
75
76 #[test]
77 fn display_not_running() {
78 assert_eq!(
79 ServiceError::NotRunning.to_string(),
80 "Service is not running"
81 );
82 }
83
84 #[test]
85 fn display_init() {
86 let msg = "db connection failed".to_string();
87 assert_eq!(
88 ServiceError::Init(msg.clone()).to_string(),
89 format!("Initialisation failed: {msg}")
90 );
91 }
92
93 #[test]
94 fn display_runtime() {
95 let msg = "network timeout".to_string();
96 assert_eq!(
97 ServiceError::Runtime(msg.clone()).to_string(),
98 format!("Runtime error: {msg}")
99 );
100 }
101
102 #[test]
103 fn display_platform() {
104 let msg = "foreground service denied".to_string();
105 assert_eq!(
106 ServiceError::Platform(msg.clone()).to_string(),
107 format!("Platform error: {msg}")
108 );
109 }
110
111 #[test]
112 fn convert_to_invoke_error_via_serialize() {
113 let err = ServiceError::Init("test".into());
116 let invoke_err: tauri::ipc::InvokeError = err.into();
117 let _val = &invoke_err.0;
119 assert!(!invoke_err.0.is_null());
120 }
121
122 #[test]
123 fn clone_roundtrip() {
124 let err = ServiceError::Init("test".into());
125 let cloned = err.clone();
126 assert_eq!(err.to_string(), cloned.to_string());
127 }
128
129 #[test]
130 fn serde_roundtrip_already_running() {
131 let err = ServiceError::AlreadyRunning;
132 let json = serde_json::to_string(&err).unwrap();
133 let de: ServiceError = serde_json::from_str(&json).unwrap();
134 assert!(matches!(de, ServiceError::AlreadyRunning));
135 }
136
137 #[test]
138 fn serde_roundtrip_init() {
139 let err = ServiceError::Init("boom".into());
140 let json = serde_json::to_string(&err).unwrap();
141 let de: ServiceError = serde_json::from_str(&json).unwrap();
142 assert!(matches!(de, ServiceError::Init(ref s) if s == "boom"));
143 }
144
145 #[cfg(feature = "desktop-service")]
146 mod desktop_service {
147 use super::*;
148
149 #[test]
150 fn display_service_install() {
151 let msg = "permission denied".to_string();
152 assert_eq!(
153 ServiceError::ServiceInstall(msg.clone()).to_string(),
154 format!("Service installation failed: {msg}")
155 );
156 }
157
158 #[test]
159 fn display_service_uninstall() {
160 let msg = "not found".to_string();
161 assert_eq!(
162 ServiceError::ServiceUninstall(msg.clone()).to_string(),
163 format!("Service uninstallation failed: {msg}")
164 );
165 }
166
167 #[test]
168 fn display_ipc_error() {
169 let msg = "connection lost".to_string();
170 assert_eq!(
171 ServiceError::Ipc(msg.clone()).to_string(),
172 format!("IPC error: {msg}")
173 );
174 }
175
176 #[test]
177 fn serde_roundtrip_service_install() {
178 let err = ServiceError::ServiceInstall("fail".into());
179 let json = serde_json::to_string(&err).unwrap();
180 let de: ServiceError = serde_json::from_str(&json).unwrap();
181 assert!(matches!(de, ServiceError::ServiceInstall(ref s) if s == "fail"));
182 }
183
184 #[test]
185 fn serde_roundtrip_service_uninstall() {
186 let err = ServiceError::ServiceUninstall("fail".into());
187 let json = serde_json::to_string(&err).unwrap();
188 let de: ServiceError = serde_json::from_str(&json).unwrap();
189 assert!(matches!(de, ServiceError::ServiceUninstall(ref s) if s == "fail"));
190 }
191
192 #[test]
193 fn serde_roundtrip_ipc() {
194 let err = ServiceError::Ipc("socket closed".into());
195 let json = serde_json::to_string(&err).unwrap();
196 let de: ServiceError = serde_json::from_str(&json).unwrap();
197 assert!(matches!(de, ServiceError::Ipc(ref s) if s == "socket closed"));
198 }
199
200 #[test]
201 fn clone_roundtrip_service_install() {
202 let err = ServiceError::ServiceInstall("fail".into());
203 let cloned = err.clone();
204 assert_eq!(err.to_string(), cloned.to_string());
205 }
206
207 #[test]
208 fn clone_roundtrip_service_uninstall() {
209 let err = ServiceError::ServiceUninstall("fail".into());
210 let cloned = err.clone();
211 assert_eq!(err.to_string(), cloned.to_string());
212 }
213
214 #[test]
215 fn clone_roundtrip_ipc() {
216 let err = ServiceError::Ipc("timeout".into());
217 let cloned = err.clone();
218 assert_eq!(err.to_string(), cloned.to_string());
219 }
220 }
221}