diff --git a/crates/common/src/macros/define_wrapper_type.rs b/crates/common/src/macros/define_wrapper_type.rs index 2196595..95e0de9 100644 --- a/crates/common/src/macros/define_wrapper_type.rs +++ b/crates/common/src/macros/define_wrapper_type.rs @@ -7,6 +7,15 @@ macro_rules! impl_for_wrapper { } } }; + (FromStr, $ident: ident) => { + impl std::str::FromStr for $ident { + type Err = anyhow::Error; + + fn from_str(s: &str) -> anyhow::Result { + s.parse().map(Self).map_err(Into::into) + } + } + }; } /// Defines wrappers around types. diff --git a/crates/core/src/main.rs b/crates/core/src/main.rs index a3c5f56..8ec81ad 100644 --- a/crates/core/src/main.rs +++ b/crates/core/src/main.rs @@ -71,7 +71,8 @@ fn main() -> anyhow::Result<()> { let (reporter, report_aggregator_task) = ReportAggregator::new(args.clone()).into_task(); - let body = async { + let number_of_threads = args.number_of_threads; + let body = async move { let tests = collect_corpora(&args)? .into_iter() .inspect(|(corpus, _)| { @@ -83,7 +84,7 @@ fn main() -> anyhow::Result<()> { .inspect(|metadata_file| { reporter .report_metadata_file_discovery_event( - metadata_file.metadata_file_path.as_path(), + metadata_file.metadata_file_path.clone(), metadata_file.content.clone(), ) .expect("Can't fail") @@ -100,7 +101,7 @@ fn main() -> anyhow::Result<()> { }; tokio::runtime::Builder::new_multi_thread() - .worker_threads(args.number_of_threads) + .worker_threads(number_of_threads) .enable_all() .build() .expect("Failed building the Runtime") @@ -183,16 +184,15 @@ where let (report_tx, report_rx) = mpsc::unbounded_channel::<(Test<'_>, CaseResult)>(); let tests = prepare_tests::(args, metadata_files); - let driver_task = start_driver_task::(args, tests, report_tx) - .await? - .inspect(|_| { - reporter - .report_execution_completed_event() - .expect("Failed to inform the report aggregator of the task finishing") - }); + let driver_task = start_driver_task::(args, tests, report_tx).await?; let status_reporter_task = start_reporter_task(report_rx); - let (_, _, rtn) = tokio::join!(status_reporter_task, driver_task, report_aggregator_task); + drop(reporter); + let (_, _, rtn) = tokio::join!( + status_reporter_task.inspect(|_| info!("Status reporter completed")), + driver_task.inspect(|_| info!("Driver completed")), + report_aggregator_task.inspect(|_| info!("Report aggregator completed")) + ); rtn?; Ok(()) diff --git a/crates/format/src/case.rs b/crates/format/src/case.rs index 333d8e4..c98ac46 100644 --- a/crates/format/src/case.rs +++ b/crates/format/src/case.rs @@ -73,5 +73,5 @@ define_wrapper_type!( /// A wrapper type for the index of test cases found in metadata file. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] #[serde(transparent)] - pub struct CaseIdx(usize) impl Display; + pub struct CaseIdx(usize) impl Display, FromStr; ); diff --git a/crates/report/src/aggregator.rs b/crates/report/src/aggregator.rs index 21ba45b..ef99cca 100644 --- a/crates/report/src/aggregator.rs +++ b/crates/report/src/aggregator.rs @@ -2,23 +2,25 @@ //! reporters and combines them into a single unified report. use std::{ - collections::BTreeSet, + collections::{BTreeSet, HashMap, HashSet}, fs::OpenOptions, - path::PathBuf, time::{SystemTime, UNIX_EPOCH}, }; use anyhow::Result; +use revive_dt_compiler::Mode; use revive_dt_config::Arguments; -use revive_dt_format::corpus::Corpus; +use revive_dt_format::{case::CaseIdx, corpus::Corpus}; use serde::Serialize; +use serde_with::{DisplayFromStr, serde_as}; use tokio::sync::{ broadcast::{Sender, channel}, mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel}, }; use crate::{ - SubscribeToEventsEvent, + SubscribeToEventsEvent, TestIgnoredEvent, + common::MetadataFilePath, reporter_event::ReporterEvent, runner_event::{CorpusFileDiscoveryEvent, MetadataFileDiscoveryEvent, Reporter, RunnerEvent}, }; @@ -26,6 +28,7 @@ use crate::{ pub struct ReportAggregator { /* Internal Report State */ report: Report, + remaining_cases: HashMap>, /* Channels */ runner_tx: Option>, runner_rx: UnboundedReceiver, @@ -38,6 +41,7 @@ impl ReportAggregator { let (listener_tx, _) = channel::(1024); Self { report: Report::new(config), + remaining_cases: Default::default(), runner_tx: Some(runner_tx), runner_rx, listener_tx, @@ -66,6 +70,9 @@ impl ReportAggregator { RunnerEvent::MetadataFileDiscovery(event) => { self.handle_metadata_file_discovery_event(*event); } + RunnerEvent::TestIgnored(event) => { + self.handle_test_ignored_event(*event); + } } } @@ -96,10 +103,26 @@ impl ReportAggregator { } fn handle_metadata_file_discovery_event(&mut self, event: MetadataFileDiscoveryEvent) { - self.report.metadata_files.insert(event.path); + self.report.metadata_files.insert(event.path.clone()); + self.remaining_cases.insert( + event.path, + event + .metadata + .cases + .iter() + .enumerate() + .map(|(id, _)| id) + .map(CaseIdx::new) + .collect(), + ); + } + + fn handle_test_ignored_event(&mut self, _: TestIgnoredEvent) { + todo!() } } +#[serde_as] #[derive(Clone, Debug, Serialize)] pub struct Report { /// The configuration that the tool was started up with. @@ -107,7 +130,11 @@ pub struct Report { /// The list of corpus files that the tool found. pub corpora: Vec, /// The list of metadata files that were found by the tool. - pub metadata_files: BTreeSet, + pub metadata_files: BTreeSet, + /// Information relating to each test case. + #[serde_as(as = "HashMap<_, HashMap>>")] + pub test_case_information: + HashMap>>, } impl Report { @@ -116,6 +143,10 @@ impl Report { config, corpora: Default::default(), metadata_files: Default::default(), + test_case_information: Default::default(), } } } + +#[derive(Clone, Debug, Serialize)] +pub struct TestCaseReport {} diff --git a/crates/report/src/common.rs b/crates/report/src/common.rs index 0f21c13..4f27568 100644 --- a/crates/report/src/common.rs +++ b/crates/report/src/common.rs @@ -10,6 +10,7 @@ use serde_with::{DisplayFromStr, serde_as}; define_wrapper_type!( #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] + #[serde(transparent)] pub struct MetadataFilePath(PathBuf); ); diff --git a/crates/report/src/runner_event.rs b/crates/report/src/runner_event.rs index 5ad26da..2d2e35a 100644 --- a/crates/report/src/runner_event.rs +++ b/crates/report/src/runner_event.rs @@ -1,12 +1,11 @@ //! The types associated with the events sent by the runner to the reporter. - -use std::path::PathBuf; +#![allow(dead_code)] use revive_dt_format::corpus::Corpus; use revive_dt_format::metadata::Metadata; use tokio::sync::{broadcast, oneshot}; -use crate::ReporterEvent; +use crate::{ReporterEvent, common::MetadataFilePath}; macro_rules! keep_if_doc { (#[doc = $doc:expr]) => { @@ -91,6 +90,16 @@ macro_rules! define_event { } impl [< $ident Reporter >] { + pub fn test_specific_reporter( + &self, + test_specifier: impl Into> + ) -> [< $ident TestSpecificReporter >] { + [< $ident TestSpecificReporter >] { + reporter: self.clone(), + test_specifier: test_specifier.into(), + } + } + fn report(&self, event: impl Into<$ident>) -> anyhow::Result<()> { self.0.send(event.into()).map_err(Into::into) } @@ -104,6 +113,18 @@ macro_rules! define_event { } )* } + + /// A reporter that's tied to a specific test case. + pub struct [< $ident TestSpecificReporter >] { + $vis reporter: [< $ident Reporter >], + $vis test_specifier: std::sync::Arc, + } + + impl [< $ident TestSpecificReporter >] { + fn report(&self, event: impl Into<$ident>) -> anyhow::Result<()> { + self.reporter.report(event) + } + } } }; } @@ -125,9 +146,13 @@ define_event! { /// An event emitted by runners when they've discovered a metadata file. MetadataFileDiscovery { /// The path of the metadata file discovered. - path: PathBuf, + path: MetadataFilePath, /// The content of the metadata file. metadata: Metadata + }, + /// An event emitted by the runners when a test case is ignored. + TestIgnored { + }, /// An event emitted by the runners when the execution is completed and the aggregator can /// stop.