#![cfg_attr(coverage_nightly, coverage(off))]
use crate::models::error::{AnalysisError, ErrorSeverity, PmatError, TemplateError};
use std::error::Error;
use std::path::PathBuf;
#[test]
fn test_error_severity_display_warning() {
assert_eq!(ErrorSeverity::Warning.to_string(), "WARNING");
}
#[test]
fn test_error_severity_display_error() {
assert_eq!(ErrorSeverity::Error.to_string(), "ERROR");
}
#[test]
fn test_error_severity_display_critical() {
assert_eq!(ErrorSeverity::Critical.to_string(), "CRITICAL");
}
#[test]
fn test_error_severity_clone() {
let severity = ErrorSeverity::Warning;
let cloned = severity.clone();
assert_eq!(severity, cloned);
}
#[test]
fn test_error_severity_copy() {
let severity = ErrorSeverity::Error;
let copied = severity;
assert_eq!(severity, copied);
}
#[test]
fn test_error_severity_debug() {
let debug_warning = format!("{:?}", ErrorSeverity::Warning);
let debug_error = format!("{:?}", ErrorSeverity::Error);
let debug_critical = format!("{:?}", ErrorSeverity::Critical);
assert!(debug_warning.contains("Warning"));
assert!(debug_error.contains("Error"));
assert!(debug_critical.contains("Critical"));
}
#[test]
fn test_error_severity_partial_eq() {
assert!(ErrorSeverity::Warning == ErrorSeverity::Warning);
assert!(ErrorSeverity::Error == ErrorSeverity::Error);
assert!(ErrorSeverity::Critical == ErrorSeverity::Critical);
assert!(ErrorSeverity::Warning != ErrorSeverity::Error);
assert!(ErrorSeverity::Error != ErrorSeverity::Critical);
assert!(ErrorSeverity::Warning != ErrorSeverity::Critical);
}
#[test]
fn test_is_recoverable_timeout_error() {
let err = PmatError::TimeoutError {
operation: "fetch".to_string(),
timeout_ms: 5000,
};
assert!(err.is_recoverable());
}
#[test]
fn test_is_recoverable_network_error() {
let err = PmatError::NetworkError {
operation: "connect".to_string(),
};
assert!(err.is_recoverable());
}
#[test]
fn test_is_recoverable_cache_error() {
let err = PmatError::CacheError {
operation: "read".to_string(),
};
assert!(err.is_recoverable());
}
#[test]
fn test_is_recoverable_resource_exhausted() {
let err = PmatError::ResourceExhausted {
resource: "memory".to_string(),
};
assert!(err.is_recoverable());
}
#[test]
fn test_not_recoverable_file_not_found() {
let err = PmatError::FileNotFound {
path: PathBuf::from("/missing"),
};
assert!(!err.is_recoverable());
}
#[test]
fn test_not_recoverable_directory_not_found() {
let err = PmatError::DirectoryNotFound {
path: PathBuf::from("/missing/dir"),
};
assert!(!err.is_recoverable());
}
#[test]
fn test_not_recoverable_permission_denied() {
let err = PmatError::PermissionDenied {
path: PathBuf::from("/protected"),
};
assert!(!err.is_recoverable());
}
#[test]
fn test_not_recoverable_parse_error() {
let err = PmatError::ParseError {
file: PathBuf::from("test.rs"),
line: Some(10),
message: "syntax error".to_string(),
};
assert!(!err.is_recoverable());
}
#[test]
fn test_not_recoverable_syntax_error() {
let err = PmatError::SyntaxError {
language: "Rust".to_string(),
message: "invalid".to_string(),
};
assert!(!err.is_recoverable());
}
#[test]
fn test_not_recoverable_validation_error() {
let err = PmatError::ValidationError {
field: "email".to_string(),
reason: "invalid format".to_string(),
};
assert!(!err.is_recoverable());
}
#[test]
fn test_not_recoverable_config_error() {
let err = PmatError::ConfigError {
key: "max_threads".to_string(),
value: "-1".to_string(),
reason: "must be positive".to_string(),
};
assert!(!err.is_recoverable());
}
#[test]
fn test_not_recoverable_quality_gate_error() {
let err = PmatError::QualityGateError {
gate_name: "coverage".to_string(),
reason: "below threshold".to_string(),
};
assert!(!err.is_recoverable());
}
#[test]
fn test_should_retry_timeout_error() {
let err = PmatError::TimeoutError {
operation: "download".to_string(),
timeout_ms: 10000,
};
assert!(err.should_retry());
}
#[test]
fn test_should_retry_network_error() {
let err = PmatError::NetworkError {
operation: "upload".to_string(),
};
assert!(err.should_retry());
}
#[test]
fn test_should_retry_resource_exhausted() {
let err = PmatError::ResourceExhausted {
resource: "connections".to_string(),
};
assert!(err.should_retry());
}
#[test]
fn test_should_not_retry_cache_error() {
let err = PmatError::CacheError {
operation: "invalidate".to_string(),
};
assert!(!err.should_retry());
}
#[test]
fn test_should_not_retry_file_not_found() {
let err = PmatError::FileNotFound {
path: PathBuf::from("/nonexistent"),
};
assert!(!err.should_retry());
}
#[test]
fn test_should_not_retry_parse_error() {
let err = PmatError::ParseError {
file: PathBuf::from("bad.rs"),
line: None,
message: "invalid".to_string(),
};
assert!(!err.should_retry());
}
#[test]
fn test_should_not_retry_validation_error() {
let err = PmatError::ValidationError {
field: "name".to_string(),
reason: "required".to_string(),
};
assert!(!err.should_retry());
}
#[test]
fn test_should_not_retry_allocation_error() {
let err = PmatError::AllocationError {
size: 1_000_000_000,
};
assert!(!err.should_retry());
}
#[test]
fn test_severity_file_not_found_is_warning() {
let err = PmatError::FileNotFound {
path: PathBuf::from("/test"),
};
assert_eq!(err.severity(), ErrorSeverity::Warning);
}
#[test]
fn test_severity_directory_not_found_is_warning() {
let err = PmatError::DirectoryNotFound {
path: PathBuf::from("/test"),
};
assert_eq!(err.severity(), ErrorSeverity::Warning);
}
#[test]
fn test_severity_validation_error_is_warning() {
let err = PmatError::ValidationError {
field: "name".to_string(),
reason: "empty".to_string(),
};
assert_eq!(err.severity(), ErrorSeverity::Warning);
}
#[test]
fn test_severity_permission_denied_is_error() {
let err = PmatError::PermissionDenied {
path: PathBuf::from("/protected"),
};
assert_eq!(err.severity(), ErrorSeverity::Error);
}
#[test]
fn test_severity_parse_error_is_error() {
let err = PmatError::ParseError {
file: PathBuf::from("test.rs"),
line: Some(1),
message: "error".to_string(),
};
assert_eq!(err.severity(), ErrorSeverity::Error);
}
#[test]
fn test_severity_syntax_error_is_error() {
let err = PmatError::SyntaxError {
language: "Rust".to_string(),
message: "error".to_string(),
};
assert_eq!(err.severity(), ErrorSeverity::Error);
}
#[test]
fn test_severity_config_error_is_error() {
let err = PmatError::ConfigError {
key: "key".to_string(),
value: "value".to_string(),
reason: "invalid".to_string(),
};
assert_eq!(err.severity(), ErrorSeverity::Error);
}
#[test]
fn test_severity_default_is_error() {
let err = PmatError::NetworkError {
operation: "test".to_string(),
};
assert_eq!(err.severity(), ErrorSeverity::Error);
}
#[test]
fn test_severity_protocol_error_is_error() {
let err = PmatError::ProtocolError {
protocol: "HTTP".to_string(),
message: "error".to_string(),
};
assert_eq!(err.severity(), ErrorSeverity::Error);
}
#[test]
fn test_severity_allocation_error_is_critical() {
let err = PmatError::AllocationError { size: 1000 };
assert_eq!(err.severity(), ErrorSeverity::Critical);
}
#[test]
fn test_severity_storage_full_error_is_critical() {
let err = PmatError::StorageFullError {
available: 0,
required: 1000,
};
assert_eq!(err.severity(), ErrorSeverity::Critical);
}
#[test]
fn test_severity_simd_error_is_critical() {
let err = PmatError::SimdError {
operation: "vectorize".to_string(),
};
assert_eq!(err.severity(), ErrorSeverity::Critical);
}
#[test]
fn test_severity_model_error_is_critical() {
let err = PmatError::ModelError {
model_name: "predictor".to_string(),
};
assert_eq!(err.severity(), ErrorSeverity::Critical);
}
#[test]
fn test_pmat_error_from_io_error_not_found() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let err: PmatError = io_err.into();
assert!(err.to_string().contains("IO error"));
assert_eq!(err.to_mcp_code(), -32003);
}
#[test]
fn test_pmat_error_from_io_error_permission_denied() {
let io_err = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "access denied");
let err: PmatError = io_err.into();
assert!(err.to_string().contains("IO error"));
assert_eq!(err.to_mcp_code(), -32003);
}
#[test]
fn test_pmat_error_from_io_error_connection_refused() {
let io_err = std::io::Error::new(std::io::ErrorKind::ConnectionRefused, "refused");
let err: PmatError = io_err.into();
assert!(err.to_string().contains("IO error"));
}
#[test]
fn test_pmat_error_from_io_error_interrupted() {
let io_err = std::io::Error::new(std::io::ErrorKind::Interrupted, "interrupted");
let err: PmatError = io_err.into();
assert!(err.to_string().contains("IO error"));
}
#[test]
fn test_pmat_error_from_json_error() {
let json_err = serde_json::from_str::<serde_json::Value>("not valid json")
.err()
.unwrap();
let err: PmatError = json_err.into();
assert!(err.to_string().contains("JSON error"));
assert_eq!(err.to_mcp_code(), -32000);
}
#[test]
fn test_pmat_error_from_anyhow_error() {
let anyhow_err = anyhow::anyhow!("something went wrong");
let err: PmatError = anyhow_err.into();
assert!(err.to_string().contains("Generic error"));
assert_eq!(err.to_mcp_code(), -32000);
}
#[test]
fn test_template_error_from_io_error() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "not found");
let err: TemplateError = io_err.into();
assert!(err.to_string().contains("IO operation failed"));
}
#[test]
fn test_template_error_from_json_error() {
let json_err = serde_json::from_str::<serde_json::Value>("{invalid}")
.err()
.unwrap();
let err: TemplateError = json_err.into();
assert!(err.to_string().contains("JSON serialization error"));
}
#[test]
fn test_template_error_from_anyhow() {
let anyhow_err = anyhow::anyhow!("cache failure");
let err: TemplateError = anyhow_err.into();
assert!(err.to_string().contains("Cache operation failed"));
}
#[test]
fn test_analysis_error_from_io_error() {
let io_err = std::io::Error::new(std::io::ErrorKind::Other, "io problem");
let err: AnalysisError = io_err.into();
assert!(err.to_string().contains("IO error"));
}
#[test]
fn test_analysis_error_from_template_error() {
let template_err = TemplateError::InvalidUri {
uri: "bad://uri".to_string(),
};
let err: AnalysisError = template_err.into();
assert!(err.to_string().contains("Template error"));
}
#[test]
fn test_template_error_s3_error_source() {
let err = TemplateError::S3Error {
operation: "GetObject".to_string(),
source: anyhow::anyhow!("network timeout"),
};
assert!(err.source().is_some());
}
#[test]
fn test_template_error_cache_error_source() {
let err = TemplateError::CacheError(anyhow::anyhow!("cache miss"));
assert!(err.source().is_some());
}
#[test]
fn test_template_error_json_error_source() {
let json_err = serde_json::from_str::<serde_json::Value>("bad")
.err()
.unwrap();
let err = TemplateError::JsonError(json_err);
assert!(err.source().is_some());
}
#[test]
fn test_template_error_io_error_source() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "not found");
let err = TemplateError::Io(io_err);
assert!(err.source().is_some());
}
#[test]
fn test_pmat_error_io_source() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "not found");
let err = PmatError::Io(io_err);
assert!(err.source().is_some());
}
#[test]
fn test_pmat_error_json_source() {
let json_err = serde_json::from_str::<serde_json::Value>("x")
.err()
.unwrap();
let err = PmatError::Json(json_err);
assert!(err.source().is_some());
}
#[test]
fn test_pmat_error_template_source() {
let template_err = TemplateError::NotFound("test".to_string());
let err = PmatError::Template(template_err);
assert!(err.source().is_some());
}
#[test]
fn test_pmat_error_analysis_source() {
let analysis_err = AnalysisError::ParseError("test".to_string());
let err = PmatError::Analysis(analysis_err);
assert!(err.source().is_some());
}
#[test]
fn test_pmat_error_other_source() {
let anyhow_err = anyhow::anyhow!("other");
let err = PmatError::Other(anyhow_err);
assert!(err.source().is_some());
}
#[test]
fn test_mcp_code_parsing_errors() {
assert_eq!(
PmatError::ParseError {
file: PathBuf::new(),
line: None,
message: String::new()
}
.to_mcp_code(),
-32004
);
assert_eq!(
PmatError::SyntaxError {
language: String::new(),
message: String::new()
}
.to_mcp_code(),
-32005
);
assert_eq!(
PmatError::AnalysisError {
file: PathBuf::new(),
reason: String::new()
}
.to_mcp_code(),
-32006
);
assert_eq!(
PmatError::AstError {
details: String::new()
}
.to_mcp_code(),
-32007
);
}
#[test]
fn test_mcp_code_simd_errors() {
assert_eq!(
PmatError::SimdError {
operation: String::new()
}
.to_mcp_code(),
-32008
);
assert_eq!(
PmatError::VectorizedError {
details: String::new()
}
.to_mcp_code(),
-32009
);
assert_eq!(
PmatError::AlignmentError {
expected: 0,
actual: 0
}
.to_mcp_code(),
-32010
);
}
#[test]
fn test_mcp_code_ml_errors() {
assert_eq!(
PmatError::ModelError {
model_name: String::new()
}
.to_mcp_code(),
-32011
);
assert_eq!(
PmatError::FeatureExtractionError {
feature_type: String::new()
}
.to_mcp_code(),
-32012
);
assert_eq!(
PmatError::TrainingDataError {
reason: String::new()
}
.to_mcp_code(),
-32013
);
}
#[test]
fn test_mcp_code_config_errors() {
assert_eq!(
PmatError::ConfigError {
key: String::new(),
value: String::new(),
reason: String::new()
}
.to_mcp_code(),
-32014
);
assert_eq!(
PmatError::ValidationError {
field: String::new(),
reason: String::new()
}
.to_mcp_code(),
-32015
);
assert_eq!(
PmatError::FormatError {
expected: String::new(),
actual: String::new()
}
.to_mcp_code(),
-32016
);
}
#[test]
fn test_mcp_code_network_errors() {
assert_eq!(
PmatError::RenderError {
template: String::new(),
line: 0,
message: String::new()
}
.to_mcp_code(),
-32018
);
assert_eq!(
PmatError::NetworkError {
operation: String::new()
}
.to_mcp_code(),
-32019
);
assert_eq!(
PmatError::ProtocolError {
protocol: String::new(),
message: String::new()
}
.to_mcp_code(),
-32020
);
assert_eq!(
PmatError::SerializationError {
format: String::new()
}
.to_mcp_code(),
-32021
);
}
#[test]
fn test_mcp_code_storage_errors() {
assert_eq!(
PmatError::CacheError {
operation: String::new()
}
.to_mcp_code(),
-32022
);
assert_eq!(
PmatError::DatabaseError {
operation: String::new()
}
.to_mcp_code(),
-32023
);
assert_eq!(
PmatError::StorageFullError {
available: 0,
required: 0
}
.to_mcp_code(),
-32024
);
assert_eq!(
PmatError::ResourceExhausted {
resource: String::new()
}
.to_mcp_code(),
-32025
);
assert_eq!(
PmatError::TimeoutError {
operation: String::new(),
timeout_ms: 0
}
.to_mcp_code(),
-32026
);
assert_eq!(PmatError::AllocationError { size: 0 }.to_mcp_code(), -32027);
}
#[test]
fn test_mcp_code_vcs_errors() {
assert_eq!(
PmatError::GitError {
operation: String::new()
}
.to_mcp_code(),
-32028
);
assert_eq!(
PmatError::RepositoryError {
repo_path: PathBuf::new()
}
.to_mcp_code(),
-32029
);
assert_eq!(
PmatError::QualityGateError {
gate_name: String::new(),
reason: String::new()
}
.to_mcp_code(),
-32030
);
assert_eq!(
PmatError::VerificationError {
property: String::new()
}
.to_mcp_code(),
-32031
);
assert_eq!(
PmatError::ProofError {
method: String::new()
}
.to_mcp_code(),
-32032
);
}
#[test]
fn test_error_with_empty_strings() {
let err = PmatError::ParseError {
file: PathBuf::from(""),
line: None,
message: "".to_string(),
};
let _ = err.to_string();
let _ = format!("{:?}", err);
let _ = err.to_mcp_code();
let _ = err.is_recoverable();
let _ = err.should_retry();
let _ = err.severity();
}
#[test]
fn test_error_with_unicode_characters() {
let err = PmatError::ParseError {
file: PathBuf::from("/path/with/\u{1F600}/emoji"),
line: Some(42),
message: "\u{4E2D}\u{6587} error with \u{1F4A5}".to_string(),
};
let msg = err.to_string();
assert!(msg.contains("\u{4E2D}\u{6587}"));
assert!(msg.contains("\u{1F4A5}"));
}
#[test]
fn test_error_with_special_characters() {
let err = PmatError::ConfigError {
key: "key\"with'quotes".to_string(),
value: "value\nwith\ttabs".to_string(),
reason: "reason\\with\\backslashes".to_string(),
};
let msg = err.to_string();
assert!(msg.contains("key\"with'quotes"));
}
#[test]
fn test_error_with_very_long_string() {
let long_str = "x".repeat(100_000);
let err = PmatError::AnalysisError {
file: PathBuf::from(&long_str),
reason: long_str.clone(),
};
let msg = err.to_string();
assert!(msg.len() > 100_000);
}
#[test]
fn test_error_with_extreme_numeric_values() {
let err = PmatError::StorageFullError {
available: u64::MAX,
required: u64::MAX,
};
let msg = err.to_string();
assert!(msg.contains(&u64::MAX.to_string()));
let err2 = PmatError::AllocationError { size: usize::MAX };
let msg2 = err2.to_string();
assert!(msg2.contains(&usize::MAX.to_string()));
let err3 = PmatError::TimeoutError {
operation: "test".to_string(),
timeout_ms: u64::MAX,
};
let msg3 = err3.to_string();
assert!(msg3.contains(&u64::MAX.to_string()));
}
#[test]
fn test_error_with_zero_values() {
let err = PmatError::StorageFullError {
available: 0,
required: 0,
};
let msg = err.to_string();
assert!(msg.contains("0"));
let err2 = PmatError::AlignmentError {
expected: 0,
actual: 0,
};
let msg2 = err2.to_string();
assert!(msg2.contains("0"));
}
#[test]
fn test_error_with_path_containing_spaces() {
let err = PmatError::FileNotFound {
path: PathBuf::from("/path with spaces/file name.rs"),
};
let msg = err.to_string();
assert!(msg.contains("path with spaces"));
}
#[test]
fn test_error_with_path_containing_dots() {
let err = PmatError::DirectoryNotFound {
path: PathBuf::from("../relative/./path"),
};
let msg = err.to_string();
assert!(msg.contains("../relative/./path"));
}
#[test]
fn test_template_error_render_with_high_line_number() {
let err = TemplateError::RenderError {
line: u32::MAX,
message: "error at end of file".to_string(),
};
let msg = err.to_string();
assert!(msg.contains(&u32::MAX.to_string()));
}
#[test]
fn test_template_error_all_mcp_codes() {
let codes = [
(
TemplateError::TemplateNotFound {
uri: "t".to_string(),
},
-32001,
),
(
TemplateError::InvalidUri {
uri: "u".to_string(),
},
-32002,
),
(
TemplateError::ValidationError {
parameter: "p".to_string(),
reason: "r".to_string(),
},
-32003,
),
(
TemplateError::RenderError {
line: 1,
message: "m".to_string(),
},
-32004,
),
];
for (err, expected) in codes {
assert_eq!(err.to_mcp_code(), expected);
}
}
#[test]
fn test_template_error_generic_mcp_codes() {
let generic_errors = [
TemplateError::NotFound("x".to_string()),
TemplateError::InvalidUtf8("x".to_string()),
TemplateError::CacheError(anyhow::anyhow!("x")),
];
for err in generic_errors {
assert_eq!(err.to_mcp_code(), -32000);
}
}
#[test]
fn test_all_pmat_variants_have_debug() {
let variants: Vec<PmatError> = vec![
PmatError::FileNotFound {
path: PathBuf::from("test"),
},
PmatError::DirectoryNotFound {
path: PathBuf::from("test"),
},
PmatError::PermissionDenied {
path: PathBuf::from("test"),
},
PmatError::Io(std::io::Error::new(std::io::ErrorKind::Other, "test")),
PmatError::ParseError {
file: PathBuf::from("test"),
line: Some(1),
message: "test".to_string(),
},
PmatError::SyntaxError {
language: "test".to_string(),
message: "test".to_string(),
},
PmatError::AnalysisError {
file: PathBuf::from("test"),
reason: "test".to_string(),
},
PmatError::AstError {
details: "test".to_string(),
},
PmatError::SimdError {
operation: "test".to_string(),
},
PmatError::VectorizedError {
details: "test".to_string(),
},
PmatError::AlignmentError {
expected: 32,
actual: 16,
},
PmatError::ModelError {
model_name: "test".to_string(),
},
PmatError::FeatureExtractionError {
feature_type: "test".to_string(),
},
PmatError::TrainingDataError {
reason: "test".to_string(),
},
PmatError::ConfigError {
key: "test".to_string(),
value: "test".to_string(),
reason: "test".to_string(),
},
PmatError::ValidationError {
field: "test".to_string(),
reason: "test".to_string(),
},
PmatError::FormatError {
expected: "test".to_string(),
actual: "test".to_string(),
},
PmatError::Template(TemplateError::NotFound("test".to_string())),
PmatError::RenderError {
template: "test".to_string(),
line: 1,
message: "test".to_string(),
},
PmatError::NetworkError {
operation: "test".to_string(),
},
PmatError::ProtocolError {
protocol: "test".to_string(),
message: "test".to_string(),
},
PmatError::SerializationError {
format: "test".to_string(),
},
PmatError::CacheError {
operation: "test".to_string(),
},
PmatError::DatabaseError {
operation: "test".to_string(),
},
PmatError::StorageFullError {
available: 100,
required: 200,
},
PmatError::ResourceExhausted {
resource: "test".to_string(),
},
PmatError::TimeoutError {
operation: "test".to_string(),
timeout_ms: 1000,
},
PmatError::AllocationError { size: 1000 },
PmatError::GitError {
operation: "test".to_string(),
},
PmatError::RepositoryError {
repo_path: PathBuf::from("test"),
},
PmatError::QualityGateError {
gate_name: "test".to_string(),
reason: "test".to_string(),
},
PmatError::VerificationError {
property: "test".to_string(),
},
PmatError::ProofError {
method: "test".to_string(),
},
PmatError::Analysis(AnalysisError::ParseError("test".to_string())),
PmatError::Other(anyhow::anyhow!("test")),
];
for err in variants {
let debug = format!("{:?}", err);
let display = format!("{}", err);
assert!(!debug.is_empty());
assert!(!display.is_empty());
}
}
#[test]
fn test_all_template_variants_have_debug() {
let variants: Vec<TemplateError> = vec![
TemplateError::S3Error {
operation: "test".to_string(),
source: anyhow::anyhow!("test"),
},
TemplateError::TemplateNotFound {
uri: "test".to_string(),
},
TemplateError::NotFound("test".to_string()),
TemplateError::InvalidUri {
uri: "test".to_string(),
},
TemplateError::RenderError {
line: 1,
message: "test".to_string(),
},
TemplateError::ValidationError {
parameter: "test".to_string(),
reason: "test".to_string(),
},
TemplateError::InvalidUtf8("test".to_string()),
TemplateError::CacheError(anyhow::anyhow!("test")),
];
for err in variants {
let debug = format!("{:?}", err);
let display = format!("{}", err);
assert!(!debug.is_empty());
assert!(!display.is_empty());
}
}
#[test]
fn test_all_analysis_variants_have_debug() {
let variants: Vec<AnalysisError> = vec![
AnalysisError::ParseError("test".to_string()),
AnalysisError::Io(std::io::Error::new(std::io::ErrorKind::Other, "test")),
AnalysisError::InvalidPath("test".to_string()),
AnalysisError::AnalysisFailed("test".to_string()),
AnalysisError::Template(TemplateError::NotFound("test".to_string())),
];
for err in variants {
let debug = format!("{:?}", err);
let display = format!("{}", err);
assert!(!debug.is_empty());
assert!(!display.is_empty());
}
}
#[test]
fn test_retry_implies_recoverable() {
let errors: Vec<PmatError> = vec![
PmatError::TimeoutError {
operation: "x".to_string(),
timeout_ms: 1000,
},
PmatError::NetworkError {
operation: "x".to_string(),
},
PmatError::ResourceExhausted {
resource: "x".to_string(),
},
];
for err in errors {
if err.should_retry() {
assert!(
err.is_recoverable(),
"should_retry implies is_recoverable for {:?}",
err
);
}
}
}
#[test]
fn test_mcp_codes_are_negative() {
let errors: Vec<PmatError> = vec![
PmatError::FileNotFound {
path: PathBuf::new(),
},
PmatError::ParseError {
file: PathBuf::new(),
line: None,
message: String::new(),
},
PmatError::SimdError {
operation: String::new(),
},
PmatError::ModelError {
model_name: String::new(),
},
PmatError::ConfigError {
key: String::new(),
value: String::new(),
reason: String::new(),
},
PmatError::NetworkError {
operation: String::new(),
},
PmatError::CacheError {
operation: String::new(),
},
PmatError::GitError {
operation: String::new(),
},
];
for err in errors {
assert!(
err.to_mcp_code() < 0,
"MCP code should be negative for {:?}",
err
);
}
}
#[test]
fn test_severity_never_panics() {
let errors: Vec<PmatError> = vec![
PmatError::FileNotFound {
path: PathBuf::from(""),
},
PmatError::TimeoutError {
operation: "".to_string(),
timeout_ms: 0,
},
PmatError::Other(anyhow::anyhow!("")),
];
for err in errors {
let _ = err.severity(); }
}