Skip to main content

solana_runtime/
program_cache_utils.rs

1//! Utilities for driving program cache scenarios through `Bank`.
2
3use {
4    crate::bank::Bank,
5    solana_program_runtime::{
6        loaded_programs::ProgramRuntimeEnvironment,
7        program_cache_entry::{ProgramCacheEntry, ProgramCacheEntryType},
8    },
9    solana_pubkey::Pubkey,
10    std::sync::Arc,
11};
12
13pub enum EntryType {
14    FailedVerification,
15    Loaded,
16}
17
18pub struct ExpectedEntry<'a> {
19    pub entry_type: EntryType,
20    pub deployment_slot: u64,
21    pub environment: &'a ProgramRuntimeEnvironment,
22}
23
24pub fn current_env(bank: &Bank) -> ProgramRuntimeEnvironment {
25    bank.get_transaction_processor()
26        .program_runtime_environment_for_epoch(bank.epoch())
27}
28
29fn get_entry_env(entry: &ProgramCacheEntry) -> &ProgramRuntimeEnvironment {
30    entry
31        .program
32        .get_environment()
33        .expect("entry carries an environment")
34}
35
36fn find_all_cached_entries_for_key(
37    bank: &Bank,
38    program_id: &Pubkey,
39) -> Vec<Arc<ProgramCacheEntry>> {
40    let processor = bank.get_transaction_processor();
41    let cache = processor.global_program_cache.read().unwrap();
42    cache
43        .get_flattened_entries_for_tests()
44        .into_iter()
45        .filter_map(|(key, entry)| (key == *program_id).then_some(entry))
46        .collect()
47}
48
49pub fn assert_cache_contents(bank: &Bank, program_id: &Pubkey, expected_entries: &[ExpectedEntry]) {
50    let entries = find_all_cached_entries_for_key(bank, program_id);
51
52    let len = entries.len();
53    let expected_len = expected_entries.len();
54    assert_eq!(
55        len, expected_len,
56        "program should have {expected_len} entries. Got {len}: {entries:?}",
57    );
58
59    for (i, expected_entry) in expected_entries.iter().enumerate() {
60        let entry = entries.get(i).unwrap();
61        match expected_entry.entry_type {
62            EntryType::FailedVerification => {
63                assert!(
64                    matches!(entry.program, ProgramCacheEntryType::FailedVerification(_)),
65                    "Entry {i} should be cached as a failed verification entry",
66                );
67            }
68            EntryType::Loaded => {
69                assert!(
70                    matches!(entry.program, ProgramCacheEntryType::Loaded(_)),
71                    "Entry {i} should be cached as a loaded entry",
72                );
73            }
74        }
75        let deployment_slot = entry.deployment_slot;
76        let expected_deployment_slot = expected_entry.deployment_slot;
77        assert_eq!(
78            deployment_slot, expected_deployment_slot,
79            "Entry {i} should have deployment slot of {expected_deployment_slot}. Got \
80             {deployment_slot}",
81        );
82        let environment = get_entry_env(entry);
83        let expected_environment = expected_entry.environment;
84        assert_eq!(
85            environment, expected_environment,
86            "Entry {i} has unexpected environment",
87        );
88    }
89}