Skip to content

Commit 2d85083

Browse files
committed
improve tests
1 parent d99dfe4 commit 2d85083

4 files changed

Lines changed: 209 additions & 12 deletions

File tree

Cargo.lock

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

basics/checking-accounts/asm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ solana-native-token = "3.0.0"
1313
solana-pubkey = "3.0.0"
1414
solana-transaction = "3.0.1"
1515
solana-system-interface.workspace = true
16+
solana-transaction-error = "3.0.0"
1617

1718
[features]
1819
test-sbf = []

basics/checking-accounts/asm/src/lib.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
mod tests {
33

44
use litesvm::LiteSVM;
5+
use solana_instruction::error::InstructionError;
56
use solana_keypair::{Keypair, Signer};
67
use solana_native_token::LAMPORTS_PER_SOL;
78
use solana_pubkey::Pubkey;
89
use solana_system_interface::instruction::create_account;
910
use solana_transaction::{AccountMeta, Instruction, Transaction};
11+
use solana_transaction_error::TransactionError;
1012

1113
#[test]
1214
fn test_checking_accounts() {
@@ -91,8 +93,8 @@ mod tests {
9193
svm.latest_blockhash(),
9294
);
9395

94-
let res = svm.send_transaction(tx);
95-
assert!(res.is_err()); // error code 1
96+
let err = svm.send_transaction(tx).unwrap_err();
97+
assert_eq!(err.err, TransactionError::InstructionError(0, InstructionError::Custom(1)));
9698
}
9799

98100
#[test]
@@ -126,8 +128,8 @@ mod tests {
126128
svm.latest_blockhash(),
127129
);
128130

129-
let res = svm.send_transaction(tx);
130-
assert!(res.is_err()); // error code 2
131+
let err = svm.send_transaction(tx).unwrap_err();
132+
assert_eq!(err.err, TransactionError::InstructionError(0, InstructionError::Custom(2)));
131133
}
132134

133135
#[test]
@@ -162,8 +164,8 @@ mod tests {
162164
svm.latest_blockhash(),
163165
);
164166

165-
let res = svm.send_transaction(tx);
166-
assert!(res.is_err()); // error code 3
167+
let err = svm.send_transaction(tx).unwrap_err();
168+
assert_eq!(err.err, TransactionError::InstructionError(0, InstructionError::Custom(3)));
167169
}
168170

169171
#[test]
@@ -194,8 +196,8 @@ mod tests {
194196
svm.latest_blockhash(),
195197
);
196198

197-
let res = svm.send_transaction(tx);
198-
assert!(res.is_err()); // error code 4
199+
let err = svm.send_transaction(tx).unwrap_err();
200+
assert_eq!(err.err, TransactionError::InstructionError(0, InstructionError::Custom(4)));
199201
}
200202

201203
#[test]
@@ -227,8 +229,8 @@ mod tests {
227229
svm.latest_blockhash(),
228230
);
229231

230-
let res = svm.send_transaction(tx);
231-
assert!(res.is_err()); // error code 6
232+
let err = svm.send_transaction(tx).unwrap_err();
233+
assert_eq!(err.err, TransactionError::InstructionError(0, InstructionError::Custom(6)));
232234
}
233235

234236
#[test]
@@ -261,7 +263,7 @@ mod tests {
261263
svm.latest_blockhash(),
262264
);
263265

264-
let res = svm.send_transaction(tx);
265-
assert!(res.is_err()); // error code 5
266+
let err = svm.send_transaction(tx).unwrap_err();
267+
assert_eq!(err.err, TransactionError::InstructionError(0, InstructionError::Custom(5)));
266268
}
267269
}

basics/checking-accounts/asm/tests/test.ts

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { describe, test } from "node:test";
2+
import assert from "node:assert";
23
import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from "@solana/web3.js";
34
import { start } from "solana-bankrun";
45

@@ -51,4 +52,196 @@ describe("Checking accounts", async () => {
5152

5253
await client.processTransaction(tx);
5354
});
55+
56+
test("Invalid number of accounts (error 1)", async () => {
57+
const blockhash = context.lastBlockhash;
58+
const ix = new TransactionInstruction({
59+
keys: [{ pubkey: payer.publicKey, isSigner: true, isWritable: true }],
60+
programId: PROGRAM_ID,
61+
data: Buffer.alloc(0),
62+
});
63+
64+
const tx = new Transaction();
65+
tx.recentBlockhash = blockhash;
66+
tx.add(ix).sign(payer);
67+
68+
const res = await client.tryProcessTransaction(tx);
69+
assert.equal(res.result, "Error processing Instruction 0: custom program error: 0x1");
70+
});
71+
72+
test("Payer not signer (error 2)", async () => {
73+
const blockhash = context.lastBlockhash;
74+
const feePayer = Keypair.generate();
75+
const fakePayer = Keypair.generate();
76+
const acCreate = Keypair.generate();
77+
const acChange = Keypair.generate();
78+
79+
const fund = SystemProgram.transfer({
80+
fromPubkey: payer.publicKey,
81+
toPubkey: feePayer.publicKey,
82+
lamports: 10_000_000,
83+
});
84+
const fundTx = new Transaction();
85+
fundTx.recentBlockhash = blockhash;
86+
fundTx.add(fund).sign(payer);
87+
await client.processTransaction(fundTx);
88+
89+
const ix = new TransactionInstruction({
90+
keys: [
91+
{ pubkey: fakePayer.publicKey, isSigner: false, isWritable: true }, // not a signer
92+
{ pubkey: acCreate.publicKey, isSigner: true, isWritable: true },
93+
{ pubkey: acChange.publicKey, isSigner: true, isWritable: true },
94+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
95+
],
96+
programId: PROGRAM_ID,
97+
data: Buffer.alloc(0),
98+
});
99+
100+
const tx = new Transaction();
101+
tx.recentBlockhash = context.lastBlockhash;
102+
tx.add(ix).sign(feePayer, acCreate, acChange);
103+
104+
const res = await client.tryProcessTransaction(tx);
105+
assert.equal(res.result, "Error processing Instruction 0: custom program error: 0x2");
106+
});
107+
108+
test("Account to create already initialized (error 3)", async () => {
109+
const blockhash = context.lastBlockhash;
110+
const acCreate = Keypair.generate();
111+
const acChange = Keypair.generate();
112+
113+
// Fund acCreate so it appears initialized
114+
const fund = SystemProgram.transfer({
115+
fromPubkey: payer.publicKey,
116+
toPubkey: acCreate.publicKey,
117+
lamports: 1_000_000,
118+
});
119+
// Fund acChange so it is initialized and owned by our program
120+
const fundChange = SystemProgram.createAccount({
121+
fromPubkey: payer.publicKey,
122+
newAccountPubkey: acChange.publicKey,
123+
lamports: Number(rent.minimumBalance(BigInt(0))),
124+
space: 0,
125+
programId: PROGRAM_ID,
126+
});
127+
128+
const setupTx = new Transaction();
129+
setupTx.recentBlockhash = blockhash;
130+
setupTx.add(fund, fundChange).sign(payer, acChange);
131+
await client.processTransaction(setupTx);
132+
133+
const ix = new TransactionInstruction({
134+
keys: [
135+
{ pubkey: payer.publicKey, isSigner: true, isWritable: true },
136+
{ pubkey: acCreate.publicKey, isSigner: true, isWritable: true },
137+
{ pubkey: acChange.publicKey, isSigner: true, isWritable: true },
138+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
139+
],
140+
programId: PROGRAM_ID,
141+
data: Buffer.alloc(0),
142+
});
143+
144+
const tx = new Transaction();
145+
tx.recentBlockhash = context.lastBlockhash;
146+
tx.add(ix).sign(payer, acCreate, acChange);
147+
148+
const res = await client.tryProcessTransaction(tx);
149+
assert.equal(res.result, "Error processing Instruction 0: custom program error: 0x3");
150+
});
151+
152+
test("Account to change not initialized (error 4)", async () => {
153+
const blockhash = context.lastBlockhash;
154+
const acCreate = Keypair.generate();
155+
const acChange = Keypair.generate(); // no lamports
156+
157+
const ix = new TransactionInstruction({
158+
keys: [
159+
{ pubkey: payer.publicKey, isSigner: true, isWritable: true },
160+
{ pubkey: acCreate.publicKey, isSigner: true, isWritable: true },
161+
{ pubkey: acChange.publicKey, isSigner: true, isWritable: true },
162+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
163+
],
164+
programId: PROGRAM_ID,
165+
data: Buffer.alloc(0),
166+
});
167+
168+
const tx = new Transaction();
169+
tx.recentBlockhash = blockhash;
170+
tx.add(ix).sign(payer, acCreate, acChange);
171+
172+
const res = await client.tryProcessTransaction(tx);
173+
assert.equal(res.result, "Error processing Instruction 0: custom program error: 0x4");
174+
});
175+
176+
test("Invalid system program (error 5)", async () => {
177+
const blockhash = context.lastBlockhash;
178+
const acCreate = Keypair.generate();
179+
const acChange = Keypair.generate();
180+
const fakeSystemProgram = PublicKey.unique();
181+
182+
const fund = SystemProgram.createAccount({
183+
fromPubkey: payer.publicKey,
184+
newAccountPubkey: acChange.publicKey,
185+
lamports: Number(rent.minimumBalance(BigInt(0))),
186+
space: 0,
187+
programId: PROGRAM_ID,
188+
});
189+
const setupTx = new Transaction();
190+
setupTx.recentBlockhash = blockhash;
191+
setupTx.add(fund).sign(payer, acChange);
192+
await client.processTransaction(setupTx);
193+
194+
const ix = new TransactionInstruction({
195+
keys: [
196+
{ pubkey: payer.publicKey, isSigner: true, isWritable: true },
197+
{ pubkey: acCreate.publicKey, isSigner: true, isWritable: true },
198+
{ pubkey: acChange.publicKey, isSigner: true, isWritable: true },
199+
{ pubkey: fakeSystemProgram, isSigner: false, isWritable: false },
200+
],
201+
programId: PROGRAM_ID,
202+
data: Buffer.alloc(0),
203+
});
204+
205+
const tx = new Transaction();
206+
tx.recentBlockhash = context.lastBlockhash;
207+
tx.add(ix).sign(payer, acCreate, acChange);
208+
209+
const res = await client.tryProcessTransaction(tx);
210+
assert.equal(res.result, "Error processing Instruction 0: custom program error: 0x5");
211+
});
212+
213+
test("Account to change wrong owner (error 6)", async () => {
214+
const blockhash = context.lastBlockhash;
215+
const acCreate = Keypair.generate();
216+
const acChange = Keypair.generate();
217+
218+
// Fund acChange but keep it owned by the system program (no createAccount with PROGRAM_ID)
219+
const fund = SystemProgram.transfer({
220+
fromPubkey: payer.publicKey,
221+
toPubkey: acChange.publicKey,
222+
lamports: 1_000_000,
223+
});
224+
const setupTx = new Transaction();
225+
setupTx.recentBlockhash = blockhash;
226+
setupTx.add(fund).sign(payer);
227+
await client.processTransaction(setupTx);
228+
229+
const ix = new TransactionInstruction({
230+
keys: [
231+
{ pubkey: payer.publicKey, isSigner: true, isWritable: true },
232+
{ pubkey: acCreate.publicKey, isSigner: true, isWritable: true },
233+
{ pubkey: acChange.publicKey, isSigner: true, isWritable: true },
234+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
235+
],
236+
programId: PROGRAM_ID,
237+
data: Buffer.alloc(0),
238+
});
239+
240+
const tx = new Transaction();
241+
tx.recentBlockhash = context.lastBlockhash;
242+
tx.add(ix).sign(payer, acCreate, acChange);
243+
244+
const res = await client.tryProcessTransaction(tx);
245+
assert.equal(res.result, "Error processing Instruction 0: custom program error: 0x6");
246+
});
54247
});

0 commit comments

Comments
 (0)