use multi_codec::Codec;
use multi_hash::{Builder, Error, Multihash, SAFE_HASH_CODECS};
use multi_util::CodecInfo;
#[test]
fn test_invalid_codec_rejected() {
let result = Builder::new_from_bytes(Codec::DagCbor, b"data");
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), Error::UnsupportedHash { .. }));
}
#[test]
fn test_missing_hash_detected() {
let result = Builder::new(Codec::Sha2256).try_build();
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), Error::MissingHash));
}
#[test]
fn test_malformed_data_rejected() {
let invalid = vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
let result = Multihash::try_from(invalid.as_ref());
assert!(result.is_err());
}
#[test]
fn test_truncated_multihash() {
let truncated = vec![0x12]; let result = Multihash::try_from(truncated.as_ref());
assert!(result.is_err());
}
#[test]
fn test_empty_bytes_rejected() {
let result = Multihash::try_from(&[] as &[u8]);
assert!(result.is_err());
}
#[test]
fn test_concurrent_hashing() {
use std::sync::Arc;
use std::thread;
let data = Arc::new(b"concurrent test data".to_vec());
let mut handles = vec![];
for _ in 0..4 {
let data_clone = Arc::clone(&data);
let handle = thread::spawn(move || {
for _ in 0..10 {
let mh = Builder::new_from_bytes(Codec::Sha2256, data_clone.as_ref())
.unwrap()
.try_build()
.unwrap();
assert_eq!(mh.codec(), Codec::Sha2256);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}
#[test]
fn test_deterministic_across_threads() {
use std::thread;
let data = b"deterministic test";
let mh1 = Builder::new_from_bytes(Codec::Sha2256, data)
.unwrap()
.try_build()
.unwrap();
let handle = thread::spawn(move || {
Builder::new_from_bytes(Codec::Sha2256, data)
.unwrap()
.try_build()
.unwrap()
});
let mh2 = handle.join().unwrap();
assert_eq!(mh1, mh2);
}
#[test]
fn test_null_safety() {
use multi_trait::Null;
let null_mh = Multihash::null();
assert!(null_mh.is_null());
let bytes: Vec<u8> = null_mh.clone().into();
let decoded = Multihash::try_from(bytes.as_ref()).unwrap();
assert!(decoded.is_null());
}
#[test]
fn test_error_send_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<Error>();
assert_sync::<Error>();
}
#[test]
fn test_safe_hash_codecs_functional() {
let data = b"safety test data";
for &codec in SAFE_HASH_CODECS.iter() {
let mh = Builder::new_from_bytes(codec, data)
.unwrap()
.try_build()
.unwrap();
assert_eq!(mh.codec(), codec);
let bytes: Vec<u8> = mh.clone().into();
let decoded = Multihash::try_from(bytes.as_ref()).unwrap();
assert_eq!(mh, decoded);
}
}