Refactors the common code of test and bench targets into the solana_runtime::bpf_test_utils module. (#13203)
(cherry picked from commit 65ee3a6bdd)
			
			
This commit is contained in:
		
				
					committed by
					
						
						Michael Vines
					
				
			
			
				
	
			
			
			
						parent
						
							24bd4ff6d4
						
					
				
				
					commit
					36b7c2ea97
				
			@@ -6,24 +6,22 @@ extern crate test;
 | 
				
			|||||||
extern crate solana_bpf_loader_program;
 | 
					extern crate solana_bpf_loader_program;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
 | 
					use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
 | 
				
			||||||
use solana_bpf_loader_program::syscalls::SyscallError;
 | 
					 | 
				
			||||||
use solana_measure::measure::Measure;
 | 
					use solana_measure::measure::Measure;
 | 
				
			||||||
use solana_rbpf::vm::{EbpfVm, InstructionMeter};
 | 
					use solana_rbpf::vm::{EbpfVm, InstructionMeter};
 | 
				
			||||||
use solana_runtime::{
 | 
					use solana_runtime::{
 | 
				
			||||||
    bank::Bank,
 | 
					    bank::Bank,
 | 
				
			||||||
    bank_client::BankClient,
 | 
					    bank_client::BankClient,
 | 
				
			||||||
 | 
					    bpf_test_utils::MockInvokeContext,
 | 
				
			||||||
    genesis_utils::{create_genesis_config, GenesisConfigInfo},
 | 
					    genesis_utils::{create_genesis_config, GenesisConfigInfo},
 | 
				
			||||||
    loader_utils::load_program,
 | 
					    loader_utils::load_program,
 | 
				
			||||||
    process_instruction::{
 | 
					    process_instruction::{ComputeMeter, InvokeContext},
 | 
				
			||||||
        ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use solana_sdk::{
 | 
					use solana_sdk::{
 | 
				
			||||||
    account::Account,
 | 
					    account::Account,
 | 
				
			||||||
    bpf_loader,
 | 
					    bpf_loader,
 | 
				
			||||||
    client::SyncClient,
 | 
					    client::SyncClient,
 | 
				
			||||||
    entrypoint::SUCCESS,
 | 
					    entrypoint::SUCCESS,
 | 
				
			||||||
    instruction::{AccountMeta, CompiledInstruction, Instruction, InstructionError},
 | 
					    instruction::{AccountMeta, Instruction},
 | 
				
			||||||
    message::Message,
 | 
					    message::Message,
 | 
				
			||||||
    pubkey::Pubkey,
 | 
					    pubkey::Pubkey,
 | 
				
			||||||
    signature::{Keypair, Signer},
 | 
					    signature::{Keypair, Signer},
 | 
				
			||||||
@@ -193,7 +191,7 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
 | 
				
			|||||||
    const BUDGET: u64 = 200_000;
 | 
					    const BUDGET: u64 = 200_000;
 | 
				
			||||||
    let loader_id = bpf_loader::id();
 | 
					    let loader_id = bpf_loader::id();
 | 
				
			||||||
    let mut invoke_context = MockInvokeContext::default();
 | 
					    let mut invoke_context = MockInvokeContext::default();
 | 
				
			||||||
    invoke_context.compute_meter.borrow_mut().remaining = BUDGET;
 | 
					    invoke_context.compute_meter.remaining = BUDGET;
 | 
				
			||||||
    let compute_meter = invoke_context.get_compute_meter();
 | 
					    let compute_meter = invoke_context.get_compute_meter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let elf = load_elf("tuner").unwrap();
 | 
					    let elf = load_elf("tuner").unwrap();
 | 
				
			||||||
@@ -225,80 +223,6 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Default)]
 | 
					 | 
				
			||||||
pub struct MockInvokeContext {
 | 
					 | 
				
			||||||
    key: Pubkey,
 | 
					 | 
				
			||||||
    logger: MockLogger,
 | 
					 | 
				
			||||||
    compute_budget: ComputeBudget,
 | 
					 | 
				
			||||||
    compute_meter: Rc<RefCell<MockComputeMeter>>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
impl InvokeContext for MockInvokeContext {
 | 
					 | 
				
			||||||
    fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn pop(&mut self) {}
 | 
					 | 
				
			||||||
    fn verify_and_update(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        _message: &Message,
 | 
					 | 
				
			||||||
        _instruction: &CompiledInstruction,
 | 
					 | 
				
			||||||
        _accounts: &[Rc<RefCell<Account>>],
 | 
					 | 
				
			||||||
    ) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
 | 
					 | 
				
			||||||
        Ok(&self.key)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] {
 | 
					 | 
				
			||||||
        &[]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
 | 
					 | 
				
			||||||
        Rc::new(RefCell::new(self.logger.clone()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_compute_budget(&self) -> &ComputeBudget {
 | 
					 | 
				
			||||||
        &self.compute_budget
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
 | 
					 | 
				
			||||||
        self.compute_meter.clone()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc<dyn Executor>) {}
 | 
					 | 
				
			||||||
    fn get_executor(&mut self, _pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn record_instruction(&self, _instruction: &Instruction) {}
 | 
					 | 
				
			||||||
    fn is_feature_active(&self, _feature_id: &Pubkey) -> bool {
 | 
					 | 
				
			||||||
        true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#[derive(Debug, Default, Clone)]
 | 
					 | 
				
			||||||
pub struct MockLogger {
 | 
					 | 
				
			||||||
    pub log: Rc<RefCell<Vec<String>>>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
impl Logger for MockLogger {
 | 
					 | 
				
			||||||
    fn log_enabled(&self) -> bool {
 | 
					 | 
				
			||||||
        true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn log(&mut self, message: &str) {
 | 
					 | 
				
			||||||
        self.log.borrow_mut().push(message.to_string());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#[derive(Debug, Default, Clone)]
 | 
					 | 
				
			||||||
pub struct MockComputeMeter {
 | 
					 | 
				
			||||||
    pub remaining: u64,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
impl ComputeMeter for MockComputeMeter {
 | 
					 | 
				
			||||||
    fn consume(&mut self, amount: u64) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
        let exceeded = self.remaining < amount;
 | 
					 | 
				
			||||||
        self.remaining = self.remaining.saturating_sub(amount);
 | 
					 | 
				
			||||||
        if exceeded {
 | 
					 | 
				
			||||||
            return Err(InstructionError::ComputationalBudgetExceeded);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_remaining(&self) -> u64 {
 | 
					 | 
				
			||||||
        self.remaining
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Passed to the VM to enforce the compute budget
 | 
					/// Passed to the VM to enforce the compute budget
 | 
				
			||||||
#[derive(Clone)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
struct MockInstructionMeter {
 | 
					struct MockInstructionMeter {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,15 +7,14 @@ use solana_bpf_loader_program::{
 | 
				
			|||||||
    create_vm,
 | 
					    create_vm,
 | 
				
			||||||
    serialization::{deserialize_parameters, serialize_parameters},
 | 
					    serialization::{deserialize_parameters, serialize_parameters},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use solana_rbpf::vm::{EbpfVm, InstructionMeter};
 | 
					use solana_rbpf::vm::EbpfVm;
 | 
				
			||||||
use solana_runtime::{
 | 
					use solana_runtime::{
 | 
				
			||||||
    bank::Bank,
 | 
					    bank::Bank,
 | 
				
			||||||
    bank_client::BankClient,
 | 
					    bank_client::BankClient,
 | 
				
			||||||
 | 
					    bpf_test_utils::MockInvokeContext,
 | 
				
			||||||
    genesis_utils::{create_genesis_config, GenesisConfigInfo},
 | 
					    genesis_utils::{create_genesis_config, GenesisConfigInfo},
 | 
				
			||||||
    loader_utils::load_program,
 | 
					    loader_utils::load_program,
 | 
				
			||||||
    process_instruction::{
 | 
					    process_instruction::ComputeBudget,
 | 
				
			||||||
        ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use solana_sdk::{
 | 
					use solana_sdk::{
 | 
				
			||||||
    account::Account,
 | 
					    account::Account,
 | 
				
			||||||
@@ -31,7 +30,7 @@ use solana_sdk::{
 | 
				
			|||||||
    sysvar::{clock, fees, rent, slot_hashes, stake_history},
 | 
					    sysvar::{clock, fees, rent, slot_hashes, stake_history},
 | 
				
			||||||
    transaction::{Transaction, TransactionError},
 | 
					    transaction::{Transaction, TransactionError},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use std::{cell::RefCell, env, fs::File, io::Read, path::PathBuf, rc::Rc, sync::Arc};
 | 
					use std::{cell::RefCell, env, fs::File, io::Read, path::PathBuf, sync::Arc};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// BPF program file extension
 | 
					/// BPF program file extension
 | 
				
			||||||
const PLATFORM_FILE_EXTENSION_BPF: &str = "so";
 | 
					const PLATFORM_FILE_EXTENSION_BPF: &str = "so";
 | 
				
			||||||
@@ -776,82 +775,6 @@ fn assert_instruction_count() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Mock InvokeContext
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug, Default)]
 | 
					 | 
				
			||||||
struct MockInvokeContext {
 | 
					 | 
				
			||||||
    pub key: Pubkey,
 | 
					 | 
				
			||||||
    pub logger: MockLogger,
 | 
					 | 
				
			||||||
    pub compute_budget: ComputeBudget,
 | 
					 | 
				
			||||||
    pub compute_meter: MockComputeMeter,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
impl InvokeContext for MockInvokeContext {
 | 
					 | 
				
			||||||
    fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn pop(&mut self) {}
 | 
					 | 
				
			||||||
    fn verify_and_update(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        _message: &Message,
 | 
					 | 
				
			||||||
        _instruction: &CompiledInstruction,
 | 
					 | 
				
			||||||
        _accounts: &[Rc<RefCell<Account>>],
 | 
					 | 
				
			||||||
    ) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
 | 
					 | 
				
			||||||
        Ok(&self.key)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] {
 | 
					 | 
				
			||||||
        &[]
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
 | 
					 | 
				
			||||||
        Rc::new(RefCell::new(self.logger.clone()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_compute_budget(&self) -> &ComputeBudget {
 | 
					 | 
				
			||||||
        &self.compute_budget
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
 | 
					 | 
				
			||||||
        Rc::new(RefCell::new(self.compute_meter.clone()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc<dyn Executor>) {}
 | 
					 | 
				
			||||||
    fn get_executor(&mut self, _pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn record_instruction(&self, _instruction: &Instruction) {}
 | 
					 | 
				
			||||||
    fn is_feature_active(&self, _feature_id: &Pubkey) -> bool {
 | 
					 | 
				
			||||||
        true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug, Default, Clone)]
 | 
					 | 
				
			||||||
struct MockComputeMeter {}
 | 
					 | 
				
			||||||
impl ComputeMeter for MockComputeMeter {
 | 
					 | 
				
			||||||
    fn consume(&mut self, _amount: u64) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn get_remaining(&self) -> u64 {
 | 
					 | 
				
			||||||
        u64::MAX
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#[derive(Debug, Default, Clone)]
 | 
					 | 
				
			||||||
struct MockLogger {}
 | 
					 | 
				
			||||||
impl Logger for MockLogger {
 | 
					 | 
				
			||||||
    fn log_enabled(&self) -> bool {
 | 
					 | 
				
			||||||
        true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn log(&mut self, _message: &str) {
 | 
					 | 
				
			||||||
        // println!("{}", message);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct TestInstructionMeter {}
 | 
					 | 
				
			||||||
impl InstructionMeter for TestInstructionMeter {
 | 
					 | 
				
			||||||
    fn consume(&mut self, _amount: u64) {}
 | 
					 | 
				
			||||||
    fn get_remaining(&self) -> u64 {
 | 
					 | 
				
			||||||
        u64::MAX
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg(any(feature = "bpf_rust"))]
 | 
					#[cfg(any(feature = "bpf_rust"))]
 | 
				
			||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn test_program_bpf_instruction_introspection() {
 | 
					fn test_program_bpf_instruction_introspection() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -313,102 +313,14 @@ mod tests {
 | 
				
			|||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
    use rand::Rng;
 | 
					    use rand::Rng;
 | 
				
			||||||
    use solana_runtime::{
 | 
					    use solana_runtime::{
 | 
				
			||||||
 | 
					        bpf_test_utils::MockInvokeContext,
 | 
				
			||||||
        feature_set::FeatureSet,
 | 
					        feature_set::FeatureSet,
 | 
				
			||||||
        message_processor::{Executors, ThisInvokeContext},
 | 
					        message_processor::{Executors, ThisInvokeContext},
 | 
				
			||||||
        process_instruction::{ComputeBudget, Logger, ProcessInstruction},
 | 
					        process_instruction::ComputeBudget,
 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    use solana_sdk::{
 | 
					 | 
				
			||||||
        account::Account, instruction::CompiledInstruction, instruction::Instruction,
 | 
					 | 
				
			||||||
        message::Message, rent::Rent,
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					    use solana_sdk::{account::Account, rent::Rent};
 | 
				
			||||||
    use std::{cell::RefCell, fs::File, io::Read, ops::Range, rc::Rc};
 | 
					    use std::{cell::RefCell, fs::File, io::Read, ops::Range, rc::Rc};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[derive(Debug, Default, Clone)]
 | 
					 | 
				
			||||||
    pub struct MockComputeMeter {
 | 
					 | 
				
			||||||
        pub remaining: u64,
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    impl ComputeMeter for MockComputeMeter {
 | 
					 | 
				
			||||||
        fn consume(&mut self, amount: u64) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
            let exceeded = self.remaining < amount;
 | 
					 | 
				
			||||||
            self.remaining = self.remaining.saturating_sub(amount);
 | 
					 | 
				
			||||||
            if exceeded {
 | 
					 | 
				
			||||||
                return Err(InstructionError::ComputationalBudgetExceeded);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            Ok(())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn get_remaining(&self) -> u64 {
 | 
					 | 
				
			||||||
            self.remaining
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[derive(Debug, Default, Clone)]
 | 
					 | 
				
			||||||
    pub struct MockLogger {
 | 
					 | 
				
			||||||
        pub log: Rc<RefCell<Vec<String>>>,
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    impl Logger for MockLogger {
 | 
					 | 
				
			||||||
        fn log_enabled(&self) -> bool {
 | 
					 | 
				
			||||||
            true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn log(&mut self, message: &str) {
 | 
					 | 
				
			||||||
            self.log.borrow_mut().push(message.to_string());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[derive(Debug)]
 | 
					 | 
				
			||||||
    pub struct MockInvokeContext {
 | 
					 | 
				
			||||||
        pub key: Pubkey,
 | 
					 | 
				
			||||||
        pub logger: MockLogger,
 | 
					 | 
				
			||||||
        pub compute_budget: ComputeBudget,
 | 
					 | 
				
			||||||
        pub compute_meter: MockComputeMeter,
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    impl Default for MockInvokeContext {
 | 
					 | 
				
			||||||
        fn default() -> Self {
 | 
					 | 
				
			||||||
            MockInvokeContext {
 | 
					 | 
				
			||||||
                key: Pubkey::default(),
 | 
					 | 
				
			||||||
                logger: MockLogger::default(),
 | 
					 | 
				
			||||||
                compute_budget: ComputeBudget::default(),
 | 
					 | 
				
			||||||
                compute_meter: MockComputeMeter {
 | 
					 | 
				
			||||||
                    remaining: std::u64::MAX,
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    impl InvokeContext for MockInvokeContext {
 | 
					 | 
				
			||||||
        fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
            Ok(())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn pop(&mut self) {}
 | 
					 | 
				
			||||||
        fn verify_and_update(
 | 
					 | 
				
			||||||
            &mut self,
 | 
					 | 
				
			||||||
            _message: &Message,
 | 
					 | 
				
			||||||
            _instruction: &CompiledInstruction,
 | 
					 | 
				
			||||||
            _accounts: &[Rc<RefCell<Account>>],
 | 
					 | 
				
			||||||
        ) -> Result<(), InstructionError> {
 | 
					 | 
				
			||||||
            Ok(())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
 | 
					 | 
				
			||||||
            Ok(&self.key)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] {
 | 
					 | 
				
			||||||
            &[]
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
 | 
					 | 
				
			||||||
            Rc::new(RefCell::new(self.logger.clone()))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn get_compute_budget(&self) -> &ComputeBudget {
 | 
					 | 
				
			||||||
            &self.compute_budget
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
 | 
					 | 
				
			||||||
            Rc::new(RefCell::new(self.compute_meter.clone()))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc<dyn Executor>) {}
 | 
					 | 
				
			||||||
        fn get_executor(&mut self, _pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
 | 
					 | 
				
			||||||
            None
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        fn record_instruction(&self, _instruction: &Instruction) {}
 | 
					 | 
				
			||||||
        fn is_feature_active(&self, _feature_id: &Pubkey) -> bool {
 | 
					 | 
				
			||||||
            true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    struct TestInstructionMeter {
 | 
					    struct TestInstructionMeter {
 | 
				
			||||||
        remaining: u64,
 | 
					        remaining: u64,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1237,7 +1237,7 @@ fn call<'a>(
 | 
				
			|||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
    use crate::tests::{MockComputeMeter, MockLogger};
 | 
					    use solana_runtime::bpf_test_utils::{MockComputeMeter, MockLogger};
 | 
				
			||||||
    use solana_sdk::hash::hashv;
 | 
					    use solana_sdk::hash::hashv;
 | 
				
			||||||
    use std::str::FromStr;
 | 
					    use std::str::FromStr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										96
									
								
								runtime/src/bpf_test_utils.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								runtime/src/bpf_test_utils.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					use crate::process_instruction::{
 | 
				
			||||||
 | 
					    ComputeBudget, ComputeMeter, Executor, InvokeContext, Logger, ProcessInstruction,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use solana_sdk::{
 | 
				
			||||||
 | 
					    account::Account, instruction::CompiledInstruction, instruction::Instruction,
 | 
				
			||||||
 | 
					    instruction::InstructionError, message::Message, pubkey::Pubkey,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use std::{cell::RefCell, rc::Rc, sync::Arc};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Default, Clone)]
 | 
				
			||||||
 | 
					pub struct MockComputeMeter {
 | 
				
			||||||
 | 
					    pub remaining: u64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					impl ComputeMeter for MockComputeMeter {
 | 
				
			||||||
 | 
					    fn consume(&mut self, amount: u64) -> Result<(), InstructionError> {
 | 
				
			||||||
 | 
					        let exceeded = self.remaining < amount;
 | 
				
			||||||
 | 
					        self.remaining = self.remaining.saturating_sub(amount);
 | 
				
			||||||
 | 
					        if exceeded {
 | 
				
			||||||
 | 
					            return Err(InstructionError::ComputationalBudgetExceeded);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn get_remaining(&self) -> u64 {
 | 
				
			||||||
 | 
					        self.remaining
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Default, Clone)]
 | 
				
			||||||
 | 
					pub struct MockLogger {
 | 
				
			||||||
 | 
					    pub log: Rc<RefCell<Vec<String>>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					impl Logger for MockLogger {
 | 
				
			||||||
 | 
					    fn log_enabled(&self) -> bool {
 | 
				
			||||||
 | 
					        true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn log(&mut self, message: &str) {
 | 
				
			||||||
 | 
					        self.log.borrow_mut().push(message.to_string());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct MockInvokeContext {
 | 
				
			||||||
 | 
					    pub key: Pubkey,
 | 
				
			||||||
 | 
					    pub logger: MockLogger,
 | 
				
			||||||
 | 
					    pub compute_budget: ComputeBudget,
 | 
				
			||||||
 | 
					    pub compute_meter: MockComputeMeter,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					impl Default for MockInvokeContext {
 | 
				
			||||||
 | 
					    fn default() -> Self {
 | 
				
			||||||
 | 
					        MockInvokeContext {
 | 
				
			||||||
 | 
					            key: Pubkey::default(),
 | 
				
			||||||
 | 
					            logger: MockLogger::default(),
 | 
				
			||||||
 | 
					            compute_budget: ComputeBudget::default(),
 | 
				
			||||||
 | 
					            compute_meter: MockComputeMeter {
 | 
				
			||||||
 | 
					                remaining: std::i64::MAX as u64,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					impl InvokeContext for MockInvokeContext {
 | 
				
			||||||
 | 
					    fn push(&mut self, _key: &Pubkey) -> Result<(), InstructionError> {
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn pop(&mut self) {}
 | 
				
			||||||
 | 
					    fn verify_and_update(
 | 
				
			||||||
 | 
					        &mut self,
 | 
				
			||||||
 | 
					        _message: &Message,
 | 
				
			||||||
 | 
					        _instruction: &CompiledInstruction,
 | 
				
			||||||
 | 
					        _accounts: &[Rc<RefCell<Account>>],
 | 
				
			||||||
 | 
					    ) -> Result<(), InstructionError> {
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn get_caller(&self) -> Result<&Pubkey, InstructionError> {
 | 
				
			||||||
 | 
					        Ok(&self.key)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn get_programs(&self) -> &[(Pubkey, ProcessInstruction)] {
 | 
				
			||||||
 | 
					        &[]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn get_logger(&self) -> Rc<RefCell<dyn Logger>> {
 | 
				
			||||||
 | 
					        Rc::new(RefCell::new(self.logger.clone()))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn get_compute_budget(&self) -> &ComputeBudget {
 | 
				
			||||||
 | 
					        &self.compute_budget
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn get_compute_meter(&self) -> Rc<RefCell<dyn ComputeMeter>> {
 | 
				
			||||||
 | 
					        Rc::new(RefCell::new(self.compute_meter.clone()))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn add_executor(&mut self, _pubkey: &Pubkey, _executor: Arc<dyn Executor>) {}
 | 
				
			||||||
 | 
					    fn get_executor(&mut self, _pubkey: &Pubkey) -> Option<Arc<dyn Executor>> {
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn record_instruction(&self, _instruction: &Instruction) {}
 | 
				
			||||||
 | 
					    fn is_feature_active(&self, _feature_id: &Pubkey) -> bool {
 | 
				
			||||||
 | 
					        true
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -10,6 +10,7 @@ pub mod bank_forks;
 | 
				
			|||||||
pub mod bank_utils;
 | 
					pub mod bank_utils;
 | 
				
			||||||
mod blockhash_queue;
 | 
					mod blockhash_queue;
 | 
				
			||||||
pub mod bloom;
 | 
					pub mod bloom;
 | 
				
			||||||
 | 
					pub mod bpf_test_utils;
 | 
				
			||||||
pub mod builtins;
 | 
					pub mod builtins;
 | 
				
			||||||
pub mod commitment;
 | 
					pub mod commitment;
 | 
				
			||||||
pub mod epoch_stakes;
 | 
					pub mod epoch_stakes;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user