use crate::spinner::AnalysisPhase;
pub(crate) trait AnalysisProgress: Sync {
fn set_phase(&self, phase: AnalysisPhase);
fn report_file_progress(&self, _done: usize, _total: usize) {}
fn note(&self, message: String) {
eprintln!("{message}");
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
use std::sync::Mutex;
struct RecordingProgress {
phases: Mutex<Vec<AnalysisPhase>>,
}
impl AnalysisProgress for RecordingProgress {
fn set_phase(&self, phase: AnalysisPhase) {
self.phases
.lock()
.expect("lock must not be poisoned")
.push(phase);
}
}
#[test]
fn should_record_phase_and_no_op_file_progress_when_using_default_impl() {
let progress = RecordingProgress {
phases: Mutex::new(Vec::new()),
};
progress.set_phase(AnalysisPhase::Diffing);
progress.report_file_progress(3, 10);
let expected = vec![AnalysisPhase::Diffing];
let actual = progress
.phases
.into_inner()
.expect("lock must not be poisoned");
assert_eq!(expected, actual);
}
struct BufferingProgress {
notes: Mutex<Vec<String>>,
}
impl AnalysisProgress for BufferingProgress {
fn set_phase(&self, _phase: AnalysisPhase) {}
fn note(&self, message: String) {
self.notes
.lock()
.expect("lock must not be poisoned")
.push(message);
}
}
#[test]
fn should_buffer_note_instead_of_printing_when_note_is_overridden() {
let progress = BufferingProgress {
notes: Mutex::new(Vec::new()),
};
progress.note("note: diff is empty, nothing to analyze".to_string());
progress.note("note: no symbols under nonexistent/path.rs".to_string());
let expected = vec![
"note: diff is empty, nothing to analyze".to_string(),
"note: no symbols under nonexistent/path.rs".to_string(),
];
let actual = progress
.notes
.into_inner()
.expect("lock must not be poisoned");
assert_eq!(expected, actual);
}
}