light_program_test/utils/
assert.rs

1use light_client::rpc::RpcError;
2use solana_banks_client::BanksClientError;
3use solana_instruction::error::InstructionError;
4use solana_sdk::transaction::TransactionError;
5
6#[allow(clippy::result_large_err)]
7pub fn assert_rpc_error<T>(
8    result: Result<T, RpcError>,
9    index_instruction: u8,
10    expected_error_code: u32,
11) -> Result<(), RpcError> {
12    match result {
13        Err(RpcError::TransactionError(TransactionError::InstructionError(
14            index,
15            InstructionError::Custom(error_code),
16        ))) if index != index_instruction => Err(RpcError::AssertRpcError(
17            format!(
18                "Expected error code: {}, got: {} error: {}",
19                expected_error_code,
20                error_code,
21                unsafe { result.unwrap_err_unchecked() }
22            )
23            .to_string(),
24        )),
25        Err(RpcError::BanksError(BanksClientError::TransactionError(
26            TransactionError::InstructionError(index, InstructionError::Custom(error_code)),
27        ))) if index != index_instruction => Err(RpcError::AssertRpcError(
28            format!(
29                "Expected error code: {}, got: {} error: {}",
30                expected_error_code,
31                error_code,
32                unsafe { result.unwrap_err_unchecked() }
33            )
34            .to_string(),
35        )),
36        Err(RpcError::BanksError(BanksClientError::TransactionError(
37            TransactionError::InstructionError(index, InstructionError::Custom(error_code)),
38        ))) if index == index_instruction && error_code == expected_error_code => Ok(()),
39        Err(RpcError::TransactionError(TransactionError::InstructionError(
40            index,
41            InstructionError::Custom(error_code),
42        ))) if index == index_instruction && error_code == expected_error_code => Ok(()),
43
44        // Handle built-in Solana errors (non-Custom) - TransactionError variants
45        Err(RpcError::TransactionError(TransactionError::InstructionError(index, ref err)))
46            if index == index_instruction =>
47        {
48            match (err, expected_error_code) {
49                (InstructionError::GenericError, 0) => Ok(()),
50                (InstructionError::InvalidArgument, 1) => Ok(()),
51                (InstructionError::InvalidInstructionData, 2) => Ok(()),
52                (InstructionError::InvalidAccountData, 3) => Ok(()),
53                (InstructionError::AccountDataTooSmall, 5) => Ok(()),
54                (InstructionError::InsufficientFunds, 6) => Ok(()),
55                (InstructionError::IncorrectProgramId, 7) => Ok(()),
56                (InstructionError::MissingRequiredSignature, 8) => Ok(()),
57                (InstructionError::AccountAlreadyInitialized, 9) => Ok(()),
58                (InstructionError::UninitializedAccount, 10) => Ok(()),
59                (InstructionError::NotEnoughAccountKeys, 11) => Ok(()),
60                (InstructionError::AccountBorrowFailed, 12) => Ok(()),
61                (InstructionError::MaxSeedLengthExceeded, 13) => Ok(()),
62                (InstructionError::InvalidSeeds, 14) => Ok(()),
63                (InstructionError::BorshIoError(_), 15) => Ok(()),
64                (InstructionError::AccountNotRentExempt, 16) => Ok(()),
65                (InstructionError::InvalidRealloc, 17) => Ok(()),
66                (InstructionError::ComputationalBudgetExceeded, 18) => Ok(()),
67                (InstructionError::PrivilegeEscalation, 19) => Ok(()),
68                (InstructionError::ProgramEnvironmentSetupFailure, 20) => Ok(()),
69                (InstructionError::ProgramFailedToComplete, 21) => Ok(()),
70                (InstructionError::ProgramFailedToCompile, 22) => Ok(()),
71                (InstructionError::Immutable, 23) => Ok(()),
72                (InstructionError::IncorrectAuthority, 24) => Ok(()),
73                (InstructionError::AccountNotExecutable, 25) => Ok(()),
74                (InstructionError::InvalidAccountOwner, 26) => Ok(()),
75                (InstructionError::ArithmeticOverflow, 27) => Ok(()),
76                (InstructionError::UnsupportedSysvar, 28) => Ok(()),
77                (InstructionError::IllegalOwner, 29) => Ok(()),
78                (InstructionError::MaxAccountsDataAllocationsExceeded, 30) => Ok(()),
79                (InstructionError::MaxAccountsExceeded, 31) => Ok(()),
80                (InstructionError::MaxInstructionTraceLengthExceeded, 32) => Ok(()),
81                (InstructionError::BuiltinProgramsMustConsumeComputeUnits, 33) => Ok(()),
82                _ => Err(RpcError::AssertRpcError(format!(
83                    "Expected error code {}, but got {:?}",
84                    expected_error_code, err
85                ))),
86            }
87        }
88
89        // Handle built-in Solana errors (non-Custom) - BanksClientError variants
90        Err(RpcError::BanksError(BanksClientError::TransactionError(
91            TransactionError::InstructionError(index, ref err),
92        ))) if index == index_instruction => match (err, expected_error_code) {
93            (InstructionError::GenericError, 0) => Ok(()),
94            (InstructionError::InvalidArgument, 1) => Ok(()),
95            (InstructionError::InvalidInstructionData, 2) => Ok(()),
96            (InstructionError::InvalidAccountData, 3) => Ok(()),
97            (InstructionError::AccountDataTooSmall, 5) => Ok(()),
98            (InstructionError::InsufficientFunds, 6) => Ok(()),
99            (InstructionError::IncorrectProgramId, 7) => Ok(()),
100            (InstructionError::MissingRequiredSignature, 8) => Ok(()),
101            (InstructionError::AccountAlreadyInitialized, 9) => Ok(()),
102            (InstructionError::UninitializedAccount, 10) => Ok(()),
103            (InstructionError::NotEnoughAccountKeys, 11) => Ok(()),
104            (InstructionError::AccountBorrowFailed, 12) => Ok(()),
105            (InstructionError::MaxSeedLengthExceeded, 13) => Ok(()),
106            (InstructionError::InvalidSeeds, 14) => Ok(()),
107            (InstructionError::BorshIoError(_), 15) => Ok(()),
108            (InstructionError::AccountNotRentExempt, 16) => Ok(()),
109            (InstructionError::InvalidRealloc, 17) => Ok(()),
110            (InstructionError::ComputationalBudgetExceeded, 18) => Ok(()),
111            (InstructionError::PrivilegeEscalation, 19) => Ok(()),
112            (InstructionError::ProgramEnvironmentSetupFailure, 20) => Ok(()),
113            (InstructionError::ProgramFailedToComplete, 21) => Ok(()),
114            (InstructionError::ProgramFailedToCompile, 22) => Ok(()),
115            (InstructionError::Immutable, 23) => Ok(()),
116            (InstructionError::IncorrectAuthority, 24) => Ok(()),
117            (InstructionError::AccountNotExecutable, 25) => Ok(()),
118            (InstructionError::InvalidAccountOwner, 26) => Ok(()),
119            (InstructionError::ArithmeticOverflow, 27) => Ok(()),
120            (InstructionError::UnsupportedSysvar, 28) => Ok(()),
121            (InstructionError::IllegalOwner, 29) => Ok(()),
122            (InstructionError::MaxAccountsDataAllocationsExceeded, 30) => Ok(()),
123            (InstructionError::MaxAccountsExceeded, 31) => Ok(()),
124            (InstructionError::MaxInstructionTraceLengthExceeded, 32) => Ok(()),
125            (InstructionError::BuiltinProgramsMustConsumeComputeUnits, 33) => Ok(()),
126            _ => Err(RpcError::AssertRpcError(format!(
127                "Expected error code {}, but got {:?}",
128                expected_error_code, err
129            ))),
130        },
131
132        Err(RpcError::TransactionError(TransactionError::InstructionError(
133            0,
134            InstructionError::ProgramFailedToComplete,
135        ))) => Ok(()),
136        Err(e) => Err(RpcError::AssertRpcError(format!(
137            "Unexpected error type: {:?}",
138            e
139        ))),
140        _ => Err(RpcError::AssertRpcError(String::from(
141            "Unexpected error type",
142        ))),
143    }
144}