Skip to content

Commit 27a5d39

Browse files
fix(forge): show backtrace line only on -vvvvv (#12211)
* fix(forge): show backtrace line only on -vvvvv * fix tests * Update docs * Fix --------- Co-authored-by: 0xrusowsky <[email protected]>
1 parent c034500 commit 27a5d39

File tree

7 files changed

+15191
-45
lines changed

7 files changed

+15191
-45
lines changed

crates/cast/tests/cli/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ Display options:
9292
- 2 (-vv): Print logs for all tests.
9393
- 3 (-vvv): Print execution traces for failing tests.
9494
- 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests.
95-
- 5 (-vvvvv): Print execution and setup traces for all tests, including storage changes.
95+
- 5 (-vvvvv): Print execution and setup traces for all tests, including storage changes
96+
and
97+
backtraces with line numbers.
9698
9799
Find more information in the book: https://getfoundry.sh/cast/overview
98100

crates/cli/src/opts/global.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ pub struct GlobalArgs {
1818
/// - 2 (-vv): Print logs for all tests.
1919
/// - 3 (-vvv): Print execution traces for failing tests.
2020
/// - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests.
21-
/// - 5 (-vvvvv): Print execution and setup traces for all tests, including storage changes.
21+
/// - 5 (-vvvvv): Print execution and setup traces for all tests, including storage changes and
22+
/// backtraces with line numbers.
2223
#[arg(help_heading = "Display options", global = true, short, long, verbatim_doc_comment, conflicts_with = "quiet", action = ArgAction::Count)]
2324
verbosity: Verbosity,
2425

crates/evm/traces/src/lib.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,13 @@ impl TraceMode {
358358
}
359359

360360
pub fn with_verbosity(self, verbosity: u8) -> Self {
361-
// Enable step recording for backtraces when verbosity >= 3
362-
// We need to ensure we're recording JUMP AND JUMPDEST steps:
363-
if verbosity >= 3 { std::cmp::max(self, Self::Steps) } else { self }
361+
match verbosity {
362+
0..3 => self,
363+
3..=4 => std::cmp::max(self, Self::Call),
364+
// Enable step recording for backtraces when verbosity is 5 or higher.
365+
// We need to ensure we're recording JUMP AND JUMPDEST steps.
366+
_ => std::cmp::min(self, Self::Steps),
367+
}
364368
}
365369

366370
pub fn into_config(self) -> Option<TracingInspectorConfig> {

crates/forge/tests/cli/backtrace.rs

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ forgetest!(test_backtraces, |prj, cmd| {
1212

1313
prj.add_test("Backtrace.t.sol", include_str!("../fixtures/backtraces/Backtrace.t.sol"));
1414

15-
let output = cmd.args(["test", "-vvv"]).assert_failure();
15+
let output = cmd.args(["test", "-vvvvv"]).assert_failure();
1616

1717
output.stdout_eq(str![[r#"
1818
[COMPILING_FILES] with [SOLC_VERSION]
@@ -165,7 +165,7 @@ contract BacktraceTest is DSTest {
165165
"#,
166166
);
167167

168-
let output = cmd.args(["test", "-vvv"]).assert_failure();
168+
let output = cmd.args(["test", "-vvvvv"]).assert_failure();
169169

170170
output.stdout_eq(str![[r#"
171171
[COMPILING_FILES] with [SOLC_VERSION]
@@ -239,7 +239,7 @@ contract BacktraceTest is DSTest {
239239

240240
// Second run - mixed compilation (SimpleRevert fresh, BacktraceTest fresh, HelperContract
241241
// cached)
242-
let output = cmd.forge_fuse().args(["test", "-vvv"]).assert_failure();
242+
let output = cmd.forge_fuse().args(["test", "-vvvvv"]).assert_failure();
243243

244244
output.stdout_eq(str![[r#"
245245
[COMPILING_FILES] with [SOLC_VERSION]
@@ -306,65 +306,65 @@ Ran 9 tests for test/LibraryBacktrace.t.sol:LibraryBacktraceTest
306306
[FAIL: DivisionByZero()] testExternalDivisionByZero() ([GAS])
307307
...
308308
Backtrace:
309-
at ExternalMathLib.div (src/libraries/ExternalMathLib.sol:11:48)
310-
at LibraryConsumer.externalDivide (src/LibraryConsumer.sol:43:95)
311-
at LibraryBacktraceTest.testExternalDivisionByZero (test/LibraryBacktrace.t.sol:49:60)
309+
at ExternalMathLib.div
310+
at LibraryConsumer.externalDivide
311+
at LibraryBacktraceTest.testExternalDivisionByZero
312312
313313
[FAIL: panic: arithmetic underflow or overflow (0x11)] testExternalOverflow() ([GAS])
314314
...
315315
Backtrace:
316316
at ExternalMathLib.mul
317-
at LibraryConsumer.externalMultiply (src/LibraryConsumer.sol:49:97)
318-
at LibraryBacktraceTest.testExternalOverflow (test/LibraryBacktrace.t.sol:59:54)
317+
at LibraryConsumer.externalMultiply
318+
at LibraryBacktraceTest.testExternalOverflow
319319
320320
[FAIL: ExternalMathLib: value must be positive] testExternalRequire() ([GAS])
321321
...
322322
Backtrace:
323-
at ExternalMathLib.requirePositive (src/libraries/ExternalMathLib.sol:32:87)
324-
at LibraryConsumer.externalCheckPositive (src/LibraryConsumer.sol:61:95)
325-
at LibraryBacktraceTest.testExternalRequire (test/LibraryBacktrace.t.sol:64:53)
323+
at ExternalMathLib.requirePositive
324+
at LibraryConsumer.externalCheckPositive
325+
at LibraryBacktraceTest.testExternalRequire
326326
327327
[FAIL: Underflow()] testExternalUnderflow() ([GAS])
328328
...
329329
Backtrace:
330-
at ExternalMathLib.sub (src/libraries/ExternalMathLib.sol:25:63)
331-
at LibraryConsumer.externalSubtract (src/LibraryConsumer.sol:55:97)
332-
at LibraryBacktraceTest.testExternalUnderflow (test/LibraryBacktrace.t.sol:54:55)
330+
at ExternalMathLib.sub
331+
at LibraryConsumer.externalSubtract
332+
at LibraryBacktraceTest.testExternalUnderflow
333333
334334
[FAIL: DivisionByZero()] testInternalDivisionByZero() ([GAS])
335335
...
336336
Backtrace:
337-
at LibraryConsumer.internalDivide (src/libraries/InternalMathLib.sol:11:48)
338-
at LibraryBacktraceTest.testInternalDivisionByZero (test/LibraryBacktrace.t.sol:27:60)
337+
at LibraryConsumer.internalDivide
338+
at LibraryBacktraceTest.testInternalDivisionByZero
339339
340340
[FAIL: panic: arithmetic underflow or overflow (0x11)] testInternalOverflow() ([GAS])
341341
Traces:
342342
...
343343
Backtrace:
344344
at LibraryConsumer.internalMultiply
345-
at LibraryBacktraceTest.testInternalOverflow (test/LibraryBacktrace.t.sol:37:54)
345+
at LibraryBacktraceTest.testInternalOverflow
346346
347347
[FAIL: InternalMathLib: value must be positive] testInternalRequire() ([GAS])
348348
Traces:
349349
...
350350
Backtrace:
351-
at LibraryConsumer.internalCheckPositive (src/libraries/InternalMathLib.sol:32:87)
352-
at LibraryBacktraceTest.testInternalRequire (test/LibraryBacktrace.t.sol:42:53)
351+
at LibraryConsumer.internalCheckPositive
352+
at LibraryBacktraceTest.testInternalRequire
353353
354354
[FAIL: Underflow()] testInternalUnderflow() ([GAS])
355355
Traces:
356356
...
357357
Backtrace:
358-
at LibraryConsumer.internalSubtract (src/libraries/InternalMathLib.sol:25:63)
359-
at LibraryBacktraceTest.testInternalUnderflow (test/LibraryBacktrace.t.sol:32:55)
358+
at LibraryConsumer.internalSubtract
359+
at LibraryBacktraceTest.testInternalUnderflow
360360
361361
[FAIL: DivisionByZero()] testMixedLibraryFailure() ([GAS])
362362
Traces:
363363
...
364364
Backtrace:
365-
at ExternalMathLib.div (src/libraries/ExternalMathLib.sol:11:48)
366-
at LibraryConsumer.mixedCalculation (src/LibraryConsumer.sol:72:62)
367-
at LibraryBacktraceTest.testMixedLibraryFailure (test/LibraryBacktrace.t.sol:72:105)
365+
at ExternalMathLib.div
366+
at LibraryConsumer.mixedCalculation
367+
at LibraryBacktraceTest.testMixedLibraryFailure
368368
369369
Suite result: FAILED. 0 passed; 9 failed; 0 skipped; [ELAPSED]
370370
...
@@ -389,7 +389,7 @@ forgetest!(test_multiple_libraries_same_file, |prj, cmd| {
389389
);
390390

391391
let output = cmd
392-
.args(["test", "-vvv", "--ast", "--mc", "MultipleLibraryBacktraceTest"])
392+
.args(["test", "-vvvvv", "--ast", "--mc", "MultipleLibraryBacktraceTest"])
393393
.assert_failure();
394394

395395
output.stdout_eq(str![[r#"
@@ -401,28 +401,28 @@ Ran 4 tests for test/MultipleLibraryBacktrace.t.sol:MultipleLibraryBacktraceTest
401401
[FAIL: FirstLibError()] testAllLibrariesFirstFails() ([GAS])
402402
...
403403
Backtrace:
404-
at MultipleLibraryConsumer.useAllLibraries (src/libraries/MultipleLibraries.sol:8:6)
404+
at MultipleLibraryConsumer.useAllLibraries (src/libraries/MultipleLibraries.sol:10:42)
405405
at MultipleLibraryBacktraceTest.testAllLibrariesFirstFails (test/MultipleLibraryBacktrace.t.sol:31:60)
406406
407407
[FAIL: FirstLibError()] testFirstLibraryError() ([GAS])
408408
Traces:
409409
...
410410
Backtrace:
411-
at MultipleLibraryConsumer.useFirstLib (src/libraries/MultipleLibraries.sol:8:6)
411+
at MultipleLibraryConsumer.useFirstLib (src/libraries/MultipleLibraries.sol:10:42)
412412
at MultipleLibraryBacktraceTest.testFirstLibraryError (test/MultipleLibraryBacktrace.t.sol:16:55)
413413
414414
[FAIL: SecondLibError()] testSecondLibraryError() ([GAS])
415415
Traces:
416416
...
417417
Backtrace:
418-
at MultipleLibraryConsumer.useSecondLib (src/libraries/MultipleLibraries.sol:24:6)
418+
at MultipleLibraryConsumer.useSecondLib (src/libraries/MultipleLibraries.sol:26:41)
419419
at MultipleLibraryBacktraceTest.testSecondLibraryError (test/MultipleLibraryBacktrace.t.sol:21:56)
420420
421421
[FAIL: ThirdLibError()] testThirdLibraryError() ([GAS])
422422
Traces:
423423
...
424424
Backtrace:
425-
at MultipleLibraryConsumer.useThirdLib (src/libraries/MultipleLibraries.sol:40:6)
425+
at MultipleLibraryConsumer.useThirdLib (src/libraries/MultipleLibraries.sol:42:42)
426426
at MultipleLibraryBacktraceTest.testThirdLibraryError (test/MultipleLibraryBacktrace.t.sol:26:55)
427427
428428
Suite result: FAILED. 0 passed; 4 failed; 0 skipped; [ELAPSED]
@@ -446,7 +446,7 @@ forgetest!(test_fork_backtrace, |prj, cmd| {
446446
prj.add_test("ForkBacktrace.t.sol", include_str!("../fixtures/backtraces/ForkBacktrace.t.sol"));
447447

448448
let output = cmd
449-
.args(["test", "-vvv", "--fork-url", &fork_url, "--match-contract", "ForkBacktraceTest"])
449+
.args(["test", "-vvvvv", "--fork-url", &fork_url, "--match-contract", "ForkBacktraceTest"])
450450
.assert_failure();
451451

452452
output.stdout_eq(str![[r#"
@@ -500,7 +500,7 @@ Suite result: FAILED. 0 passed; 5 failed; 0 skipped; [ELAPSED]
500500
"test",
501501
"--mt",
502502
"testTransferFromWithoutApproval",
503-
"-vvv",
503+
"-vvvvv",
504504
"--fork-url",
505505
&fork_url,
506506
"--etherscan-api-key",
@@ -534,7 +534,7 @@ forgetest!(test_backtrace_via_ir_disables_source_lines, |prj, cmd| {
534534

535535
prj.update_config(|c| c.via_ir = true);
536536

537-
let output = cmd.args(["test", "-vvv"]).assert_failure();
537+
let output = cmd.args(["test", "-vvvvv"]).assert_failure();
538538
output.stdout_eq(str![[r#"
539539
[COMPILING_FILES] with [SOLC_VERSION]
540540
[SOLC_VERSION] [ELAPSED]

crates/forge/tests/cli/cmd.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ Display options:
7070
- 2 (-vv): Print logs for all tests.
7171
- 3 (-vvv): Print execution traces for failing tests.
7272
- 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests.
73-
- 5 (-vvvvv): Print execution and setup traces for all tests, including storage changes.
73+
- 5 (-vvvvv): Print execution and setup traces for all tests, including storage changes
74+
and
75+
backtraces with line numbers.
7476
7577
Find more information in the book: https://getfoundry.sh/forge/overview
7678

crates/forge/tests/cli/test_cmd/mod.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -315,14 +315,15 @@ contract SimpleContractTest is DSTest {
315315
}
316316
"#;
317317

318+
#[cfg(not(feature = "isolate-by-default"))]
318319
forgetest!(can_run_test_with_json_output_verbose, |prj, cmd| {
319320
prj.insert_ds_test();
320321
prj.insert_console();
321322

322323
prj.add_source("Simple.t.sol", SIMPLE_CONTRACT);
323324

324325
// Assert that with verbose output the json output includes the traces
325-
cmd.args(["test", "-vvv", "--json"])
326+
cmd.args(["test", "-vvvvv", "--json"])
326327
.assert_success()
327328
.stdout_eq(file!["../../fixtures/SimpleContractTestVerbose.json": Json]);
328329
});
@@ -624,7 +625,7 @@ contract CustomTypesTest is Test {
624625
"#,
625626
);
626627

627-
cmd.args(["test", "-vvvv"]).assert_failure().stdout_eq(str![[r#"
628+
cmd.args(["test", "-vvvvv"]).assert_failure().stdout_eq(str![[r#"
628629
[COMPILING_FILES] with [SOLC_VERSION]
629630
[SOLC_VERSION] [ELAPSED]
630631
Compiler run successful!
@@ -3020,7 +3021,7 @@ contract SuppressTracesTest is Test {
30203021
);
30213022

30223023
// Show traces and logs for failed test only.
3023-
cmd.args(["test", "--mc", "SuppressTracesTest", "-vvvv", "-s"]).assert_failure().stdout_eq(
3024+
cmd.args(["test", "--mc", "SuppressTracesTest", "-vvvvv", "-s"]).assert_failure().stdout_eq(
30243025
str![[r#"
30253026
[COMPILING_FILES] with [SOLC_VERSION]
30263027
[SOLC_VERSION] [ELAPSED]
@@ -3043,6 +3044,8 @@ Traces:
30433044
├─ [0] console::log("test increment failure") [staticcall]
30443045
│ └─ ← [Stop]
30453046
├─ [22418] Counter::increment()
3047+
│ ├─ storage changes:
3048+
│ │ @ 0: 0 → 1
30463049
│ └─ ← [Stop]
30473050
├─ [424] Counter::number() [staticcall]
30483051
│ └─ ← [Return] 1
@@ -3103,7 +3106,7 @@ Traces:
31033106
31043107
Backtrace:
31053108
at VM.assertEq
3106-
at SuppressTracesTest.test_increment_failure (lib/forge-std/src/StdAssertions.sol:[..]:[..])
3109+
at SuppressTracesTest.test_increment_failure
31073110
31083111
[PASS] test_increment_success() ([GAS])
31093112
Logs:
@@ -3861,7 +3864,7 @@ contract NonContractCallRevertTest is Test {
38613864
"#,
38623865
);
38633866

3864-
cmd.args(["test", "--mc", "NonContractCallRevertTest", "-vvv"])
3867+
cmd.args(["test", "--mc", "NonContractCallRevertTest", "-vvvvv"])
38653868
.assert_failure()
38663869
.stdout_eq(str![[r#"
38673870
[COMPILING_FILES] with [SOLC_VERSION]
@@ -3874,6 +3877,13 @@ Logs:
38743877
test non contract call failure
38753878
38763879
Traces:
3880+
[157143] NonContractCallRevertTest::setUp()
3881+
├─ [96345] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
3882+
│ └─ ← [Return] 481 bytes of code
3883+
├─ [22492] Counter::setNumber(1)
3884+
│ └─ ← [Stop]
3885+
└─ ← [Stop]
3886+
38773887
[6350] NonContractCallRevertTest::test_non_contract_call_failure()
38783888
├─ [0] console::log("test non contract call failure") [staticcall]
38793889
│ └─ ← [Stop]
@@ -3889,6 +3899,13 @@ Logs:
38893899
test non contract (void) call failure
38903900
38913901
Traces:
3902+
[157143] NonContractCallRevertTest::setUp()
3903+
├─ [96345] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
3904+
│ └─ ← [Return] 481 bytes of code
3905+
├─ [22492] Counter::setNumber(1)
3906+
│ └─ ← [Stop]
3907+
└─ ← [Stop]
3908+
38923909
[6215] NonContractCallRevertTest::test_non_contract_void_call_failure()
38933910
├─ [0] console::log("test non contract (void) call failure") [staticcall]
38943911
│ └─ ← [Stop]
@@ -3902,6 +3919,13 @@ Logs:
39023919
test non supported fn selector call failure
39033920
39043921
Traces:
3922+
[157143] NonContractCallRevertTest::setUp()
3923+
├─ [96345] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
3924+
│ └─ ← [Return] 481 bytes of code
3925+
├─ [22492] Counter::setNumber(1)
3926+
│ └─ ← [Stop]
3927+
└─ ← [Stop]
3928+
39053929
[8620] NonContractCallRevertTest::test_non_supported_selector_call_failure()
39063930
├─ [0] console::log("test non supported fn selector call failure") [staticcall]
39073931
│ └─ ← [Stop]
@@ -3971,7 +3995,7 @@ contract NonContractDelegateCallRevertTest is Test {
39713995
"#,
39723996
);
39733997

3974-
cmd.args(["test", "--mc", "NonContractDelegateCallRevertTest", "-vvv"])
3998+
cmd.args(["test", "--mc", "NonContractDelegateCallRevertTest", "-vvvvv"])
39753999
.assert_failure()
39764000
.stdout_eq(str![[r#"
39774001
[COMPILING_FILES] with [SOLC_VERSION]
@@ -3988,6 +4012,8 @@ Traces:
39884012
├─ [0] console::log("Test: Simulating call to unlinked library") [staticcall]
39894013
│ └─ ← [Stop]
39904014
├─ [214746] → new LibraryCaller@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
4015+
│ ├─ storage changes:
4016+
│ │ @ 0: 0 → 0x000000000000000000000000deadbeef00000000000000000000000000000000
39914017
│ └─ ← [Return] 960 bytes of code
39924018
├─ [3896] LibraryCaller::foobar(10)
39934019
│ ├─ [0] 0xdEADBEeF00000000000000000000000000000000::foo(10) [delegatecall]

crates/forge/tests/fixtures/SimpleContractTestVerbose.json

Lines changed: 15112 additions & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)