Skip to content

Commit c73137d

Browse files
authored
Optionally remove test gas limit in forc test (#7495)
## Description This PR adds `--no-gas-limit` CLI option to `forc test`. The option increases tx gas limit in `forc test` to `u64::MAX`, essentially removing it. The motivation for the change was the need to benchmark heavy gas consuming algorithms. E.g., a brute force prime factorization of the number 9223372021822390277 took 21_474_836_627 gas units. The new `TestGasLimit` enum provides a `Limit(limit)` variant which is currently unused, but added for future extensions, if we want to limit the test gas to a particular value. ## Checklist - [ ] I have linked to any relevant issues. - [ ] I have commented my code, particularly in hard-to-understand areas. - [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [ ] I have added tests that prove my fix is effective or that my feature works. - [ ] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers.
1 parent ec51769 commit c73137d

File tree

6 files changed

+70
-14
lines changed

6 files changed

+70
-14
lines changed

.typos.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ extend-ignore-identifiers-re = [
1212
"ALOC",
1313
"Aloc",
1414
"aloc",
15+
"SHW",
1516
]
1617

1718
extend-ignore-re = [

forc-plugins/forc-debug/src/server/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use forc_pkg::{
2020
use forc_test::{
2121
execute::{DebugResult, TestExecutor},
2222
setup::TestSetup,
23-
BuiltTests,
23+
BuiltTests, TestGasLimit,
2424
};
2525
use fuel_tx::GasCostsValues;
2626
use serde::{Deserialize, Serialize};
@@ -252,6 +252,7 @@ impl DapServer {
252252
// TODO: (GAS-COSTS) Provide gas costs values here, similar like in `forc test`.
253253
// See: https://github.com/FuelLabs/sway/issues/7472
254254
GasCostsValues::default(),
255+
TestGasLimit::default(),
255256
)
256257
.ok()
257258
})

forc-test/src/execute.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::ecal::EcalSyscallHandler;
22
use crate::maxed_consensus_params;
33
use crate::setup::TestSetup;
4+
use crate::TestGasLimit;
45
use crate::TestResult;
56
use crate::TEST_METADATA_SEED;
67
use forc_pkg::PkgTestEntry;
@@ -50,6 +51,7 @@ impl TestExecutor {
5051
test_entry: &PkgTestEntry,
5152
name: String,
5253
gas_costs_values: GasCostsValues,
54+
gas_limit: TestGasLimit,
5355
) -> anyhow::Result<Self> {
5456
let storage = test_setup.storage().clone();
5557

@@ -76,7 +78,7 @@ impl TestExecutor {
7678

7779
let mut tx_builder = tx::TransactionBuilder::script(bytecode.to_vec(), script_input_data);
7880

79-
let params = maxed_consensus_params(gas_costs_values);
81+
let params = maxed_consensus_params(gas_costs_values, gas_limit);
8082

8183
tx_builder
8284
.with_params(params)

forc-test/src/lib.rs

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ pub struct TestResult {
8181
pub ecal: Box<EcalSyscallHandler>,
8282
}
8383

84+
#[derive(Default, Debug, Clone, Copy)]
85+
pub enum TestGasLimit {
86+
#[default]
87+
Default,
88+
Unlimited,
89+
Limited(u64),
90+
}
91+
8492
const TEST_METADATA_SEED: u64 = 0x7E57u64;
8593
/// A mapping from each member package of a build plan to its compiled contract dependencies.
8694
type ContractDependencyMap = HashMap<pkg::Pinned, Vec<Arc<pkg::BuiltPackage>>>;
@@ -265,7 +273,7 @@ impl PackageWithDeploymentToTest {
265273
// We are not concerned about gas costs of contract deployments for tests,
266274
// only the gas costs of test executions. So, we can simply provide the
267275
// default, built-in, gas costs values here.
268-
let params = maxed_consensus_params(GasCostsValues::default());
276+
let params = maxed_consensus_params(GasCostsValues::default(), TestGasLimit::default());
269277
let storage = vm::storage::MemoryStorage::default();
270278
let interpreter_params = InterpreterParams::new(gas_price, params.clone());
271279
let mut interpreter: vm::prelude::Interpreter<_, _, _, vm::interpreter::NotSupportedEcal> =
@@ -433,6 +441,7 @@ impl<'a> PackageTests {
433441
test_runners: &rayon::ThreadPool,
434442
test_filter: Option<&TestFilter>,
435443
gas_costs_values: GasCostsValues,
444+
gas_limit: TestGasLimit,
436445
) -> anyhow::Result<TestedPackage> {
437446
let pkg_with_tests = self.built_pkg_with_tests();
438447
let tests = test_runners.install(|| {
@@ -467,6 +476,7 @@ impl<'a> PackageTests {
467476
test_entry,
468477
name,
469478
gas_costs_values.clone(),
479+
gas_limit,
470480
)?
471481
.execute()
472482
})
@@ -663,14 +673,21 @@ impl BuiltTests {
663673
test_runner_count: TestRunnerCount,
664674
test_filter: Option<TestFilter>,
665675
gas_costs_values: GasCostsValues,
676+
gas_limit: TestGasLimit,
666677
) -> anyhow::Result<Tested> {
667678
let test_runners = match test_runner_count {
668679
TestRunnerCount::Manual(runner_count) => rayon::ThreadPoolBuilder::new()
669680
.num_threads(runner_count)
670681
.build(),
671682
TestRunnerCount::Auto => rayon::ThreadPoolBuilder::new().build(),
672683
}?;
673-
run_tests(self, &test_runners, test_filter, gas_costs_values)
684+
run_tests(
685+
self,
686+
&test_runners,
687+
test_filter,
688+
gas_costs_values,
689+
gas_limit,
690+
)
674691
}
675692
}
676693

@@ -684,11 +701,19 @@ pub fn build(opts: TestOpts) -> anyhow::Result<BuiltTests> {
684701

685702
/// Returns a `ConsensusParameters` which has maximum length/size allowance for scripts, contracts,
686703
/// and transactions.
687-
pub(crate) fn maxed_consensus_params(gas_costs_values: GasCostsValues) -> ConsensusParameters {
704+
pub(crate) fn maxed_consensus_params(
705+
gas_costs_values: GasCostsValues,
706+
gas_limit: TestGasLimit,
707+
) -> ConsensusParameters {
688708
let script_params = ScriptParameters::DEFAULT
689709
.with_max_script_length(u64::MAX)
690710
.with_max_script_data_length(u64::MAX);
691-
let tx_params = TxParameters::DEFAULT.with_max_size(u64::MAX);
711+
let tx_params = match gas_limit {
712+
TestGasLimit::Default => TxParameters::DEFAULT,
713+
TestGasLimit::Unlimited => TxParameters::DEFAULT.with_max_gas_per_tx(u64::MAX),
714+
TestGasLimit::Limited(limit) => TxParameters::DEFAULT.with_max_gas_per_tx(limit),
715+
}
716+
.with_max_size(u64::MAX);
692717
let contract_params = ContractParameters::DEFAULT
693718
.with_contract_max_size(u64::MAX)
694719
.with_max_storage_slots(u64::MAX);
@@ -697,6 +722,7 @@ pub(crate) fn maxed_consensus_params(gas_costs_values: GasCostsValues) -> Consen
697722
tx_params,
698723
contract_params,
699724
gas_costs: gas_costs_values.into(),
725+
block_gas_limit: u64::MAX,
700726
..Default::default()
701727
})
702728
}
@@ -750,18 +776,28 @@ fn run_tests(
750776
test_runners: &rayon::ThreadPool,
751777
test_filter: Option<TestFilter>,
752778
gas_costs_values: GasCostsValues,
779+
gas_limit: TestGasLimit,
753780
) -> anyhow::Result<Tested> {
754781
match built {
755782
BuiltTests::Package(pkg) => {
756-
let tested_pkg =
757-
pkg.run_tests(test_runners, test_filter.as_ref(), gas_costs_values.clone())?;
783+
let tested_pkg = pkg.run_tests(
784+
test_runners,
785+
test_filter.as_ref(),
786+
gas_costs_values.clone(),
787+
gas_limit,
788+
)?;
758789
Ok(Tested::Package(Box::new(tested_pkg)))
759790
}
760791
BuiltTests::Workspace(workspace) => {
761792
let tested_pkgs = workspace
762793
.into_iter()
763794
.map(|pkg| {
764-
pkg.run_tests(test_runners, test_filter.as_ref(), gas_costs_values.clone())
795+
pkg.run_tests(
796+
test_runners,
797+
test_filter.as_ref(),
798+
gas_costs_values.clone(),
799+
gas_limit,
800+
)
765801
})
766802
.collect::<anyhow::Result<Vec<TestedPackage>>>()?;
767803
Ok(Tested::Workspace(tested_pkgs))
@@ -775,7 +811,7 @@ mod tests {
775811

776812
use fuel_tx::GasCostsValues;
777813

778-
use crate::{build, BuiltTests, TestFilter, TestOpts, TestResult};
814+
use crate::{build, BuiltTests, TestFilter, TestGasLimit, TestOpts, TestResult};
779815

780816
/// Name of the folder containing required data for tests to run, such as an example forc
781817
/// project.
@@ -813,7 +849,12 @@ mod tests {
813849
) -> anyhow::Result<Vec<TestResult>> {
814850
let built_tests = test_package_built_tests(package_name)?;
815851
let test_runner_count = crate::TestRunnerCount::Auto;
816-
let tested = built_tests.run(test_runner_count, test_filter, GasCostsValues::default())?;
852+
let tested = built_tests.run(
853+
test_runner_count,
854+
test_filter,
855+
GasCostsValues::default(),
856+
TestGasLimit::default(),
857+
)?;
817858
match tested {
818859
crate::Tested::Package(tested_pkg) => Ok(tested_pkg.tests),
819860
crate::Tested::Workspace(_) => {

forc/src/cli/commands/test.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use crate::cli::{self, shared::IrCliOpt};
22
use ansiterm::Colour;
33
use clap::Parser;
44
use forc_pkg as pkg;
5-
use forc_test::{GasCostsSource, TestFilter, TestResult, TestRunnerCount, TestedPackage};
5+
use forc_test::{
6+
GasCostsSource, TestFilter, TestGasLimit, TestResult, TestRunnerCount, TestedPackage,
7+
};
68
use forc_tracing::println_action_green;
79
use forc_util::{
810
tx_utils::{decode_fuel_vm_log_data, format_log_receipts},
@@ -68,6 +70,9 @@ pub struct Command {
6870
/// [possible values: built-in, mainnet, testnet, <FILE_PATH>]
6971
#[clap(long)]
7072
pub gas_costs: Option<GasCostsSource>,
73+
/// Remove gas limit for test executions.
74+
#[clap(long)]
75+
pub no_gas_limit: bool,
7176
}
7277

7378
/// The set of options provided for controlling output of a test.
@@ -107,6 +112,11 @@ pub(crate) fn exec(cmd: Command) -> ForcResult<()> {
107112
.as_ref()
108113
.unwrap_or(&GasCostsSource::BuiltIn)
109114
.provide_gas_costs()?;
115+
let gas_limit = if cmd.no_gas_limit {
116+
TestGasLimit::Unlimited
117+
} else {
118+
TestGasLimit::Default
119+
};
110120
let opts = opts_from_cmd(cmd);
111121
let built_tests = forc_test::build(opts)?;
112122
let start = std::time::Instant::now();
@@ -123,7 +133,7 @@ pub(crate) fn exec(cmd: Command) -> ForcResult<()> {
123133
formatted_test_count_string(num_tests_ignored)
124134
),
125135
);
126-
let tested = built_tests.run(test_runner_count, test_filter, gas_costs_values)?;
136+
let tested = built_tests.run(test_runner_count, test_filter, gas_costs_values, gas_limit)?;
127137
let duration = start.elapsed();
128138

129139
// Eventually we'll print this in a fancy manner, but this will do for testing.

test/src/e2e_vm_tests/harness.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use forc_client::{
99
NodeTarget,
1010
};
1111
use forc_pkg::{BuildProfile, Built, BuiltPackage, PrintOpts};
12-
use forc_test::ecal::EcalSyscallHandler;
12+
use forc_test::{ecal::EcalSyscallHandler, TestGasLimit};
1313
use fuel_tx::TransactionBuilder;
1414
use fuel_vm::checked_transaction::builder::TransactionBuilderExt;
1515
use fuel_vm::fuel_tx::{self, consensus_parameters::ConsensusParametersV1};
@@ -366,6 +366,7 @@ pub(crate) async fn compile_and_run_unit_tests(
366366
forc_test::TestRunnerCount::Auto,
367367
test_filter,
368368
run_config.gas_costs_values.clone(),
369+
TestGasLimit::default(),
369370
)?;
370371
match tested {
371372
forc_test::Tested::Package(tested_pkg) => Ok(vec![*tested_pkg]),

0 commit comments

Comments
 (0)