Skip to content

Commit fe15156

Browse files
committed
improve loader cache size tests
1 parent 57727bc commit fe15156

File tree

1 file changed

+90
-49
lines changed

1 file changed

+90
-49
lines changed

svm/src/account_loader.rs

Lines changed: 90 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)