From e3ac9e9679fe3cbe292962dc3cf818accda3808b Mon Sep 17 00:00:00 2001 From: Tyera Eulberg Date: Tue, 12 Mar 2019 18:28:07 -0600 Subject: [PATCH] Move thin client tests to integration test suite --- Cargo.lock | 22 +++++- Cargo.toml | 4 +- tests/thin_client.rs | 184 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 tests/thin_client.rs diff --git a/Cargo.lock b/Cargo.lock index 961c7d5a20..f4d507ca15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1990,7 +1990,6 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1998,6 +1997,7 @@ dependencies = [ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "solana-budget-api 0.13.0", "solana-budget-program 0.13.0", + "solana-client 0.13.0", "solana-drone 0.13.0", "solana-logger 0.13.0", "solana-metrics 0.13.0", @@ -2032,6 +2032,7 @@ dependencies = [ "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "solana 0.13.0", + "solana-client 0.13.0", "solana-drone 0.13.0", "solana-logger 0.13.0", "solana-metrics 0.13.0", @@ -2093,6 +2094,22 @@ dependencies = [ "solana-sdk 0.13.0", ] +[[package]] +name = "solana-client" +version = "0.13.0" +dependencies = [ + "bincode 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-http-server 10.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-logger 0.13.0", + "solana-metrics 0.13.0", + "solana-sdk 0.13.0", +] + [[package]] name = "solana-drone" version = "0.13.0" @@ -2405,6 +2422,7 @@ dependencies = [ "solana 0.13.0", "solana-budget-api 0.13.0", "solana-budget-program 0.13.0", + "solana-client 0.13.0", "solana-drone 0.13.0", "solana-logger 0.13.0", "solana-sdk 0.13.0", @@ -2426,10 +2444,12 @@ dependencies = [ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "solana 0.13.0", "solana-budget-program 0.13.0", + "solana-client 0.13.0", "solana-logger 0.13.0", "solana-netutil 0.13.0", "solana-runtime 0.13.0", "solana-sdk 0.13.0", + "solana-vote-api 0.13.0", "sys-info 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index a3ba40e20f..bb69aba64b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,11 +28,13 @@ rayon = "1.0.0" reqwest = "0.9.11" serde_json = "1.0.39" solana = { path = "core", version = "0.13.0" } +solana-budget-program = { path = "programs/budget", version = "0.13.0" } +solana-client = { path = "client", version = "0.13.0" } solana-logger = { path = "logger", version = "0.13.0" } solana-netutil = { path = "netutil", version = "0.13.0" } solana-runtime = { path = "runtime", version = "0.13.0" } -solana-budget-program = { path = "programs/budget", version = "0.13.0" } solana-sdk = { path = "sdk", version = "0.13.0" } +solana-vote-api = { path = "programs/vote_api", version = "0.13.0" } sys-info = "0.5.6" [[bench]] diff --git a/tests/thin_client.rs b/tests/thin_client.rs new file mode 100644 index 0000000000..fa330ebb2c --- /dev/null +++ b/tests/thin_client.rs @@ -0,0 +1,184 @@ +use bincode::{deserialize, serialize}; +use log::*; +use solana::cluster_client::mk_client; +use solana::fullnode::new_fullnode_for_tests; +use solana::gossip_service::discover; +use solana_client::thin_client::{retry_get_balance, ThinClient}; +use solana_logger; +use solana_sdk::signature::{Keypair, KeypairUtil}; +use solana_sdk::system_instruction::SystemInstruction; +use solana_sdk::system_transaction::SystemTransaction; +use solana_vote_api::vote_state::VoteState; +use solana_vote_api::vote_transaction::VoteTransaction; +use std::fs::remove_dir_all; +use std::net::UdpSocket; +use std::thread::sleep; +use std::time::Duration; + +#[test] +fn test_thin_client_basic() { + solana_logger::setup(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); + let bob_pubkey = Keypair::new().pubkey(); + discover(&leader_data.gossip, 1).unwrap(); + + let mut client = mk_client(&leader_data); + + let transaction_count = client.transaction_count(); + assert_eq!(transaction_count, 0); + + let blockhash = client.get_recent_blockhash(); + info!("test_thin_client blockhash: {:?}", blockhash); + + let signature = client + .transfer(500, &alice, &bob_pubkey, &blockhash) + .unwrap(); + info!("test_thin_client signature: {:?}", signature); + client.poll_for_signature(&signature).unwrap(); + + let balance = client.get_balance(&bob_pubkey); + assert_eq!(balance.unwrap(), 500); + + let transaction_count = client.transaction_count(); + assert_eq!(transaction_count, 1); + server.close().unwrap(); + remove_dir_all(ledger_path).unwrap(); +} + +#[test] +#[ignore] +fn test_bad_sig() { + solana_logger::setup(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); + let bob_pubkey = Keypair::new().pubkey(); + discover(&leader_data.gossip, 1).unwrap(); + + let mut client = mk_client(&leader_data); + + let blockhash = client.get_recent_blockhash(); + + let tx = SystemTransaction::new_account(&alice, &bob_pubkey, 500, blockhash, 0); + + let _sig = client.transfer_signed(&tx).unwrap(); + + let blockhash = client.get_recent_blockhash(); + + let mut tr2 = SystemTransaction::new_account(&alice, &bob_pubkey, 501, blockhash, 0); + let mut instruction2 = deserialize(tr2.userdata(0)).unwrap(); + if let SystemInstruction::Move { ref mut lamports } = instruction2 { + *lamports = 502; + } + tr2.instructions[0].userdata = serialize(&instruction2).unwrap(); + let signature = client.transfer_signed(&tr2).unwrap(); + client.poll_for_signature(&signature).unwrap(); + + let balance = client.get_balance(&bob_pubkey); + assert_eq!(balance.unwrap(), 1001); + server.close().unwrap(); + remove_dir_all(ledger_path).unwrap(); +} + +#[test] +fn test_register_vote_account() { + solana_logger::setup(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); + discover(&leader_data.gossip, 1).unwrap(); + + let mut client = mk_client(&leader_data); + + // Create the validator account, transfer some lamports to that account + let validator_keypair = Keypair::new(); + let blockhash = client.get_recent_blockhash(); + let signature = client + .transfer(500, &alice, &validator_keypair.pubkey(), &blockhash) + .unwrap(); + + client.poll_for_signature(&signature).unwrap(); + + // Create and register the vote account + let validator_vote_account_keypair = Keypair::new(); + let vote_account_id = validator_vote_account_keypair.pubkey(); + let blockhash = client.get_recent_blockhash(); + + let transaction = + VoteTransaction::new_account(&validator_keypair, &vote_account_id, blockhash, 1, 1); + let signature = client.transfer_signed(&transaction).unwrap(); + client.poll_for_signature(&signature).unwrap(); + + let balance = retry_get_balance(&mut client, &vote_account_id, Some(1)) + .expect("Expected balance for new account to exist"); + assert_eq!(balance, 1); + + const LAST: usize = 30; + for run in 0..=LAST { + let account_user_data = client + .get_account_userdata(&vote_account_id) + .expect("Expected valid response for account userdata") + .expect("Expected valid account userdata to exist after account creation"); + + let vote_state = VoteState::deserialize(&account_user_data); + + if vote_state.map(|vote_state| vote_state.delegate_id) == Ok(vote_account_id) { + break; + } + + if run == LAST { + panic!("Expected successful vote account registration"); + } + sleep(Duration::from_millis(900)); + } + + server.close().unwrap(); + remove_dir_all(ledger_path).unwrap(); +} + +#[test] +fn test_transaction_count() { + // set a bogus address, see that we don't hang + solana_logger::setup(); + let addr = "0.0.0.0:1234".parse().unwrap(); + let transactions_socket = UdpSocket::bind("0.0.0.0:0").unwrap(); + let mut client = + ThinClient::new_with_timeout(addr, addr, transactions_socket, Duration::from_secs(2)); + assert_eq!(client.transaction_count(), 0); +} + +#[test] +fn test_zero_balance_after_nonzero() { + solana_logger::setup(); + let (server, leader_data, alice, ledger_path) = new_fullnode_for_tests(); + let bob_keypair = Keypair::new(); + discover(&leader_data.gossip, 1).unwrap(); + + let mut client = mk_client(&leader_data); + let blockhash = client.get_recent_blockhash(); + info!("test_thin_client blockhash: {:?}", blockhash); + + let starting_alice_balance = client.poll_get_balance(&alice.pubkey()).unwrap(); + info!("Alice has {} lamports", starting_alice_balance); + + info!("Give Bob 500 lamports"); + let signature = client + .transfer(500, &alice, &bob_keypair.pubkey(), &blockhash) + .unwrap(); + client.poll_for_signature(&signature).unwrap(); + + let bob_balance = client.poll_get_balance(&bob_keypair.pubkey()); + assert_eq!(bob_balance.unwrap(), 500); + + info!("Take Bob's 500 lamports away"); + let signature = client + .transfer(500, &bob_keypair, &alice.pubkey(), &blockhash) + .unwrap(); + client.poll_for_signature(&signature).unwrap(); + let alice_balance = client.poll_get_balance(&alice.pubkey()).unwrap(); + assert_eq!(alice_balance, starting_alice_balance); + + info!("Should get an error when Bob's balance hits zero and is purged"); + let bob_balance = client.poll_get_balance(&bob_keypair.pubkey()); + info!("Bob's balance is {:?}", bob_balance); + assert!(bob_balance.is_err(),); + + server.close().unwrap(); + remove_dir_all(ledger_path).unwrap(); +}