use dig_block::{BlockError, Bytes32};
use std::error::Error as StdError;
fn byte_tag(b: u8) -> Bytes32 {
Bytes32::new([b; 32])
}
#[test]
fn err001_invalid_data_display_contains_message() {
let e = BlockError::InvalidData("test".into());
let s = e.to_string();
assert!(s.contains("invalid data"), "{}", s);
assert!(s.contains("test"), "{}", s);
}
#[test]
fn err001_invalid_version_display_contains_expected_and_actual() {
let e = BlockError::InvalidVersion {
expected: 1,
actual: 99,
};
let s = e.to_string();
assert!(s.contains("invalid version"), "{}", s);
assert!(s.contains("99"), "actual version should appear: {}", s);
assert!(s.contains('1'), "expected version should appear: {}", s);
}
#[test]
fn err001_too_large_shows_size_and_max() {
let e = BlockError::TooLarge {
size: 20_000_000,
max: 10_000_000,
};
let s = e.to_string();
assert!(s.contains("20000000"), "{}", s);
assert!(s.contains("10000000"), "{}", s);
assert!(s.to_lowercase().contains("large"), "{}", s);
}
#[test]
fn err001_cost_exceeded_shows_cost_and_max() {
let e = BlockError::CostExceeded {
cost: 1_000_000,
max: 500_000,
};
let s = e.to_string();
assert!(s.contains("1000000") || s.contains("1_000_000"), "{}", s);
assert!(s.contains("500000") || s.contains("500_000"), "{}", s);
assert!(s.to_lowercase().contains("cost"), "{}", s);
}
#[test]
fn err001_spend_bundle_count_mismatch_shows_counts() {
let e = BlockError::SpendBundleCountMismatch {
header: 5,
actual: 3,
};
let s = e.to_string();
assert!(s.contains('5'), "{}", s);
assert!(s.contains('3'), "{}", s);
}
#[test]
fn err001_invalid_spends_root_shows_hashes() {
let expected = byte_tag(0x01);
let computed = byte_tag(0x02);
let e = BlockError::InvalidSpendsRoot { expected, computed };
let s = e.to_string();
assert!(s.len() > 32, "display should mention roots: {}", s);
}
#[test]
fn err001_invalid_receipts_root_shows_hashes() {
let e = BlockError::InvalidReceiptsRoot {
expected: byte_tag(0xee),
computed: byte_tag(0xdd),
};
assert!(!e.to_string().is_empty());
}
#[test]
fn err001_invalid_parent_shows_hashes() {
let e = BlockError::InvalidParent {
expected: byte_tag(0xaa),
got: byte_tag(0xbb),
};
let s = e.to_string();
assert!(
s.to_lowercase().contains("parent") || s.contains("expected"),
"{}",
s
);
}
#[test]
fn err001_unit_variants_non_empty_display() {
let cases: Vec<BlockError> = vec![
BlockError::InvalidSlashProposalsRoot,
BlockError::SlashProposalPayloadTooLarge,
BlockError::TooManySlashProposals,
BlockError::InvalidAdditionsRoot,
BlockError::InvalidRemovalsRoot,
BlockError::InvalidFilterHash,
BlockError::AdditionsCountMismatch {
header: 0,
actual: 1,
},
BlockError::RemovalsCountMismatch {
header: 0,
actual: 1,
},
BlockError::SlashProposalCountMismatch {
header: 0,
actual: 1,
},
];
for e in cases {
assert!(!e.to_string().trim().is_empty(), "{e:?}");
}
}
#[test]
fn err001_duplicate_output_shows_coin_id() {
let coin = byte_tag(0x7c);
let e = BlockError::DuplicateOutput { coin_id: coin };
let s = e.to_string();
assert!(
s.to_lowercase().contains("duplicate") || s.contains("coin"),
"{}",
s
);
}
#[test]
fn err001_double_spend_shows_coin_id() {
let coin = byte_tag(0x3d);
let e = BlockError::DoubleSpendInBlock { coin_id: coin };
let s = e.to_string();
assert!(
s.to_lowercase().contains("double") || s.contains("coin"),
"{}",
s
);
}
#[test]
fn err001_timestamp_too_far_shows_both_times() {
let e = BlockError::TimestampTooFarInFuture {
timestamp: 9_999_999,
max_allowed: 1_000_000,
};
let s = e.to_string();
assert!(s.contains("9999999") || s.contains("9_999_999"), "{}", s);
assert!(s.contains("1000000") || s.contains("1_000_000"), "{}", s);
}
#[test]
fn err001_implements_std_error() {
let e: BlockError = BlockError::InvalidData("x".into());
let _: &dyn StdError = &e;
let _ = e.source(); }
#[test]
fn err001_block_error_is_clone() {
let e = BlockError::InvalidVersion {
expected: 1,
actual: 2,
};
assert_eq!(e.to_string(), e.clone().to_string());
}