Skip to content

Commit 3aa419a

Browse files
feat: add LiteSVM Rust tests for all Anchor programs
Adds Rust integration tests using LiteSVM and solana-kite for all 46 Anchor programs. These run via anchor test → cargo test. Existing TypeScript tests preserved — this PR only adds the Rust test files, updates Cargo.toml dev-dependencies, and changes the Anchor.toml test script. Based on anchor-10-existing-tests (#558).
1 parent 1fb50ed commit 3aa419a

File tree

137 files changed

+7176
-45
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+7176
-45
lines changed

basics/account-data/anchor/Anchor.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ cluster = "Localnet"
1515
wallet = "~/.config/solana/id.json"
1616

1717
[scripts]
18-
test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
18+
test = "cargo test"
1919
litesvm-test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/litesvm.test.ts" #For litesvm test

basics/account-data/anchor/programs/anchor-program-example/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,12 @@ custom-panic = []
2222
[dependencies]
2323
anchor-lang = "1.0.0"
2424

25+
[dev-dependencies]
26+
litesvm = "0.11.0"
27+
solana-signer = "3.0.0"
28+
solana-keypair = "3.0.1"
29+
borsh = "1.6.1"
30+
solana-kite = "0.3.0"
31+
2532
[lints.rust]
2633
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use {
2+
anchor_lang::{
3+
solana_program::{instruction::Instruction, system_program},
4+
AnchorSerialize, InstructionData, ToAccountMetas,
5+
},
6+
borsh::BorshDeserialize,
7+
litesvm::LiteSVM,
8+
solana_keypair::Keypair,
9+
solana_kite::{create_wallet, send_transaction_from_instructions},
10+
solana_signer::Signer,
11+
};
12+
13+
/// Deserialize the AddressInfo account (8-byte discriminator + fields).
14+
#[derive(BorshDeserialize)]
15+
struct AddressInfoAccount {
16+
_discriminator: [u8; 8],
17+
name: String,
18+
house_number: u8,
19+
street: String,
20+
city: String,
21+
}
22+
23+
#[test]
24+
fn test_create_address_info() {
25+
let program_id = account_data_anchor_program::id();
26+
let mut svm = LiteSVM::new();
27+
let bytes = include_bytes!("../../../target/deploy/account_data_anchor_program.so");
28+
svm.add_program(program_id, bytes).unwrap();
29+
let payer = create_wallet(&mut svm, 10_000_000_000).unwrap();
30+
31+
let address_info_keypair = Keypair::new();
32+
33+
let instruction = Instruction::new_with_bytes(
34+
program_id,
35+
&account_data_anchor_program::instruction::CreateAddressInfo {
36+
name: "Joe C".to_string(),
37+
house_number: 136,
38+
street: "Mile High Dr.".to_string(),
39+
city: "Solana Beach".to_string(),
40+
}
41+
.data(),
42+
account_data_anchor_program::accounts::CreateAddressInfo {
43+
payer: payer.pubkey(),
44+
address_info: address_info_keypair.pubkey(),
45+
system_program: system_program::id(),
46+
}
47+
.to_account_metas(None),
48+
);
49+
50+
send_transaction_from_instructions(
51+
&mut svm,
52+
vec![instruction],
53+
&[&payer, &address_info_keypair],
54+
&payer.pubkey(),
55+
)
56+
.unwrap();
57+
58+
// Read the account data back
59+
let account = svm.get_account(&address_info_keypair.pubkey()).unwrap();
60+
let info = AddressInfoAccount::deserialize(&mut &account.data[..]).unwrap();
61+
62+
assert_eq!(info.name, "Joe C");
63+
assert_eq!(info.house_number, 136);
64+
assert_eq!(info.street, "Mile High Dr.");
65+
assert_eq!(info.city, "Solana Beach");
66+
}

basics/checking-accounts/anchor/Anchor.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ cluster = "localnet"
1313
wallet = "~/.config/solana/id.json"
1414

1515
[scripts]
16-
test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
16+
test = "cargo test"

basics/checking-accounts/anchor/programs/anchor-program-example/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,12 @@ custom-panic = []
2222
[dependencies]
2323
anchor-lang = "1.0.0"
2424

25+
[dev-dependencies]
26+
litesvm = "0.11.0"
27+
solana-signer = "3.0.0"
28+
solana-keypair = "3.0.1"
29+
borsh = "1.6.1"
30+
solana-kite = "0.3.0"
31+
2532
[lints.rust]
2633
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use {
2+
anchor_lang::{
3+
solana_program::{instruction::Instruction, system_instruction, system_program},
4+
InstructionData, ToAccountMetas,
5+
},
6+
litesvm::LiteSVM,
7+
solana_keypair::Keypair,
8+
solana_kite::{create_wallet, send_transaction_from_instructions},
9+
solana_signer::Signer,
10+
};
11+
12+
#[test]
13+
fn test_check_accounts() {
14+
let program_id = checking_account_program::id();
15+
let mut svm = LiteSVM::new();
16+
let bytes = include_bytes!("../../../target/deploy/checking_account_program.so");
17+
svm.add_program(program_id, bytes).unwrap();
18+
let payer = create_wallet(&mut svm, 10_000_000_000).unwrap();
19+
20+
let account_to_change = Keypair::new();
21+
let account_to_create = Keypair::new();
22+
23+
// First, create an account owned by our program (like the TS test does)
24+
let rent_exempt_balance = svm.minimum_balance_for_rent_exemption(0);
25+
let create_account_ix = system_instruction::create_account(
26+
&payer.pubkey(),
27+
&account_to_change.pubkey(),
28+
rent_exempt_balance,
29+
0,
30+
&program_id,
31+
);
32+
send_transaction_from_instructions(
33+
&mut svm,
34+
vec![create_account_ix],
35+
&[&payer, &account_to_change],
36+
&payer.pubkey(),
37+
)
38+
.unwrap();
39+
40+
svm.expire_blockhash();
41+
42+
// Now call check_accounts
43+
let check_accounts_ix = Instruction::new_with_bytes(
44+
program_id,
45+
&checking_account_program::instruction::CheckAccounts {}.data(),
46+
checking_account_program::accounts::CheckingAccounts {
47+
payer: payer.pubkey(),
48+
account_to_create: account_to_create.pubkey(),
49+
account_to_change: account_to_change.pubkey(),
50+
system_program: system_program::id(),
51+
}
52+
.to_account_metas(None),
53+
);
54+
send_transaction_from_instructions(
55+
&mut svm,
56+
vec![check_accounts_ix],
57+
&[&payer],
58+
&payer.pubkey(),
59+
)
60+
.unwrap();
61+
}

basics/close-account/anchor/Anchor.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ cluster = "Localnet"
1515
wallet = "~/.config/solana/id.json"
1616

1717
[scripts]
18-
test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
18+
test = "cargo test"

basics/close-account/anchor/programs/close-account/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,11 @@ custom-panic = []
2222
[dependencies]
2323
anchor-lang = "1.0.0"
2424

25+
[dev-dependencies]
26+
litesvm = "0.11.0"
27+
solana-signer = "3.0.0"
28+
solana-keypair = "3.0.1"
29+
solana-kite = "0.3.0"
30+
2531
[lints.rust]
2632
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use {
2+
anchor_lang::{
3+
solana_program::{instruction::Instruction, pubkey::Pubkey, system_program},
4+
InstructionData, ToAccountMetas,
5+
},
6+
litesvm::LiteSVM,
7+
solana_keypair::Keypair,
8+
solana_kite::{create_wallet, send_transaction_from_instructions},
9+
solana_signer::Signer,
10+
};
11+
12+
fn setup() -> (LiteSVM, Keypair) {
13+
let program_id = close_account_program::id();
14+
let mut svm = LiteSVM::new();
15+
let bytes = include_bytes!("../../../target/deploy/close_account_program.so");
16+
svm.add_program(program_id, bytes).unwrap();
17+
let payer = create_wallet(&mut svm, 10_000_000_000).unwrap();
18+
(svm, payer)
19+
}
20+
21+
#[test]
22+
fn test_create_and_close_user() {
23+
let (mut svm, payer) = setup();
24+
let program_id = close_account_program::id();
25+
26+
// Derive the PDA for the user's account
27+
let (user_account_pda, _bump) =
28+
Pubkey::find_program_address(&[b"USER", payer.pubkey().as_ref()], &program_id);
29+
30+
// Create user
31+
let create_ix = Instruction::new_with_bytes(
32+
program_id,
33+
&close_account_program::instruction::CreateUser {
34+
name: "John Doe".to_string(),
35+
}
36+
.data(),
37+
close_account_program::accounts::CreateUserContext {
38+
user: payer.pubkey(),
39+
user_account: user_account_pda,
40+
system_program: system_program::id(),
41+
}
42+
.to_account_metas(None),
43+
);
44+
send_transaction_from_instructions(&mut svm, vec![create_ix], &[&payer], &payer.pubkey())
45+
.unwrap();
46+
47+
// Verify account exists and has correct data
48+
let account = svm
49+
.get_account(&user_account_pda)
50+
.expect("Account should exist after creation");
51+
assert!(account.data.len() > 0, "Account should have data");
52+
53+
svm.expire_blockhash();
54+
55+
// Close user
56+
let close_ix = Instruction::new_with_bytes(
57+
program_id,
58+
&close_account_program::instruction::CloseUser {}.data(),
59+
close_account_program::accounts::CloseUserContext {
60+
user: payer.pubkey(),
61+
user_account: user_account_pda,
62+
}
63+
.to_account_metas(None),
64+
);
65+
send_transaction_from_instructions(&mut svm, vec![close_ix], &[&payer], &payer.pubkey())
66+
.unwrap();
67+
68+
// Verify account is closed
69+
let account = svm.get_account(&user_account_pda);
70+
assert!(account.is_none(), "Account should be closed");
71+
}

basics/counter/anchor/Anchor.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ cluster = "Localnet"
1515
wallet = "~/.config/solana/id.json"
1616

1717
[scripts]
18-
test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
18+
test = "cargo test"

0 commit comments

Comments
 (0)