Skip to content

Commit e20374d

Browse files
authored
Configurable Logging Levels & More Ignore Options (#237)
* Allow for changing the logging levels of node and rpcs * Allow for ignoring cases with failing steps * Add logging level config for geth
1 parent fd18bf7 commit e20374d

File tree

10 files changed

+249
-66
lines changed

10 files changed

+249
-66
lines changed

crates/config/src/lib.rs

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,14 @@ impl AsRef<ReportConfiguration> for Context {
218218
}
219219
}
220220

221-
impl AsRef<IgnoreSuccessConfiguration> for Context {
222-
fn as_ref(&self) -> &IgnoreSuccessConfiguration {
221+
impl AsRef<IgnoreCasesConfiguration> for Context {
222+
fn as_ref(&self) -> &IgnoreCasesConfiguration {
223+
static DEFAULT: LazyLock<IgnoreCasesConfiguration> = LazyLock::new(Default::default);
224+
223225
match self {
224226
Self::Test(context) => context.as_ref().as_ref(),
225-
Self::Benchmark(..) => unreachable!(),
226-
Self::ExportJsonSchema | Self::ExportGenesis(..) => unreachable!(),
227+
Self::Benchmark(..) => &DEFAULT,
228+
Self::ExportJsonSchema | Self::ExportGenesis(..) => &DEFAULT,
227229
}
228230
}
229231
}
@@ -317,9 +319,9 @@ pub struct TestExecutionContext {
317319
#[clap(flatten, next_help_heading = "Report Configuration")]
318320
pub report_configuration: ReportConfiguration,
319321

320-
/// Configuration parameters for ignoring certain test cases based on the report
322+
/// Configuration parameters for ignoring certain test cases.
321323
#[clap(flatten, next_help_heading = "Ignore Success Configuration")]
322-
pub ignore_success_configuration: IgnoreSuccessConfiguration,
324+
pub ignore_configuration: IgnoreCasesConfiguration,
323325
}
324326

325327
impl TestExecutionContext {
@@ -623,9 +625,9 @@ impl AsRef<ReportConfiguration> for TestExecutionContext {
623625
}
624626
}
625627

626-
impl AsRef<IgnoreSuccessConfiguration> for TestExecutionContext {
627-
fn as_ref(&self) -> &IgnoreSuccessConfiguration {
628-
&self.ignore_success_configuration
628+
impl AsRef<IgnoreCasesConfiguration> for TestExecutionContext {
629+
fn as_ref(&self) -> &IgnoreCasesConfiguration {
630+
&self.ignore_configuration
629631
}
630632
}
631633

@@ -856,6 +858,14 @@ pub struct GethConfiguration {
856858
value_parser = parse_duration
857859
)]
858860
pub start_timeout_ms: Duration,
861+
862+
/// The logging configuration to pass to the binary when it's being started.
863+
#[clap(
864+
id = "geth.logging-level",
865+
long = "geth.logging-level",
866+
default_value = "3"
867+
)]
868+
pub logging_level: String,
859869
}
860870

861871
/// A set of configuration parameters for kurtosis.
@@ -904,6 +914,14 @@ pub struct ReviveDevNodeConfiguration {
904914
)]
905915
pub consensus: String,
906916

917+
/// The logging configuration to pass to the binary when it's being started.
918+
#[clap(
919+
id = "revive-dev-node.logging-level",
920+
long = "revive-dev-node.logging-level",
921+
default_value = "error,evm=debug,sc_rpc_server=info,runtime::revive=debug"
922+
)]
923+
pub logging_level: String,
924+
907925
/// Specifies the connection string of an existing node that's not managed by the framework.
908926
///
909927
/// If this argument is specified then the framework will not spawn certain nodes itself but
@@ -969,6 +987,14 @@ pub struct PolkadotOmnichainNodeConfiguration {
969987
long = "polkadot-omni-node.parachain-id"
970988
)]
971989
pub parachain_id: Option<usize>,
990+
991+
/// The logging configuration to pass to the binary when it's being started.
992+
#[clap(
993+
id = "polkadot-omni-node.logging-level",
994+
long = "polkadot-omni-node.logging-level",
995+
default_value = "error,evm=debug,sc_rpc_server=info,runtime::revive=debug"
996+
)]
997+
pub logging_level: String,
972998
}
973999

9741000
/// A set of configuration parameters for the ETH RPC.
@@ -989,6 +1015,14 @@ pub struct EthRpcConfiguration {
9891015
value_parser = parse_duration
9901016
)]
9911017
pub start_timeout_ms: Duration,
1018+
1019+
/// The logging configuration to pass to the binary when it's being started.
1020+
#[clap(
1021+
id = "eth-rpc.logging-level",
1022+
long = "eth-rpc.logging-level",
1023+
default_value = "info,eth-rpc=debug"
1024+
)]
1025+
pub logging_level: String,
9921026
}
9931027

9941028
/// A set of configuration parameters for the genesis.
@@ -1132,10 +1166,28 @@ pub struct ReportConfiguration {
11321166
}
11331167

11341168
#[derive(Clone, Debug, Parser, Serialize, Deserialize)]
1135-
pub struct IgnoreSuccessConfiguration {
1136-
/// The path of the report generated by the tool to use to ignore the cases that succeeded.
1137-
#[clap(long = "ignore-success.report-path")]
1138-
pub path: Option<PathBuf>,
1169+
pub struct IgnoreCasesConfiguration {
1170+
/// The path to a report where all of the succeeding cases found in should
1171+
/// be ignored.
1172+
#[clap(
1173+
id = "ignore.succeeding-cases-from-report",
1174+
long = "ignore.succeeding-cases-from-report"
1175+
)]
1176+
pub succeeding_cases_from_report: Option<PathBuf>,
1177+
1178+
/// Allows the tool to ignore any test case where there's a step that's
1179+
/// expected to fail
1180+
#[clap(
1181+
id = "ignore.cases-with-failing-steps",
1182+
long = "ignore.cases-with-failing-steps"
1183+
)]
1184+
pub ignore_cases_with_failing_steps: bool,
1185+
}
1186+
1187+
impl Default for IgnoreCasesConfiguration {
1188+
fn default() -> Self {
1189+
IgnoreCasesConfiguration::parse_from(["ignore-cases-configuration"])
1190+
}
11391191
}
11401192

11411193
/// Represents the working directory that the program uses.

crates/core/src/differential_benchmarks/entry_point.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub async fn handle_differential_benchmarks(
9797
&full_context,
9898
&corpus,
9999
&platforms_and_nodes,
100-
None,
100+
&Default::default(),
101101
reporter.clone(),
102102
)
103103
.await

crates/core/src/differential_tests/entry_point.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::{
1010
use ansi_term::{ANSIStrings, Color};
1111
use anyhow::Context as _;
1212
use futures::{FutureExt, StreamExt};
13-
use revive_dt_common::{cached_fs::read_to_string, types::PrivateKeyAllocator};
13+
use revive_dt_common::types::PrivateKeyAllocator;
1414
use revive_dt_core::Platform;
1515
use revive_dt_format::corpus::Corpus;
1616
use tokio::sync::{Mutex, RwLock, Semaphore};
@@ -21,7 +21,10 @@ use revive_dt_report::{Reporter, ReporterEvent, TestCaseStatus};
2121

2222
use crate::{
2323
differential_tests::Driver,
24-
helpers::{CachedCompiler, NodePool, create_test_definitions_stream},
24+
helpers::{
25+
CachedCompiler, NodePool, TestCaseIgnoreResolvedConfiguration,
26+
create_test_definitions_stream,
27+
},
2528
};
2629

2730
/// Handles the differential testing executing it according to the information defined in the
@@ -81,20 +84,14 @@ pub async fn handle_differential_tests(
8184
info!("Spawned the platform nodes");
8285

8386
// Preparing test definitions.
84-
let only_execute_failed_tests = match context.ignore_success_configuration.path.as_ref() {
85-
Some(path) => {
86-
let report = read_to_string(path)
87-
.context("Failed to read the report file to ignore the succeeding test cases")?;
88-
Some(serde_json::from_str(&report).context("Failed to deserialize report")?)
89-
}
90-
None => None,
91-
};
87+
let test_case_ignore_configuration =
88+
TestCaseIgnoreResolvedConfiguration::try_from(context.ignore_configuration.clone())?;
9289
let full_context = Context::Test(Box::new(context.clone()));
9390
let test_definitions = create_test_definitions_stream(
9491
&full_context,
9592
&corpus,
9693
&platforms_and_nodes,
97-
only_execute_failed_tests.as_ref(),
94+
&test_case_ignore_configuration,
9895
reporter.clone(),
9996
)
10097
.await

crates/core/src/helpers/test.rs

Lines changed: 108 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ use std::collections::BTreeMap;
22
use std::sync::Arc;
33
use std::{borrow::Cow, path::Path};
44

5+
use anyhow::Context as _;
56
use futures::{Stream, StreamExt, stream};
67
use indexmap::{IndexMap, indexmap};
8+
use revive_dt_common::cached_fs::read_to_string;
79
use revive_dt_common::types::PlatformIdentifier;
8-
use revive_dt_config::Context;
10+
use revive_dt_config::{Context, IgnoreCasesConfiguration};
911
use revive_dt_format::corpus::Corpus;
1012
use serde_json::{Value, json};
1113

@@ -29,7 +31,7 @@ pub async fn create_test_definitions_stream<'a>(
2931
context: &Context,
3032
corpus: &'a Corpus,
3133
platforms_and_nodes: &'a BTreeMap<PlatformIdentifier, (&dyn Platform, NodePool)>,
32-
only_execute_failed_tests: Option<&Report>,
34+
test_case_ignore_configuration: &TestCaseIgnoreResolvedConfiguration,
3335
reporter: Reporter,
3436
) -> impl Stream<Item = TestDefinition<'a>> {
3537
let cloned_reporter = reporter.clone();
@@ -130,7 +132,7 @@ pub async fn create_test_definitions_stream<'a>(
130132
)
131133
// Filter out the test cases which are incompatible or that can't run in the current setup.
132134
.filter_map(move |test| async move {
133-
match test.check_compatibility(only_execute_failed_tests) {
135+
match test.check_compatibility(test_case_ignore_configuration) {
134136
Ok(()) => Some(test),
135137
Err((reason, additional_information)) => {
136138
debug!(
@@ -165,6 +167,69 @@ pub async fn create_test_definitions_stream<'a>(
165167
})
166168
}
167169

170+
#[derive(Clone, Debug, Default)]
171+
pub struct TestCaseIgnoreResolvedConfiguration {
172+
/// Some existing report which will be used for a number of purposes.
173+
pub report: Option<Report>,
174+
175+
/// Controls if test cases which succeeded from the existing report should
176+
/// be ignored or not.
177+
pub ignore_succeeding_test_cases_from_report: bool,
178+
179+
/// Controls if test cases which contain steps expected to fail should be
180+
/// ignored or not.
181+
pub ignore_cases_with_failing_steps: bool,
182+
}
183+
184+
impl TestCaseIgnoreResolvedConfiguration {
185+
pub fn with_report(self, report: impl Into<Option<Report>>) -> Self {
186+
self.mutate(|this| this.report = report.into())
187+
}
188+
189+
pub fn with_ignore_succeeding_test_cases_from_report(
190+
self,
191+
ignore_succeeding_test_cases_from_report: bool,
192+
) -> Self {
193+
self.mutate(|this| {
194+
this.ignore_succeeding_test_cases_from_report = ignore_succeeding_test_cases_from_report
195+
})
196+
}
197+
198+
pub fn with_ignore_cases_with_failing_steps(
199+
self,
200+
ignore_cases_with_failing_steps: bool,
201+
) -> Self {
202+
self.mutate(|this| this.ignore_cases_with_failing_steps = ignore_cases_with_failing_steps)
203+
}
204+
205+
fn mutate(mut self, mutator: impl FnOnce(&mut Self)) -> Self {
206+
mutator(&mut self);
207+
self
208+
}
209+
}
210+
211+
impl TryFrom<IgnoreCasesConfiguration> for TestCaseIgnoreResolvedConfiguration {
212+
type Error = anyhow::Error;
213+
214+
fn try_from(value: IgnoreCasesConfiguration) -> Result<Self, Self::Error> {
215+
let mut this = Self::default()
216+
.with_ignore_cases_with_failing_steps(value.ignore_cases_with_failing_steps);
217+
218+
this = if let Some(succeeding_cases_from_report) = value.succeeding_cases_from_report {
219+
let content = read_to_string(succeeding_cases_from_report)
220+
.context("Failed to read report at the specified path")?;
221+
let report =
222+
serde_json::from_str::<Report>(&content).context("Failed to deserialize report")?;
223+
this.with_report(report)
224+
.with_ignore_succeeding_test_cases_from_report(true)
225+
} else {
226+
this
227+
};
228+
229+
Ok(this)
230+
}
231+
}
232+
168233
/// This is a full description of a differential test to run alongside the full metadata file, the
169234
/// specific case to be tested, the platforms that the tests should run on, the specific nodes of
170235
/// these platforms that they should run on, the compilers to use, and everything else needed making
@@ -192,14 +257,14 @@ impl<'a> TestDefinition<'a> {
192257
/// Checks if this test can be ran with the current configuration.
193258
pub fn check_compatibility(
194259
&self,
195-
only_execute_failed_tests: Option<&Report>,
260+
test_case_ignore_configuration: &TestCaseIgnoreResolvedConfiguration,
196261
) -> TestCheckFunctionResult {
197262
self.check_metadata_file_ignored()?;
198263
self.check_case_file_ignored()?;
199264
self.check_target_compatibility()?;
200265
self.check_evm_version_compatibility()?;
201266
self.check_compiler_compatibility()?;
202-
self.check_ignore_succeeded(only_execute_failed_tests)?;
267+
self.check_ignore_configuration(test_case_ignore_configuration)?;
203268
Ok(())
204269
}
205270

@@ -317,32 +382,49 @@ impl<'a> TestDefinition<'a> {
317382

318383
/// Checks if the test case should be executed or not based on the passed report and whether the
319384
/// user has instructed the tool to ignore the already succeeding test cases.
320-
fn check_ignore_succeeded(
385+
fn check_ignore_configuration(
321386
&self,
322-
only_execute_failed_tests: Option<&Report>,
387+
test_case_ignore_configuration: &TestCaseIgnoreResolvedConfiguration,
323388
) -> TestCheckFunctionResult {
324-
let Some(report) = only_execute_failed_tests else {
325-
return Ok(());
326-
};
327-
328-
let test_case_status = report
329-
.execution_information
330-
.get(&(self.metadata_file_path.to_path_buf().into()))
331-
.and_then(|obj| obj.case_reports.get(&self.case_idx))
332-
.and_then(|obj| obj.mode_execution_reports.get(&self.mode))
333-
.and_then(|obj| obj.status.as_ref());
334-
335-
match test_case_status {
336-
Some(TestCaseStatus::Failed { .. }) => Ok(()),
337-
Some(TestCaseStatus::Ignored { .. }) => Err((
338-
"Ignored since it was ignored in a previous run",
389+
// Check if the test case should be ignored based on it containing
390+
// failing steps.
391+
if test_case_ignore_configuration.ignore_cases_with_failing_steps
392+
&& self.case.any_step_expected_to_fail()
393+
{
394+
return Err((
395+
"Ignored since it contains steps which are expected to fail",
339396
indexmap! {},
340-
)),
341-
Some(TestCaseStatus::Succeeded { .. }) => {
342-
Err(("Ignored since it succeeded in a prior run", indexmap! {}))
397+
));
398+
}
399+
400+
// Check if the succeeding cases from the provided report should be
401+
// ignored or not.
402+
if let (Some(report), true) = (
403+
test_case_ignore_configuration.report.as_ref(),
404+
test_case_ignore_configuration.ignore_succeeding_test_cases_from_report,
405+
) {
406+
let test_case_status = report
407+
.execution_information
408+
.get(&(self.metadata_file_path.to_path_buf().into()))
409+
.and_then(|obj| obj.case_reports.get(&self.case_idx))
410+
.and_then(|obj| obj.mode_execution_reports.get(&self.mode))
411+
.and_then(|obj| obj.status.as_ref());
412+
413+
match test_case_status {
414+
Some(TestCaseStatus::Failed { .. }) | None => {}
415+
Some(TestCaseStatus::Ignored { .. }) => {
416+
return Err((
417+
"Ignored since it was ignored in a previous run",
418+
indexmap! {},
419+
));
420+
}
421+
Some(TestCaseStatus::Succeeded { .. }) => {
422+
return Err(("Ignored since it succeeded in a prior run", indexmap! {}));
423+
}
343424
}
344-
None => Ok(()),
345425
}
426+
427+
Ok(())
346428
}
347429
}
348430

0 commit comments

Comments
 (0)