@@ -5,7 +5,7 @@ use clap::{Parser, ValueHint};
55use eyre:: { Context , OptionExt , Result } ;
66use forge:: {
77 decode:: decode_console_logs,
8- gas_report:: GasReport ,
8+ gas_report:: { GasReport , GasReportKind } ,
99 multi_runner:: matches_contract,
1010 result:: { SuiteResult , TestOutcome , TestStatus } ,
1111 traces:: {
@@ -112,7 +112,7 @@ pub struct TestArgs {
112112 json : bool ,
113113
114114 /// Output test results as JUnit XML report.
115- #[ arg( long, conflicts_with = "json" , help_heading = "Display options" ) ]
115+ #[ arg( long, conflicts_with_all ( [ "json" , "gas_report" ] ) , help_heading = "Display options" ) ]
116116 junit : bool ,
117117
118118 /// Stop running tests after the first failure.
@@ -474,6 +474,9 @@ impl TestArgs {
474474
475475 trace ! ( target: "forge::test" , "running all tests" ) ;
476476
477+ // If we need to render to a serialized format, we should not print anything else to stdout.
478+ let silent = self . gas_report && self . json ;
479+
477480 let num_filtered = runner. matching_test_functions ( filter) . count ( ) ;
478481 if num_filtered != 1 && ( self . debug . is_some ( ) || self . flamegraph || self . flamechart ) {
479482 let action = if self . flamegraph {
@@ -500,7 +503,7 @@ impl TestArgs {
500503 }
501504
502505 // Run tests in a non-streaming fashion and collect results for serialization.
503- if self . json {
506+ if ! self . gas_report && self . json {
504507 let mut results = runner. test_collect ( filter) ;
505508 results. values_mut ( ) . for_each ( |suite_result| {
506509 for test_result in suite_result. test_results . values_mut ( ) {
@@ -565,9 +568,13 @@ impl TestArgs {
565568 }
566569 let mut decoder = builder. build ( ) ;
567570
568- let mut gas_report = self
569- . gas_report
570- . then ( || GasReport :: new ( config. gas_reports . clone ( ) , config. gas_reports_ignore . clone ( ) ) ) ;
571+ let mut gas_report = self . gas_report . then ( || {
572+ GasReport :: new (
573+ config. gas_reports . clone ( ) ,
574+ config. gas_reports_ignore . clone ( ) ,
575+ if self . json { GasReportKind :: JSON } else { GasReportKind :: Markdown } ,
576+ )
577+ } ) ;
571578
572579 let mut gas_snapshots = BTreeMap :: < String , BTreeMap < String , String > > :: new ( ) ;
573580
@@ -588,30 +595,34 @@ impl TestArgs {
588595 self . flamechart ;
589596
590597 // Print suite header.
591- println ! ( ) ;
592- for warning in suite_result. warnings . iter ( ) {
593- eprintln ! ( "{} {warning}" , "Warning:" . yellow( ) . bold( ) ) ;
594- }
595- if !tests. is_empty ( ) {
596- let len = tests. len ( ) ;
597- let tests = if len > 1 { "tests" } else { "test" } ;
598- println ! ( "Ran {len} {tests} for {contract_name}" ) ;
598+ if !silent {
599+ println ! ( ) ;
600+ for warning in suite_result. warnings . iter ( ) {
601+ eprintln ! ( "{} {warning}" , "Warning:" . yellow( ) . bold( ) ) ;
602+ }
603+ if !tests. is_empty ( ) {
604+ let len = tests. len ( ) ;
605+ let tests = if len > 1 { "tests" } else { "test" } ;
606+ println ! ( "Ran {len} {tests} for {contract_name}" ) ;
607+ }
599608 }
600609
601610 // Process individual test results, printing logs and traces when necessary.
602611 for ( name, result) in tests {
603- shell:: println ( result. short_result ( name) ) ?;
604-
605- // We only display logs at level 2 and above
606- if verbosity >= 2 {
607- // We only decode logs from Hardhat and DS-style console events
608- let console_logs = decode_console_logs ( & result. logs ) ;
609- if !console_logs. is_empty ( ) {
610- println ! ( "Logs:" ) ;
611- for log in console_logs {
612- println ! ( " {log}" ) ;
612+ if !silent {
613+ shell:: println ( result. short_result ( name) ) ?;
614+
615+ // We only display logs at level 2 and above
616+ if verbosity >= 2 {
617+ // We only decode logs from Hardhat and DS-style console events
618+ let console_logs = decode_console_logs ( & result. logs ) ;
619+ if !console_logs. is_empty ( ) {
620+ println ! ( "Logs:" ) ;
621+ for log in console_logs {
622+ println ! ( " {log}" ) ;
623+ }
624+ println ! ( ) ;
613625 }
614- println ! ( ) ;
615626 }
616627 }
617628
@@ -653,7 +664,7 @@ impl TestArgs {
653664 }
654665 }
655666
656- if !decoded_traces. is_empty ( ) {
667+ if !silent && ! decoded_traces. is_empty ( ) {
657668 shell:: println ( "Traces:" ) ?;
658669 for trace in & decoded_traces {
659670 shell:: println ( trace) ?;
@@ -760,7 +771,9 @@ impl TestArgs {
760771 }
761772
762773 // Print suite summary.
763- shell:: println ( suite_result. summary ( ) ) ?;
774+ if !silent {
775+ shell:: println ( suite_result. summary ( ) ) ?;
776+ }
764777
765778 // Add the suite result to the outcome.
766779 outcome. results . insert ( contract_name, suite_result) ;
@@ -781,7 +794,7 @@ impl TestArgs {
781794 outcome. gas_report = Some ( finalized) ;
782795 }
783796
784- if !outcome. results . is_empty ( ) {
797+ if !silent && ! outcome. results . is_empty ( ) {
785798 shell:: println ( outcome. summary ( duration) ) ?;
786799
787800 if self . summary {
@@ -1063,7 +1076,7 @@ contract FooBarTest is DSTest {
10631076 let call_cnts = gas_report
10641077 . contracts
10651078 . values( )
1066- . flat_map( |c| c. functions. values( ) . flat_map( |f| f. values( ) . map( |v| v. calls . len( ) ) ) )
1079+ . flat_map( |c| c. functions. values( ) . flat_map( |f| f. values( ) . map( |v| v. frames . len( ) ) ) )
10671080 . collect:: <Vec <_>>( ) ;
10681081 // assert that all functions were called at least 100 times
10691082 assert!( call_cnts. iter( ) . all( |c| * c > 100 ) ) ;
0 commit comments