Skip to content

Commit

Permalink
test: enable running tests against live node
Browse files Browse the repository at this point in the history
  • Loading branch information
iqdecay committed Jan 22, 2024
1 parent ef4d54b commit c97aecb
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 31 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ env:
FORC_VERSION: 0.48.0
FORC_PATCH_BRANCH: ""
FORC_PATCH_REVISION: ""
TEST_WALLET_SECRET_KEY_1: ${{ secrets.TEST_WALLET_SECRET_KEY_1 }}
TEST_WALLET_SECRET_KEY_2: ${{ secrets.TEST_WALLET_SECRET_KEY_2 }}
TEST_WALLET_SECRET_KEY_3: ${{ secrets.TEST_WALLET_SECRET_KEY_3 }}

jobs:
setup-test-projects:
Expand Down Expand Up @@ -172,6 +175,12 @@ jobs:
args: run --all-targets --workspace
download_sway_artifacts: sway-examples
install_fuel_core: true
- command: nextest # test some functions against live nodes
# the live node features requires using one thread only to avoid transaction collision
args: run --features "test-against-live-node" -j 1 --workspace
download_sway_artifacts: sway-examples
# not all tests use the live nodes so fuel-core binary remains necessary
install_fuel_core: true
- cargo_command: test
args: --doc --workspace
- cargo_command: machete
Expand Down
2 changes: 1 addition & 1 deletion examples/providers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod tests {
// Create a provider pointing to the testnet.
// This example will not work as the testnet does not support the new version of fuel-core
// yet
let provider = Provider::connect("beta-5.fuel.network").await.unwrap();
let provider = Provider::connect(TESTNET_NODE_URL).await.unwrap();

// Setup a private key
let secret =
Expand Down
1 change: 1 addition & 0 deletions packages/fuels-core/src/utils/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ pub const DEFAULT_GAS_ESTIMATION_TOLERANCE: f64 = 0.2;
pub const WITNESS_STATIC_SIZE: usize = 8;
const SIGNATURE_SIZE: usize = 64;
pub const SIGNATURE_WITNESS_SIZE: usize = WITNESS_STATIC_SIZE + SIGNATURE_SIZE;
pub const TESTNET_NODE_URL: &str = "beta-5.fuel.network";
17 changes: 9 additions & 8 deletions packages/fuels-macros/src/setup_program_test/code_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub(crate) fn generate_setup_program_test_code(

let project_lookup = generate_project_lookup(&generate_bindings)?;
let abigen_code = abigen_code(&project_lookup);
let wallet_code = wallet_initialization_code(initialize_wallets);
let wallet_code = wallet_initialization_code(initialize_wallets)?;
let deploy_code = contract_deploying_code(&deploy_contract, &project_lookup);
let script_code = script_loading_code(&load_scripts, &project_lookup);

Expand Down Expand Up @@ -66,21 +66,22 @@ fn generate_abigen_targets(project_lookup: &HashMap<String, Project>) -> Vec<Abi
.collect()
}

fn wallet_initialization_code(maybe_command: Option<InitializeWalletCommand>) -> TokenStream {
fn wallet_initialization_code(
maybe_command: Option<InitializeWalletCommand>,
) -> syn::Result<TokenStream> {
let command = if let Some(command) = maybe_command {
command
} else {
return Default::default();
return Ok(Default::default());
};

let wallet_names = extract_wallet_names(&command);

if wallet_names.is_empty() {
return Default::default();
return Ok(Default::default());
}

let num_wallets = wallet_names.len();
quote! {

Ok(quote! {
let [#(#wallet_names),*]: [_; #num_wallets] = launch_custom_provider_and_get_wallets(
WalletsConfig::new(Some(#num_wallets as u64), None, None),
None,
Expand All @@ -90,7 +91,7 @@ fn wallet_initialization_code(maybe_command: Option<InitializeWalletCommand>) ->
.expect("Error while trying to fetch wallets from the custom provider")
.try_into()
.expect("Should have the exact number of wallets");
}
})
}

fn extract_wallet_names(command: &InitializeWalletCommand) -> Vec<Ident> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ command_parser!(
Wallets -> InitializeWalletCommand,
Abigen -> AbigenCommand,
Deploy -> DeployContractCommand,
LoadScript -> LoadScriptCommand
LoadScript -> LoadScriptCommand,
);

impl Parse for TestProgramCommands {
Expand Down
1 change: 1 addition & 0 deletions packages/fuels-test-helpers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ which = { workspace = true, default-features = false }
default = ["fuels-accounts", "std"]
std = ["fuels-accounts?/std", "fuels-core/std"]
fuel-core-lib = ["fuel-core"]
test-against-live-node = []
45 changes: 42 additions & 3 deletions packages/fuels-test-helpers/src/accounts.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use fuel_crypto::SecretKey;
use std::mem::size_of;
use std::str::FromStr;

use fuel_crypto::SecretKey;
use fuels_accounts::wallet::WalletUnlocked;
use fuels_core::types::errors::Result;
use fuels_accounts::{provider::Provider, wallet::WalletUnlocked};
use fuels_core::{constants::TESTNET_NODE_URL, error, types::errors::Result};

use crate::{
node_types::{ChainConfig, Config},
Expand Down Expand Up @@ -85,6 +86,44 @@ pub async fn launch_custom_provider_and_get_wallets(
Ok(wallets)
}

pub async fn connect_to_testnet_node_and_get_wallets(
num_wallets: usize,
) -> Result<Vec<WalletUnlocked>> {
if num_wallets > 3 {
error!(
InvalidData,
"Trying to get more than 3 wallets from beta node"
);
}
let provider = Provider::connect(TESTNET_NODE_URL)
.await
.expect("Should be able to connect to {TESTNET_NODE_URL}");
let wallets = (1..=num_wallets)
.map(|wallet_counter| {
let private_key_string =
std::env::var(format!("TEST_WALLET_SECRET_KEY_{wallet_counter}"))
.expect("Should find private key in ENV");
let private_key = SecretKey::from_str(private_key_string.as_str())
.expect("Should be able to transform into private key");
WalletUnlocked::new_from_private_key(private_key, Some(provider.clone()))
})
.collect::<Vec<WalletUnlocked>>();
Ok(wallets)
}

pub async fn maybe_live_wallet(num_wallets: usize) -> Result<Vec<WalletUnlocked>> {
if cfg!(feature = "test-against-live-node") {
connect_to_testnet_node_and_get_wallets(num_wallets).await
} else {
launch_custom_provider_and_get_wallets(
WalletsConfig::new(Some(num_wallets as u64), None, None),
None,
None,
)
.await
}
}

#[cfg(test)]
mod tests {
use fuel_core_chain_config::ChainConfig;
Expand Down
1 change: 1 addition & 0 deletions packages/fuels/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@ std = [
]
# TODO: To be removed once https://github.com/FuelLabs/fuels-rs/issues/881 is unblocked.
test-type-paths = []
test-against-live-node = []
fuel-core-lib = ["fuels-test-helpers?/fuel-core-lib", "dep:fuel-core"]
rocksdb = ["fuel-core?/rocksdb"]
79 changes: 65 additions & 14 deletions packages/fuels/tests/contracts.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#[allow(unused_imports)]
use std::future::Future;
use std::thread::sleep;
use std::time::Duration;
use std::vec;

use fuels::{
Expand Down Expand Up @@ -43,8 +45,11 @@ async fn test_multiple_args() -> Result<()> {
#[tokio::test]
async fn test_contract_calling_contract() -> Result<()> {
// Tests a contract call that calls another contract (FooCaller calls FooContract underneath)
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(
Contract(
name = "LibContract",
Expand Down Expand Up @@ -75,6 +80,9 @@ async fn test_contract_calling_contract() -> Result<()> {
let lib_contract_id2 = lib_contract_instance2.contract_id();

// Call the contract directly. It increments the given value.
if cfg!(feature = "test-against-live-node") {
sleep(Duration::from_secs(10));
}
let response = lib_contract_instance.methods().increment(42).call().await?;

assert_eq!(43, response.value);
Expand Down Expand Up @@ -144,8 +152,11 @@ async fn test_reverting_transaction() -> Result<()> {

#[tokio::test]
async fn test_multiple_read_calls() -> Result<()> {
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "MultiReadContract",
project = "packages/fuels/tests/contracts/multiple_read_calls"
Expand Down Expand Up @@ -175,8 +186,11 @@ async fn test_multiple_read_calls() -> Result<()> {

#[tokio::test]
async fn test_multi_call_beginner() -> Result<()> {
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "TestContract",
project = "packages/fuels/tests/contracts/contract_test"
Expand All @@ -198,6 +212,10 @@ async fn test_multi_call_beginner() -> Result<()> {
.add_call(call_handler_1)
.add_call(call_handler_2);

if cfg!(feature = "test-against-live-node") {
sleep(Duration::from_secs(10));
}

let (val_1, val_2): (u64, u64) = multi_call_handler.call().await?.value;

assert_eq!(val_1, 7);
Expand All @@ -208,8 +226,11 @@ async fn test_multi_call_beginner() -> Result<()> {

#[tokio::test]
async fn test_multi_call_pro() -> Result<()> {
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "TestContract",
project = "packages/fuels/tests/contracts/contract_test"
Expand Down Expand Up @@ -263,8 +284,11 @@ async fn test_multi_call_pro() -> Result<()> {

#[tokio::test]
async fn test_contract_call_fee_estimation() -> Result<()> {
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "TestContract",
project = "packages/fuels/tests/contracts/contract_test"
Expand All @@ -276,14 +300,22 @@ async fn test_contract_call_fee_estimation() -> Result<()> {
),
);

let gas_price = 100_000_000;
let gas_price = if cfg!(feature = "test-against-live-node") {
1000
} else {
100_000_000
};
let gas_limit = 800;
let tolerance = 0.2;

let expected_min_gas_price = 0; // This is the default min_gas_price from the ConsensusParameters
let expected_gas_used = 675;
let expected_metered_bytes_size = 792;
let expected_total_fee = 898;
let (expected_min_gas_price, expected_gas_used, expected_total_fee) =
if cfg!(feature = "test-against-live-node") {
(1, 960, 1_074_685)
} else {
// 0 is the default min_gas_price from the ConsensusParameters
(0, 675, 898)
};

let estimated_transaction_cost = contract_instance
.methods()
Expand Down Expand Up @@ -312,8 +344,11 @@ async fn test_contract_call_fee_estimation() -> Result<()> {

#[tokio::test]
async fn contract_call_has_same_estimated_and_used_gas() -> Result<()> {
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "TestContract",
project = "packages/fuels/tests/contracts/contract_test"
Expand Down Expand Up @@ -345,8 +380,11 @@ async fn contract_call_has_same_estimated_and_used_gas() -> Result<()> {

#[tokio::test]
async fn mult_call_has_same_estimated_and_used_gas() -> Result<()> {
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "TestContract",
project = "packages/fuels/tests/contracts/contract_test"
Expand Down Expand Up @@ -1503,8 +1541,11 @@ async fn can_configure_decoding_of_contract_return() -> Result<()> {

#[tokio::test]
async fn test_contract_submit_and_response() -> Result<()> {
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(Contract(
name = "TestContract",
project = "packages/fuels/tests/contracts/contract_test"
Expand All @@ -1519,6 +1560,9 @@ async fn test_contract_submit_and_response() -> Result<()> {
let contract_methods = contract_instance.methods();

let submitted_tx = contract_methods.get(1, 2).submit().await?;
if cfg!(feature = "test-against-live-node") {
sleep(Duration::from_secs(10));
}
let value = submitted_tx.response().await?.value;

assert_eq!(value, 3);
Expand All @@ -1534,6 +1578,9 @@ async fn test_contract_submit_and_response() -> Result<()> {
.add_call(call_handler_2);

let handle = multi_call_handler.submit().await?;
if cfg!(feature = "test-against-live-node") {
sleep(Duration::from_secs(10));
}
let (val_1, val_2): (u64, u64) = handle.response().await?.value;

assert_eq!(val_1, 7);
Expand Down Expand Up @@ -1670,8 +1717,11 @@ async fn heap_types_correctly_offset_in_create_transactions_w_storage_slots() ->

#[tokio::test]
async fn test_arguments_with_gas_forwarded() -> Result<()> {
let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
.await?
.try_into()
.expect("Vec can be converted to an array");
setup_program_test!(
Wallets("wallet"),
Abigen(
Contract(
name = "TestContract",
Expand Down Expand Up @@ -1710,7 +1760,8 @@ async fn test_arguments_with_gas_forwarded() -> Result<()> {
contract_instance_2
.methods()
.u32_vec(vec_input.clone())
.call_params(CallParameters::default().with_gas_forwarded(1024))?
// from tests, it seems that it uses ~2500gas
.call_params(CallParameters::default().with_gas_forwarded(3000))?
.call()
.await?;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/fuels/tests/providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ async fn testnet_hello_world() -> Result<()> {
));

// Create a provider pointing to the testnet.
let provider = Provider::connect("beta-5.fuel.network").await.unwrap();
let provider = Provider::connect(TESTNET_NODE_URL).await.unwrap();

// Setup the private key.
let secret =
Expand Down
Loading

0 comments on commit c97aecb

Please sign in to comment.