2021-01-15 23:05:26 -08:00
const assert = require ( "assert" ) ;
2021-12-15 15:11:41 -08:00
const anchor = require ( "@project-serum/anchor" ) ;
2021-06-09 13:02:50 -07:00
const { Account , Transaction , TransactionInstruction } = anchor . web3 ;
2021-01-15 23:05:26 -08:00
2022-02-20 14:28:24 -08:00
// sleep to allow logs to come in
const sleep = ( ms ) =>
new Promise ( ( resolve ) => {
setTimeout ( ( ) => resolve ( ) , ms ) ;
} ) ;
const withLogTest = async ( callback , expectedLog ) => {
let logTestOk = false ;
const listener = anchor . getProvider ( ) . connection . onLogs (
"all" ,
( logs ) => {
if ( logs . logs . some ( ( logLine ) => logLine === expectedLog ) ) {
logTestOk = true ;
} else {
console . log ( logs ) ;
}
} ,
"recent"
) ;
try {
await callback ( ) ;
} catch ( err ) {
anchor . getProvider ( ) . connection . removeOnLogsListener ( listener ) ;
throw err ;
}
await sleep ( 3000 ) ;
anchor . getProvider ( ) . connection . removeOnLogsListener ( listener ) ;
assert . ok ( logTestOk ) ;
} ;
2021-01-15 23:05:26 -08:00
describe ( "errors" , ( ) => {
// Configure the client to use the local cluster.
2022-02-20 14:28:24 -08:00
const localProvider = anchor . Provider . local ( ) ;
localProvider . opts . skipPreflight = true ;
anchor . setProvider ( localProvider ) ;
2021-01-15 23:05:26 -08:00
const program = anchor . workspace . Errors ;
it ( "Emits a Hello error" , async ( ) => {
2022-02-20 14:28:24 -08:00
await withLogTest ( async ( ) => {
try {
const tx = await program . rpc . hello ( ) ;
assert . ok ( false ) ;
} catch ( err ) {
const errMsg =
"This is an error message clients will automatically display" ;
assert . equal ( err . toString ( ) , errMsg ) ;
assert . equal ( err . msg , errMsg ) ;
assert . equal ( err . code , 6000 ) ;
}
} , "Program log: AnchorError thrown in programs/errors/src/lib.rs:13. Error Code: Hello. Error Number: 6000. Error Message: This is an error message clients will automatically display." ) ;
} ) ;
it ( "Emits a Hello error via require!" , async ( ) => {
2021-01-15 23:05:26 -08:00
try {
2022-02-20 14:28:24 -08:00
const tx = await program . rpc . testRequire ( ) ;
2021-01-15 23:05:26 -08:00
assert . ok ( false ) ;
} catch ( err ) {
const errMsg =
"This is an error message clients will automatically display" ;
assert . equal ( err . toString ( ) , errMsg ) ;
assert . equal ( err . msg , errMsg ) ;
2021-12-08 13:50:08 -08:00
assert . equal ( err . code , 6000 ) ;
2021-01-15 23:05:26 -08:00
}
} ) ;
2022-02-20 14:28:24 -08:00
it ( "Emits a Hello error via err!" , async ( ) => {
try {
const tx = await program . rpc . testErr ( ) ;
assert . ok ( false ) ;
} catch ( err ) {
const errMsg =
"This is an error message clients will automatically display" ;
assert . equal ( err . toString ( ) , errMsg ) ;
assert . equal ( err . msg , errMsg ) ;
assert . equal ( err . code , 6000 ) ;
}
} ) ;
it ( "Logs a ProgramError" , async ( ) => {
await withLogTest ( async ( ) => {
try {
const tx = await program . rpc . testProgramError ( ) ;
assert . ok ( false ) ;
} catch ( err ) {
// No-op (withLogTest expects the callback to catch the initial tx error)
}
} , "Program log: ProgramError occurred. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid." ) ;
} ) ;
it ( "Logs a ProgramError with source" , async ( ) => {
await withLogTest ( async ( ) => {
try {
const tx = await program . rpc . testProgramErrorWithSource ( ) ;
assert . ok ( false ) ;
} catch ( err ) {
// No-op (withLogTest expects the callback to catch the initial tx error)
}
} , "Program log: ProgramError thrown in programs/errors/src/lib.rs:38. Error Code: InvalidAccountData. Error Number: 17179869184. Error Message: An account's data contents was invalid." ) ;
} ) ;
2021-01-15 23:05:26 -08:00
it ( "Emits a HelloNoMsg error" , async ( ) => {
try {
const tx = await program . rpc . helloNoMsg ( ) ;
assert . ok ( false ) ;
} catch ( err ) {
const errMsg = "HelloNoMsg" ;
assert . equal ( err . toString ( ) , errMsg ) ;
assert . equal ( err . msg , errMsg ) ;
2021-12-08 13:50:08 -08:00
assert . equal ( err . code , 6000 + 123 ) ;
2021-01-15 23:05:26 -08:00
}
} ) ;
it ( "Emits a HelloNext error" , async ( ) => {
try {
const tx = await program . rpc . helloNext ( ) ;
assert . ok ( false ) ;
} catch ( err ) {
const errMsg = "HelloNext" ;
assert . equal ( err . toString ( ) , errMsg ) ;
assert . equal ( err . msg , errMsg ) ;
2021-12-08 13:50:08 -08:00
assert . equal ( err . code , 6000 + 124 ) ;
2021-06-09 13:02:50 -07:00
}
} ) ;
it ( "Emits a mut error" , async ( ) => {
2022-02-20 14:28:24 -08:00
await withLogTest ( async ( ) => {
try {
const tx = await program . rpc . mutError ( {
accounts : {
myAccount : anchor . web3 . SYSVAR _RENT _PUBKEY ,
} ,
} ) ;
assert . ok ( false ) ;
} catch ( err ) {
const errMsg = "A mut constraint was violated" ;
assert . equal ( err . toString ( ) , errMsg ) ;
assert . equal ( err . msg , errMsg ) ;
assert . equal ( err . code , 2000 ) ;
}
} , "Program log: AnchorError caused by account: my_account. Error Code: ConstraintMut. Error Number: 2000. Error Message: A mut constraint was violated." ) ;
2021-06-09 13:02:50 -07:00
} ) ;
2021-07-03 11:58:23 -07:00
it ( "Emits a has one error" , async ( ) => {
2021-06-09 13:02:50 -07:00
try {
const account = new Account ( ) ;
2021-07-03 11:58:23 -07:00
const tx = await program . rpc . hasOneError ( {
2021-06-09 13:02:50 -07:00
accounts : {
myAccount : account . publicKey ,
owner : anchor . web3 . SYSVAR _RENT _PUBKEY ,
rent : anchor . web3 . SYSVAR _RENT _PUBKEY ,
} ,
instructions : [
2021-07-03 11:58:23 -07:00
await program . account . hasOneAccount . createInstruction ( account ) ,
2021-06-09 13:02:50 -07:00
] ,
signers : [ account ] ,
} ) ;
assert . ok ( false ) ;
} catch ( err ) {
2021-07-03 11:58:23 -07:00
const errMsg = "A has_one constraint was violated" ;
2021-06-09 13:02:50 -07:00
assert . equal ( err . toString ( ) , errMsg ) ;
assert . equal ( err . msg , errMsg ) ;
2021-12-08 13:50:08 -08:00
assert . equal ( err . code , 2001 ) ;
2021-06-09 13:02:50 -07:00
}
} ) ;
// This test uses a raw transaction and provider instead of a program
// instance since the client won't allow one to send a transaction
// with an invalid signer account.
it ( "Emits a signer error" , async ( ) => {
2022-02-20 14:28:24 -08:00
let signature ;
const listener = anchor
. getProvider ( )
. connection . onLogs ( "all" , ( logs ) => ( signature = logs . signature ) ) ;
2021-06-09 13:02:50 -07:00
try {
const tx = new Transaction ( ) ;
tx . add (
new TransactionInstruction ( {
keys : [
{
pubkey : anchor . web3 . SYSVAR _RENT _PUBKEY ,
isWritable : false ,
isSigner : false ,
} ,
] ,
programId : program . programId ,
data : program . coder . instruction . encode ( "signer_error" , { } ) ,
} )
) ;
await program . provider . send ( tx ) ;
assert . ok ( false ) ;
} catch ( err ) {
2022-02-20 14:28:24 -08:00
await sleep ( 3000 ) ;
anchor . getProvider ( ) . connection . removeOnLogsListener ( listener ) ;
const errMsg = ` Error: Raw transaction ${ signature } failed ({"err":{"InstructionError":[0,{"Custom":3010}]}}) ` ;
2021-06-09 13:02:50 -07:00
assert . equal ( err . toString ( ) , errMsg ) ;
2022-02-20 14:28:24 -08:00
} finally {
anchor . getProvider ( ) . connection . removeOnLogsListener ( listener ) ;
2021-01-15 23:05:26 -08:00
}
} ) ;
2021-10-21 15:51:20 -07:00
it ( "Emits a raw custom error" , async ( ) => {
try {
const tx = await program . rpc . rawCustomError ( {
accounts : {
myAccount : anchor . web3 . SYSVAR _RENT _PUBKEY ,
} ,
} ) ;
assert . ok ( false ) ;
} catch ( err ) {
const errMsg = "HelloCustom" ;
assert . equal ( err . toString ( ) , errMsg ) ;
assert . equal ( err . msg , errMsg ) ;
2021-12-08 13:50:08 -08:00
assert . equal ( err . code , 6000 + 125 ) ;
2021-10-21 15:51:20 -07:00
}
} ) ;
2021-11-18 07:42:07 -08:00
it ( "Emits a account not initialized error" , async ( ) => {
2022-02-20 14:28:24 -08:00
await withLogTest ( async ( ) => {
try {
const tx = await program . rpc . accountNotInitializedError ( {
accounts : {
notInitializedAccount : new anchor . web3 . Keypair ( ) . publicKey ,
} ,
} ) ;
assert . fail (
"Unexpected success in creating a transaction that should have fail with `AccountNotInitialized` error"
) ;
} catch ( err ) {
const errMsg =
"The program expected this account to be already initialized" ;
assert . equal ( err . toString ( ) , errMsg ) ;
}
} , "Program log: AnchorError caused by account: not_initialized_account. Error Code: AccountNotInitialized. Error Number: 3012. Error Message: The program expected this account to be already initialized." ) ;
2021-11-18 07:42:07 -08:00
} ) ;
2021-01-15 23:05:26 -08:00
} ) ;