|
| 1 | +use quasar_svm::{Account, Instruction, Pubkey, QuasarSvm}; |
| 2 | +use solana_address::Address; |
| 3 | + |
| 4 | +/// Lever program's program ID — must match the lever's declare_id!(). |
| 5 | +fn lever_program_id() -> Pubkey { |
| 6 | + Pubkey::from(crate::LEVER_PROGRAM_ID) |
| 7 | +} |
| 8 | + |
| 9 | +/// PowerStatus discriminator from the lever program. |
| 10 | +const POWER_STATUS_DISCRIMINATOR: u8 = 1; |
| 11 | + |
| 12 | +fn setup() -> QuasarSvm { |
| 13 | + let hand_elf = include_bytes!("../target/deploy/quasar_hand.so"); |
| 14 | + let lever_elf = include_bytes!("../../lever/target/deploy/quasar_lever.so"); |
| 15 | + QuasarSvm::new() |
| 16 | + .with_program(&Pubkey::from(crate::ID), hand_elf) |
| 17 | + .with_program(&lever_program_id(), lever_elf) |
| 18 | +} |
| 19 | + |
| 20 | +fn power_account(address: Pubkey, is_on: bool) -> Account { |
| 21 | + // Account data: [discriminator: u8] [is_on: u8] |
| 22 | + let data = vec![POWER_STATUS_DISCRIMINATOR, if is_on { 1 } else { 0 }]; |
| 23 | + Account { |
| 24 | + address, |
| 25 | + lamports: 1_000_000_000, |
| 26 | + data, |
| 27 | + owner: lever_program_id(), |
| 28 | + executable: false, |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +/// Build pull_lever instruction data (discriminator = 0). |
| 33 | +/// Wire format: [disc=0] [name: String] |
| 34 | +fn build_pull_lever(name: &str) -> Vec<u8> { |
| 35 | + let mut data = vec![0u8]; // discriminator = 0 |
| 36 | + data.extend_from_slice(&(name.len() as u32).to_le_bytes()); |
| 37 | + data.extend_from_slice(name.as_bytes()); |
| 38 | + data |
| 39 | +} |
| 40 | + |
| 41 | +#[test] |
| 42 | +fn test_pull_lever_turns_on() { |
| 43 | + let mut svm = setup(); |
| 44 | + |
| 45 | + let (power_addr, _bump) = Pubkey::find_program_address(&[b"power"], &lever_program_id()); |
| 46 | + |
| 47 | + let ix = Instruction { |
| 48 | + program_id: Pubkey::from(crate::ID), |
| 49 | + accounts: vec![ |
| 50 | + solana_instruction::AccountMeta::new( |
| 51 | + Address::from(power_addr.to_bytes()), |
| 52 | + false, |
| 53 | + ), |
| 54 | + solana_instruction::AccountMeta::new_readonly( |
| 55 | + Address::from(lever_program_id().to_bytes()), |
| 56 | + false, |
| 57 | + ), |
| 58 | + ], |
| 59 | + data: build_pull_lever("Alice"), |
| 60 | + }; |
| 61 | + |
| 62 | + // The lever program account is provided by the SVM (loaded via with_program). |
| 63 | + // Only the power data account needs to be passed explicitly. |
| 64 | + let result = svm.process_instruction( |
| 65 | + &ix, |
| 66 | + &[power_account(power_addr, false)], |
| 67 | + ); |
| 68 | + |
| 69 | + result.assert_success(); |
| 70 | + |
| 71 | + let logs = result.logs.join("\n"); |
| 72 | + assert!(logs.contains("Hand is pulling"), "hand should log"); |
| 73 | + assert!(logs.contains("pulling the power switch"), "lever should log"); |
| 74 | + assert!(logs.contains("now on"), "power should turn on"); |
| 75 | + |
| 76 | + let account = result.account(&power_addr).unwrap(); |
| 77 | + assert_eq!(account.data[1], 1, "power should be on"); |
| 78 | +} |
| 79 | + |
| 80 | +#[test] |
| 81 | +fn test_pull_lever_turns_off() { |
| 82 | + let mut svm = setup(); |
| 83 | + |
| 84 | + let (power_addr, _bump) = Pubkey::find_program_address(&[b"power"], &lever_program_id()); |
| 85 | + |
| 86 | + let ix = Instruction { |
| 87 | + program_id: Pubkey::from(crate::ID), |
| 88 | + accounts: vec![ |
| 89 | + solana_instruction::AccountMeta::new( |
| 90 | + Address::from(power_addr.to_bytes()), |
| 91 | + false, |
| 92 | + ), |
| 93 | + solana_instruction::AccountMeta::new_readonly( |
| 94 | + Address::from(lever_program_id().to_bytes()), |
| 95 | + false, |
| 96 | + ), |
| 97 | + ], |
| 98 | + data: build_pull_lever("Bob"), |
| 99 | + }; |
| 100 | + |
| 101 | + let result = svm.process_instruction( |
| 102 | + &ix, |
| 103 | + &[power_account(power_addr, true)], |
| 104 | + ); |
| 105 | + |
| 106 | + result.assert_success(); |
| 107 | + |
| 108 | + let logs = result.logs.join("\n"); |
| 109 | + assert!(logs.contains("now off"), "power should turn off"); |
| 110 | + |
| 111 | + let account = result.account(&power_addr).unwrap(); |
| 112 | + assert_eq!(account.data[1], 0, "power should be off"); |
| 113 | +} |
0 commit comments