More TestValidator cleanup

This commit is contained in:
Michael Vines
2020-11-25 17:00:47 -08:00
committed by mergify[bot]
parent b5f7e39be8
commit 43b82b31e5
13 changed files with 345 additions and 552 deletions

View File

@ -1,8 +1,6 @@
use {
crate::{
cluster_info::Node,
contact_info::ContactInfo,
gossip_service::discover_cluster,
validator::{Validator, ValidatorConfig},
},
solana_ledger::create_new_tmp_ledger,
@ -11,83 +9,111 @@ use {
hash::Hash,
native_token::sol_to_lamports,
pubkey::Pubkey,
rent::Rent,
signature::{Keypair, Signer},
},
std::{path::PathBuf, sync::Arc},
std::{fs::remove_dir_all, net::SocketAddr, path::PathBuf, sync::Arc},
};
pub struct TestValidator {
pub server: Validator,
pub leader_data: ContactInfo,
pub alice: Keypair,
pub ledger_path: PathBuf,
pub genesis_hash: Hash,
pub vote_pubkey: Pubkey,
}
struct TestValidatorConfig {
fee_rate_governor: FeeRateGovernor,
validator_identity_lamports: u64,
validator_stake_lamports: u64,
mint_lamports: u64,
pub struct TestValidatorConfig {
pub fee_rate_governor: FeeRateGovernor,
pub mint_lamports: u64,
pub rent: Rent,
pub validator_identity_keypair: Keypair,
pub validator_identity_lamports: u64,
pub validator_stake_lamports: u64,
}
impl Default for TestValidatorConfig {
fn default() -> Self {
TestValidatorConfig {
fee_rate_governor: FeeRateGovernor::new(0, 0),
Self {
fee_rate_governor: FeeRateGovernor::default(),
mint_lamports: sol_to_lamports(500_000_000.),
rent: Rent::default(),
validator_identity_keypair: Keypair::new(),
validator_identity_lamports: sol_to_lamports(500.),
validator_stake_lamports: sol_to_lamports(1.),
mint_lamports: sol_to_lamports(500_000_000.),
}
}
}
pub struct TestValidator {
validator: Validator,
ledger_path: PathBuf,
preserve_ledger: bool,
genesis_hash: Hash,
mint_keypair: Keypair,
vote_account_address: Pubkey,
tpu: SocketAddr,
rpc_url: String,
rpc_pubsub_url: String,
}
impl Default for TestValidator {
fn default() -> Self {
Self::new(TestValidatorConfig::default())
}
}
impl TestValidator {
pub fn with_no_fee() -> Self {
pub fn with_no_fees() -> Self {
Self::new(TestValidatorConfig {
fee_rate_governor: FeeRateGovernor::new(0, 0),
rent: Rent {
lamports_per_byte_year: 1,
exemption_threshold: 1.0,
..Rent::default()
},
..TestValidatorConfig::default()
})
}
pub fn with_custom_fee(target_lamports_per_signature: u64) -> Self {
pub fn with_custom_fees(target_lamports_per_signature: u64) -> Self {
Self::new(TestValidatorConfig {
fee_rate_governor: FeeRateGovernor::new(target_lamports_per_signature, 0),
rent: Rent {
lamports_per_byte_year: 1,
exemption_threshold: 1.0,
..Rent::default()
},
..TestValidatorConfig::default()
})
}
fn new(config: TestValidatorConfig) -> Self {
pub fn new(config: TestValidatorConfig) -> Self {
use solana_ledger::genesis_utils::{
create_genesis_config_with_leader_ex, GenesisConfigInfo,
};
let TestValidatorConfig {
fee_rate_governor,
mint_lamports,
rent,
validator_identity_keypair,
validator_identity_lamports,
validator_stake_lamports,
mint_lamports,
} = config;
let node_keypair = Arc::new(Keypair::new());
let node = Node::new_localhost_with_pubkey(&node_keypair.pubkey());
let contact_info = node.info.clone();
let validator_identity_keypair = Arc::new(validator_identity_keypair);
let node = Node::new_localhost_with_pubkey(&validator_identity_keypair.pubkey());
let GenesisConfigInfo {
mut genesis_config,
mint_keypair,
voting_keypair,
voting_keypair: vote_account_keypair,
} = create_genesis_config_with_leader_ex(
mint_lamports,
&contact_info.id,
&node.info.id,
&Keypair::new(),
&solana_sdk::pubkey::new_rand(),
&Keypair::new().pubkey(),
validator_stake_lamports,
validator_identity_lamports,
solana_sdk::genesis_config::ClusterType::Development,
);
genesis_config.rent.lamports_per_byte_year = 1;
genesis_config.rent.exemption_threshold = 1.0;
genesis_config.rent = rent;
genesis_config.fee_rate_governor = fee_rate_governor;
let (ledger_path, blockhash) = create_new_tmp_ledger!(&genesis_config);
@ -96,24 +122,63 @@ impl TestValidator {
rpc_addrs: Some((node.info.rpc, node.info.rpc_pubsub, node.info.rpc_banks)),
..ValidatorConfig::default()
};
let vote_pubkey = voting_keypair.pubkey();
let node = Validator::new(
let vote_account_address = vote_account_keypair.pubkey();
let rpc_url = format!("http://{}:{}", node.info.rpc.ip(), node.info.rpc.port());
let rpc_pubsub_url = format!("ws://{}/", node.info.rpc_pubsub);
let tpu = node.info.tpu;
let validator = Validator::new(
node,
&node_keypair,
&validator_identity_keypair,
&ledger_path,
&voting_keypair.pubkey(),
vec![Arc::new(voting_keypair)],
&vote_account_keypair.pubkey(),
vec![Arc::new(vote_account_keypair)],
None,
&config,
);
discover_cluster(&contact_info.gossip, 1).expect("Node startup failed");
TestValidator {
server: node,
leader_data: contact_info,
alice: mint_keypair,
validator,
vote_account_address,
mint_keypair,
ledger_path,
genesis_hash: blockhash,
vote_pubkey,
tpu,
rpc_url,
rpc_pubsub_url,
preserve_ledger: false,
}
}
pub fn close(self) {
self.validator.close().unwrap();
if !self.preserve_ledger {
remove_dir_all(&self.ledger_path).unwrap();
}
}
pub fn tpu(&self) -> &SocketAddr {
&self.tpu
}
pub fn mint_keypair(&self) -> Keypair {
Keypair::from_bytes(&self.mint_keypair.to_bytes()).unwrap()
}
pub fn rpc_url(&self) -> String {
self.rpc_url.clone()
}
pub fn rpc_pubsub_url(&self) -> String {
self.rpc_pubsub_url.clone()
}
pub fn genesis_hash(&self) -> Hash {
self.genesis_hash
}
pub fn vote_account_address(&self) -> Pubkey {
self.vote_account_address
}
}

View File

@ -16,7 +16,6 @@ use solana_sdk::{
signature::Signer, system_transaction,
};
use std::{
fs::remove_dir_all,
net::{IpAddr, SocketAddr},
sync::{
atomic::{AtomicBool, Ordering},
@ -31,16 +30,12 @@ use systemstat::Ipv4Addr;
fn test_rpc_client() {
solana_logger::setup();
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = TestValidator::with_no_fee();
let test_validator = TestValidator::with_no_fees();
let alice = test_validator.mint_keypair();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let client = RpcClient::new_socket(leader_data.rpc);
let client = RpcClient::new(test_validator.rpc_url());
assert_eq!(
client.get_version().unwrap().solana_core,
@ -84,9 +79,7 @@ fn test_rpc_client() {
client.get_balance(&alice.pubkey()).unwrap(),
original_alice_balance - sol_to_lamports(20.0)
);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
test_validator.close();
}
#[test]

View File

@ -9,10 +9,9 @@ use reqwest::{self, header::CONTENT_TYPE};
use serde_json::{json, Value};
use solana_account_decoder::UiAccount;
use solana_client::{
rpc_client::{get_rpc_request_str, RpcClient},
rpc_client::RpcClient,
rpc_response::{Response, RpcSignatureResult},
};
use solana_core::contact_info::ContactInfo;
use solana_core::{rpc_pubsub::gen_client::Client as PubsubClient, test_validator::TestValidator};
use solana_sdk::{
commitment_config::CommitmentConfig, hash::Hash, signature::Signer, system_transaction,
@ -20,7 +19,6 @@ use solana_sdk::{
};
use std::{
collections::HashSet,
fs::remove_dir_all,
net::UdpSocket,
sync::mpsc::channel,
thread::sleep,
@ -39,12 +37,10 @@ macro_rules! json_req {
}}
}
fn post_rpc(request: Value, data: &ContactInfo) -> Value {
fn post_rpc(request: Value, rpc_url: &str) -> Value {
let client = reqwest::blocking::Client::new();
let rpc_addr = data.rpc;
let rpc_string = get_rpc_request_str(rpc_addr, false);
let response = client
.post(&rpc_string)
.post(rpc_url)
.header(CONTENT_TYPE, "application/json")
.body(request.to_string())
.send()
@ -56,17 +52,14 @@ fn post_rpc(request: Value, data: &ContactInfo) -> Value {
fn test_rpc_send_tx() {
solana_logger::setup();
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = TestValidator::with_no_fee();
let test_validator = TestValidator::with_no_fees();
let alice = test_validator.mint_keypair();
let rpc_url = test_validator.rpc_url();
let bob_pubkey = solana_sdk::pubkey::new_rand();
let req = json_req!("getRecentBlockhash", json!([]));
let json = post_rpc(req, &leader_data);
let json = post_rpc(req, &rpc_url);
let blockhash: Hash = json["result"]["value"]["blockhash"]
.as_str()
@ -79,7 +72,7 @@ fn test_rpc_send_tx() {
let serialized_encoded_tx = bs58::encode(serialize(&tx).unwrap()).into_string();
let req = json_req!("sendTransaction", json!([serialized_encoded_tx]));
let json: Value = post_rpc(req, &leader_data);
let json: Value = post_rpc(req, &rpc_url);
let signature = &json["result"];
@ -88,7 +81,7 @@ fn test_rpc_send_tx() {
let request = json_req!("confirmTransaction", [signature]);
for _ in 0..solana_sdk::clock::DEFAULT_TICKS_PER_SLOT {
let json = post_rpc(request.clone(), &leader_data);
let json = post_rpc(request.clone(), &rpc_url);
if true == json["result"]["value"] {
confirmed_tx = true;
@ -111,70 +104,62 @@ fn test_rpc_send_tx() {
"getAccountInfo",
json!([bs58::encode(bob_pubkey).into_string(), config])
);
let json: Value = post_rpc(req, &leader_data);
let json: Value = post_rpc(req, &rpc_url);
info!("{:?}", json["result"]["value"]);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
test_validator.close();
}
#[test]
fn test_rpc_invalid_requests() {
solana_logger::setup();
let TestValidator {
server,
leader_data,
ledger_path,
..
} = TestValidator::with_no_fee();
let test_validator = TestValidator::with_no_fees();
let rpc_url = test_validator.rpc_url();
let bob_pubkey = solana_sdk::pubkey::new_rand();
// test invalid get_balance request
let req = json_req!("getBalance", json!(["invalid9999"]));
let json = post_rpc(req, &leader_data);
let json = post_rpc(req, &rpc_url);
let the_error = json["error"]["message"].as_str().unwrap();
assert_eq!(the_error, "Invalid param: Invalid");
// test invalid get_account_info request
let req = json_req!("getAccountInfo", json!(["invalid9999"]));
let json = post_rpc(req, &leader_data);
let json = post_rpc(req, &rpc_url);
let the_error = json["error"]["message"].as_str().unwrap();
assert_eq!(the_error, "Invalid param: Invalid");
// test invalid get_account_info request
let req = json_req!("getAccountInfo", json!([bob_pubkey.to_string()]));
let json = post_rpc(req, &leader_data);
let json = post_rpc(req, &rpc_url);
let the_value = &json["result"]["value"];
assert!(the_value.is_null());
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
test_validator.close();
}
#[test]
fn test_rpc_subscriptions() {
solana_logger::setup();
let TestValidator {
server,
leader_data,
alice,
ledger_path,
genesis_hash,
..
} = TestValidator::with_no_fee();
let test_validator = TestValidator::with_no_fees();
let alice = test_validator.mint_keypair();
let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
transactions_socket.connect(leader_data.tpu).unwrap();
transactions_socket.connect(test_validator.tpu()).unwrap();
// Create transaction signatures to subscribe to
let transactions: Vec<Transaction> = (0..1000)
.map(|_| {
system_transaction::transfer(&alice, &solana_sdk::pubkey::new_rand(), 1, genesis_hash)
system_transaction::transfer(
&alice,
&solana_sdk::pubkey::new_rand(),
1,
test_validator.genesis_hash(),
)
})
.collect();
let mut signature_set: HashSet<String> = transactions
@ -195,11 +180,10 @@ fn test_rpc_subscriptions() {
// Create the pub sub runtime
let mut rt = Runtime::new().unwrap();
let rpc_pubsub_url = format!("ws://{}/", leader_data.rpc_pubsub);
// Subscribe to all signatures
rt.spawn({
let connect = ws::try_connect::<PubsubClient>(&rpc_pubsub_url).unwrap();
let connect = ws::try_connect::<PubsubClient>(&test_validator.rpc_pubsub_url()).unwrap();
let signature_set = signature_set.clone();
connect
.and_then(move |client| {
@ -256,7 +240,7 @@ fn test_rpc_subscriptions() {
// Wait for signature subscriptions
ready_receiver.recv_timeout(Duration::from_secs(2)).unwrap();
let rpc_client = RpcClient::new_socket(leader_data.rpc);
let rpc_client = RpcClient::new(test_validator.rpc_url());
let mut mint_balance = rpc_client
.get_balance_with_commitment(&alice.pubkey(), CommitmentConfig::recent())
.unwrap()
@ -326,6 +310,5 @@ fn test_rpc_subscriptions() {
}
rt.shutdown_now().wait().unwrap();
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
test_validator.close();
}