use thiserror::Error;
#[derive(Error, Debug)]
pub enum IdentityError {
#[error("failed to generate keypair: {0}")]
KeyGeneration(String),
#[error("invalid public key: {0}")]
InvalidPublicKey(String),
#[error("invalid secret key: {0}")]
InvalidSecretKey(String),
#[error("PeerId verification failed")]
PeerIdMismatch,
#[error("key storage error: {0}")]
Storage(#[from] std::io::Error),
#[error("serialization error: {0}")]
Serialization(String),
#[error("certificate verification failed: {0}")]
CertificateVerification(String),
}
pub type Result<T> = std::result::Result<T, IdentityError>;
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
use super::*;
#[test]
fn test_key_generation_error_display() {
let err = IdentityError::KeyGeneration("RNG failed".to_string());
assert_eq!(err.to_string(), "failed to generate keypair: RNG failed");
}
#[test]
fn test_invalid_public_key_error_display() {
let err = IdentityError::InvalidPublicKey("size mismatch".to_string());
assert_eq!(err.to_string(), "invalid public key: size mismatch");
}
#[test]
fn test_invalid_secret_key_error_display() {
let err = IdentityError::InvalidSecretKey("corrupted".to_string());
assert_eq!(err.to_string(), "invalid secret key: corrupted");
}
#[test]
fn test_peer_id_mismatch_error_display() {
let err = IdentityError::PeerIdMismatch;
assert_eq!(err.to_string(), "PeerId verification failed");
}
#[test]
fn test_serialization_error_display() {
let err = IdentityError::Serialization("invalid bincode".to_string());
assert_eq!(err.to_string(), "serialization error: invalid bincode");
}
#[test]
fn test_result_type_ok() {
let result: Result<i32> = Ok(42);
match result {
Ok(val) => assert_eq!(val, 42),
Err(_) => panic!("expected Ok variant"),
}
}
#[test]
fn test_result_type_err() {
let result: Result<i32> = Err(IdentityError::KeyGeneration("test".to_string()));
assert!(result.is_err());
}
#[test]
fn test_storage_error_conversion() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let id_err: IdentityError = io_err.into();
assert!(matches!(id_err, IdentityError::Storage(_)));
}
#[test]
fn test_error_debug() {
let err = IdentityError::KeyGeneration("test failure".to_string());
let debug_str = format!("{:?}", err);
assert!(debug_str.contains("KeyGeneration"));
}
}
#[derive(Error, Debug)]
pub enum NetworkError {
#[error("failed to create network node: {0}")]
NodeCreation(String),
#[error("connection failed: {0}")]
ConnectionFailed(String),
#[error("connection timeout to peer {peer_id:?} after {timeout:?}")]
ConnectionTimeout {
peer_id: [u8; 32],
timeout: std::time::Duration,
},
#[error("already connected to peer {0:?}")]
AlreadyConnected([u8; 32]),
#[error("not connected to peer {0:?}")]
NotConnected([u8; 32]),
#[error("connection closed to peer {0:?}")]
ConnectionClosed([u8; 32]),
#[error("connection reset by peer {0:?}")]
ConnectionReset([u8; 32]),
#[error("peer not found: {0}")]
PeerNotFound(String),
#[error("cache error: {0}")]
CacheError(String),
#[error("NAT traversal failed: {0}")]
NatTraversalFailed(String),
#[error("address discovery failed: {0}")]
AddressDiscoveryFailed(String),
#[error("stream error: {0}")]
StreamError(String),
#[error("event broadcast error: {0}")]
BroadcastError(String),
#[error("authentication failed for peer {peer_id:?}: {reason}")]
AuthenticationFailed {
peer_id: [u8; 32],
reason: String,
},
#[error("protocol violation from peer {peer_id:?}: {violation}")]
ProtocolViolation {
peer_id: [u8; 32],
violation: String,
},
#[error("invalid peer ID: {0}")]
InvalidPeerId(String),
#[error("maximum connections reached: {current} >= {limit}")]
MaxConnectionsReached {
current: u32,
limit: u32,
},
#[error("message too large: {size} bytes exceeds limit of {limit}")]
MessageTooLarge {
size: usize,
limit: usize,
},
#[error("payload too large: {size} bytes exceeds limit of {max}")]
PayloadTooLarge {
size: usize,
max: usize,
},
#[error("invalid message: {0}")]
InvalidMessage(String),
#[error("agent not connected: {0:?}")]
AgentNotConnected([u8; 32]),
#[error("agent not found: {0:?}")]
AgentNotFound([u8; 32]),
#[error("channel closed: {0}")]
ChannelClosed(String),
#[error("invalid bootstrap node address: {0}")]
InvalidBootstrapNode(String),
#[error("configuration error: {0}")]
ConfigError(String),
#[error("node error: {0}")]
NodeError(String),
#[error("connection error: {0}")]
ConnectionError(String),
#[error("serialization error: {0}")]
SerializationError(String),
#[error("timestamp error: {0}")]
TimestampError(String),
}
pub type NetworkResult<T> = std::result::Result<T, NetworkError>;
#[derive(Error, Debug)]
pub enum PresenceError {
#[error("presence manager not initialized")]
NotInitialized,
#[error("beacon broadcast failed: {0}")]
BeaconFailed(String),
#[error("FOAF query failed: {0}")]
FoafQueryFailed(String),
#[error("presence subscription failed: {0}")]
SubscriptionFailed(String),
#[error("presence internal error: {0}")]
Internal(String),
}
impl From<PresenceError> for NetworkError {
fn from(e: PresenceError) -> Self {
NetworkError::NodeError(e.to_string())
}
}
pub type PresenceResult<T> = std::result::Result<T, PresenceError>;
#[cfg(test)]
mod network_tests {
#![allow(clippy::unwrap_used)]
use super::*;
use std::time::Duration;
#[test]
fn test_node_creation_error_display() {
let err = NetworkError::NodeCreation("binding failed".to_string());
assert_eq!(
err.to_string(),
"failed to create network node: binding failed"
);
}
#[test]
fn test_connection_failed_error_display() {
let err = NetworkError::ConnectionFailed("timeout".to_string());
assert_eq!(err.to_string(), "connection failed: timeout");
}
#[test]
fn test_connection_timeout_error_display() {
let err = NetworkError::ConnectionTimeout {
peer_id: [1u8; 32],
timeout: Duration::from_secs(30),
};
assert!(err.to_string().contains("connection timeout"));
assert!(err.to_string().contains("30s"));
}
#[test]
fn test_already_connected_error_display() {
let err = NetworkError::AlreadyConnected([2u8; 32]);
assert!(err.to_string().contains("already connected"));
}
#[test]
fn test_not_connected_error_display() {
let err = NetworkError::NotConnected([3u8; 32]);
assert!(err.to_string().contains("not connected"));
}
#[test]
fn test_connection_closed_error_display() {
let err = NetworkError::ConnectionClosed([4u8; 32]);
assert!(err.to_string().contains("connection closed"));
}
#[test]
fn test_connection_reset_error_display() {
let err = NetworkError::ConnectionReset([5u8; 32]);
assert!(err.to_string().contains("connection reset"));
}
#[test]
fn test_peer_not_found_error_display() {
let err = NetworkError::PeerNotFound("unknown peer".to_string());
assert_eq!(err.to_string(), "peer not found: unknown peer");
}
#[test]
fn test_cache_error_display() {
let err = NetworkError::CacheError("serialization failed".to_string());
assert_eq!(err.to_string(), "cache error: serialization failed");
}
#[test]
fn test_nat_traversal_failed_error_display() {
let err = NetworkError::NatTraversalFailed("hole punching failed".to_string());
assert_eq!(
err.to_string(),
"NAT traversal failed: hole punching failed"
);
}
#[test]
fn test_address_discovery_failed_error_display() {
let err = NetworkError::AddressDiscoveryFailed("no interfaces found".to_string());
assert_eq!(
err.to_string(),
"address discovery failed: no interfaces found"
);
}
#[test]
fn test_stream_error_display() {
let err = NetworkError::StreamError("stream closed".to_string());
assert_eq!(err.to_string(), "stream error: stream closed");
}
#[test]
fn test_broadcast_error_display() {
let err = NetworkError::BroadcastError("receiver dropped".to_string());
assert_eq!(err.to_string(), "event broadcast error: receiver dropped");
}
#[test]
fn test_authentication_failed_error_display() {
let err = NetworkError::AuthenticationFailed {
peer_id: [6u8; 32],
reason: "invalid signature".to_string(),
};
assert!(err.to_string().contains("authentication failed"));
assert!(err.to_string().contains("invalid signature"));
}
#[test]
fn test_protocol_violation_error_display() {
let err = NetworkError::ProtocolViolation {
peer_id: [7u8; 32],
violation: "invalid message format".to_string(),
};
assert!(err.to_string().contains("protocol violation"));
assert!(err.to_string().contains("invalid message format"));
}
#[test]
fn test_invalid_peer_id_error_display() {
let err = NetworkError::InvalidPeerId("wrong length".to_string());
assert_eq!(err.to_string(), "invalid peer ID: wrong length");
}
#[test]
fn test_max_connections_reached_error_display() {
let err = NetworkError::MaxConnectionsReached {
current: 100,
limit: 100,
};
assert!(err.to_string().contains("maximum connections reached"));
assert!(err.to_string().contains("100"));
}
#[test]
fn test_message_too_large_error_display() {
let err = NetworkError::MessageTooLarge {
size: 1024 * 1024,
limit: 1024,
};
assert!(err.to_string().contains("message too large"));
assert!(err.to_string().contains("1048576"));
assert!(err.to_string().contains("1024"));
}
#[test]
fn test_channel_closed_error_display() {
let err = NetworkError::ChannelClosed("sender dropped".to_string());
assert_eq!(err.to_string(), "channel closed: sender dropped");
}
#[test]
fn test_network_result_type_ok() {
let result: NetworkResult<i32> = Ok(42);
match result {
Ok(val) => assert_eq!(val, 42),
Err(_) => panic!("expected Ok variant"),
}
}
#[test]
fn test_network_result_type_err() {
let result: NetworkResult<i32> = Err(NetworkError::NodeCreation("test".to_string()));
assert!(result.is_err());
}
}