1use reth_db::DatabaseError;
4use reth_provider::ProviderError;
5use std::path::{Path, PathBuf};
6use thiserror::Error;
7
8#[derive(Debug, Error)]
14#[non_exhaustive]
15pub enum Error {
16 #[error("test was skipped")]
18 Skipped,
19 #[error("block {block_number} failed to process: {err}")]
23 BlockProcessingFailed {
24 block_number: u64,
26 #[source]
28 err: Box<dyn std::error::Error + Send + Sync>,
29 },
30 #[error("an error occurred interacting with the file system at {path}: {error}")]
32 Io {
33 path: PathBuf,
35 #[source]
37 error: std::io::Error,
38 },
39 #[error("an error occurred deserializing the test at {path}: {error}")]
41 CouldNotDeserialize {
42 path: PathBuf,
44 #[source]
46 error: serde_json::Error,
47 },
48 #[error(transparent)]
50 Database(#[from] DatabaseError),
51 #[error("test failed: {0}")]
53 Assertion(String),
54 #[error("test failed: {0}")]
56 Provider(#[from] ProviderError),
57 #[error("an error occurred deserializing RLP: {0}")]
59 RlpDecodeError(#[from] alloy_rlp::Error),
60 #[error("an error occurred during consensus checks: {0}")]
62 ConsensusError(#[from] reth_consensus::ConsensusError),
63}
64
65impl Error {
66 pub fn block_failed(
68 block_number: u64,
69 err: impl std::error::Error + Send + Sync + 'static,
70 ) -> Self {
71 Self::BlockProcessingFailed { block_number, err: Box::new(err) }
72 }
73}
74
75#[derive(Debug)]
77pub struct CaseResult {
78 pub desc: String,
80 pub path: PathBuf,
82 pub result: Result<(), Error>,
84}
85
86impl CaseResult {
87 pub fn new(path: &Path, desc: String, result: Result<(), Error>) -> Self {
89 Self { desc, path: path.into(), result }
90 }
91}
92
93pub(crate) fn assert_tests_pass(suite_name: &str, path: &Path, results: &[CaseResult]) {
95 let (passed, failed, skipped) = categorize_results(results);
96
97 print_results(suite_name, path, &passed, &failed, &skipped);
98
99 assert!(failed.is_empty(), "Some tests failed (see above)");
100}
101
102pub(crate) fn categorize_results(
104 results: &[CaseResult],
105) -> (Vec<&CaseResult>, Vec<&CaseResult>, Vec<&CaseResult>) {
106 let mut passed = Vec::new();
107 let mut failed = Vec::new();
108 let mut skipped = Vec::new();
109
110 for case in results {
111 match case.result.as_ref().err() {
112 Some(Error::Skipped) => skipped.push(case),
113 Some(_) => failed.push(case),
114 None => passed.push(case),
115 }
116 }
117
118 (passed, failed, skipped)
119}
120
121pub(crate) fn print_results(
123 suite_name: &str,
124 path: &Path,
125 passed: &[&CaseResult],
126 failed: &[&CaseResult],
127 skipped: &[&CaseResult],
128) {
129 println!("Suite: {suite_name} (at {})", path.display());
130 println!(
131 "Ran {} tests ({} passed, {} failed, {} skipped)",
132 passed.len() + failed.len() + skipped.len(),
133 passed.len(),
134 failed.len(),
135 skipped.len()
136 );
137
138 for case in skipped {
139 println!("[S] Case {} skipped", case.path.display());
140 }
141
142 for case in failed {
143 let error = case.result.as_ref().unwrap_err();
144 println!("[!] Case {} failed (description: {}): {}", case.path.display(), case.desc, error);
145 }
146}