1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum LagoError {
5 #[error("journal error: {0}")]
6 Journal(String),
7
8 #[error("store error: {0}")]
9 Store(String),
10
11 #[error("serialization error: {0}")]
12 Serialization(#[from] serde_json::Error),
13
14 #[error("session not found: {0}")]
15 SessionNotFound(String),
16
17 #[error("branch not found: {0}")]
18 BranchNotFound(String),
19
20 #[error("event not found: {0}")]
21 EventNotFound(String),
22
23 #[error("blob not found: {0}")]
24 BlobNotFound(String),
25
26 #[error("file not found: {0}")]
27 FileNotFound(String),
28
29 #[error("sequence conflict: expected {expected}, got {actual}")]
30 SequenceConflict { expected: u64, actual: u64 },
31
32 #[error("policy denied: {0}")]
33 PolicyDenied(String),
34
35 #[error("invalid argument: {0}")]
36 InvalidArgument(String),
37
38 #[error("io error: {0}")]
39 Io(#[from] std::io::Error),
40
41 #[error("hashline error: {0}")]
42 HashLine(#[from] crate::hashline::HashLineError),
43
44 #[error("sandbox error: {0}")]
45 Sandbox(String),
46
47 #[error("internal error: {0}")]
48 Internal(String),
49}
50
51pub type LagoResult<T> = Result<T, LagoError>;
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn error_display_journal() {
59 let e = LagoError::Journal("disk full".into());
60 assert_eq!(e.to_string(), "journal error: disk full");
61 }
62
63 #[test]
64 fn error_display_store() {
65 let e = LagoError::Store("corrupt blob".into());
66 assert_eq!(e.to_string(), "store error: corrupt blob");
67 }
68
69 #[test]
70 fn error_display_not_found_variants() {
71 assert_eq!(
72 LagoError::SessionNotFound("S1".into()).to_string(),
73 "session not found: S1"
74 );
75 assert_eq!(
76 LagoError::BranchNotFound("B1".into()).to_string(),
77 "branch not found: B1"
78 );
79 assert_eq!(
80 LagoError::EventNotFound("E1".into()).to_string(),
81 "event not found: E1"
82 );
83 assert_eq!(
84 LagoError::BlobNotFound("H1".into()).to_string(),
85 "blob not found: H1"
86 );
87 assert_eq!(
88 LagoError::FileNotFound("/foo".into()).to_string(),
89 "file not found: /foo"
90 );
91 }
92
93 #[test]
94 fn error_display_sequence_conflict() {
95 let e = LagoError::SequenceConflict {
96 expected: 10,
97 actual: 5,
98 };
99 assert_eq!(e.to_string(), "sequence conflict: expected 10, got 5");
100 }
101
102 #[test]
103 fn error_display_policy_denied() {
104 let e = LagoError::PolicyDenied("blocked by rule X".into());
105 assert_eq!(e.to_string(), "policy denied: blocked by rule X");
106 }
107
108 #[test]
109 fn error_from_io() {
110 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "gone");
111 let e: LagoError = io_err.into();
112 assert!(e.to_string().contains("io error"));
113 }
114
115 #[test]
116 fn error_from_serde_json() {
117 let bad_json: Result<serde_json::Value, _> = serde_json::from_str("{invalid");
118 let e: LagoError = bad_json.unwrap_err().into();
119 assert!(e.to_string().contains("serialization error"));
120 }
121
122 #[test]
123 fn error_from_hashline() {
124 let hl_err = crate::hashline::HashLineError::LineOutOfBounds {
125 line_num: 10,
126 total_lines: 5,
127 };
128 let e: LagoError = hl_err.into();
129 assert!(e.to_string().contains("hashline error"));
130 assert!(e.to_string().contains("line 10 out of bounds"));
131 }
132
133 #[test]
134 fn error_display_sandbox() {
135 let e = LagoError::Sandbox("container failed".into());
136 assert_eq!(e.to_string(), "sandbox error: container failed");
137 }
138}