@@ -773,7 +773,7 @@ mod tests {
773773 std:: { borrow:: Cow , cell:: RefCell , collections:: HashMap , sync:: Arc } ,
774774 } ;
775775
776- #[ derive( Default ) ]
776+ #[ derive( Clone , Default ) ]
777777 struct TestCallbacks {
778778 accounts_map : HashMap < Pubkey , AccountSharedData > ,
779779 #[ allow( clippy:: type_complexity) ]
@@ -2796,72 +2796,113 @@ mod tests {
27962796 ) ;
27972797
27982798 // edge cases involving program cache
2799+
2800+ // we set up a clean loader first
2801+ // the account loader checks its own internal cache prior to the program cache
2802+ // this means we must test every case against a loader that has, and has not, seen the relevant account
2803+ // NOTE when program cache usage is fixed, we will go to the program cache first
2804+ // so this will no longer be necessary
2805+ drop ( account_loader) ;
2806+ let mut clean_loader: AccountLoader < _ > = ( & mock_bank) . into ( ) ;
27992807 let program2_entry = ProgramCacheEntry {
28002808 account_size : ( program2_size + programdata2_size) as usize ,
28012809 account_owner : ProgramCacheEntryOwner :: LoaderV3 ,
28022810 ..ProgramCacheEntry :: default ( )
28032811 } ;
2804- account_loader
2812+ clean_loader
28052813 . program_cache
28062814 . replenish ( program2, Arc :: new ( program2_entry) ) ;
28072815
2808- // normal invocation uses the combined cache size
2809- let ixns = vec ! [ Instruction :: new_with_bytes( program2, & [ ] , vec![ ] ) ] ;
2810- test_data_size (
2811- & mut account_loader,
2812- ixns,
2813- program2_size + programdata2_size + upgradeable_loader_size + fee_payer_size,
2816+ let mut cache_test_txs = vec ! [ ] ;
2817+
2818+ // normal program invocation uses the combined cache size
2819+ let normal_tx = SanitizedTransaction :: from_transaction_for_tests (
2820+ Transaction :: new_signed_with_payer (
2821+ & [ Instruction :: new_with_bytes ( program2, & [ ] , vec ! [ ] ) ] ,
2822+ Some ( & fee_payer) ,
2823+ & [ & fee_payer_keypair] ,
2824+ Hash :: default ( ) ,
2825+ ) ,
28142826 ) ;
2827+ let normal_tx_size =
2828+ program2_size + programdata2_size + upgradeable_loader_size + fee_payer_size;
2829+ cache_test_txs. push ( ( normal_tx, normal_tx_size) ) ;
2830+
2831+ // program as writable, non-instruction account, bypasses the cache
2832+ let writable_tx =
2833+ new_unchecked_sanitized_transaction_with_writable_program ( program2, fee_payer) ;
2834+ let writable_tx_size = program2_size + upgradeable_loader_size + fee_payer_size;
2835+ cache_test_txs. push ( ( writable_tx, writable_tx_size) ) ;
28152836
28162837 // program as instruction account bypasses the cache
2817- let ixns = vec ! [ Instruction :: new_with_bytes(
2818- program2,
2819- & [ ] ,
2820- vec![ account_meta( program2, false ) ] ,
2821- ) ] ;
2822- test_data_size (
2823- & mut account_loader,
2824- ixns,
2825- program2_size + upgradeable_loader_size + fee_payer_size,
2838+ let instruction_tx = SanitizedTransaction :: from_transaction_for_tests (
2839+ Transaction :: new_signed_with_payer (
2840+ & [ Instruction :: new_with_bytes (
2841+ program2,
2842+ & [ ] ,
2843+ vec ! [ account_meta( program2, false ) ] ,
2844+ ) ] ,
2845+ Some ( & fee_payer) ,
2846+ & [ & fee_payer_keypair] ,
2847+ Hash :: default ( ) ,
2848+ ) ,
28262849 ) ;
2850+ let instruction_tx_size = program2_size + upgradeable_loader_size + fee_payer_size;
2851+ cache_test_txs. push ( ( instruction_tx, instruction_tx_size) ) ;
28272852
28282853 // programdata as instruction account double-counts it
2829- let ixns = vec ! [ Instruction :: new_with_bytes(
2830- program2,
2831- & [ ] ,
2832- vec![ account_meta( programdata2, false ) ] ,
2833- ) ] ;
2834- test_data_size (
2835- & mut account_loader,
2836- ixns,
2837- program2_size + programdata2_size * 2 + upgradeable_loader_size + fee_payer_size,
2854+ let programdata_tx = SanitizedTransaction :: from_transaction_for_tests (
2855+ Transaction :: new_signed_with_payer (
2856+ & [ Instruction :: new_with_bytes (
2857+ program2,
2858+ & [ ] ,
2859+ vec ! [ account_meta( programdata2, false ) ] ,
2860+ ) ] ,
2861+ Some ( & fee_payer) ,
2862+ & [ & fee_payer_keypair] ,
2863+ Hash :: default ( ) ,
2864+ ) ,
28382865 ) ;
2839-
2840- // both as instruction accounts, for completeness
2841- let ixns = vec ! [ Instruction :: new_with_bytes(
2842- program2,
2843- & [ ] ,
2844- vec![
2845- account_meta( program2, false ) ,
2846- account_meta( programdata2, false ) ,
2847- ] ,
2848- ) ] ;
2849- test_data_size (
2850- & mut account_loader,
2851- ixns,
2852- program2_size + programdata2_size + upgradeable_loader_size + fee_payer_size,
2866+ let programdata_tx_size =
2867+ program2_size + programdata2_size * 2 + upgradeable_loader_size + fee_payer_size;
2868+ cache_test_txs. push ( ( programdata_tx, programdata_tx_size) ) ;
2869+
2870+ // program and programdata as instruction accounts
2871+ // loading one account can never affect the loading of a different account
2872+ // we only include it for completeness
2873+ let double_instruction_tx = SanitizedTransaction :: from_transaction_for_tests (
2874+ Transaction :: new_signed_with_payer (
2875+ & [ Instruction :: new_with_bytes (
2876+ program2,
2877+ & [ ] ,
2878+ vec ! [
2879+ account_meta( program2, false ) ,
2880+ account_meta( programdata2, false ) ,
2881+ ] ,
2882+ ) ] ,
2883+ Some ( & fee_payer) ,
2884+ & [ & fee_payer_keypair] ,
2885+ Hash :: default ( ) ,
2886+ ) ,
28532887 ) ;
2888+ let double_instruction_tx_size =
2889+ program2_size + programdata2_size + upgradeable_loader_size + fee_payer_size;
2890+ cache_test_txs. push ( ( double_instruction_tx, double_instruction_tx_size) ) ;
28542891
2855- // writable program bypasses the cache
2856- let tx = new_unchecked_sanitized_transaction_with_writable_program ( program2, fee_payer) ;
2857- test_transaction_data_size (
2858- & mut account_loader,
2859- tx,
2860- program2_size + upgradeable_loader_size + fee_payer_size,
2861- ) ;
2892+ // first test all cases against a clean loader
2893+ for ( tx, size) in cache_test_txs. clone ( ) {
2894+ test_transaction_data_size ( & mut clean_loader. clone ( ) , tx, size) ;
2895+ }
28622896
2863- // NOTE for the new loader we *must* also test arbitrary permutations of the cache transactions
2864- // to ensure that the batched loading is overridden on a tx-per-tx basis
2897+ // next test all cases against a dirty loader
2898+ // we loop twice to ensure every transaction runs against a fully populated internal cache
2899+ // this ensures there is no difference in behavior regardless of where the account is loaded from
2900+ let mut dirty_loader = clean_loader. clone ( ) ;
2901+ for _ in 0 ..1 {
2902+ for ( tx, size) in cache_test_txs. clone ( ) {
2903+ test_transaction_data_size ( & mut dirty_loader, tx, size) ;
2904+ }
2905+ }
28652906 }
28662907 }
28672908}
0 commit comments