/// 自定义断言模块 /// /// 提供针对NAC公链的专用断言函数 use crate::common::fixtures::{Address, Hash, TestBlock, TestTransaction}; /// 断言地址相等 #[macro_export] macro_rules! assert_address_eq { ($left:expr, $right:expr) => { assert_eq!( $left.as_bytes(), $right.as_bytes(), "Addresses are not equal" ); }; ($left:expr, $right:expr, $($arg:tt)+) => { assert_eq!( $left.as_bytes(), $right.as_bytes(), $($arg)+ ); }; } /// 断言哈希相等 #[macro_export] macro_rules! assert_hash_eq { ($left:expr, $right:expr) => { assert_eq!( $left.as_bytes(), $right.as_bytes(), "Hashes are not equal" ); }; ($left:expr, $right:expr, $($arg:tt)+) => { assert_eq!( $left.as_bytes(), $right.as_bytes(), $($arg)+ ); }; } /// 断言交易有效 pub fn assert_transaction_valid(tx: &TestTransaction) { assert_ne!(tx.from, tx.to, "Transaction from and to addresses must be different"); assert!(tx.amount > 0, "Transaction amount must be positive"); assert!(tx.timestamp > 0, "Transaction timestamp must be positive"); } /// 断言区块有效 pub fn assert_block_valid(block: &TestBlock) { assert!(block.number >= 0, "Block number must be non-negative"); assert!(block.timestamp > 0, "Block timestamp must be positive"); // 验证所有交易 for tx in &block.transactions { assert_transaction_valid(tx); } } /// 断言区块链有效 pub fn assert_blockchain_valid(blocks: &[TestBlock]) { assert!(!blocks.is_empty(), "Blockchain must not be empty"); // 验证第一个区块 assert_eq!(blocks[0].number, 0, "First block must have number 0"); // 验证区块链接 for i in 1..blocks.len() { assert_eq!( blocks[i].number, blocks[i - 1].number + 1, "Block numbers must be sequential" ); assert_eq!( blocks[i].parent_hash, blocks[i - 1].hash, "Block {} parent hash must match previous block hash", i ); } // 验证所有区块 for block in blocks { assert_block_valid(block); } } /// 断言余额充足 pub fn assert_sufficient_balance(balance: u64, amount: u64) { assert!( balance >= amount, "Insufficient balance: {} < {}", balance, amount ); } /// 断言在范围内 pub fn assert_in_range( value: T, min: T, max: T, name: &str, ) { assert!( value >= min && value <= max, "{} must be in range [{}, {}], got {}", name, min, max, value ); } /// 断言最终一致性 /// /// 用于异步测试,验证最终所有节点达到一致状态 pub fn assert_eventually_consistent( values: &[T], name: &str, ) { if values.is_empty() { return; } let first = &values[0]; for (i, value) in values.iter().enumerate() { assert_eq!( value, first, "{} at index {} is not consistent with first value. Expected: {:?}, Got: {:?}", name, i, first, value ); } } /// 断言TPS满足要求 pub fn assert_tps_meets_requirement(actual_tps: f64, required_tps: f64) { assert!( actual_tps >= required_tps, "TPS does not meet requirement: {} < {}", actual_tps, required_tps ); } /// 断言延迟在可接受范围内 pub fn assert_latency_acceptable(latency_ms: u64, max_latency_ms: u64) { assert!( latency_ms <= max_latency_ms, "Latency exceeds maximum: {} ms > {} ms", latency_ms, max_latency_ms ); } #[cfg(test)] mod tests { use super::*; use crate::common::fixtures::{create_test_blockchain, create_test_transaction}; #[test] fn test_assert_address_eq() { let addr1 = Address::from_index(1); let addr2 = Address::from_index(1); assert_address_eq!(addr1, addr2); } #[test] #[should_panic(expected = "Addresses are not equal")] fn test_assert_address_eq_fail() { let addr1 = Address::from_index(1); let addr2 = Address::from_index(2); assert_address_eq!(addr1, addr2); } #[test] fn test_assert_hash_eq() { let hash1 = Hash::zero(); let hash2 = Hash::zero(); assert_hash_eq!(hash1, hash2); } #[test] fn test_assert_transaction_valid() { let tx = create_test_transaction(0, 1, 100); assert_transaction_valid(&tx); } #[test] #[should_panic(expected = "from and to addresses must be different")] fn test_assert_transaction_valid_same_address() { let tx = create_test_transaction(0, 0, 100); assert_transaction_valid(&tx); } #[test] fn test_assert_blockchain_valid() { let blocks = create_test_blockchain(10); assert_blockchain_valid(&blocks); } #[test] fn test_assert_sufficient_balance() { assert_sufficient_balance(1000, 500); } #[test] #[should_panic(expected = "Insufficient balance")] fn test_assert_sufficient_balance_fail() { assert_sufficient_balance(100, 500); } #[test] fn test_assert_in_range() { assert_in_range(50, 0, 100, "value"); } #[test] #[should_panic(expected = "must be in range")] fn test_assert_in_range_fail() { assert_in_range(150, 0, 100, "value"); } #[test] fn test_assert_eventually_consistent() { let values = vec![42, 42, 42, 42]; assert_eventually_consistent(&values, "test_value"); } #[test] #[should_panic(expected = "is not consistent")] fn test_assert_eventually_consistent_fail() { let values = vec![42, 42, 43, 42]; assert_eventually_consistent(&values, "test_value"); } #[test] fn test_assert_tps_meets_requirement() { assert_tps_meets_requirement(10000.0, 5000.0); } #[test] #[should_panic(expected = "TPS does not meet requirement")] fn test_assert_tps_meets_requirement_fail() { assert_tps_meets_requirement(3000.0, 5000.0); } #[test] fn test_assert_latency_acceptable() { assert_latency_acceptable(50, 100); } #[test] #[should_panic(expected = "Latency exceeds maximum")] fn test_assert_latency_acceptable_fail() { assert_latency_acceptable(150, 100); } }