Skip to main content

rustbridge_bundle/
error.rs

1//! Error types for bundle operations.
2
3use thiserror::Error;
4
5/// Errors that can occur during bundle operations.
6#[derive(Debug, Error)]
7pub enum BundleError {
8    /// I/O error during file operations.
9    #[error("I/O error: {0}")]
10    Io(#[from] std::io::Error),
11
12    /// JSON parsing or serialization error.
13    #[error("JSON error: {0}")]
14    Json(#[from] serde_json::Error),
15
16    /// ZIP archive error.
17    #[error("Archive error: {0}")]
18    Zip(#[from] zip::result::ZipError),
19
20    /// Manifest validation error.
21    #[error("Invalid manifest: {0}")]
22    InvalidManifest(String),
23
24    /// Checksum mismatch.
25    #[error("Checksum mismatch for {path}: expected {expected}, got {actual}")]
26    ChecksumMismatch {
27        path: String,
28        expected: String,
29        actual: String,
30    },
31
32    /// Platform not supported in this bundle.
33    #[error("Platform not supported: {0}")]
34    UnsupportedPlatform(String),
35
36    /// Missing required file in bundle.
37    #[error("Missing required file: {0}")]
38    MissingFile(String),
39
40    /// Library file not found.
41    #[error("Library not found: {0}")]
42    LibraryNotFound(String),
43
44    /// Requested variant not found for platform.
45    #[error("Variant '{variant}' not found for platform '{platform}'")]
46    VariantNotFound { platform: String, variant: String },
47
48    /// Invalid variant name format.
49    #[error("Invalid variant name '{0}': must be lowercase alphanumeric with hyphens")]
50    InvalidVariantName(String),
51
52    /// Schema mismatch when combining bundles.
53    #[error("Schema mismatch: {0}")]
54    SchemaMismatch(String),
55
56    /// Signature verification failed.
57    #[error("Signature verification failed: {0}")]
58    SignatureVerificationFailed(String),
59
60    /// No public key available for verification.
61    #[error("No public key available for signature verification")]
62    NoPublicKey,
63}
64
65#[cfg(test)]
66mod tests {
67    #![allow(non_snake_case)]
68
69    use super::*;
70
71    #[test]
72    fn BundleError___io___displays_message() {
73        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
74        let err: BundleError = io_err.into();
75
76        assert!(err.to_string().contains("I/O error"));
77    }
78
79    #[test]
80    fn BundleError___invalid_manifest___displays_message() {
81        let err = BundleError::InvalidManifest("missing name".to_string());
82
83        assert_eq!(err.to_string(), "Invalid manifest: missing name");
84    }
85
86    #[test]
87    fn BundleError___checksum_mismatch___displays_all_fields() {
88        let err = BundleError::ChecksumMismatch {
89            path: "lib/test.so".to_string(),
90            expected: "sha256:expected".to_string(),
91            actual: "sha256:actual".to_string(),
92        };
93
94        let msg = err.to_string();
95        assert!(msg.contains("lib/test.so"));
96        assert!(msg.contains("sha256:expected"));
97        assert!(msg.contains("sha256:actual"));
98    }
99
100    #[test]
101    fn BundleError___unsupported_platform___displays_platform() {
102        let err = BundleError::UnsupportedPlatform("linux-arm".to_string());
103
104        assert_eq!(err.to_string(), "Platform not supported: linux-arm");
105    }
106
107    #[test]
108    fn BundleError___missing_file___displays_path() {
109        let err = BundleError::MissingFile("manifest.json".to_string());
110
111        assert_eq!(err.to_string(), "Missing required file: manifest.json");
112    }
113
114    #[test]
115    fn BundleError___library_not_found___displays_path() {
116        let err = BundleError::LibraryNotFound("/path/to/lib.so".to_string());
117
118        assert_eq!(err.to_string(), "Library not found: /path/to/lib.so");
119    }
120
121    #[test]
122    fn BundleError___from_io_error___converts() {
123        let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
124        let bundle_err: BundleError = io_err.into();
125
126        assert!(matches!(bundle_err, BundleError::Io(_)));
127    }
128
129    #[test]
130    fn BundleError___variant_not_found___displays_details() {
131        let err = BundleError::VariantNotFound {
132            platform: "linux-x86_64".to_string(),
133            variant: "debug".to_string(),
134        };
135
136        let msg = err.to_string();
137        assert!(msg.contains("debug"));
138        assert!(msg.contains("linux-x86_64"));
139    }
140
141    #[test]
142    fn BundleError___invalid_variant_name___displays_name() {
143        let err = BundleError::InvalidVariantName("INVALID".to_string());
144
145        assert_eq!(
146            err.to_string(),
147            "Invalid variant name 'INVALID': must be lowercase alphanumeric with hyphens"
148        );
149    }
150
151    #[test]
152    fn BundleError___schema_mismatch___displays_reason() {
153        let err = BundleError::SchemaMismatch("checksums differ".to_string());
154
155        assert_eq!(err.to_string(), "Schema mismatch: checksums differ");
156    }
157}