use super::{
DisplayConfig, DisplayerKind, FinalStatusLevel, MaxProgressRunning, StatusLevel,
TestOutputDisplay,
displayer::{DisplayReporter, DisplayReporterBuilder, ShowTerminalProgress},
};
use crate::{
config::core::EvaluatableProfile,
errors::WriteEventError,
list::TestList,
record::{ShortestRunIdPrefix, StoreSizes},
redact::Redactor,
reporter::{
aggregator::EventAggregator, displayer::ShowProgress, events::*,
structured::StructuredReporter,
},
write_str::WriteStr,
};
use std::time::Duration;
#[derive(Clone, Debug, Default)]
pub struct ReporterStats {
pub recording_sizes: Option<StoreSizes>,
pub run_finished: Option<RunFinishedInfo>,
}
#[derive(Clone, Copy, Debug)]
pub struct RunFinishedInfo {
pub stats: RunFinishedStats,
pub elapsed: Duration,
pub outstanding_not_seen_count: Option<usize>,
}
pub enum ReporterOutput<'a> {
Terminal,
Writer {
writer: &'a mut (dyn WriteStr + Send),
use_unicode: bool,
},
}
#[derive(Debug, Default)]
pub struct ReporterBuilder {
no_capture: bool,
should_colorize: bool,
failure_output: Option<TestOutputDisplay>,
success_output: Option<TestOutputDisplay>,
status_level: Option<StatusLevel>,
final_status_level: Option<FinalStatusLevel>,
verbose: bool,
show_progress: ShowProgress,
no_output_indent: bool,
max_progress_running: MaxProgressRunning,
redactor: Redactor,
}
impl ReporterBuilder {
pub fn set_no_capture(&mut self, no_capture: bool) -> &mut Self {
self.no_capture = no_capture;
self
}
pub fn set_colorize(&mut self, should_colorize: bool) -> &mut Self {
self.should_colorize = should_colorize;
self
}
pub fn set_failure_output(&mut self, failure_output: TestOutputDisplay) -> &mut Self {
self.failure_output = Some(failure_output);
self
}
pub fn set_success_output(&mut self, success_output: TestOutputDisplay) -> &mut Self {
self.success_output = Some(success_output);
self
}
pub fn set_status_level(&mut self, status_level: StatusLevel) -> &mut Self {
self.status_level = Some(status_level);
self
}
pub fn set_final_status_level(&mut self, final_status_level: FinalStatusLevel) -> &mut Self {
self.final_status_level = Some(final_status_level);
self
}
pub fn set_verbose(&mut self, verbose: bool) -> &mut Self {
self.verbose = verbose;
self
}
pub fn set_show_progress(&mut self, show_progress: ShowProgress) -> &mut Self {
self.show_progress = show_progress;
self
}
pub fn set_no_output_indent(&mut self, no_output_indent: bool) -> &mut Self {
self.no_output_indent = no_output_indent;
self
}
pub fn set_max_progress_running(
&mut self,
max_progress_running: MaxProgressRunning,
) -> &mut Self {
self.max_progress_running = max_progress_running;
self
}
pub fn set_redactor(&mut self, redactor: Redactor) -> &mut Self {
self.redactor = redactor;
self
}
}
impl ReporterBuilder {
pub fn build<'a>(
&self,
test_list: &TestList,
profile: &EvaluatableProfile<'a>,
show_term_progress: ShowTerminalProgress,
output: ReporterOutput<'a>,
structured_reporter: StructuredReporter<'a>,
) -> Reporter<'a> {
let aggregator = EventAggregator::new(test_list.mode(), profile);
let display_reporter = DisplayReporterBuilder {
mode: test_list.mode(),
default_filter: profile.default_filter().clone(),
display_config: DisplayConfig {
show_progress: self.show_progress,
no_capture: self.no_capture,
status_level: self.status_level,
final_status_level: self.final_status_level,
profile_status_level: profile.status_level(),
profile_final_status_level: profile.final_status_level(),
},
run_count: test_list.run_count(),
success_output: self.success_output,
failure_output: self.failure_output,
should_colorize: self.should_colorize,
verbose: self.verbose,
no_output_indent: self.no_output_indent,
max_progress_running: self.max_progress_running,
show_term_progress,
displayer_kind: DisplayerKind::Live,
redactor: self.redactor.clone(),
}
.build(output);
Reporter {
display_reporter,
structured_reporter,
metadata_reporter: aggregator,
run_finished: None,
}
}
}
pub struct Reporter<'a> {
display_reporter: DisplayReporter<'a>,
metadata_reporter: EventAggregator<'a>,
structured_reporter: StructuredReporter<'a>,
run_finished: Option<RunFinishedInfo>,
}
impl<'a> Reporter<'a> {
pub fn report_event(&mut self, event: ReporterEvent<'a>) -> Result<(), WriteEventError> {
match event {
ReporterEvent::Tick => {
self.tick();
Ok(())
}
ReporterEvent::Test(event) => self.write_event(event),
}
}
pub fn finish(mut self) -> ReporterStats {
self.display_reporter.finish();
let recording_sizes = self.structured_reporter.finish();
ReporterStats {
recording_sizes,
run_finished: self.run_finished,
}
}
pub fn set_run_id_unique_prefix(&mut self, prefix: ShortestRunIdPrefix) {
self.display_reporter.set_run_id_unique_prefix(prefix);
}
fn tick(&mut self) {
self.display_reporter.tick();
}
fn write_event(&mut self, event: Box<TestEvent<'a>>) -> Result<(), WriteEventError> {
if let TestEventKind::RunFinished {
run_stats,
elapsed,
outstanding_not_seen,
..
} = &event.kind
{
self.run_finished = Some(RunFinishedInfo {
stats: *run_stats,
elapsed: *elapsed,
outstanding_not_seen_count: outstanding_not_seen.as_ref().map(|t| t.total_not_seen),
});
}
self.display_reporter.write_event(&event)?;
self.structured_reporter.write_event(&event)?;
self.metadata_reporter.write_event(event)?;
Ok(())
}
}