Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit a5c4b1e

Browse files
authored
Switch shared-mem tests to programtest (#1611)
1 parent 589da55 commit a5c4b1e

File tree

3 files changed

+143
-137
lines changed

3 files changed

+143
-137
lines changed

Cargo.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shared-memory/program/Cargo.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ repository = "https://github.com/solana-labs/solana-program-library"
77
license = "Apache-2.0"
88
edition = "2018"
99

10+
[features]
11+
test-bpf = []
12+
1013
[dependencies]
1114
arrayref = "0.3.6"
12-
solana-program = "1.6.2"
15+
solana-program = "=1.6.2"
1316

1417
[dev-dependencies]
15-
solana-bpf-loader-program = "1.6.2"
16-
solana-sdk = "1.6.2"
17-
solana_rbpf = "0.2"
18+
solana-program-test = "=1.6.2"
19+
solana-sdk = "=1.6.2"
1820

1921
[lib]
2022
crate-type = ["cdylib", "lib"]
Lines changed: 136 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,180 +1,185 @@
1-
use solana_bpf_loader_program::serialization::serialize_parameters;
2-
use solana_program::{
3-
bpf_loader, entrypoint::SUCCESS, program_error::ProgramError, pubkey::Pubkey,
4-
};
5-
use solana_sdk::{account::AccountSharedData, keyed_account::KeyedAccount};
6-
use spl_shared_memory::entrypoint;
7-
8-
// TODO: Rework `assert_instruction_count` test to use solana-program-test, avoiding the need to
9-
// link directly with the BPF VM
10-
/*
11-
fn load_program(name: &str) -> Vec<u8> {
12-
let mut file =
13-
File::open(&name).unwrap_or_else(|err| panic!("Unable to open {}: {}", name, err));
1+
// Program test does not support calling a raw program entrypoint, only `process_instruction`
2+
#![cfg(feature = "test-bpf")]
143

15-
let mut program = Vec::new();
16-
file.read_to_end(&mut program).unwrap();
17-
program
18-
}
19-
20-
fn run_program(
21-
program_id: &Pubkey,
22-
parameter_accounts: &[KeyedAccount],
23-
instruction_data: &[u8],
24-
) -> u64 {
25-
let program_account = Account {
26-
data: load_program("../../target/deploy/spl_shared_memory.so"),
27-
..Account::default()
28-
};
29-
let loader_id = bpf_loader::id();
30-
let mut invoke_context = MockInvokeContext::default();
31-
let executable = EbpfVm::<solana_bpf_loader_program::BPFError>::create_executable_from_elf(
32-
&&program_account.data,
33-
None,
34-
)
35-
.unwrap();
36-
let (mut vm, heap_region) = create_vm(
37-
&loader_id,
38-
executable.as_ref(),
39-
parameter_accounts,
40-
&mut invoke_context,
41-
)
42-
.unwrap();
43-
let mut parameter_bytes = serialize_parameters(
44-
&loader_id,
45-
program_id,
46-
parameter_accounts,
47-
&instruction_data,
48-
)
49-
.unwrap();
50-
assert_eq!(
51-
SUCCESS,
52-
vm.execute_program(parameter_bytes.as_mut_slice(), &[], &[heap_region])
53-
.unwrap()
54-
);
55-
deserialize_parameters(&loader_id, parameter_accounts, &parameter_bytes).unwrap();
56-
vm.get_total_instruction_count()
57-
}
4+
use solana_program_test::*;
5+
use solana_sdk::{
6+
account::Account,
7+
instruction::InstructionError,
8+
instruction::{AccountMeta, Instruction},
9+
pubkey::Pubkey,
10+
signature::Signer,
11+
transaction::{Transaction, TransactionError},
12+
};
5813

59-
#[test]
60-
fn assert_instruction_count() {
14+
#[tokio::test]
15+
async fn assert_instruction_count() {
6116
const OFFSET: usize = 51;
6217
const NUM_TO_SHARE: usize = 500;
6318
let program_id = Pubkey::new_unique();
6419
let shared_key = Pubkey::new_unique();
65-
let shared_account = Account::new_ref(u64::MAX, OFFSET + NUM_TO_SHARE * 2, &program_id);
6620

67-
// Send some data to share
68-
let parameter_accounts = vec![KeyedAccount::new(&shared_key, true, &shared_account)];
21+
let mut program_test = ProgramTest::new(
22+
"spl_shared_memory", // Run the BPF version with `cargo test-bpf`
23+
program_id,
24+
None,
25+
);
26+
program_test.add_account(
27+
shared_key,
28+
Account {
29+
lamports: 5000000000000,
30+
data: vec![0_u8; NUM_TO_SHARE * 2],
31+
owner: program_id,
32+
..Account::default()
33+
},
34+
);
35+
program_test.set_bpf_compute_max_units(480);
36+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
37+
38+
// success
6939
let content = vec![42; NUM_TO_SHARE];
7040
let mut instruction_data = OFFSET.to_le_bytes().to_vec();
7141
instruction_data.extend_from_slice(&content);
72-
let share_count = run_program(&program_id, &parameter_accounts[..], &instruction_data);
73-
const BASELINE_COUNT: u64 = 1474; // 113 if NUM_TO_SHARE is 8
74-
println!(
75-
"BPF instructions executed {:?} (expected {:?})",
76-
share_count, BASELINE_COUNT
77-
);
78-
assert_eq!(
79-
&shared_account.borrow().data[OFFSET..OFFSET + NUM_TO_SHARE],
80-
content
42+
let mut transaction = Transaction::new_with_payer(
43+
&[Instruction::new_with_bytes(
44+
program_id,
45+
&instruction_data,
46+
vec![AccountMeta::new(shared_key, false)],
47+
)],
48+
Some(&payer.pubkey()),
8149
);
82-
assert!(share_count <= BASELINE_COUNT);
50+
transaction.sign(&[&payer], recent_blockhash);
51+
banks_client.process_transaction(transaction).await.unwrap();
8352
}
84-
*/
8553

86-
#[test]
87-
fn test_share_data() {
54+
#[tokio::test]
55+
async fn test_helloworld() {
8856
const OFFSET: usize = 51;
8957
const NUM_TO_SHARE: usize = 500;
90-
let program_id = Pubkey::new(&[0; 32]);
58+
let program_id = Pubkey::new_unique();
9159
let shared_key = Pubkey::new_unique();
92-
let shared_account = AccountSharedData::new_ref(u64::MAX, NUM_TO_SHARE * 2, &program_id);
60+
61+
let mut program_test = ProgramTest::new(
62+
"spl_shared_memory", // Run the BPF version with `cargo test-bpf`
63+
program_id,
64+
None,
65+
);
66+
program_test.add_account(
67+
shared_key,
68+
Account {
69+
lamports: 5000000000000,
70+
data: vec![0_u8; NUM_TO_SHARE * 2],
71+
owner: program_id,
72+
..Account::default()
73+
},
74+
);
75+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
9376

9477
// success
9578
let content = vec![42; NUM_TO_SHARE];
9679
let mut instruction_data = OFFSET.to_le_bytes().to_vec();
9780
instruction_data.extend_from_slice(&content);
98-
let keyed_accounts = vec![KeyedAccount::new(&shared_key, true, &shared_account)];
99-
let mut input = serialize_parameters(
100-
&bpf_loader::id(),
101-
&program_id,
102-
&keyed_accounts,
103-
&instruction_data,
104-
)
105-
.unwrap();
106-
assert_eq!(unsafe { entrypoint(input.as_mut_ptr()) }, SUCCESS);
81+
let mut transaction = Transaction::new_with_payer(
82+
&[Instruction::new_with_bytes(
83+
program_id,
84+
&instruction_data,
85+
vec![AccountMeta::new(shared_key, false)],
86+
)],
87+
Some(&payer.pubkey()),
88+
);
89+
transaction.sign(&[&payer], recent_blockhash);
90+
banks_client.process_transaction(transaction).await.unwrap();
10791

10892
// success zero offset
10993
let content = vec![42; NUM_TO_SHARE];
11094
let mut instruction_data = 0_usize.to_le_bytes().to_vec();
11195
instruction_data.extend_from_slice(&content);
112-
let keyed_accounts = vec![KeyedAccount::new(&shared_key, true, &shared_account)];
113-
let mut input = serialize_parameters(
114-
&bpf_loader::id(),
115-
&program_id,
116-
&keyed_accounts,
117-
&instruction_data,
118-
)
119-
.unwrap();
120-
assert_eq!(unsafe { entrypoint(input.as_mut_ptr()) }, SUCCESS);
96+
let mut transaction = Transaction::new_with_payer(
97+
&[Instruction::new_with_bytes(
98+
program_id,
99+
&instruction_data,
100+
vec![AccountMeta::new(shared_key, false)],
101+
)],
102+
Some(&payer.pubkey()),
103+
);
104+
transaction.sign(&[&payer], recent_blockhash);
105+
banks_client.process_transaction(transaction).await.unwrap();
121106

122107
// too few accounts
123-
let mut input =
124-
serialize_parameters(&bpf_loader::id(), &program_id, &[], &instruction_data).unwrap();
108+
let content = vec![42; NUM_TO_SHARE];
109+
let mut instruction_data = OFFSET.to_le_bytes().to_vec();
110+
instruction_data.extend_from_slice(&content);
111+
let mut transaction = Transaction::new_with_payer(
112+
&[Instruction::new_with_bytes(
113+
program_id,
114+
&instruction_data,
115+
vec![],
116+
)],
117+
Some(&payer.pubkey()),
118+
);
119+
transaction.sign(&[&payer], recent_blockhash);
120+
let result = banks_client.process_transaction(transaction).await;
125121
assert_eq!(
126-
unsafe { entrypoint(input.as_mut_ptr()) },
127-
u64::from(ProgramError::NotEnoughAccountKeys)
122+
result.unwrap_err().unwrap(),
123+
TransactionError::InstructionError(0, InstructionError::NotEnoughAccountKeys)
128124
);
129125

130126
// too many accounts
131-
let keyed_accounts = vec![
132-
KeyedAccount::new(&shared_key, true, &shared_account),
133-
KeyedAccount::new(&shared_key, true, &shared_account),
134-
];
135-
let mut input = serialize_parameters(
136-
&bpf_loader::id(),
137-
&program_id,
138-
&keyed_accounts,
139-
&instruction_data,
140-
)
141-
.unwrap();
127+
let content = vec![42; NUM_TO_SHARE];
128+
let mut instruction_data = OFFSET.to_le_bytes().to_vec();
129+
instruction_data.extend_from_slice(&content);
130+
let mut transaction = Transaction::new_with_payer(
131+
&[Instruction::new_with_bytes(
132+
program_id,
133+
&instruction_data,
134+
vec![
135+
AccountMeta::new(shared_key, false),
136+
AccountMeta::new(shared_key, false),
137+
],
138+
)],
139+
Some(&payer.pubkey()),
140+
);
141+
transaction.sign(&[&payer], recent_blockhash);
142+
let result = banks_client.process_transaction(transaction).await;
142143
assert_eq!(
143-
unsafe { entrypoint(input.as_mut_ptr()) },
144-
u64::from(ProgramError::InvalidArgument)
144+
result.unwrap_err().unwrap(),
145+
TransactionError::InstructionError(0, InstructionError::InvalidArgument)
145146
);
146147

147148
// account data too small
148-
let keyed_accounts = vec![KeyedAccount::new(&shared_key, true, &shared_account)];
149149
let content = vec![42; NUM_TO_SHARE * 10];
150150
let mut instruction_data = OFFSET.to_le_bytes().to_vec();
151151
instruction_data.extend_from_slice(&content);
152-
let mut input = serialize_parameters(
153-
&bpf_loader::id(),
154-
&program_id,
155-
&keyed_accounts,
156-
&instruction_data,
157-
)
158-
.unwrap();
152+
let mut transaction = Transaction::new_with_payer(
153+
&[Instruction::new_with_bytes(
154+
program_id,
155+
&instruction_data,
156+
vec![AccountMeta::new(shared_key, false)],
157+
)],
158+
Some(&payer.pubkey()),
159+
);
160+
transaction.sign(&[&payer], recent_blockhash);
161+
let result = banks_client.process_transaction(transaction).await;
159162
assert_eq!(
160-
unsafe { entrypoint(input.as_mut_ptr()) },
161-
u64::from(ProgramError::AccountDataTooSmall)
163+
result.unwrap_err().unwrap(),
164+
TransactionError::InstructionError(0, InstructionError::AccountDataTooSmall)
162165
);
163166

164167
// offset too large
165-
let keyed_accounts = vec![KeyedAccount::new(&shared_key, true, &shared_account)];
166168
let content = vec![42; NUM_TO_SHARE];
167169
let mut instruction_data = (OFFSET * 10).to_le_bytes().to_vec();
168170
instruction_data.extend_from_slice(&content);
169-
let mut input = serialize_parameters(
170-
&bpf_loader::id(),
171-
&program_id,
172-
&keyed_accounts,
173-
&instruction_data,
174-
)
175-
.unwrap();
171+
let mut transaction = Transaction::new_with_payer(
172+
&[Instruction::new_with_bytes(
173+
program_id,
174+
&instruction_data,
175+
vec![AccountMeta::new(shared_key, false)],
176+
)],
177+
Some(&payer.pubkey()),
178+
);
179+
transaction.sign(&[&payer], recent_blockhash);
180+
let result = banks_client.process_transaction(transaction).await;
176181
assert_eq!(
177-
unsafe { entrypoint(input.as_mut_ptr()) },
178-
u64::from(ProgramError::AccountDataTooSmall)
182+
result.unwrap_err().unwrap(),
183+
TransactionError::InstructionError(0, InstructionError::AccountDataTooSmall)
179184
);
180185
}

0 commit comments

Comments
 (0)