Skip to main content

lago_core/
error.rs

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}