262 lines
6.5 KiB
Rust
262 lines
6.5 KiB
Rust
/// 自定义断言模块
|
|
///
|
|
/// 提供针对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<T: PartialOrd + std::fmt::Display>(
|
|
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<T: PartialEq + std::fmt::Debug>(
|
|
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);
|
|
}
|
|
}
|