use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum PluginError {
#[error("ABI version mismatch: host={host:#010x}, plugin={plugin:#010x}")]
AbiVersionMismatch {
host: u32,
plugin: u32,
},
#[error("failed to load plugin library: {0}")]
LibraryLoad(String),
#[error("required symbol missing from plugin: {0}")]
SymbolMissing(String),
#[error("sandbox error: {0}")]
Sandbox(String),
#[error("invalid plugin path: {0}")]
InvalidPath(String),
#[error("plugin is not loaded")]
NotLoaded,
#[error("invalid plugin metadata: {0}")]
InvalidMetadata(String),
}
pub type Result<T> = core::result::Result<T, PluginError>;
#[cfg(test)]
mod tests {
use super::{PluginError, Result};
#[test]
fn abi_version_mismatch_display_includes_both_words() {
let msg = PluginError::AbiVersionMismatch {
host: 0x0001_0000,
plugin: 0x0002_0000,
}
.to_string();
assert_eq!(
msg,
"ABI version mismatch: host=0x00010000, plugin=0x00020000"
);
}
#[test]
fn library_load_display_includes_detail() {
let msg = PluginError::LibraryLoad("libfoo.so: undefined symbol".into()).to_string();
assert_eq!(
msg,
"failed to load plugin library: libfoo.so: undefined symbol"
);
}
#[test]
fn symbol_missing_display_includes_symbol_name() {
let msg = PluginError::SymbolMissing("audio_plugin_abi_magic".into()).to_string();
assert_eq!(
msg,
"required symbol missing from plugin: audio_plugin_abi_magic"
);
}
#[test]
fn sandbox_display_includes_detail() {
let msg = PluginError::Sandbox("cap_enter: not in capability mode".into()).to_string();
assert_eq!(msg, "sandbox error: cap_enter: not in capability mode");
}
#[test]
fn invalid_path_display_includes_path() {
let msg = PluginError::InvalidPath("/etc/plugin.so".into()).to_string();
assert_eq!(msg, "invalid plugin path: /etc/plugin.so");
}
#[test]
fn not_loaded_display_is_human_readable() {
let msg = PluginError::NotLoaded.to_string();
assert_eq!(msg, "plugin is not loaded");
}
#[test]
fn invalid_metadata_display_includes_detail() {
let msg = PluginError::InvalidMetadata("name is empty".into()).to_string();
assert_eq!(msg, "invalid plugin metadata: name is empty");
}
#[test]
fn result_alias_ok_carries_value() {
let ok: Result<u32> = Ok(42);
assert_eq!(ok.map(|v| v + 1), Ok(43));
}
#[test]
fn result_alias_err_carries_plugin_error() {
let err: Result<u32> = Err(PluginError::NotLoaded);
assert_eq!(err.err(), Some(PluginError::NotLoaded));
}
#[test]
fn clone_and_partial_eq_hold() {
let a = PluginError::AbiVersionMismatch { host: 1, plugin: 2 };
assert_eq!(a.clone(), a);
assert_ne!(
PluginError::LibraryLoad("x".into()),
PluginError::SymbolMissing("x".into()),
);
}
}