diff --git a/Cargo.toml b/Cargo.toml index 3b0e21c3b..f3df85d57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,10 +139,4 @@ members = [ "programs/print", "programs/move_funds", ] -default-members = [ - ".", - "common", - "programs/noop", - "programs/print", - "programs/move_funds", -] + diff --git a/src/dynamic_program.rs b/src/dynamic_program.rs index 0367e04fe..a7424c885 100644 --- a/src/dynamic_program.rs +++ b/src/dynamic_program.rs @@ -98,11 +98,7 @@ impl DynamicProgram { #[cfg(test)] mod tests { use super::*; - use bincode::serialize; - use solana_program_interface::account::Account; - use solana_program_interface::pubkey::Pubkey; use std::path::Path; - use std::thread; #[test] fn test_create_library_path() { @@ -114,131 +110,6 @@ mod tests { assert_eq!(true, Path::new(&path).exists()); } - #[test] - fn test_program_noop() { - let data: Vec = vec![0]; - let keys = vec![Pubkey::default(); 2]; - let mut accounts = vec![Account::default(), Account::default()]; - accounts[0].tokens = 100; - accounts[1].tokens = 1; - - { - let mut infos: Vec<_> = (&keys) - .into_iter() - .zip(&mut accounts) - .map(|(key, account)| KeyedAccount { key, account }) - .collect(); - - let dp = DynamicProgram::new("noop".to_string()); - dp.call(&mut infos, &data); - } - } - - #[test] - #[ignore] - fn test_program_print() { - let data: Vec = vec![0]; - let keys = vec![Pubkey::default(); 2]; - let mut accounts = vec![Account::default(), Account::default()]; - accounts[0].tokens = 100; - accounts[1].tokens = 1; - - { - let mut infos: Vec<_> = (&keys) - .into_iter() - .zip(&mut accounts) - .map(|(key, account)| KeyedAccount { key, account }) - .collect(); - - let dp = DynamicProgram::new("print".to_string()); - dp.call(&mut infos, &data); - } - } - - #[test] - fn test_program_move_funds_success() { - let tokens: i64 = 100; - let data: Vec = serialize(&tokens).unwrap(); - let keys = vec![Pubkey::default(); 2]; - let mut accounts = vec![Account::default(), Account::default()]; - accounts[0].tokens = 100; - accounts[1].tokens = 1; - - { - let mut infos: Vec<_> = (&keys) - .into_iter() - .zip(&mut accounts) - .map(|(key, account)| KeyedAccount { key, account }) - .collect(); - - let dp = DynamicProgram::new("move_funds".to_string()); - dp.call(&mut infos, &data); - } - assert_eq!(0, accounts[0].tokens); - assert_eq!(101, accounts[1].tokens); - } - - #[test] - fn test_program_move_funds_insufficient_funds() { - let tokens: i64 = 100; - let data: Vec = serialize(&tokens).unwrap(); - let keys = vec![Pubkey::default(); 2]; - let mut accounts = vec![Account::default(), Account::default()]; - accounts[0].tokens = 10; - accounts[1].tokens = 1; - - { - let mut infos: Vec<_> = (&keys) - .into_iter() - .zip(&mut accounts) - .map(|(key, account)| KeyedAccount { key, account }) - .collect(); - - let dp = DynamicProgram::new("move_funds".to_string()); - dp.call(&mut infos, &data); - } - assert_eq!(10, accounts[0].tokens); - assert_eq!(1, accounts[1].tokens); - } - - #[test] - fn test_program_move_funds_succes_many_threads() { - let num_threads = 42; // number of threads to spawn - let num_iters = 100; // number of iterations of test in each thread - let mut threads = Vec::new(); - for _t in 0..num_threads { - threads.push(thread::spawn(move || { - for _i in 0..num_iters { - { - let tokens: i64 = 100; - let data: Vec = serialize(&tokens).unwrap(); - let keys = vec![Pubkey::default(); 2]; - let mut accounts = vec![Account::default(), Account::default()]; - accounts[0].tokens = 100; - accounts[1].tokens = 1; - - { - let mut infos: Vec<_> = (&keys) - .into_iter() - .zip(&mut accounts) - .map(|(key, account)| KeyedAccount { key, account }) - .collect(); - - let dp = DynamicProgram::new("move_funds".to_string()); - dp.call(&mut infos, &data); - } - assert_eq!(0, accounts[0].tokens); - assert_eq!(101, accounts[1].tokens); - } - } - })); - } - - for thread in threads { - thread.join().unwrap(); - } - } - // TODO add more tests to validate the Userdata and Account data is // moving across the boundary correctly diff --git a/src/system_program.rs b/src/system_program.rs index e2d225f22..429cdb95a 100644 --- a/src/system_program.rs +++ b/src/system_program.rs @@ -97,14 +97,12 @@ impl SystemProgram { } #[cfg(test)] mod test { - use bincode::serialize; use hash::Hash; use signature::{Keypair, KeypairUtil}; - use solana_program_interface::account::{Account, KeyedAccount}; + use solana_program_interface::account::Account; use solana_program_interface::pubkey::Pubkey; use std::collections::HashMap; use std::sync::RwLock; - use std::thread; use system_program::SystemProgram; use system_transaction::SystemTransaction; use transaction::Transaction; @@ -216,112 +214,6 @@ mod test { assert_eq!(accounts[1].userdata.len(), 3); } #[test] - fn test_load_call() { - // first load the program - let loaded_programs = RwLock::new(HashMap::new()); - { - let from = Keypair::new(); - let mut accounts = vec![Account::default(), Account::default()]; - let program_id = Pubkey::default(); // same program id for both - let tx = Transaction::system_load( - &from, - Hash::default(), - 0, - program_id, - "move_funds".to_string(), - ); - - SystemProgram::process_transaction(&tx, &mut accounts, &loaded_programs); - } - // then call the program - { - let program_id = Pubkey::default(); // same program id for both - let keys = vec![Pubkey::default(), Pubkey::default()]; - let mut accounts = vec![Account::default(), Account::default()]; - accounts[0].tokens = 100; - accounts[1].tokens = 1; - let tokens: i64 = 100; - let data: Vec = serialize(&tokens).unwrap(); - { - let hash = loaded_programs.write().unwrap(); - match hash.get(&program_id) { - Some(dp) => { - let mut infos: Vec<_> = (&keys) - .into_iter() - .zip(&mut accounts) - .map(|(key, account)| KeyedAccount { key, account }) - .collect(); - - dp.call(&mut infos, &data); - } - None => panic!("failed to find program in hash"), - } - } - assert_eq!(0, accounts[0].tokens); - assert_eq!(101, accounts[1].tokens); - } - } - #[test] - fn test_load_call_many_threads() { - let num_threads = 42; - let num_iters = 100; - let mut threads = Vec::new(); - for _t in 0..num_threads { - threads.push(thread::spawn(move || { - let _tid = thread::current().id(); - for _i in 0..num_iters { - // first load the program - let loaded_programs = RwLock::new(HashMap::new()); - { - let from = Keypair::new(); - let mut accounts = vec![Account::default(), Account::default()]; - let program_id = Pubkey::default(); // same program id for both - let tx = Transaction::system_load( - &from, - Hash::default(), - 0, - program_id, - "move_funds".to_string(), - ); - - SystemProgram::process_transaction(&tx, &mut accounts, &loaded_programs); - } - // then call the program - { - let program_id = Pubkey::default(); // same program id for both - let keys = vec![Pubkey::default(), Pubkey::default()]; - let mut accounts = vec![Account::default(), Account::default()]; - accounts[0].tokens = 100; - accounts[1].tokens = 1; - let tokens: i64 = 100; - let data: Vec = serialize(&tokens).unwrap(); - { - let hash = loaded_programs.write().unwrap(); - match hash.get(&program_id) { - Some(dp) => { - let mut infos: Vec<_> = (&keys) - .into_iter() - .zip(&mut accounts) - .map(|(key, account)| KeyedAccount { key, account }) - .collect(); - - dp.call(&mut infos, &data); - } - None => panic!("failed to find program in hash"), - } - } - assert_eq!(0, accounts[0].tokens); - assert_eq!(101, accounts[1].tokens); - } - } - })); - } - - for thread in threads { - thread.join().unwrap(); - } - } - #[test] fn test_create_assign() { let from = Keypair::new(); let program = Keypair::new(); diff --git a/tests/programs.rs b/tests/programs.rs new file mode 100644 index 000000000..e968f1bea --- /dev/null +++ b/tests/programs.rs @@ -0,0 +1,250 @@ +extern crate bincode; +extern crate solana; +extern crate solana_program_interface; + +use std::collections::HashMap; +use std::sync::RwLock; +use std::thread; + +use bincode::serialize; + +use solana::dynamic_program::DynamicProgram; +use solana::hash::Hash; +use solana::signature::{Keypair, KeypairUtil}; +use solana::system_program::SystemProgram; +use solana::system_transaction::SystemTransaction; +use solana::transaction::Transaction; +use solana_program_interface::account::{Account, KeyedAccount}; +use solana_program_interface::pubkey::Pubkey; + +#[test] +fn test_native_noop() { + let data: Vec = vec![0]; + let keys = vec![Pubkey::default(); 2]; + let mut accounts = vec![Account::default(), Account::default()]; + accounts[0].tokens = 100; + accounts[1].tokens = 1; + + { + let mut infos: Vec<_> = (&keys) + .into_iter() + .zip(&mut accounts) + .map(|(key, account)| KeyedAccount { key, account }) + .collect(); + + let dp = DynamicProgram::new("noop".to_string()); + dp.call(&mut infos, &data); + } +} + +#[test] +#[ignore] +fn test_native_print() { + let data: Vec = vec![0]; + let keys = vec![Pubkey::default(); 2]; + let mut accounts = vec![Account::default(), Account::default()]; + accounts[0].tokens = 100; + accounts[1].tokens = 1; + + { + let mut infos: Vec<_> = (&keys) + .into_iter() + .zip(&mut accounts) + .map(|(key, account)| KeyedAccount { key, account }) + .collect(); + + let dp = DynamicProgram::new("print".to_string()); + dp.call(&mut infos, &data); + } +} + +#[test] +fn test_native_move_funds_success() { + let tokens: i64 = 100; + let data: Vec = serialize(&tokens).unwrap(); + let keys = vec![Pubkey::default(); 2]; + let mut accounts = vec![Account::default(), Account::default()]; + accounts[0].tokens = 100; + accounts[1].tokens = 1; + + { + let mut infos: Vec<_> = (&keys) + .into_iter() + .zip(&mut accounts) + .map(|(key, account)| KeyedAccount { key, account }) + .collect(); + + let dp = DynamicProgram::new("move_funds".to_string()); + dp.call(&mut infos, &data); + } + assert_eq!(0, accounts[0].tokens); + assert_eq!(101, accounts[1].tokens); +} + +#[test] +fn test_native_move_funds_insufficient_funds() { + let tokens: i64 = 100; + let data: Vec = serialize(&tokens).unwrap(); + let keys = vec![Pubkey::default(); 2]; + let mut accounts = vec![Account::default(), Account::default()]; + accounts[0].tokens = 10; + accounts[1].tokens = 1; + + { + let mut infos: Vec<_> = (&keys) + .into_iter() + .zip(&mut accounts) + .map(|(key, account)| KeyedAccount { key, account }) + .collect(); + + let dp = DynamicProgram::new("move_funds".to_string()); + dp.call(&mut infos, &data); + } + assert_eq!(10, accounts[0].tokens); + assert_eq!(1, accounts[1].tokens); +} + +#[test] +fn test_native_move_funds_succes_many_threads() { + let num_threads = 42; // number of threads to spawn + let num_iters = 100; // number of iterations of test in each thread + let mut threads = Vec::new(); + for _t in 0..num_threads { + threads.push(thread::spawn(move || { + for _i in 0..num_iters { + { + let tokens: i64 = 100; + let data: Vec = serialize(&tokens).unwrap(); + let keys = vec![Pubkey::default(); 2]; + let mut accounts = vec![Account::default(), Account::default()]; + accounts[0].tokens = 100; + accounts[1].tokens = 1; + + { + let mut infos: Vec<_> = (&keys) + .into_iter() + .zip(&mut accounts) + .map(|(key, account)| KeyedAccount { key, account }) + .collect(); + + let dp = DynamicProgram::new("move_funds".to_string()); + dp.call(&mut infos, &data); + } + assert_eq!(0, accounts[0].tokens); + assert_eq!(101, accounts[1].tokens); + } + } + })); + } + + for thread in threads { + thread.join().unwrap(); + } +} + +#[test] +fn test_system_program_load_call() { + // first load the program + let loaded_programs = RwLock::new(HashMap::new()); + { + let from = Keypair::new(); + let mut accounts = vec![Account::default(), Account::default()]; + let program_id = Pubkey::default(); // same program id for both + let tx = Transaction::system_load( + &from, + Hash::default(), + 0, + program_id, + "move_funds".to_string(), + ); + + SystemProgram::process_transaction(&tx, &mut accounts, &loaded_programs); + } + // then call the program + { + let program_id = Pubkey::default(); // same program id for both + let keys = vec![Pubkey::default(), Pubkey::default()]; + let mut accounts = vec![Account::default(), Account::default()]; + accounts[0].tokens = 100; + accounts[1].tokens = 1; + let tokens: i64 = 100; + let data: Vec = serialize(&tokens).unwrap(); + { + let hash = loaded_programs.write().unwrap(); + match hash.get(&program_id) { + Some(dp) => { + let mut infos: Vec<_> = (&keys) + .into_iter() + .zip(&mut accounts) + .map(|(key, account)| KeyedAccount { key, account }) + .collect(); + + dp.call(&mut infos, &data); + } + None => panic!("failed to find program in hash"), + } + } + assert_eq!(0, accounts[0].tokens); + assert_eq!(101, accounts[1].tokens); + } +} +#[test] +fn test_system_program_load_call_many_threads() { + let num_threads = 42; + let num_iters = 100; + let mut threads = Vec::new(); + for _t in 0..num_threads { + threads.push(thread::spawn(move || { + let _tid = thread::current().id(); + for _i in 0..num_iters { + // first load the program + let loaded_programs = RwLock::new(HashMap::new()); + { + let from = Keypair::new(); + let mut accounts = vec![Account::default(), Account::default()]; + let program_id = Pubkey::default(); // same program id for both + let tx = Transaction::system_load( + &from, + Hash::default(), + 0, + program_id, + "move_funds".to_string(), + ); + + SystemProgram::process_transaction(&tx, &mut accounts, &loaded_programs); + } + // then call the program + { + let program_id = Pubkey::default(); // same program id for both + let keys = vec![Pubkey::default(), Pubkey::default()]; + let mut accounts = vec![Account::default(), Account::default()]; + accounts[0].tokens = 100; + accounts[1].tokens = 1; + let tokens: i64 = 100; + let data: Vec = serialize(&tokens).unwrap(); + { + let hash = loaded_programs.write().unwrap(); + match hash.get(&program_id) { + Some(dp) => { + let mut infos: Vec<_> = (&keys) + .into_iter() + .zip(&mut accounts) + .map(|(key, account)| KeyedAccount { key, account }) + .collect(); + + dp.call(&mut infos, &data); + } + None => panic!("failed to find program in hash"), + } + } + assert_eq!(0, accounts[0].tokens); + assert_eq!(101, accounts[1].tokens); + } + } + })); + } + + for thread in threads { + thread.join().unwrap(); + } +}