122 lines
4.0 KiB
Rust
122 lines
4.0 KiB
Rust
use log::*;
|
|
use rand::{thread_rng, Rng};
|
|
use rayon::prelude::*;
|
|
use solana_runtime::{accounts_db::AccountsDb, accounts_index::Ancestors};
|
|
use solana_sdk::genesis_config::ClusterType;
|
|
use solana_sdk::{account::Account, clock::Slot, pubkey::Pubkey};
|
|
use std::collections::HashSet;
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
use std::sync::Arc;
|
|
use std::time::Instant;
|
|
|
|
#[test]
|
|
fn test_shrink_and_clean() {
|
|
solana_logger::setup();
|
|
|
|
// repeat the whole test scenario
|
|
for _ in 0..5 {
|
|
let accounts = Arc::new(AccountsDb::new_single());
|
|
let accounts_for_shrink = accounts.clone();
|
|
|
|
// spawn the slot shrinking background thread
|
|
let exit = Arc::new(AtomicBool::default());
|
|
let exit_for_shrink = exit.clone();
|
|
let shrink_thread = std::thread::spawn(move || loop {
|
|
if exit_for_shrink.load(Ordering::Relaxed) {
|
|
break;
|
|
}
|
|
accounts_for_shrink.process_stale_slot_v1();
|
|
});
|
|
|
|
let mut alive_accounts = vec![];
|
|
let owner = Pubkey::default();
|
|
|
|
// populate the AccountsDb with plenty of food for slot shrinking
|
|
// also this simulates realistic some heavy spike account updates in the wild
|
|
for current_slot in 0..100 {
|
|
while alive_accounts.len() <= 10 {
|
|
alive_accounts.push((
|
|
solana_sdk::pubkey::new_rand(),
|
|
Account::new(thread_rng().gen_range(0, 50), 0, &owner),
|
|
));
|
|
}
|
|
|
|
alive_accounts.retain(|(_pubkey, account)| account.lamports >= 1);
|
|
|
|
for (pubkey, account) in alive_accounts.iter_mut() {
|
|
account.lamports -= 1;
|
|
accounts.store_uncached(current_slot, &[(&pubkey, &account)]);
|
|
}
|
|
accounts.add_root(current_slot);
|
|
}
|
|
|
|
// let's dance.
|
|
for _ in 0..10 {
|
|
accounts.clean_accounts(None);
|
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
|
}
|
|
|
|
// cleanup
|
|
exit.store(true, Ordering::Relaxed);
|
|
shrink_thread.join().unwrap();
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_bad_bank_hash() {
|
|
solana_logger::setup();
|
|
use solana_sdk::signature::{Keypair, Signer};
|
|
let db = AccountsDb::new(Vec::new(), &ClusterType::Development);
|
|
|
|
let some_slot: Slot = 0;
|
|
let ancestors: Ancestors = [(some_slot, 0)].iter().copied().collect();
|
|
|
|
let max_accounts = 200;
|
|
let mut accounts_keys: Vec<_> = (0..max_accounts)
|
|
.into_par_iter()
|
|
.map(|_| {
|
|
let key = Keypair::new().pubkey();
|
|
let lamports = thread_rng().gen_range(0, 100);
|
|
let some_data_len = thread_rng().gen_range(0, 1000);
|
|
let account = Account::new(lamports, some_data_len, &key);
|
|
(key, account)
|
|
})
|
|
.collect();
|
|
|
|
let mut existing = HashSet::new();
|
|
let mut last_print = Instant::now();
|
|
for i in 0..5_000 {
|
|
if last_print.elapsed().as_millis() > 5000 {
|
|
info!("i: {}", i);
|
|
last_print = Instant::now();
|
|
}
|
|
let num_accounts = thread_rng().gen_range(0, 100);
|
|
(0..num_accounts).into_iter().for_each(|_| {
|
|
let mut idx;
|
|
loop {
|
|
idx = thread_rng().gen_range(0, max_accounts);
|
|
if existing.contains(&idx) {
|
|
continue;
|
|
}
|
|
existing.insert(idx);
|
|
break;
|
|
}
|
|
accounts_keys[idx].1.lamports = thread_rng().gen_range(0, 1000);
|
|
});
|
|
|
|
let account_refs: Vec<_> = existing
|
|
.iter()
|
|
.map(|idx| (&accounts_keys[*idx].0, &accounts_keys[*idx].1))
|
|
.collect();
|
|
db.store_uncached(some_slot, &account_refs);
|
|
|
|
for (key, account) in &account_refs {
|
|
assert_eq!(
|
|
db.load_account_hash(&ancestors, &key),
|
|
AccountsDb::hash_account(some_slot, &account, &key, &ClusterType::Development)
|
|
);
|
|
}
|
|
existing.clear();
|
|
}
|
|
}
|