use std::error::Error as _;
use std::io;
use rocketmq_error::Error;
use rocketmq_error::ErrorContext;
use rocketmq_error::SharedError;
use rocketmq_error::CORE_CONFIGURATION_INVALID;
use rocketmq_error::TRANSPORT_CONNECTION_FAILED;
fn assert_shared_contract(canonical: Error, expected_cause: Option<&str>) {
let shared: SharedError = std::sync::Arc::new(canonical);
let wrapped = std::sync::Arc::clone(&shared);
assert_eq!(wrapped.descriptor(), shared.descriptor());
assert_eq!(wrapped.context(), shared.context());
assert_eq!(wrapped.code(), shared.code());
assert_eq!(wrapped.recovery_hint(), shared.recovery_hint());
assert_eq!(wrapped.severity(), shared.severity());
assert_eq!(wrapped.exposure(), shared.exposure());
assert_eq!(wrapped.to_string(), shared.to_string());
assert_eq!(wrapped.source().map(ToString::to_string).as_deref(), expected_cause);
if expected_cause.is_some() {
assert!(wrapped
.source()
.and_then(|source| source.downcast_ref::<io::Error>())
.is_some());
}
assert!(std::sync::Arc::ptr_eq(&shared, &wrapped));
}
#[test]
fn shared_error_clones_preserve_typed_metadata_and_source_chains() {
assert_shared_contract(Error::new(&TRANSPORT_CONNECTION_FAILED), None);
assert_shared_contract(
Error::caused_by(
&CORE_CONFIGURATION_INVALID,
io::Error::new(io::ErrorKind::InvalidInput, "invalid timeout"),
)
.with_context(ErrorContext::new()),
Some("invalid timeout"),
);
}
#[test]
fn multiple_carriers_reuse_the_original_canonical_snapshot() {
let shared: SharedError = std::sync::Arc::new(Error::new(&TRANSPORT_CONNECTION_FAILED));
let first = std::sync::Arc::clone(&shared);
let second = std::sync::Arc::clone(&shared);
assert!(std::sync::Arc::ptr_eq(&first, &second));
assert!(std::sync::Arc::ptr_eq(&shared, &first));
}