Skip to content

Commit 018c83b

Browse files
varex83agentvarex83
andcommitted
fix(cli/mev): address review feedback on tests and deny.toml
- test_mev_timeout: use MockServer with 500ms delay and 10ms timeout to actually exercise the token.cancelled() / TimeoutInterrupted path - Replace hardcoded ports 19950-19960 with refused_addr() helper that binds :0 and drops the listener, giving OS-assigned ports that are guaranteed available - test_mev_default_scenario: assert PingMeasure is Good|Poor instead of exact Good to avoid latency-sensitive flakiness on loaded CI runners - Replace infallible u32→usize and SLOT_TIME→u64 try_from/unwrap_or with direct as casts - deny.toml: add reason fields to RUSTSEC-2026-0098 and RUSTSEC-2026-0099 Co-Authored-By: Bohdan Ohorodnii <35969035+varex83@users.noreply.github.com>
1 parent b0068a5 commit 018c83b

2 files changed

Lines changed: 59 additions & 43 deletions

File tree

crates/cli/src/commands/test/mev.rs

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ async fn mev_create_block_test(target: &str, conf: &TestMevArgs) -> TestResult {
354354
};
355355

356356
all_blocks_rtt.push(rtt);
357-
if all_blocks_rtt.len() == usize::try_from(conf.number_of_payloads).unwrap_or(usize::MAX) {
357+
if all_blocks_rtt.len() == conf.number_of_payloads as usize {
358358
break;
359359
}
360360

@@ -365,7 +365,7 @@ async fn mev_create_block_test(target: &str, conf: &TestMevArgs) -> TestResult {
365365
return test_res.fail(MevTestError::ElapsedNanosConversion(e.to_string()));
366366
}
367367
};
368-
let slot_nanos = u64::try_from(SLOT_TIME.as_nanos()).unwrap_or(1);
368+
let slot_nanos = SLOT_TIME.as_nanos() as u64;
369369
let remainder_nanos = elapsed_nanos.checked_rem(slot_nanos).unwrap_or(0);
370370
let slot_remainder = SLOT_TIME
371371
.checked_sub(Duration::from_nanos(remainder_nanos))
@@ -584,8 +584,8 @@ async fn create_mev_block(
584584
}
585585

586586
let payload = build_blinded_block_payload(&builder_bid)?;
587-
let payload_json = serde_json::to_vec(&payload)
588-
.map_err(|e| MevTestError::PayloadMarshal(e.to_string()))?;
587+
let payload_json =
588+
serde_json::to_vec(&payload).map_err(|e| MevTestError::PayloadMarshal(e.to_string()))?;
589589

590590
let rtt_submit_block = request_rtt(
591591
format!("{target}/eth/v1/builder/blinded_blocks"),
@@ -688,14 +688,20 @@ fn format_mev_relay_name(url_string: &str) -> String {
688688
format!("{scheme}://{hash_short}@{host}")
689689
}
690690

691-
692691
#[cfg(test)]
693692
mod tests {
694693
use super::*;
695694
use std::time::Duration as StdDuration;
696695
use tokio_util::sync::CancellationToken;
697696
use wiremock::{Mock, MockServer, ResponseTemplate, matchers::method};
698697

698+
fn refused_addr() -> String {
699+
let l = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
700+
let addr = l.local_addr().unwrap();
701+
drop(l);
702+
format!("http://{addr}")
703+
}
704+
699705
fn default_test_config() -> TestConfigArgs {
700706
TestConfigArgs {
701707
output_json: String::new(),
@@ -759,21 +765,32 @@ mod tests {
759765
let mut buf = Vec::new();
760766
let res = run(args, &mut buf, CancellationToken::new()).await.unwrap();
761767

762-
assert_verdict(
763-
&res.targets,
764-
&url,
765-
&[
766-
("Ping", TestVerdict::Ok),
767-
("PingMeasure", TestVerdict::Good),
768-
("CreateBlock", TestVerdict::Skip),
769-
],
768+
let target_results = res.targets.get(&url).expect("missing target");
769+
let by_name: std::collections::HashMap<&str, TestVerdict> = target_results
770+
.iter()
771+
.map(|r| (r.name.as_str(), r.verdict))
772+
.collect();
773+
774+
assert_eq!(by_name["Ping"], TestVerdict::Ok, "Ping should be Ok");
775+
assert_eq!(
776+
by_name["CreateBlock"],
777+
TestVerdict::Skip,
778+
"CreateBlock should be Skip"
779+
);
780+
assert!(
781+
matches!(
782+
by_name["PingMeasure"],
783+
TestVerdict::Good | TestVerdict::Poor
784+
),
785+
"PingMeasure should be Good or Poor, got {:?}",
786+
by_name.get("PingMeasure")
770787
);
771788
}
772789

773790
#[tokio::test]
774791
async fn test_mev_connection_refused() {
775-
let endpoint1 = "http://localhost:19950".to_string();
776-
let endpoint2 = "http://localhost:19951".to_string();
792+
let endpoint1 = refused_addr();
793+
let endpoint2 = refused_addr();
777794
let args = default_mev_args(vec![endpoint1.clone(), endpoint2.clone()]);
778795

779796
let mut buf = Vec::new();
@@ -802,27 +819,28 @@ mod tests {
802819

803820
#[tokio::test]
804821
async fn test_mev_timeout() {
805-
let endpoint1 = "http://localhost:19952".to_string();
806-
let endpoint2 = "http://localhost:19953".to_string();
807-
let mut args = default_mev_args(vec![endpoint1.clone(), endpoint2.clone()]);
808-
args.test_config.timeout = StdDuration::from_nanos(100);
822+
let server = MockServer::start().await;
823+
Mock::given(method("GET"))
824+
.respond_with(ResponseTemplate::new(200).set_delay(StdDuration::from_millis(500)))
825+
.mount(&server)
826+
.await;
827+
828+
let url = server.uri();
829+
let mut args = default_mev_args(vec![url.clone()]);
830+
args.test_config.timeout = StdDuration::from_millis(10);
809831

810832
let mut buf = Vec::new();
811833
let res = run(args, &mut buf, CancellationToken::new()).await.unwrap();
812834

813-
for endpoint in [&endpoint1, &endpoint2] {
814-
let target_results = res.targets.get(endpoint).expect("missing target");
815-
assert!(!target_results.is_empty());
816-
for r in target_results {
817-
// CreateBlock skips immediately (load_test=false); others should fail due to
818-
// timeout
819-
let expected = if r.name == "CreateBlock" {
820-
TestVerdict::Skip
821-
} else {
822-
TestVerdict::Fail
823-
};
824-
assert_eq!(r.verdict, expected, "verdict mismatch for {}", r.name);
825-
}
835+
let target_results = res.targets.get(&url).expect("missing target");
836+
assert!(!target_results.is_empty());
837+
for r in target_results {
838+
let expected = if r.name == "CreateBlock" {
839+
TestVerdict::Skip
840+
} else {
841+
TestVerdict::Fail
842+
};
843+
assert_eq!(r.verdict, expected, "verdict mismatch for {}", r.name);
826844
}
827845
}
828846

@@ -831,8 +849,8 @@ mod tests {
831849
let dir = tempfile::tempdir().unwrap();
832850
let json_path = dir.path().join("output.json");
833851

834-
let endpoint1 = "http://localhost:19954".to_string();
835-
let endpoint2 = "http://localhost:19955".to_string();
852+
let endpoint1 = refused_addr();
853+
let endpoint2 = refused_addr();
836854
let mut args = default_mev_args(vec![endpoint1, endpoint2]);
837855
args.test_config.quiet = true;
838856
args.test_config.output_json = json_path.to_str().unwrap().to_string();
@@ -845,7 +863,7 @@ mod tests {
845863

846864
#[tokio::test]
847865
async fn test_mev_unsupported_test() {
848-
let mut args = default_mev_args(vec!["http://localhost:19956".to_string()]);
866+
let mut args = default_mev_args(vec![refused_addr()]);
849867
args.test_config.test_cases = Some(vec!["notSupportedTest".to_string()]);
850868

851869
let mut buf = Vec::new();
@@ -860,8 +878,8 @@ mod tests {
860878

861879
#[tokio::test]
862880
async fn test_mev_custom_test_cases() {
863-
let endpoint1 = "http://localhost:19957".to_string();
864-
let endpoint2 = "http://localhost:19958".to_string();
881+
let endpoint1 = refused_addr();
882+
let endpoint2 = refused_addr();
865883
let mut args = default_mev_args(vec![endpoint1.clone(), endpoint2.clone()]);
866884
args.test_config.test_cases = Some(vec!["Ping".to_string()]);
867885

@@ -881,8 +899,8 @@ mod tests {
881899
let dir = tempfile::tempdir().unwrap();
882900
let file_path = dir.path().join("mev-test-output.json");
883901

884-
let endpoint1 = "http://localhost:19959".to_string();
885-
let endpoint2 = "http://localhost:19960".to_string();
902+
let endpoint1 = refused_addr();
903+
let endpoint2 = refused_addr();
886904
let mut args = default_mev_args(vec![endpoint1, endpoint2]);
887905
args.test_config.output_json = file_path.to_str().unwrap().to_string();
888906

deny.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ ignore = [
3030
# (stuck on 0.7.3) and `alloy-signer-local` (stuck on 0.8.5). Neither is
3131
# reachable from Pluto's loggers. Remove once upstream bumps to >=0.9.3.
3232
{ id = "RUSTSEC-2026-0097", reason = "transitive rand <0.9.3 via cuckoofilter and alloy-signer-local; not triggerable from our code" },
33-
# rustls-webpki URI name constraint bypass — transitive dep
34-
{ id = "RUSTSEC-2026-0098" },
35-
# rustls-webpki wildcard name constraint bypass — transitive dep
36-
{ id = "RUSTSEC-2026-0099" },
33+
{ id = "RUSTSEC-2026-0098", reason = "rustls-webpki URI name constraint bypass; transitive dep via hyper-rustls, not triggerable from our code" },
34+
{ id = "RUSTSEC-2026-0099", reason = "rustls-webpki wildcard name constraint bypass; transitive dep via hyper-rustls, not triggerable from our code" },
3735
]
3836
unmaintained = "workspace"
3937

0 commit comments

Comments
 (0)