move program tests to integration
This commit is contained in:
		| @@ -139,10 +139,4 @@ members = [ | |||||||
|     "programs/print", |     "programs/print", | ||||||
|     "programs/move_funds", |     "programs/move_funds", | ||||||
| ] | ] | ||||||
| default-members = [ |  | ||||||
|     ".", |  | ||||||
|     "common", |  | ||||||
|     "programs/noop", |  | ||||||
|     "programs/print", |  | ||||||
|     "programs/move_funds", |  | ||||||
| ] |  | ||||||
|   | |||||||
| @@ -98,11 +98,7 @@ impl DynamicProgram { | |||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|     use super::*; |     use super::*; | ||||||
|     use bincode::serialize; |  | ||||||
|     use solana_program_interface::account::Account; |  | ||||||
|     use solana_program_interface::pubkey::Pubkey; |  | ||||||
|     use std::path::Path; |     use std::path::Path; | ||||||
|     use std::thread; |  | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_create_library_path() { |     fn test_create_library_path() { | ||||||
| @@ -114,131 +110,6 @@ mod tests { | |||||||
|         assert_eq!(true, Path::new(&path).exists()); |         assert_eq!(true, Path::new(&path).exists()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |  | ||||||
|     fn test_program_noop() { |  | ||||||
|         let data: Vec<u8> = 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<u8> = 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<u8> = 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<u8> = 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<u8> = 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 |     // TODO add more tests to validate the Userdata and Account data is | ||||||
|     // moving across the boundary correctly |     // moving across the boundary correctly | ||||||
|  |  | ||||||
|   | |||||||
| @@ -97,14 +97,12 @@ impl SystemProgram { | |||||||
| } | } | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod test { | mod test { | ||||||
|     use bincode::serialize; |  | ||||||
|     use hash::Hash; |     use hash::Hash; | ||||||
|     use signature::{Keypair, KeypairUtil}; |     use signature::{Keypair, KeypairUtil}; | ||||||
|     use solana_program_interface::account::{Account, KeyedAccount}; |     use solana_program_interface::account::Account; | ||||||
|     use solana_program_interface::pubkey::Pubkey; |     use solana_program_interface::pubkey::Pubkey; | ||||||
|     use std::collections::HashMap; |     use std::collections::HashMap; | ||||||
|     use std::sync::RwLock; |     use std::sync::RwLock; | ||||||
|     use std::thread; |  | ||||||
|     use system_program::SystemProgram; |     use system_program::SystemProgram; | ||||||
|     use system_transaction::SystemTransaction; |     use system_transaction::SystemTransaction; | ||||||
|     use transaction::Transaction; |     use transaction::Transaction; | ||||||
| @@ -216,112 +214,6 @@ mod test { | |||||||
|         assert_eq!(accounts[1].userdata.len(), 3); |         assert_eq!(accounts[1].userdata.len(), 3); | ||||||
|     } |     } | ||||||
|     #[test] |     #[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<u8> = 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<u8> = 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() { |     fn test_create_assign() { | ||||||
|         let from = Keypair::new(); |         let from = Keypair::new(); | ||||||
|         let program = Keypair::new(); |         let program = Keypair::new(); | ||||||
|   | |||||||
							
								
								
									
										250
									
								
								tests/programs.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								tests/programs.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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<u8> = 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<u8> = 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<u8> = 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<u8> = 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<u8> = 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<u8> = 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<u8> = 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(); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user