Rust-analyzer not working in integration tests


I am new to solana and i am trying to write tests for program but rust-analyzer is not working for intitalize.rs file , i have tried various solution but none of them worked , here's my toml file :

 [package]
name = "program"
version = "0.1.0"
edition = "2021"

[features]
no-entrypoint = []

[dependencies]
solana-program = "2.3.0"
spl-token = { version = "8.0.0", features = ["no-entrypoint"] }
thiserror = "2.0.14"

[lib]
crate-type = ["cdylib", "lib"]

[dev-dependencies]
solana-program-test = "2.3.7"
solana-sdk = "2.3.1"
solana-system-interface = { version = "2.0.0", features = ["bincode"] }
tokio = { version = "1.47.1", features = ["full"] }

[[test]]
name = "integ_tests"
path = "/tests/initialize.rs"
test = true

The problem probably comes from the absolute path. rust-analyzer and cargo interpret the paths relative to the Cargo.toml directory, and here your path is absolute. Try to remove the /:

[[test]]
name = "integ_tests"
path = "tests/initialize.rs"
test = true

Then, restart the lsp (just by closing and reopening vscode).

But by default, all the .rs files on the tests directory are considered as tests, so it should work without the [[test]] section.

By the way, can you fix your formatting please? Just add ``` at the beginning and at the end of your code block, it's more readable.

Hey @a-rust-coder thanks for that , autocomplete works , but it does not show things like
depreciated module and errors like no reference ....
I do have another question , how am i supposed to import src/ files in initialize.rs,
currently it does not work

here's the file :

use solana_program_test::*;
use solana_sdk::{instruction::{AccountMeta, Instruction}, msg, program_option::COption, program_pack::Pack, pubkey::Pubkey, rent, signature::Keypair, transaction::Transaction};
use tokio;
use lib::{entrypoint::process_instruction, error::VaultError, state::Vault};

#[tokio::test]
async fn test_intialize_vault(){
    // -  Start a Local Validator
    // -  first we would need to specify the program and its entry point 
    let program_id = Pubkey::new_unique();
    let mut program_test = ProgramTest::new(
        "vault_program",
        program_id,
        processor!(process_instruction)
    );
    

    let (mut banks_client,payer,recent_blockhash) = program_test.start().await;
    let rent = banks_client.get_rent().await.unwrap();

    // 0 : we would need intializer , the signer , the vault creator which would start the vault
    // bank will acts as initializer in test environment


    // 1 : we need underlying_token_mint , which we need to use as shares eg:USDC
    let mint = Keypair::new();
    // this ix just creates the mint account on ix , at this point it is nothing but just garbage account
    msg!("mint create instruction");
    let mint_create_ix = solana_system_interface::instruction::create_account(
         &&payer.pubkey(),
         &&mint.pubkey(),
        rent.minimum_balance(spl_token::state::Mint::LEN), 
         spl_token::state::Mint::LEN as u64,
          &spl_token::id()
    );

    // this ix sets the configuration of mint , which will make solana recognize it
    msg!("initialize mint ix");
    let mint_init_ix = spl_token::instruction::initialize_mint(
        &spl_token::id(), 
        &&mint.pubkey(), 
        &&payer.pubkey(), 
        None, 
        6)?;

    // 2 : token account which will be hold the deposited tokens
    msg!("Deposit Token PDA");
    let (deposit_token,deposit_token_bump) = Pubkey::find_program_address(&[b"deposit_token"], &program_id);

    // 3 : Shares token mint which will be used by vault program as shares for giving as ownership
    msg!("Share mint PDA");
    let (share_mint,share_mint_bump) = Pubkey::find_program_address(&[b"share_mint"], &program_id);

    // creating a vault account pda
    msg!("Vault PDA");
    let (vault_pda,vault_bump) = Pubkey::find_program_address(&[b"vault_pda"], &program_id);

    msg!("Creating Transaction of creating mint and intializing acc");
    let tx = Transaction::new_signed_with_payer(&[
        mint_create_ix,
        mint_init_ix,
    ], 
        Some(payer.pubkey()), 
        &[&payer,&mint],   // Signatures
        recent_blockhash);

    msg!("Processing create mint Tx ....");
    banks_client.process_transaction(tx).await.unwrap();


    // This was the setup 
    // 5. Ab hume Init ix bhejni h to the network
    msg!("Creating Init Ix");
    let init_ix = Instruction {
        program_id,
        accounts:vec![
            AccountMeta::new(&&payer.pubkey(), true),
            AccountMeta::new(&&mint.pubkey(),false),
            AccountMeta::new(deposit_token,false),
            AccountMeta::new(share_mint,false),
            AccountMeta::new(vault_pda,false),
            AccountMeta::new_readonly(spl_token::id(), false),
            AccountMeta::new_readonly(system_program::id(), false),
            AccountMeta::new_readonly(rent::sysvar::id(), false),
        ],
        data:vec![0u8]          // Data ka pehla byte should specify what kind of instruction is it 
    };
    // fetch fresh blockhash and send Init tx
    msg!("Finding Recent BlockHash");
    let recent_blockhash2 = banks_client.get_latest_blockhash().await.unwrap();

    msg!("Creating init Transaction");
    let init_tx = Transaction::new_signed_with_payer(&[
            init_ix
        ], 
            Some(&&payer.pubkey()), 
            &[&payer],   // Signatures
            recent_blockhash2
        );

    msg!("Processing Init Tx ....");
    banks_client.process_transaction(init_tx).await.unwrap();

    msg!("Getting Intialized Vault Acc PDA");
    let vault_acc = banks_client.get_account(vault_pda).await.unwrap().unwrap();

    let vault_data = Vault::unpack(&vault_acc.data).unwrap();

    if !vault_data.is_initialized {
        msg!("Vault is not Intialized ?");
        return Err(VaultError::VaultUnIntialized.into());
    }

    if vault_data.deposit_token_acc != deposit_token {
        msg!("Deposit Token Account is invalid");
        return Err(VaultError::InvalidDepositTokenAccount.into());
    }

    if vault_data.mint_acc != &&mint.pubkey() {
        msg!("Mint Account is not invalid");
        return Err(VaultError::InvalidMintAccount.into());
    }

    if vault_data.share_mint_acc != share_mint {
        msg!("Share Mint Account is invalid");
        return Err(VaultError::InvalidShareMintAccount.into());
    }


    msg!("Getting Deposit Token Account");
    let deposit_token_acc = banks_client.get_account(deposit_token).await.unwrap().unwrap();
    msg!("Unpacking Deposit Token Account Data");
    let deposit_token_acc_data = spl_token::state::Account::unpack(&deposit_token_acc.data)?;

    if *deposit_token_acc.owner != spl_token::id() {
        msg!("deposit token account indeed is a not token");
        return Err(VaultError::NotAToken.into());
    }

    if deposit_token_acc_data.owner != vault_pda {
        msg!("Owner of deposit token account is not correct");
        return Err(VaultError::InvalidTokenAuthority.into());
    } 

    let share_mint_acc = banks_client.get_account(share_mint).await.unwrap().unwrap();
    let share_mint_acc_data = spl_token::state::Mint::unpack(&share_mint_acc.data)?;

    if !share_mint_acc_data.is_initialized {
        msg!("Share Mint is Not Intialised");
        return Err(VaultError::MintUnitialised.into());
    }

    if share_mint_acc_data.mint_authority != COption::Some(vault_pda) {
        msg!("Owner of Share Mint is invalid");
        return Err(VaultError::InvalidMintAuthority.into());
    }

    msg!("Vault initialized successfully!");
}

When you have external test files, like here - typically in tests - then the imports behave as if it was an other crate. It means you can import elements from your lib with the name of your lib. For example, if your crate is named program, as in your Cargo.toml, then you can write:

use program::{entrypoint::process_instruction, error::VaultError, state::Vault};

It behaves exactly like if your were using your library in an other crate.

1 Like

@a-rust-coder thank you so much for that , can you help with this too ,
it does not show things like depreciated module and errors like no reference present in current file

Can you give more details on the error please? Like the code from the lib and the code from the tests, and the excepted behavior? Also, does cargo check or cargo test show these errors?

@a-rust-coder what i mean to say is that , let's say i remove this line from the initialize.rs file, then it should show red squigglies on wherever these are used but it does not , that's the issue , i hope that clears the question

use program::{entrypoint::process_instruction, error::VaultError, state::Vault};

There are several possibilities for this problem.

First, try to run cargo check --all-targets with a mistake in your code to be sure the file is tracked by cargo and the error is correctly reported. If there is the excepted error, then maybe there is an error or a miss in the configuration of cargo-analyzer. You can try to add the following to your_project/.vscode/settings.json:

{
    "rust-analyzer.cargo.autoreload": true,
    "rust-analyzer.procMacro.enable": true,
    "rust-analyzer.checkOnSave.command": "clippy",
    "rust-analyzer.cargo.loadOutDirsFromCheck": true,
} 

Then, restart vscode and test to remove the imports and save the file.

If it doesn't work, maybe the internal cache is corrupted. Close vscode, and try the following commands:

rm -rf ~/.cargo/registry
rm -rf ~/.rust-analyzer
rm -rf you_project/target

It will take a while when you'll reopen vscode, but it may fix the bug if this is a cache error.

If it still doesn't fix the bug, then there are two possibilities:

  • There is an other extension interfering with Rust Analyzer. Try to disable all other extensions to see if it works.

  • Rust Analyzer is too slow. Maybe Rust Analyzer just takes a lot of time to check for errors, because you're using big libraries with a lot of proc macros. In that case, the error should be shown if it's present when you open vscode. Try to remove the imports, close and reopen vscode. If the error is shown and Rust Analyzer is well configures, the problem is just that it takes a while to update the state.

1 Like

Hey @a-rust-coder , so i ran vscode in wsl and RA works correctly in that environment (in windows RA had some issue with perl ) . Thanks for help !!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.