Skip to content

Commit 0d9b0f5

Browse files
committed
Add show edge coveerage setting, enable inspector per invariant test
1 parent 6f4dd9b commit 0d9b0f5

File tree

7 files changed

+26
-21
lines changed

7 files changed

+26
-21
lines changed

crates/config/src/invariant.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ pub struct InvariantConfig {
2626
pub max_assume_rejects: u32,
2727
/// Number of runs to execute and include in the gas report.
2828
pub gas_report_samples: u32,
29-
/// Path where invariant corpus is stored. If not configured then coverage guided fuzzing is
30-
/// disabled.
29+
/// Path where invariant corpus is stored, enables coverage guided fuzzing and edge coverage
30+
/// metrics.
3131
pub corpus_dir: Option<PathBuf>,
3232
/// Whether corpus to use gzip file compression and decompression.
3333
pub corpus_gzip: bool,
@@ -43,6 +43,8 @@ pub struct InvariantConfig {
4343
pub timeout: Option<u32>,
4444
/// Display counterexample as solidity calls.
4545
pub show_solidity: bool,
46+
/// Whether to collect and display edge coverage metrics.
47+
pub show_edge_coverage: bool,
4648
}
4749

4850
impl Default for InvariantConfig {
@@ -64,6 +66,7 @@ impl Default for InvariantConfig {
6466
show_metrics: true,
6567
timeout: None,
6668
show_solidity: false,
69+
show_edge_coverage: false,
6770
}
6871
}
6972
}
@@ -88,6 +91,7 @@ impl InvariantConfig {
8891
show_metrics: true,
8992
timeout: None,
9093
show_solidity: false,
94+
show_edge_coverage: false,
9195
}
9296
}
9397
}

crates/evm/evm/src/executors/invariant/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ impl<'a> InvariantExecutor<'a> {
357357
runs < self.config.runs
358358
};
359359

360+
// Invariant runs with edge coverage if corpus dir is set or showing edge coverage.
361+
let edge_coverage_enabled =
362+
self.config.corpus_dir.is_some() || self.config.show_edge_coverage;
363+
360364
'stop: while continue_campaign(runs) {
361365
let initial_seq = corpus_manager.new_sequence(&invariant_test)?;
362366

@@ -407,9 +411,9 @@ impl<'a> InvariantExecutor<'a> {
407411

408412
// Collect line coverage from last fuzzed call.
409413
invariant_test.merge_coverage(call_result.line_coverage.clone());
410-
// If coverage guided fuzzing is enabled then merge edge count with current history
414+
// If running with edge coverage then merge edge count with the current history
411415
// map and set new coverage in current run.
412-
if self.config.corpus_dir.is_some() {
416+
if edge_coverage_enabled {
413417
let (new_coverage, is_edge) =
414418
call_result.merge_edge_coverage(&mut self.history_map);
415419
if new_coverage {
@@ -514,15 +518,14 @@ impl<'a> InvariantExecutor<'a> {
514518

515519
// End current invariant test run.
516520
invariant_test.end_run(current_run, self.config.gas_report_samples as usize);
517-
518521
if let Some(progress) = progress {
519522
// If running with progress then increment completed runs.
520523
progress.inc(1);
521524
// Display metrics in progress bar.
522-
if self.config.corpus_dir.is_some() {
525+
if edge_coverage_enabled {
523526
progress.set_message(format!("{}", &corpus_manager.metrics));
524527
}
525-
} else if self.config.corpus_dir.is_some()
528+
} else if edge_coverage_enabled
526529
&& last_metrics_report.elapsed() > DURATION_BETWEEN_METRICS_REPORT
527530
{
528531
// Display metrics inline if corpus dir set.

crates/evm/evm/src/inspectors/stack.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ pub struct InspectorStackBuilder {
5757
pub logs: Option<bool>,
5858
/// Whether line coverage info should be collected.
5959
pub line_coverage: Option<bool>,
60-
/// Whether edge coverage info should be collected.
61-
pub edge_coverage: Option<bool>,
6260
/// Whether to print all opcode traces into the console. Useful for debugging the EVM.
6361
pub print: Option<bool>,
6462
/// The chisel state inspector.
@@ -138,13 +136,6 @@ impl InspectorStackBuilder {
138136
self
139137
}
140138

141-
/// Set whether to collect edge coverage information.
142-
#[inline]
143-
pub fn edge_coverage(mut self, yes: bool) -> Self {
144-
self.edge_coverage = Some(yes);
145-
self
146-
}
147-
148139
/// Set whether to enable the trace printer.
149140
#[inline]
150141
pub fn print(mut self, yes: bool) -> Self {
@@ -194,7 +185,6 @@ impl InspectorStackBuilder {
194185
trace_mode,
195186
logs,
196187
line_coverage,
197-
edge_coverage,
198188
print,
199189
chisel_state,
200190
enable_isolation,
@@ -221,7 +211,6 @@ impl InspectorStackBuilder {
221211
stack.set_chisel(chisel_state);
222212
}
223213
stack.collect_line_coverage(line_coverage.unwrap_or(false));
224-
stack.collect_edge_coverage(edge_coverage.unwrap_or(false));
225214
stack.collect_logs(logs.unwrap_or(true));
226215
stack.print(print.unwrap_or(false));
227216
stack.tracing(trace_mode);

crates/forge/src/multi_runner.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,6 @@ impl TestRunnerConfig {
360360
.cheatcodes(cheats_config)
361361
.trace_mode(self.trace_mode())
362362
.line_coverage(self.line_coverage)
363-
.edge_coverage(self.config.invariant.corpus_dir.is_some())
364363
.enable_isolation(self.isolation)
365364
.odyssey(self.odyssey)
366365
.create2_deployer(self.evm_opts.create2_deployer)

crates/forge/src/runner.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,15 @@ impl<'a> FunctionRunner<'a> {
705705
let runner = self.invariant_runner();
706706
let invariant_config = &self.config.invariant;
707707

708+
let mut executor = self.clone_executor();
709+
// Enable edge coverage if running with coverage guided fuzzing or with edge coverage
710+
// metrics (useful for benchmarking the fuzzer).
711+
executor.inspector_mut().collect_edge_coverage(
712+
invariant_config.corpus_dir.is_some() || invariant_config.show_edge_coverage,
713+
);
714+
708715
let mut evm = InvariantExecutor::new(
709-
self.clone_executor(),
716+
executor,
710717
runner,
711718
invariant_config.clone(),
712719
identified_contracts,

crates/forge/tests/cli/config.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@ corpus_min_size = 0
11211121
failure_persist_dir = "cache/invariant"
11221122
show_metrics = true
11231123
show_solidity = false
1124+
show_edge_coverage = false
11241125
11251126
[labels]
11261127
@@ -1234,7 +1235,8 @@ exclude = []
12341235
"failure_persist_dir": "cache/invariant",
12351236
"show_metrics": true,
12361237
"timeout": null,
1237-
"show_solidity": false
1238+
"show_solidity": false,
1239+
"show_edge_coverage": false
12381240
},
12391241
"ffi": false,
12401242
"allow_internal_expect_revert": false,

crates/forge/tests/it/test_helpers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ impl ForgeTestProfile {
160160
show_metrics: true,
161161
timeout: None,
162162
show_solidity: false,
163+
show_edge_coverage: false,
163164
};
164165

165166
config.sanitized()

0 commit comments

Comments
 (0)