first
This commit is contained in:
114
tests/blockchain_tests.rs
Normal file
114
tests/blockchain_tests.rs
Normal file
@ -0,0 +1,114 @@
|
||||
use aicoin::blockchain::{Block, Blockchain, Transaction};
|
||||
use aicoin::wallet::Wallet;
|
||||
|
||||
#[test]
|
||||
fn test_genesis_block() {
|
||||
let blockchain = Blockchain::new();
|
||||
assert_eq!(blockchain.chain.len(), 1);
|
||||
assert_eq!(blockchain.chain[0].index, 0);
|
||||
assert_eq!(blockchain.chain[0].previous_hash, "0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_transaction() {
|
||||
let mut blockchain = Blockchain::new();
|
||||
let wallet1 = Wallet::new(None);
|
||||
let wallet2 = Wallet::new(None);
|
||||
|
||||
// Give wallet1 some coins
|
||||
*blockchain.balances.entry(wallet1.address.clone()).or_insert(0.0) = 100.0;
|
||||
|
||||
let transaction = Transaction::new(
|
||||
wallet1.address.clone(),
|
||||
wallet2.address.clone(),
|
||||
50.0,
|
||||
None,
|
||||
);
|
||||
|
||||
assert!(blockchain.add_transaction(transaction).is_ok());
|
||||
assert_eq!(blockchain.pending_transactions.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insufficient_balance() {
|
||||
let mut blockchain = Blockchain::new();
|
||||
let wallet1 = Wallet::new(None);
|
||||
let wallet2 = Wallet::new(None);
|
||||
|
||||
let transaction = Transaction::new(
|
||||
wallet1.address.clone(),
|
||||
wallet2.address.clone(),
|
||||
50.0,
|
||||
None,
|
||||
);
|
||||
|
||||
assert!(blockchain.add_transaction(transaction).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mining() {
|
||||
let mut blockchain = Blockchain::new();
|
||||
let wallet1 = Wallet::new(None);
|
||||
let wallet2 = Wallet::new(None);
|
||||
let miner = Wallet::new(None);
|
||||
|
||||
// Give wallet1 some coins
|
||||
*blockchain.balances.entry(wallet1.address.clone()).or_insert(0.0) = 100.0;
|
||||
|
||||
let transaction = Transaction::new(
|
||||
wallet1.address.clone(),
|
||||
wallet2.address.clone(),
|
||||
30.0,
|
||||
None,
|
||||
);
|
||||
|
||||
blockchain.add_transaction(transaction).unwrap();
|
||||
blockchain.mine_pending_transactions(miner.address.clone());
|
||||
|
||||
assert_eq!(blockchain.chain.len(), 2);
|
||||
assert_eq!(blockchain.pending_transactions.len(), 0);
|
||||
|
||||
// Check balances
|
||||
let wallet1_balance = blockchain.get_balance(&wallet1.address);
|
||||
let wallet2_balance = blockchain.get_balance(&wallet2.address);
|
||||
let miner_balance = blockchain.get_balance(&miner.address);
|
||||
|
||||
assert!(wallet1_balance < 70.0); // Less due to fees
|
||||
assert_eq!(wallet2_balance, 30.0);
|
||||
assert!(miner_balance > 50.0); // Mining reward + fees
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blockchain_validity() {
|
||||
let mut blockchain = Blockchain::new();
|
||||
assert!(blockchain.is_valid());
|
||||
|
||||
let wallet = Wallet::new(None);
|
||||
blockchain.mine_pending_transactions(wallet.address);
|
||||
|
||||
assert!(blockchain.is_valid());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_fee_calculation() {
|
||||
assert_eq!(Transaction::calculate_fee(100.0), 0.1);
|
||||
assert_eq!(Transaction::calculate_fee(5.0), 0.01); // Minimum fee
|
||||
assert_eq!(Transaction::calculate_fee(1000.0), 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_adjustment() {
|
||||
let mut blockchain = Blockchain::new();
|
||||
blockchain.difficulty_adjustment_interval = 2; // Adjust every 2 blocks
|
||||
|
||||
let initial_difficulty = blockchain.difficulty;
|
||||
let wallet = Wallet::new(None);
|
||||
|
||||
// Mine several blocks
|
||||
for _ in 0..3 {
|
||||
blockchain.mine_pending_transactions(wallet.address.clone());
|
||||
}
|
||||
|
||||
// Difficulty might have changed
|
||||
assert!(blockchain.difficulty >= 1);
|
||||
}
|
58
tests/transaction_tests.rs
Normal file
58
tests/transaction_tests.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use aicoin::blockchain::Transaction;
|
||||
use aicoin::wallet::Wallet;
|
||||
|
||||
#[test]
|
||||
fn test_transaction_signing() {
|
||||
let wallet = Wallet::new(None);
|
||||
let mut transaction = Transaction::new(
|
||||
wallet.address.clone(),
|
||||
"recipient_address".to_string(),
|
||||
100.0,
|
||||
Some("did:plc:test789".to_string()),
|
||||
);
|
||||
|
||||
assert!(transaction.signature.is_none());
|
||||
|
||||
if let Some(ref signing_key) = wallet.private_key {
|
||||
transaction.sign(signing_key);
|
||||
assert!(transaction.signature.is_some());
|
||||
|
||||
// Verify signature
|
||||
let verifying_key = wallet.get_verifying_key().unwrap();
|
||||
assert!(transaction.verify_signature(&verifying_key));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_hash() {
|
||||
let tx1 = Transaction::new(
|
||||
"from".to_string(),
|
||||
"to".to_string(),
|
||||
100.0,
|
||||
None,
|
||||
);
|
||||
|
||||
let tx2 = Transaction::new(
|
||||
"from".to_string(),
|
||||
"to".to_string(),
|
||||
100.0,
|
||||
None,
|
||||
);
|
||||
|
||||
// Same parameters but different timestamps should produce different hashes
|
||||
assert_ne!(tx1.calculate_hash(), tx2.calculate_hash());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_with_atproto_did() {
|
||||
let transaction = Transaction::new(
|
||||
"from".to_string(),
|
||||
"to".to_string(),
|
||||
50.0,
|
||||
Some("did:plc:user123".to_string()),
|
||||
);
|
||||
|
||||
assert_eq!(transaction.atproto_did, Some("did:plc:user123".to_string()));
|
||||
assert_eq!(transaction.amount, 50.0);
|
||||
assert_eq!(transaction.fee, 0.05);
|
||||
}
|
51
tests/wallet_tests.rs
Normal file
51
tests/wallet_tests.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use aicoin::wallet::Wallet;
|
||||
use std::fs;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
fn test_wallet_creation() {
|
||||
let wallet = Wallet::new(Some("did:plc:test123".to_string()));
|
||||
|
||||
assert!(!wallet.address.is_empty());
|
||||
assert!(!wallet.public_key.is_empty());
|
||||
assert_eq!(wallet.atproto_did, Some("did:plc:test123".to_string()));
|
||||
assert!(wallet.get_private_key_hex().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_from_private_key() {
|
||||
let wallet1 = Wallet::new(None);
|
||||
let private_key = wallet1.get_private_key_hex().unwrap();
|
||||
|
||||
let wallet2 = Wallet::from_private_key(&private_key, None).unwrap();
|
||||
|
||||
assert_eq!(wallet1.address, wallet2.address);
|
||||
assert_eq!(wallet1.public_key, wallet2.public_key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_export_import() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
let wallet_file = temp_dir.path().join("wallet.json");
|
||||
|
||||
let wallet1 = Wallet::new(Some("did:plc:test456".to_string()));
|
||||
wallet1.export_to_file(wallet_file.to_str().unwrap()).unwrap();
|
||||
|
||||
let wallet2 = Wallet::import_from_file(wallet_file.to_str().unwrap()).unwrap();
|
||||
|
||||
assert_eq!(wallet1.address, wallet2.address);
|
||||
assert_eq!(wallet1.public_key, wallet2.public_key);
|
||||
assert_eq!(wallet1.atproto_did, wallet2.atproto_did);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_import_nonexistent_file() {
|
||||
let result = Wallet::import_from_file("/nonexistent/wallet.json");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_private_key() {
|
||||
let result = Wallet::from_private_key("invalid_hex", None);
|
||||
assert!(result.is_err());
|
||||
}
|
Reference in New Issue
Block a user