1use crate::Case;
4use reth_db::DatabaseError;
5use reth_provider::ProviderError;
6use std::path::{Path, PathBuf};
7use thiserror::Error;
8
9#[derive(Debug, Error)]
15#[non_exhaustive]
16pub enum Error {
17 #[error("test was skipped")]
19 Skipped,
20 #[error("no post state found for validation")]
22 MissingPostState,
23 #[error("an error occurred interacting with the file system at {path}: {error}")]
25 Io {
26 path: PathBuf,
28 #[source]
30 error: std::io::Error,
31 },
32 #[error("an error occurred deserializing the test at {path}: {error}")]
34 CouldNotDeserialize {
35 path: PathBuf,
37 #[source]
39 error: serde_json::Error,
40 },
41 #[error(transparent)]
43 Database(#[from] DatabaseError),
44 #[error("test failed: {0}")]
46 Assertion(String),
47 #[error("test failed: {0}")]
49 Provider(#[from] ProviderError),
50 #[error("an error occurred deserializing RLP: {0}")]
52 RlpDecodeError(#[from] alloy_rlp::Error),
53}
54
55#[derive(Debug)]
57pub struct CaseResult {
58 pub desc: String,
60 pub path: PathBuf,
62 pub result: Result<(), Error>,
64}
65
66impl CaseResult {
67 pub fn new(path: &Path, case: &impl Case, result: Result<(), Error>) -> Self {
69 Self { desc: case.description(), path: path.into(), result }
70 }
71}
72
73pub(crate) fn assert_tests_pass(suite_name: &str, path: &Path, results: &[CaseResult]) {
75 let (passed, failed, skipped) = categorize_results(results);
76
77 print_results(suite_name, path, &passed, &failed, &skipped);
78
79 assert!(failed.is_empty(), "Some tests failed (see above)");
80}
81
82pub(crate) fn categorize_results(
84 results: &[CaseResult],
85) -> (Vec<&CaseResult>, Vec<&CaseResult>, Vec<&CaseResult>) {
86 let mut passed = Vec::new();
87 let mut failed = Vec::new();
88 let mut skipped = Vec::new();
89
90 for case in results {
91 match case.result.as_ref().err() {
92 Some(Error::Skipped) => skipped.push(case),
93 Some(_) => failed.push(case),
94 None => passed.push(case),
95 }
96 }
97
98 (passed, failed, skipped)
99}
100
101pub(crate) fn print_results(
103 suite_name: &str,
104 path: &Path,
105 passed: &[&CaseResult],
106 failed: &[&CaseResult],
107 skipped: &[&CaseResult],
108) {
109 println!("Suite: {suite_name} (at {})", path.display());
110 println!(
111 "Ran {} tests ({} passed, {} failed, {} skipped)",
112 passed.len() + failed.len() + skipped.len(),
113 passed.len(),
114 failed.len(),
115 skipped.len()
116 );
117
118 for case in skipped {
119 println!("[S] Case {} skipped", case.path.display());
120 }
121
122 for case in failed {
123 let error = case.result.as_ref().unwrap_err();
124 println!("[!] Case {} failed (description: {}): {}", case.path.display(), case.desc, error);
125 }
126}