use { solana_program::{ account_info::{next_account_info, AccountInfo}, clock::Clock, entrypoint::ProgramResult, instruction::{AccountMeta, Instruction, InstructionError}, program_error::ProgramError, pubkey::Pubkey, sysvar::{clock, Sysvar}, }, solana_program_test::{processor, ProgramTest, ProgramTestError}, solana_sdk::{ signature::Signer, transaction::{Transaction, TransactionError}, }, std::convert::TryInto, }; // Use a big number to be sure that we get the right error const WRONG_SLOT_ERROR: u32 = 123456; fn process_instruction( _program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8], ) -> ProgramResult { let account_info_iter = &mut accounts.iter(); let clock_info = next_account_info(account_info_iter)?; let clock = &Clock::from_account_info(clock_info)?; let expected_slot = u64::from_le_bytes(input.try_into().unwrap()); if clock.slot == expected_slot { Ok(()) } else { Err(ProgramError::Custom(WRONG_SLOT_ERROR)) } } #[tokio::test] async fn custom_warp() { let program_id = Pubkey::new_unique(); // Initialize and start the test network let program_test = ProgramTest::new( "program-test-warp", program_id, processor!(process_instruction), ); let mut context = program_test.start_with_context().await; let expected_slot = 5_000_000; let instruction = Instruction::new( program_id, &expected_slot, vec![AccountMeta::new_readonly(clock::id(), false)], ); // Fail transaction let transaction = Transaction::new_signed_with_payer( &[instruction.clone()], Some(&context.payer.pubkey()), &[&context.payer], context.last_blockhash, ); assert_eq!( context .banks_client .process_transaction(transaction) .await .unwrap_err() .unwrap(), TransactionError::InstructionError(0, InstructionError::Custom(WRONG_SLOT_ERROR)) ); // Warp to success! context.warp_to_slot(expected_slot).unwrap(); let instruction = Instruction::new( program_id, &expected_slot, vec![AccountMeta::new_readonly(clock::id(), false)], ); let transaction = Transaction::new_signed_with_payer( &[instruction], Some(&context.payer.pubkey()), &[&context.payer], context.last_blockhash, ); context .banks_client .process_transaction(transaction) .await .unwrap(); // Try warping again to the same slot assert_eq!( context.warp_to_slot(expected_slot).unwrap_err(), ProgramTestError::InvalidWarpSlot, ); }