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

Commit c01db92

Browse files
committed
single-pool: improve tests
* allow minimum delegation to be disabled, and do this by default * test initialize, deposit, and withdraw with and without minimum * test that deposit and withdraw work with sub-minium values * test that initialize fails with a sub-minimum starting amount
1 parent 2cefc84 commit c01db92

File tree

9 files changed

+151
-53
lines changed

9 files changed

+151
-53
lines changed

single-pool/program/tests/accounts.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ async fn build_instructions(
5959
.await;
6060

6161
let rent = context.banks_client.get_rent().await.unwrap();
62-
let minimum_delegation = get_minimum_delegation(
62+
let minimum_delegation = get_pool_minimum_delegation(
6363
&mut context.banks_client,
6464
&context.payer,
6565
&context.last_blockhash,
@@ -145,7 +145,7 @@ async fn build_instructions(
145145
#[test_case(TestMode::Withdraw; "withdraw")]
146146
#[tokio::test]
147147
async fn fail_account_checks(test_mode: TestMode) {
148-
let mut context = program_test().start_with_context().await;
148+
let mut context = program_test(false).start_with_context().await;
149149
let accounts = SinglePoolAccounts::default();
150150
let (instructions, i) = build_instructions(&mut context, &accounts, test_mode).await;
151151

single-pool/program/tests/create_pool_token_metadata.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fn assert_metadata(vote_account: &Pubkey, metadata: &Metadata) {
2424

2525
#[tokio::test]
2626
async fn success() {
27-
let mut context = program_test().start_with_context().await;
27+
let mut context = program_test(false).start_with_context().await;
2828
let accounts = SinglePoolAccounts::default();
2929
accounts.initialize(&mut context).await;
3030

@@ -34,7 +34,7 @@ async fn success() {
3434

3535
#[tokio::test]
3636
async fn fail_double_init() {
37-
let mut context = program_test().start_with_context().await;
37+
let mut context = program_test(false).start_with_context().await;
3838
let accounts = SinglePoolAccounts::default();
3939
accounts.initialize(&mut context).await;
4040
refresh_blockhash(&mut context).await;

single-pool/program/tests/deposit.rs

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,32 @@ use {
1919
test_case::test_case,
2020
};
2121

22-
#[test_case(true, 0, false; "activated")]
23-
#[test_case(false, 0, false; "activating")]
24-
#[test_case(true, 100_000, false; "activated_extra")]
25-
#[test_case(false, 100_000, false; "activating_extra")]
26-
#[test_case(true, 0, true; "activated_second")]
27-
#[test_case(false, 0, true; "activating_second")]
22+
#[test_case(true, 0, false, false, false; "activated::minimum_disabled")]
23+
#[test_case(true, 0, false, false, true; "activated::minimum_disabled::small")]
24+
#[test_case(true, 0, false, true, false; "activated::minimum_enabled")]
25+
#[test_case(false, 0, false, false, false; "activating::minimum_disabled")]
26+
#[test_case(false, 0, false, false, true; "activating::minimum_disabled::small")]
27+
#[test_case(false, 0, false, true, false; "activating::minimum_enabled")]
28+
#[test_case(true, 100_000, false, false, false; "activated::extra")]
29+
#[test_case(false, 100_000, false, false, false; "activating::extra")]
30+
#[test_case(true, 0, true, false, false; "activated::second")]
31+
#[test_case(false, 0, true, false, false; "activating::second")]
2832
#[tokio::test]
29-
async fn success(activate: bool, extra_lamports: u64, prior_deposit: bool) {
30-
let mut context = program_test().start_with_context().await;
33+
async fn success(
34+
activate: bool,
35+
extra_lamports: u64,
36+
prior_deposit: bool,
37+
enable_minimum_delegation: bool,
38+
small_deposit: bool,
39+
) {
40+
let mut context = program_test(enable_minimum_delegation)
41+
.start_with_context()
42+
.await;
3143
let accounts = SinglePoolAccounts::default();
3244
accounts
3345
.initialize_for_deposit(
3446
&mut context,
35-
TEST_STAKE_AMOUNT,
47+
if small_deposit { 1 } else { TEST_STAKE_AMOUNT },
3648
if prior_deposit {
3749
Some(TEST_STAKE_AMOUNT * 10)
3850
} else {
@@ -158,11 +170,17 @@ async fn success(activate: bool, extra_lamports: u64, prior_deposit: bool) {
158170
);
159171
}
160172

161-
#[test_case(true; "activated")]
162-
#[test_case(false; "activating")]
173+
#[test_case(true, false, false; "activated::minimum_disabled")]
174+
#[test_case(true, false, true; "activated::minimum_disabled::small")]
175+
#[test_case(true, true, false; "activated::minimum_enabled")]
176+
#[test_case(false, false, false; "activating::minimum_disabled")]
177+
#[test_case(false, false, true; "activating::minimum_disabled::small")]
178+
#[test_case(false, true, false; "activating::minimum_enabled")]
163179
#[tokio::test]
164-
async fn success_with_seed(activate: bool) {
165-
let mut context = program_test().start_with_context().await;
180+
async fn success_with_seed(activate: bool, enable_minimum_delegation: bool, small_deposit: bool) {
181+
let mut context = program_test(enable_minimum_delegation)
182+
.start_with_context()
183+
.await;
166184
let accounts = SinglePoolAccounts::default();
167185
let rent = context.banks_client.get_rent().await.unwrap();
168186
let minimum_stake = accounts.initialize(&mut context).await;
@@ -174,7 +192,7 @@ async fn success_with_seed(activate: bool) {
174192
&accounts.vote_account.pubkey(),
175193
&accounts.alice.pubkey(),
176194
&rent,
177-
minimum_stake,
195+
if small_deposit { 1 } else { minimum_stake },
178196
);
179197
let transaction = Transaction::new_signed_with_payer(
180198
&instructions,
@@ -261,7 +279,7 @@ async fn success_with_seed(activate: bool) {
261279
#[test_case(false; "activating")]
262280
#[tokio::test]
263281
async fn fail_uninitialized(activate: bool) {
264-
let mut context = program_test().start_with_context().await;
282+
let mut context = program_test(false).start_with_context().await;
265283
let accounts = SinglePoolAccounts::default();
266284
let stake_account = Keypair::new();
267285

@@ -331,13 +349,13 @@ async fn fail_uninitialized(activate: bool) {
331349
check_error(e, SinglePoolError::InvalidPoolAccount);
332350
}
333351

334-
#[test_case(true, true; "activated_automorph")]
335-
#[test_case(false, true; "activating_automorph")]
336-
#[test_case(true, false; "activated_unauth")]
337-
#[test_case(false, false; "activating_unauth")]
352+
#[test_case(true, true; "activated::automorph")]
353+
#[test_case(false, true; "activating::automorph")]
354+
#[test_case(true, false; "activated::unauth")]
355+
#[test_case(false, false; "activating::unauth")]
338356
#[tokio::test]
339357
async fn fail_bad_account(activate: bool, automorph: bool) {
340-
let mut context = program_test().start_with_context().await;
358+
let mut context = program_test(false).start_with_context().await;
341359
let accounts = SinglePoolAccounts::default();
342360
accounts
343361
.initialize_for_deposit(&mut context, TEST_STAKE_AMOUNT, None)
@@ -382,10 +400,10 @@ async fn fail_bad_account(activate: bool, automorph: bool) {
382400
#[test_case(false; "user_active")]
383401
#[tokio::test]
384402
async fn fail_activation_mismatch(pool_first: bool) {
385-
let mut context = program_test().start_with_context().await;
403+
let mut context = program_test(false).start_with_context().await;
386404
let accounts = SinglePoolAccounts::default();
387405

388-
let minimum_delegation = get_minimum_delegation(
406+
let minimum_delegation = get_pool_minimum_delegation(
389407
&mut context.banks_client,
390408
&context.payer,
391409
&context.last_blockhash,

single-pool/program/tests/helpers/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use {
44
solana_program_test::*,
55
solana_sdk::{
66
account::Account as SolanaAccount,
7+
feature_set::stake_raise_minimum_delegation_to_1_sol,
78
hash::Hash,
89
program_error::ProgramError,
910
pubkey::Pubkey,
@@ -34,13 +35,17 @@ pub use stake::*;
3435
pub const FIRST_NORMAL_EPOCH: u64 = 15;
3536
pub const USER_STARTING_LAMPORTS: u64 = 10_000_000_000_000; // 10k sol
3637

37-
pub fn program_test() -> ProgramTest {
38+
pub fn program_test(enable_minimum_delegation: bool) -> ProgramTest {
3839
let mut program_test = ProgramTest::default();
39-
program_test.add_program("mpl_token_metadata", inline_mpl_token_metadata::id(), None);
4040

41+
program_test.add_program("mpl_token_metadata", inline_mpl_token_metadata::id(), None);
4142
program_test.add_program("spl_single_pool", id(), processor!(Processor::process));
42-
4343
program_test.prefer_bpf(false);
44+
45+
if !enable_minimum_delegation {
46+
program_test.deactivate_feature(stake_raise_minimum_delegation_to_1_sol::id());
47+
}
48+
4449
program_test
4550
}
4651

@@ -227,7 +232,7 @@ impl SinglePoolAccounts {
227232
.await;
228233

229234
let rent = context.banks_client.get_rent().await.unwrap();
230-
let minimum_delegation = get_minimum_delegation(
235+
let minimum_delegation = get_pool_minimum_delegation(
231236
&mut context.banks_client,
232237
&context.payer,
233238
&context.last_blockhash,

single-pool/program/tests/helpers/stake.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use {
66
solana_program_test::BanksClient,
77
solana_sdk::{
88
hash::Hash,
9+
native_token::LAMPORTS_PER_SOL,
910
pubkey::Pubkey,
1011
signature::{Keypair, Signer},
1112
stake::{
@@ -38,7 +39,7 @@ pub async fn get_stake_account_rent(banks_client: &mut BanksClient) -> u64 {
3839
rent.minimum_balance(std::mem::size_of::<stake::state::StakeStateV2>())
3940
}
4041

41-
pub async fn get_minimum_delegation(
42+
pub async fn get_pool_minimum_delegation(
4243
banks_client: &mut BanksClient,
4344
payer: &Keypair,
4445
recent_blockhash: &Hash,
@@ -59,7 +60,9 @@ pub async fn get_minimum_delegation(
5960
.unwrap()
6061
.data;
6162
data.resize(8, 0);
62-
data.try_into().map(u64::from_le_bytes).unwrap()
63+
let stake_program_minimum = data.try_into().map(u64::from_le_bytes).unwrap();
64+
65+
std::cmp::max(stake_program_minimum, LAMPORTS_PER_SOL)
6366
}
6467

6568
#[allow(clippy::too_many_arguments)]

single-pool/program/tests/initialize.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@ use {
99
solana_sdk::{program_pack::Pack, signature::Signer, stake, transaction::Transaction},
1010
spl_single_pool::{error::SinglePoolError, id, instruction},
1111
spl_token::state::Mint,
12+
test_case::test_case,
1213
};
1314

15+
#[test_case(true; "minimum_enabled")]
16+
#[test_case(false; "minimum_disabled")]
1417
#[tokio::test]
15-
async fn success() {
16-
let mut context = program_test().start_with_context().await;
18+
async fn success(enable_minimum_delegation: bool) {
19+
let mut context = program_test(enable_minimum_delegation)
20+
.start_with_context()
21+
.await;
1722
let accounts = SinglePoolAccounts::default();
1823
accounts.initialize(&mut context).await;
1924

@@ -28,7 +33,7 @@ async fn success() {
2833

2934
#[tokio::test]
3035
async fn fail_double_init() {
31-
let mut context = program_test().start_with_context().await;
36+
let mut context = program_test(false).start_with_context().await;
3237
let accounts = SinglePoolAccounts::default();
3338
let minimum_delegation = accounts.initialize(&mut context).await;
3439
refresh_blockhash(&mut context).await;
@@ -56,4 +61,56 @@ async fn fail_double_init() {
5661
check_error(e, SinglePoolError::PoolAlreadyInitialized);
5762
}
5863

64+
#[test_case(true; "minimum_enabled")]
65+
#[test_case(false; "minimum_disabled")]
66+
#[tokio::test]
67+
async fn fail_below_pool_minimum(enable_minimum_delegation: bool) {
68+
let mut context = program_test(enable_minimum_delegation)
69+
.start_with_context()
70+
.await;
71+
let accounts = SinglePoolAccounts::default();
72+
let slot = context.genesis_config().epoch_schedule.first_normal_slot + 1;
73+
context.warp_to_slot(slot).unwrap();
74+
75+
create_vote(
76+
&mut context.banks_client,
77+
&context.payer,
78+
&context.last_blockhash,
79+
&accounts.validator,
80+
&accounts.voter.pubkey(),
81+
&accounts.withdrawer.pubkey(),
82+
&accounts.vote_account,
83+
)
84+
.await;
85+
86+
let rent = context.banks_client.get_rent().await.unwrap();
87+
let minimum_delegation = get_pool_minimum_delegation(
88+
&mut context.banks_client,
89+
&context.payer,
90+
&context.last_blockhash,
91+
)
92+
.await;
93+
94+
let instructions = instruction::initialize(
95+
&id(),
96+
&accounts.vote_account.pubkey(),
97+
&context.payer.pubkey(),
98+
&rent,
99+
minimum_delegation - 1,
100+
);
101+
let transaction = Transaction::new_signed_with_payer(
102+
&instructions,
103+
Some(&context.payer.pubkey()),
104+
&[&context.payer],
105+
context.last_blockhash,
106+
);
107+
108+
let e = context
109+
.banks_client
110+
.process_transaction(transaction)
111+
.await
112+
.unwrap_err();
113+
check_error(e, SinglePoolError::WrongRentAmount);
114+
}
115+
59116
// TODO test that init can succeed without mpl program

single-pool/program/tests/reactivate.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use {
2121

2222
#[tokio::test]
2323
async fn success() {
24-
let mut context = program_test().start_with_context().await;
24+
let mut context = program_test(false).start_with_context().await;
2525
let accounts = SinglePoolAccounts::default();
2626
accounts
2727
.initialize_for_deposit(&mut context, TEST_STAKE_AMOUNT, None)
@@ -131,7 +131,7 @@ async fn success() {
131131
#[test_case(false; "activating")]
132132
#[tokio::test]
133133
async fn fail_not_deactivated(activate: bool) {
134-
let mut context = program_test().start_with_context().await;
134+
let mut context = program_test(false).start_with_context().await;
135135
let accounts = SinglePoolAccounts::default();
136136
accounts.initialize(&mut context).await;
137137

single-pool/program/tests/update_pool_token_metadata.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const UPDATED_URI: &str = "updated_uri";
1616

1717
#[tokio::test]
1818
async fn success_update_pool_token_metadata() {
19-
let mut context = program_test().start_with_context().await;
19+
let mut context = program_test(false).start_with_context().await;
2020
let accounts = SinglePoolAccounts::default();
2121
accounts.initialize(&mut context).await;
2222

@@ -51,7 +51,7 @@ async fn success_update_pool_token_metadata() {
5151

5252
#[tokio::test]
5353
async fn fail_no_signature() {
54-
let mut context = program_test().start_with_context().await;
54+
let mut context = program_test(false).start_with_context().await;
5555
let accounts = SinglePoolAccounts::default();
5656
accounts.initialize(&mut context).await;
5757

@@ -92,7 +92,7 @@ enum BadWithdrawer {
9292
#[test_case(BadWithdrawer::VoteAccount; "vote_account")]
9393
#[tokio::test]
9494
async fn fail_bad_withdrawer(withdrawer_type: BadWithdrawer) {
95-
let mut context = program_test().start_with_context().await;
95+
let mut context = program_test(false).start_with_context().await;
9696
let accounts = SinglePoolAccounts::default();
9797
accounts.initialize(&mut context).await;
9898

0 commit comments

Comments
 (0)